diff options
Diffstat (limited to 'libblkid/devname.c')
-rw-r--r-- | libblkid/devname.c | 678 |
1 files changed, 0 insertions, 678 deletions
diff --git a/libblkid/devname.c b/libblkid/devname.c deleted file mode 100644 index b27b6612c..000000000 --- a/libblkid/devname.c +++ /dev/null @@ -1,678 +0,0 @@ -/* - * devname.c - get a dev by its device inode name - * - * Copyright (C) Andries Brouwer - * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o - * Copyright (C) 2001 Andreas Dilger - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ - -#define _GNU_SOURCE 1 - -#include <stdio.h> -#include <string.h> -#include <limits.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <stdlib.h> -#include <ctype.h> -#include <fcntl.h> -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#include <dirent.h> -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#ifdef HAVE_ERRNO_H -#include <errno.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. - * - * If there is no entry with the specified device name, and the create - * flag is set, then create an empty device entry. - */ -blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags) -{ - blkid_dev dev = NULL, tmp; - struct list_head *p, *pnext; - - if (!cache || !devname) - return NULL; - - list_for_each(p, &cache->bic_devs) { - tmp = list_entry(p, struct blkid_struct_dev, bid_devs); - if (strcmp(tmp->bid_name, devname)) - continue; - - DBG(DEBUG_DEVNAME, - printf("found devname %s in cache\n", tmp->bid_name)); - dev = tmp; - break; - } - - if (!dev && (flags & BLKID_DEV_CREATE)) { - if (access(devname, F_OK) < 0) - return NULL; - dev = blkid_new_dev(); - if (!dev) - return NULL; - dev->bid_time = INT_MIN; - dev->bid_name = strdup(devname); - dev->bid_cache = cache; - list_add_tail(&dev->bid_devs, &cache->bic_devs); - cache->bic_flags |= BLKID_BIC_FL_CHANGED; - } - - if (flags & BLKID_DEV_VERIFY) { - dev = blkid_verify(cache, dev); - if (!dev || !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) - return dev; - /* - * If the device is verified, then search the blkid - * cache for any entries that match on the type, uuid, - * and label, and verify them; if a cache entry can - * not be verified, then it's stale and so we remove - * it. - */ - list_for_each_safe(p, pnext, &cache->bic_devs) { - blkid_dev dev2 = list_entry(p, struct blkid_struct_dev, bid_devs); - if (dev2->bid_flags & BLKID_BID_FL_VERIFIED) - continue; - if (!dev->bid_type || !dev2->bid_type || - strcmp(dev->bid_type, dev2->bid_type)) - continue; - if (dev->bid_label && dev2->bid_label && - strcmp(dev->bid_label, dev2->bid_label)) - continue; - if (dev->bid_uuid && dev2->bid_uuid && - strcmp(dev->bid_uuid, dev2->bid_uuid)) - continue; - if ((dev->bid_label && !dev2->bid_label) || - (!dev->bid_label && dev2->bid_label) || - (dev->bid_uuid && !dev2->bid_uuid) || - (!dev->bid_uuid && dev2->bid_uuid)) - continue; - dev2 = blkid_verify(cache, dev2); - if (dev2 && !(dev2->bid_flags & BLKID_BID_FL_VERIFIED)) - blkid_free_dev(dev2); - } - } - return dev; -} - -/* Directories where we will try to search for device names */ -static const char *dirlist[] = { "/dev", "/devfs", "/devices", NULL }; - -static int is_dm_leaf(const char *devname) -{ - struct dirent *de, *d_de; - DIR *dir, *d_dir; - char path[256]; - int ret = 1; - - if ((dir = opendir("/sys/block")) == NULL) - return 0; - while ((de = readdir(dir)) != NULL) { - if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") || - !strcmp(de->d_name, devname) || - strncmp(de->d_name, "dm-", 3) || - strlen(de->d_name) > sizeof(path)-32) - continue; - sprintf(path, "/sys/block/%s/slaves", de->d_name); - if ((d_dir = opendir(path)) == NULL) - continue; - while ((d_de = readdir(d_dir)) != NULL) { - if (!strcmp(d_de->d_name, devname)) { - ret = 0; - break; - } - } - closedir(d_dir); - if (!ret) - break; - } - closedir(dir); - return ret; -} - -/* - * 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, int removable) -{ - blkid_dev dev = NULL; - struct list_head *p, *pnext; - const char **dir; - char *devname = NULL; - - /* See if we already have this device number in the cache. */ - list_for_each_safe(p, pnext, &cache->bic_devs) { - blkid_dev tmp = list_entry(p, struct blkid_struct_dev, - bid_devs); - if (tmp->bid_devno == devno) { - if (only_if_new && !access(tmp->bid_name, F_OK)) - return; - dev = blkid_verify(cache, tmp); - if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED)) - break; - dev = 0; - } - } - if (dev && dev->bid_devno == devno) - goto set_pri; - - /* Try to translate private device-mapper dm-<N> names - * to standard /dev/mapper/<name>. - */ - if (!strncmp(ptname, "dm-", 3) && isdigit(ptname[3])) { - devname = canonicalize_dm_name(ptname); - if (!devname) - blkid__scan_dir("/dev/mapper", devno, 0, &devname); - if (devname) - goto get_dev; - } - - /* - * Take a quick look at /dev/ptname for the device number. We check - * all of the likely device directories. If we don't find it, or if - * the stat information doesn't check out, use blkid_devno_to_devname() - * to find it via an exhaustive search for the device major/minor. - */ - for (dir = dirlist; *dir; dir++) { - struct stat st; - char device[256]; - - snprintf(device, sizeof(device), "%s/%s", *dir, ptname); - if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) && - dev->bid_devno == devno) - goto set_pri; - - if (stat(device, &st) == 0 && - (S_ISBLK(st.st_mode) || - (S_ISCHR(st.st_mode) && !strncmp(ptname, "ubi", 3))) && - st.st_rdev == devno) { - devname = strdup(device); - goto get_dev; - } - } - /* Do a short-cut scan of /dev/mapper first */ - if (!devname) - blkid__scan_dir("/dev/mapper", devno, 0, &devname); - if (!devname) { - devname = blkid_devno_to_devname(devno); - if (!devname) - return; - } - -get_dev: - dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL); - free(devname); - -set_pri: - if (dev) { - if (pri) - dev->bid_pri = pri; - else if (!strncmp(dev->bid_name, "/dev/mapper/", 11)) { - dev->bid_pri = BLKID_PRI_DM; - if (is_dm_leaf(ptname)) - 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; -} - -#define PROC_PARTITIONS "/proc/partitions" -#define VG_DIR "/proc/lvm/VGs" - -/* - * This function initializes the UUID cache with devices from the LVM - * proc hierarchy. We currently depend on the names of the LVM - * hierarchy giving us the device structure in /dev. (XXX is this a - * safe thing to do?) - */ -#ifdef VG_DIR -static dev_t lvm_get_devno(const char *lvm_device) -{ - FILE *lvf; - char buf[1024]; - int ma, mi; - dev_t ret = 0; - - DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device)); - if ((lvf = fopen(lvm_device, "r")) == NULL) { - DBG(DEBUG_DEVNAME, printf("%s: (%d) %m\n", lvm_device, errno)); - return 0; - } - - while (fgets(buf, sizeof(buf), lvf)) { - if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) { - ret = makedev(ma, mi); - break; - } - } - fclose(lvf); - - return ret; -} - -static void lvm_probe_all(blkid_cache cache, int only_if_new) -{ - DIR *vg_list; - struct dirent *vg_iter; - int vg_len = strlen(VG_DIR); - dev_t dev; - - if ((vg_list = opendir(VG_DIR)) == NULL) - return; - - DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR)); - - while ((vg_iter = readdir(vg_list)) != NULL) { - DIR *lv_list; - char *vdirname; - char *vg_name; - struct dirent *lv_iter; - - vg_name = vg_iter->d_name; - if (!strcmp(vg_name, ".") || !strcmp(vg_name, "..")) - continue; - vdirname = malloc(vg_len + strlen(vg_name) + 8); - if (!vdirname) - goto exit; - sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name); - - lv_list = opendir(vdirname); - free(vdirname); - if (lv_list == NULL) - continue; - - while ((lv_iter = readdir(lv_list)) != NULL) { - char *lv_name, *lvm_device; - - lv_name = lv_iter->d_name; - if (!strcmp(lv_name, ".") || !strcmp(lv_name, "..")) - continue; - - lvm_device = malloc(vg_len + strlen(vg_name) + - strlen(lv_name) + 8); - if (!lvm_device) { - closedir(lv_list); - goto exit; - } - sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name, - lv_name); - dev = lvm_get_devno(lvm_device); - sprintf(lvm_device, "%s/%s", vg_name, lv_name); - DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n", - lvm_device, - (unsigned int) dev)); - probe_one(cache, lvm_device, dev, BLKID_PRI_LVM, - only_if_new, 0); - free(lvm_device); - } - closedir(lv_list); - } -exit: - closedir(vg_list); -} -#endif - -#define PROC_EVMS_VOLUMES "/proc/evms/volumes" - -static int -evms_probe_all(blkid_cache cache, int only_if_new) -{ - char line[100]; - int ma, mi, sz, num = 0; - FILE *procpt; - char device[110]; - - procpt = fopen(PROC_EVMS_VOLUMES, "r"); - if (!procpt) - return 0; - while (fgets(line, sizeof(line), procpt)) { - if (sscanf (line, " %d %d %d %*s %*s %[^\n ]", - &ma, &mi, &sz, device) != 4) - continue; - - DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n", - device, ma, mi)); - - probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS, - 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. - */ -static int probe_all(blkid_cache cache, int only_if_new) -{ - FILE *proc; - char line[1024]; - char ptname0[128 + 1], ptname1[128 + 1], *ptname = 0; - char *ptnames[2]; - dev_t devs[2]; - int ma, mi; - unsigned long long sz; - int lens[2] = { 0, 0 }; - int which = 0, last = 0; - struct list_head *p, *pnext; - - ptnames[0] = ptname0; - ptnames[1] = ptname1; - - if (!cache) - return -BLKID_ERR_PARAM; - - if (cache->bic_flags & BLKID_BIC_FL_PROBED && - time(0) - cache->bic_time < BLKID_PROBE_INTERVAL) - return 0; - - blkid_read_cache(cache); - evms_probe_all(cache, only_if_new); -#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) - return -BLKID_ERR_PROC; - - while (fgets(line, sizeof(line), proc)) { - last = which; - which ^= 1; - ptname = ptnames[which]; - - if (sscanf(line, " %d %d %llu %128[^\n ]", - &ma, &mi, &sz, ptname) != 4) - continue; - devs[which] = makedev(ma, mi); - - DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname)); - - /* Skip whole disk devs unless they have no partitions. - * If base name of device has changed, also - * check previous dev to see if it didn't have a partn. - * heuristic: partition name ends in a digit, & partition - * names contain whole device name as substring. - * - * Skip extended partitions. - * heuristic: size is 1 - * - * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs - */ - - lens[which] = strlen(ptname); - - /* ends in a digit, clearly a partition, so check */ - if (isdigit(ptname[lens[which] - 1])) { - DBG(DEBUG_DEVNAME, - printf("partition dev %s, devno 0x%04X\n", - ptname, (unsigned int) devs[which])); - - if (sz > 1) - probe_one(cache, ptname, devs[which], 0, - only_if_new, 0); - lens[which] = 0; /* mark as checked */ - } - - /* - * If last was a whole disk and we just found a partition - * on it, remove the whole-disk dev from the cache if - * it exists. - */ - if (lens[last] && !strncmp(ptnames[last], ptname, lens[last])) { - list_for_each_safe(p, pnext, &cache->bic_devs) { - blkid_dev tmp; - - /* find blkid dev for the whole-disk devno */ - tmp = list_entry(p, struct blkid_struct_dev, - bid_devs); - if (tmp->bid_devno == devs[last]) { - DBG(DEBUG_DEVNAME, - printf("freeing %s\n", - tmp->bid_name)); - blkid_free_dev(tmp); - cache->bic_flags |= BLKID_BIC_FL_CHANGED; - break; - } - } - lens[last] = 0; - } - /* - * If last was not checked because it looked like a whole-disk - * dev, and the device's base name has changed, - * check last as well. - */ - if (lens[last] && strncmp(ptnames[last], ptname, lens[last])) { - DBG(DEBUG_DEVNAME, - 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, 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, 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 = UL_SYSFSCXT_EMPTY; - 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; - - DBG(DEBUG_PROBE, printf("Begin blkid_probe_all()\n")); - ret = probe_all(cache, 0); - if (ret == 0) { - cache->bic_time = time(0); - cache->bic_flags |= BLKID_BIC_FL_PROBED; - } - DBG(DEBUG_PROBE, printf("End blkid_probe_all() [rc=%d]\n", 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; - - DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_new()\n")); - ret = probe_all(cache, 1); - DBG(DEBUG_PROBE, printf("End blkid_probe_all_new() [rc=%d]\n", 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() [rc=%d]\n", ret)); - return ret; -} - -#ifdef TEST_PROGRAM -int main(int argc, char **argv) -{ - blkid_cache cache = NULL; - int ret; - - blkid_init_debug(DEBUG_ALL); - if (argc != 1) { - fprintf(stderr, "Usage: %s\n" - "Probe all devices and exit\n", argv[0]); - exit(1); - } - if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { - fprintf(stderr, "%s: error creating cache (%d)\n", - argv[0], ret); - exit(1); - } - 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); -} -#endif |