static void uuidcache_init(void) { char line[100]; char *s; int ma, mi, sz; static char ptname[100]; FILE *procpt; char uuid[16], *label; char device[110]; int firstPass; int handleOnFirst; if (uuidCache) return; procpt = fopen(PROC_PARTITIONS, "r"); if (!procpt) return; for (firstPass = 1; firstPass >= 0; firstPass--) { fseek(procpt, 0, SEEK_SET); while (fgets(line, sizeof(line), procpt)) { if (sscanf (line, " %d %d %d %[^\n ]", &ma, &mi, &sz, ptname) != 4) continue; /* skip extended partitions (heuristic: size 1) */ if (sz == 1) continue; /* look only at md devices on first pass */ handleOnFirst = !strncmp(ptname, "md", 2); if (firstPass != handleOnFirst) continue; /* skip entire disk (minor 0, 64, ... on ide; 0, 16, ... on sd) */ /* heuristic: partition name ends in a digit */ for(s = ptname; *s; s++); if (isdigit(s[-1])) { /* * Note: this is a heuristic only - there is no reason * why these devices should live in /dev. * Perhaps this directory should be specifiable by option. * One might for example have /devlabel with links to /dev * for the devices that may be accessed in this way. * (This is useful, if the cdrom on /dev/hdc must not * be accessed.) */ sprintf(device, "%s/%s", DEVLABELDIR, ptname); if (!get_label_uuid(device, &label, uuid)) uuidcache_addentry(strdup(device), label, uuid); } } } fclose(procpt); }
static void uuidcache_check_device(const char *device_name, int ma, int mi, int iso_only) { char *device, *last_slash; char *uuid, *label; char *ptr; int must_remove = 0; int added = 0; last_slash = NULL; device = xasprintf("/dev/%s", device_name); if (access(device, F_OK) != 0) { /* device does not exist, temporarily create */ int slash_cnt = 0; if ((ma | mi) < 0) goto ret; /* we don't know major:minor! */ ptr = device; while (*ptr) if (*ptr++ == '/') slash_cnt++; if (slash_cnt > 2) { // BUG: handles only slash_cnt == 3 case last_slash = strrchr(device, '/'); *last_slash = '\0'; if (mkdir(device, 0644)) { bb_perror_msg("can't create directory %s", device); *last_slash = '/'; last_slash = NULL; /* prevents rmdir */ } else { *last_slash = '/'; } } mknod(device, S_IFBLK | 0600, makedev(ma, mi)); must_remove = 1; } uuid = NULL; label = NULL; if (get_label_uuid(device, &label, &uuid, iso_only) == 0) { uuidcache_addentry(device, /*ma, mi,*/ label, uuid); /* "device" is owned by cache now, don't free */ added = 1; } if (must_remove) unlink(device); if (last_slash) { *last_slash = '\0'; rmdir(device); } ret: if (!added) free(device); }
static void init_lvm(void) { DIR *vg_dir, *lv_list; char *vdirname, *lvm_device; char uuid[16], *label, *vname, *lname; struct dirent *vg_iter, *lv_iter; if ((vg_dir = opendir(VG_DIR)) == NULL) return; while ((vg_iter = readdir(vg_dir)) != 0) { vname = vg_iter->d_name; if (!strcmp(vname, ".") || !strcmp(vname, "..")) continue; vdirname = malloc(strlen(VG_DIR)+strlen(vname)+8); if (!vdirname) { closedir(vg_dir); return; } sprintf(vdirname, "%s/%s/LVs", VG_DIR, vname); lv_list = opendir(vdirname); free(vdirname); if (lv_list == NULL) return; while ((lv_iter = readdir(lv_list)) != 0) { lname = lv_iter->d_name; if (!strcmp(lname, ".") || !strcmp(lname, "..")) continue; lvm_device = malloc(strlen(DEVLABELDIR) + strlen(vname)+ strlen(lname)+8); if (!lvm_device) { closedir(lv_list); closedir(vg_dir); return; } sprintf(lvm_device, "%s/%s/%s", DEVLABELDIR, vname, lname); if (!get_label_uuid(lvm_device, &label, uuid)) { uuidcache_addentry(string_copy(lvm_device), label, uuid); } else free(lvm_device); } closedir(lv_list); } closedir( vg_dir ); }
static void read_evms(void) { char line[100]; int ma, mi, sz; FILE *procpt; char uuid[16], *label, *devname; char device[110]; dev_t dev; struct stat statbuf; procpt = fopen(PROC_EVMS_VOLUMES, "r"); if (!procpt) return; while (fgets(line, sizeof(line), procpt)) { if (sscanf (line, " %d %d %d %*s %*s %[^\n ]", &ma, &mi, &sz, device) != 4) continue; /* * We first look for the device in the named location, * but if we don't find it, or if the stat information * doesn't check out, we use ext2fs_find_block_device * to find it. */ dev = makedev(ma, mi); if ((stat(device, &statbuf) < 0) || (statbuf.st_rdev != dev)) { devname = ext2fs_find_block_device(dev); } else devname = string_copy(device); if (!devname) continue; #ifdef DEBUG printf("Checking partition %s (%d, %d)\n", devname, ma, mi); #endif if (!get_label_uuid(devname, &label, uuid)) uuidcache_addentry(devname, label, uuid); else free(devname); } fclose(procpt); }
static int uuidcache_init_evms(void) { FILE *procvol; char *label; char uuid[16]; char volname[EVMS_VOLUME_NAME_SIZE+1]; char line[EVMS_VOLUME_NAME_SIZE+80]; procvol = fopen(PROC_EVMS_VOLUMES, "r"); if (!procvol) return 0; while (fgets(line, sizeof(line), procvol)) { if (sscanf(line, "%*d %*d %*d %*s %*s %[^\n]", volname) == 1) { if (!get_label_uuid(volname, &label, uuid)) uuidcache_addentry(xstrdup(volname), label, uuid); } } fclose(procvol); return 1; }
/* LVM support - Kirby Bohling */ static void uuidcache_init_lvm(void) { char buffer[PATH_MAX]; char lvm_device[PATH_MAX]; DIR *vg_dir, *lv_list; struct dirent *vg_iter, *lv_iter; char uuid[16], *label; vg_dir = opendir(VG_DIR); if (vg_dir == NULL) /* to be expected */ return; seekdir(vg_dir, 2); while ((vg_iter = readdir(vg_dir)) != 0) { sprintf(buffer, "%s/%s/LVs", VG_DIR, vg_iter->d_name); lv_list = opendir(buffer); if (lv_list == NULL) { perror("uuidcache_init_lvm"); continue; } seekdir(lv_list, 2); while ((lv_iter = readdir(lv_list)) != 0) { /* Now we have the file.. could open it and read out * where the device is, read the first line, second * field... Instead we guess. */ sprintf(lvm_device, "%s/%s/%s", DEVLABELDIR, vg_iter->d_name, lv_iter->d_name); if (!get_label_uuid(lvm_device, &label, uuid)) uuidcache_addentry(xstrdup(lvm_device), label, uuid); } closedir(lv_list); } closedir(vg_dir); }
static void uuidcache_init(void) { char line[100]; char *s; int ma, mi, sz; static char ptname[100]; FILE *procpt; char uuid[16], *label; char device[110]; int firstPass; int handleOnFirst; #if 0 char iobuf[32*1024]; /* For setvbuf */ #endif if (uuidCache) return; if (uuidcache_init_evms()) return; procpt = fopen(PROC_PARTITIONS, "r"); if (!procpt) { static int warn = 0; if (!warn++) error (_("%s: could not open %s, so UUID and LABEL " "conversion cannot be done.\n"), progname, PROC_PARTITIONS); return; } #if 0 /* Ugly kludge - the contents of /proc/partitions change in time, and this causes failures when the file is not read in one go. In particular, one cannot use stdio on /proc/partitions. Doing this ourselves is not easy either, since stat returns 0 so the size is unknown. We might try increasing buffer sizes until a single read gets all. For now only pick a largish buffer size. */ /* All these troubles are mainly caused by people who patch the kernel to keep statistics in /proc/partitions. Of course, statistics belong in some /proc/diskstats, not in some /proc file that happened to exist already. */ setvbuf(procpt, iobuf, _IOFBF, sizeof(iobuf)); #endif for (firstPass = 1; firstPass >= 0; firstPass--) { fseek(procpt, 0, SEEK_SET); while (fgets(line, sizeof(line), procpt)) { if (!index(line, '\n')) break; if (sscanf (line, " %d %d %d %[^\n ]", &ma, &mi, &sz, ptname) != 4) continue; /* skip extended partitions (heuristic: size 1) */ if (sz == 1) continue; /* look only at md devices on first pass */ handleOnFirst = !strncmp(ptname, "md", 2); if (firstPass != handleOnFirst) continue; /* skip entire disk (minor 0, 64, ... on ide; 0, 16, ... on sd) */ /* heuristic: partition name ends in a digit */ /* devfs has .../disc and .../part1 etc. */ for (s = ptname; *s; s++); if (isdigit(s[-1]) || is_xvm(ptname)) { /* * Note: this is a heuristic only - there is no reason * why these devices should live in /dev. * Perhaps this directory should be specifiable by option. * One might for example have /devlabel with links to /dev * for the devices that may be accessed in this way. * (This is useful, if the cdrom on /dev/hdc must not * be accessed.) */ sprintf(device, "%s/%s", DEVLABELDIR, ptname); if (!get_label_uuid(device, &label, uuid)) uuidcache_addentry(xstrdup(device), label, uuid); } } } fclose(procpt); uuidcache_init_lvm(); }
static void read_partitions(void) { char line[100]; char *s; int ma, mi, sz; static char ptname[100]; FILE *procpt; char uuid[16], *label, *devname; char device[110]; dev_t dev; struct stat statbuf; int firstPass; int handleOnFirst; char *iobuf; procpt = fopen(PROC_PARTITIONS, "r"); if (!procpt) return; iobuf = (char *)malloc(CBBUF); if (iobuf) setvbuf(procpt, iobuf, _IOFBF, CBBUF); for (firstPass = 1; firstPass >= 0; firstPass--) { fseek(procpt, 0, SEEK_SET); while (fgets(line, sizeof(line), procpt)) { if (sscanf (line, " %d %d %d %[^\n ]", &ma, &mi, &sz, ptname) != 4) continue; /* skip extended partitions (heuristic: size 1) */ if (sz == 1) continue; /* look only at md devices on first pass */ handleOnFirst = !strncmp(ptname, "md", 2); if (firstPass != handleOnFirst) continue; /* skip entire disk (minor 0, 64, ... on ide; 0, 16, ... on sd) */ /* heuristic: partition name ends in a digit */ /* OR partition name starts with 'lvm' */ for(s = ptname; *s; s++); if (isdigit(s[-1]) || !strncmp(ptname, "lvm", 3)) { /* * We first look in /dev for the device, but * if we don't find it, or if the stat * information doesn't check out, we use * ext2fs_find_block_device to find it. */ sprintf(device, "%s/%s", DEVLABELDIR, ptname); dev = makedev(ma, mi); if ((stat(device, &statbuf) < 0) || (statbuf.st_rdev != dev)) { devname = ext2fs_find_block_device(dev); } else devname = string_copy(device); if (!devname) continue; #ifdef DEBUG printf("Checking partition %s (%d, %d)\n", devname, ma, mi); #endif if (!get_label_uuid(devname, &label, uuid)) uuidcache_addentry(devname, label, uuid); else free(devname); } } } fclose(procpt); if (iobuf) free(iobuf); }