diff options
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 41 |
1 files changed, 41 insertions, 0 deletions
@@ -1648,3 +1648,44 @@ void append_metadata_update(struct supertype *st, void *buf, int len) unsigned int __invalid_size_argument_for_IOC = 0; #endif +/* + * Resolve from a device name, such as /dev/sdb2, to a device path, such + * as pci-0000:00:1f.2-scsi-1:0:0:0-part2 which can then be used to match + * against paths in DOMAIN lines from the config file + */ +char *get_devpath_from_devname(char *devname) +{ + char *name = strrchr(devname, '/'), *link; + DIR *by_path; + struct dirent *ent; + char symlink[PATH_MAX] = "/dev/disk/by-path/"; + char *symlinkp, target[PATH_MAX]; + int read; + + if (!name++) + name = devname; + if ((by_path = opendir("/dev/disk/by-path")) == NULL) { + fprintf(stderr, Name ": unable to open /dev/disk/by-path, " + "domain lookups not possible\n"); + return NULL; + } + symlinkp = &symlink[0] + strlen(symlink); + while ((ent = readdir(by_path)) != NULL) { + if (ent->d_type != DT_LNK) + continue; + strncpy(symlinkp, ent->d_name, + sizeof(symlink) - (symlinkp - &symlink[0])); + read = readlink(symlink, target, sizeof(target)); + if (read < 0) + continue; + link = strrchr(target, '/'); + if (!link++) + link = target; + if (strcmp(name, link) == 0) { + closedir(by_path); + return strdup(ent->d_name); + } + } + closedir(by_path); + return NULL; +} |