#include <unistd.h>
#endif
#include <stdlib.h>
-#include <string.h>
#include <ctype.h>
+#include <fcntl.h>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
-#if HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
#include <time.h>
#include "blkidP.h"
+#include "canonicalize.h" /* $(top_srcdir)/include */
+#include "pathnames.h"
+#include "sysfs.h"
+#include "at.h"
+
/*
* Find a dev struct in the cache by device name, if available.
*
}
/*
- * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs
- * provides the real DM device names in /sys/block/<ptname>/dm/name
- */
-static char *get_dm_name(const char *ptname)
-{
- FILE *f;
- size_t sz;
- char path[256], name[256], *res = NULL;
-
- snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptname);
- if ((f = fopen(path, "r")) == NULL)
- return NULL;
-
- /* read "<name>\n" from sysfs */
- if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) {
- name[sz - 1] = '\0';
- snprintf(path, sizeof(path), "/dev/mapper/%s", name);
- res = blkid_strdup(path);
- }
- fclose(f);
- return res;
-}
-
-/*
* Probe a single block device to add to the device cache.
*/
static void probe_one(blkid_cache cache, const char *ptname,
- dev_t devno, int pri, int only_if_new)
+ dev_t devno, int pri, int only_if_new, int removable)
{
blkid_dev dev = NULL;
struct list_head *p, *pnext;
* to standard /dev/mapper/<name>.
*/
if (!strncmp(ptname, "dm-", 3) && isdigit(ptname[3])) {
- devname = get_dm_name(ptname);
+ devname = canonicalize_dm_name(ptname);
if (!devname)
blkid__scan_dir("/dev/mapper", devno, 0, &devname);
if (devname)
dev->bid_devno == devno)
goto set_pri;
- if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) &&
+ if (stat(device, &st) == 0 &&
+ (S_ISBLK(st.st_mode) ||
+ (S_ISCHR(st.st_mode) && !strncmp(ptname, "ubi", 3))) &&
st.st_rdev == devno) {
devname = blkid_strdup(device);
goto get_dev;
dev->bid_pri += 5;
} else if (!strncmp(ptname, "md", 2))
dev->bid_pri = BLKID_PRI_MD;
+ if (removable)
+ dev->bid_flags |= BLKID_BID_FL_REMOVABLE;
}
return;
}
lvm_device,
(unsigned int) dev));
probe_one(cache, lvm_device, dev, BLKID_PRI_LVM,
- only_if_new);
+ only_if_new, 0);
free(lvm_device);
}
closedir(lv_list);
device, ma, mi));
probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS,
- only_if_new);
+ only_if_new, 0);
num++;
}
fclose(procpt);
return num;
}
+static void
+ubi_probe_all(blkid_cache cache, int only_if_new)
+{
+ const char **dirname;
+
+ for (dirname = dirlist; *dirname; dirname++) {
+ DBG(DEBUG_DEVNAME, printf("probing UBI volumes under %s\n",
+ *dirname));
+
+ DIR *dir;
+ struct dirent *iter;
+
+ dir = opendir(*dirname);
+ if (dir == NULL)
+ continue ;
+
+ while ((iter = readdir(dir)) != NULL) {
+ char *name;
+ struct stat st;
+ dev_t dev;
+
+ name = iter->d_name;
+#ifdef _DIRENT_HAVE_D_TYPE
+ if (iter->d_type != DT_UNKNOWN &&
+ iter->d_type != DT_CHR && iter->d_type != DT_LNK)
+ continue;
+#endif
+ if (!strcmp(name, ".") || !strcmp(name, "..") ||
+ !strstr(name, "ubi"))
+ continue;
+ if (!strcmp(name, "ubi_ctrl"))
+ continue;
+ if (fstat_at(dirfd(dir), *dirname, name, &st, 0))
+ continue;
+
+ dev = st.st_rdev;
+
+ if (!S_ISCHR(st.st_mode) || !minor(dev))
+ continue;
+ DBG(DEBUG_DEVNAME, printf("UBI vol %s/%s: devno 0x%04X\n",
+ *dirname, name, (int) dev));
+ probe_one(cache, name, dev, BLKID_PRI_UBI, only_if_new, 0);
+ }
+ closedir(dir);
+ }
+}
+
/*
* Read the device data for all available block devices in the system.
*/
#ifdef VG_DIR
lvm_probe_all(cache, only_if_new);
#endif
+ ubi_probe_all(cache, only_if_new);
proc = fopen(PROC_PARTITIONS, "r");
if (!proc)
if (sz > 1)
probe_one(cache, ptname, devs[which], 0,
- only_if_new);
+ only_if_new, 0);
lens[which] = 0; /* mark as checked */
}
printf("whole dev %s, devno 0x%04X\n",
ptnames[last], (unsigned int) devs[last]));
probe_one(cache, ptnames[last], devs[last], 0,
- only_if_new);
+ only_if_new, 0);
lens[last] = 0;
}
}
/* Handle the last device if it wasn't partitioned */
if (lens[which])
- probe_one(cache, ptname, devs[which], 0, only_if_new);
+ probe_one(cache, ptname, devs[which], 0, only_if_new, 0);
fclose(proc);
blkid_flush_cache(cache);
return 0;
}
+/* Don't use it by default -- it's pretty slow (because cdroms, floppy, ...)
+ */
+static int probe_all_removable(blkid_cache cache)
+{
+ DIR *dir;
+ struct dirent *d;
+
+ if (!cache)
+ return -BLKID_ERR_PARAM;
+
+ dir = opendir(_PATH_SYS_BLOCK);
+ if (!dir)
+ return -BLKID_ERR_PROC;
+
+ while((d = readdir(dir))) {
+ struct sysfs_cxt sysfs;
+ int removable = 0;
+ dev_t devno;
+
+#ifdef _DIRENT_HAVE_D_TYPE
+ if (d->d_type != DT_UNKNOWN && d->d_type != DT_LNK)
+ continue;
+#endif
+ if (d->d_name[0] == '.' &&
+ ((d->d_name[1] == 0) ||
+ ((d->d_name[1] == '.') && (d->d_name[2] == 0))))
+ continue;
+
+ devno = sysfs_devname_to_devno(d->d_name, NULL);
+ if (!devno)
+ continue;
+
+ if (sysfs_init(&sysfs, devno, NULL) == 0) {
+ sysfs_read_int(&sysfs, "removable", &removable);
+ sysfs_deinit(&sysfs);
+ }
+
+ if (removable)
+ probe_one(cache, d->d_name, devno, 0, 0, 1);
+ }
+
+ closedir(dir);
+ return 0;
+}
+
+
+/**
+ * blkid_probe_all:
+ * @cache: cache handler
+ *
+ * Probes all block devices.
+ *
+ * Returns: 0 on success, or number less than zero in case of error.
+ */
int blkid_probe_all(blkid_cache cache)
{
int ret;
return ret;
}
+/**
+ * blkid_probe_all_new:
+ * @cache: cache handler
+ *
+ * Probes all new block devices.
+ *
+ * Returns: 0 on success, or number less than zero in case of error.
+ */
int blkid_probe_all_new(blkid_cache cache)
{
int ret;
return ret;
}
+/**
+ * blkid_probe_all_removable:
+ * @cache: cache handler
+ *
+ * The libblkid probing is based on devices from /proc/partitions by default.
+ * This file usually does not contain removable devices (e.g. CDROMs) and this kind
+ * of devices are invisible for libblkid.
+ *
+ * This function adds removable block devices to @cache (probing is based on
+ * information from the /sys directory). Don't forget that removable devices
+ * (floppies, CDROMs, ...) could be pretty slow. It's very bad idea to call
+ * this function by default.
+ *
+ * Note that devices which were detected by this function won't be written to
+ * blkid.tab cache file.
+ *
+ * Returns: 0 on success, or number less than zero in case of error.
+ */
+int blkid_probe_all_removable(blkid_cache cache)
+{
+ int ret;
+
+ DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_removable()\n"));
+ ret = probe_all_removable(cache);
+ DBG(DEBUG_PROBE, printf("End blkid_probe_all_removable()\n"));
+ return ret;
+}
#ifdef TEST_PROGRAM
int main(int argc, char **argv)
if (blkid_probe_all(cache) < 0)
printf("%s: error probing devices\n", argv[0]);
+ if (blkid_probe_all_removable(cache) < 0)
+ printf("%s: error probing removable devices\n", argv[0]);
+
blkid_put_cache(cache);
return (0);
}