/* * Returns devname (e.g. "/dev/sda1") for the given devno. * * Note that the @buf has to be large enough to store /sys/dev/block/<maj:min> * symlinks. * * Please, use more robust blkid_devno_to_devname() in your applications. */ char *sysfs_devno_to_devpath(dev_t devno, char *buf, size_t bufsiz) { struct sysfs_cxt cxt; char *name; size_t sz; struct stat st; if (sysfs_init(&cxt, devno, NULL)) return NULL; name = sysfs_get_devname(&cxt, buf, bufsiz); sysfs_deinit(&cxt); if (!name) return NULL; sz = strlen(name); if (sz + sizeof("/dev/") > bufsiz) return NULL; /* create the final "/dev/<name>" string */ memmove(buf + 5, name, sz + 1); memcpy(buf, "/dev/", 5); if (!stat(buf, &st) && S_ISBLK(st.st_mode) && st.st_rdev == devno) return buf; return NULL; }
int main(int argc, char *argv[]) { struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY; char *devname; dev_t devno; char path[PATH_MAX]; int i; uint64_t u64; ssize_t len; if (argc != 2) errx(EXIT_FAILURE, "usage: %s <devname>", argv[0]); devname = argv[1]; devno = sysfs_devname_to_devno(devname, NULL); if (!devno) err(EXIT_FAILURE, "failed to read devno"); printf("NAME: %s\n", devname); printf("DEVNO: %u\n", (unsigned int) devno); printf("DEVNOPATH: %s\n", sysfs_devno_path(devno, path, sizeof(path))); printf("DEVPATH: %s\n", sysfs_devno_to_devpath(devno, path, sizeof(path))); printf("PARTITION: %s\n", sysfs_devno_has_attribute(devno, "partition") ? "YES" : "NOT"); if (sysfs_init(&cxt, devno, NULL)) return EXIT_FAILURE; len = sysfs_readlink(&cxt, NULL, path, sizeof(path) - 1); if (len > 0) { path[len] = '\0'; printf("DEVNOLINK: %s\n", path); } printf("SLAVES: %d\n", sysfs_count_dirents(&cxt, "slaves")); if (sysfs_read_u64(&cxt, "size", &u64)) printf("read SIZE failed\n"); else printf("SIZE: %jd\n", u64); if (sysfs_read_int(&cxt, "queue/hw_sector_size", &i)) printf("read SECTOR failed\n"); else printf("SECTOR: %d\n", i); printf("DEVNAME: %s\n", sysfs_get_devname(&cxt, path, sizeof(path))); sysfs_deinit(&cxt); return EXIT_SUCCESS; }
/* * Returns by @diskdevno whole disk device devno and (optionaly) by * @diskname the whole disk device name. */ int sysfs_devno_to_wholedisk(dev_t dev, char *diskname, size_t len, dev_t *diskdevno) { struct sysfs_cxt cxt; int is_part = 0; if (!dev || sysfs_init(&cxt, dev, NULL) != 0) return -1; is_part = sysfs_has_attribute(&cxt, "partition"); if (!is_part) { /* * Extra case for partitions mapped by device-mapper. * * All regualar partitions (added by BLKPG ioctl or kernel PT * parser) have the /sys/.../partition file. The partitions * mapped by DM don't have such file, but they have "part" * prefix in DM UUID. */ char *uuid = sysfs_strdup(&cxt, "dm/uuid"); char *tmp = uuid; char *prefix = uuid ? strsep(&tmp, "-") : NULL; if (prefix && strncasecmp(prefix, "part", 4) == 0) is_part = 1; free(uuid); if (is_part && get_dm_wholedisk(&cxt, diskname, len, diskdevno) == 0) /* * partitioned device, mapped by DM */ goto done; is_part = 0; } if (!is_part) { /* * unpartitioned device */ if (diskname && len) { if (!sysfs_get_devname(&cxt, diskname, len)) goto err; } if (diskdevno) *diskdevno = dev; } else { /* * partitioned device * - readlink /sys/dev/block/8:1 = ../../block/sda/sda1 * - dirname ../../block/sda/sda1 = ../../block/sda * - basename ../../block/sda = sda */ char linkpath[PATH_MAX]; char *name; int linklen; linklen = sysfs_readlink(&cxt, NULL, linkpath, sizeof(linkpath) - 1); if (linklen < 0) goto err; linkpath[linklen] = '\0'; stripoff_last_component(linkpath); /* dirname */ name = stripoff_last_component(linkpath); /* basename */ if (!name) goto err; if (diskname && len) { strncpy(diskname, name, len); diskname[len - 1] = '\0'; } if (diskdevno) { *diskdevno = sysfs_devname_to_devno(name, NULL); if (!*diskdevno) goto err; } } done: sysfs_deinit(&cxt); return 0; err: sysfs_deinit(&cxt); return -1; }