| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <dirent.h> |
| #include <string.h> |
| #include <sys/types.h> |
| #include <sys/sysmacros.h> |
| |
| /* |
| * devname.c |
| * |
| * Print the name of a block device. |
| */ |
| #define BUF_SIZE 512 |
| |
| static int scansysdir(char *namebuf, char *sysdir, dev_t dev) |
| { |
| char *dirtailptr = strchr(sysdir, '\0'); |
| DIR *dir; |
| int done = 0; |
| struct dirent *de; |
| char *systail; |
| FILE *sysdev; |
| unsigned long ma, mi; |
| char *ep; |
| ssize_t rd; |
| |
| if (!(dir = opendir(sysdir))) |
| return 0; |
| |
| *dirtailptr++ = '/'; |
| |
| while (!done && (de = readdir(dir))) { |
| /* Assume if we see a dot-name in sysfs it's special */ |
| if (de->d_name[0] == '.') |
| continue; |
| |
| if (de->d_type != DT_UNKNOWN && de->d_type != DT_DIR) |
| continue; |
| |
| if (strlen(de->d_name) >= |
| (BUF_SIZE - 64) - (dirtailptr - sysdir)) |
| continue; /* Badness... */ |
| |
| strcpy(dirtailptr, de->d_name); |
| systail = strchr(sysdir, '\0'); |
| |
| strcpy(systail, "/dev"); |
| if (!(sysdev = fopen(sysdir, "r"))) |
| continue; |
| |
| /* Abusing the namebuf as temporary storage here. */ |
| rd = fread(namebuf, 1, BUF_SIZE, sysdev); |
| namebuf[rd] = '\0'; /* Just in case... */ |
| |
| fclose(sysdev); |
| |
| ma = strtoul(namebuf, &ep, 10); |
| if (ma != major(dev) || *ep != ':') |
| continue; |
| |
| mi = strtoul(ep + 1, &ep, 10); |
| if (*ep != '\n') |
| continue; |
| |
| if (mi == minor(dev)) { |
| /* Found it! */ |
| strcpy(namebuf, de->d_name); |
| done = 1; |
| } else { |
| /* we have a major number match, scan for partitions */ |
| *systail = '\0'; |
| done = scansysdir(namebuf, sysdir, dev); |
| } |
| } |
| |
| closedir(dir); |
| return done; |
| } |
| |
| const char *bdevname(dev_t dev) |
| { |
| static char buf[BUF_SIZE]; |
| char sysdir[BUF_SIZE]; |
| char *p; |
| |
| strcpy(sysdir, "/sys/block"); |
| |
| if (!scansysdir(buf, sysdir, dev)) |
| strcpy(buf, "dev"); /* prints e.g. dev(3,5) */ |
| |
| p = strchr(buf, '\0'); |
| snprintf(p, sizeof buf - (p - buf), "(%d,%d)", major(dev), minor(dev)); |
| |
| return buf; |
| } |
| |
| #ifdef TEST_DEVNAME /* Standalone test */ |
| |
| int main(int argc, char *argv[]) |
| { |
| dev_t dev; |
| int i; |
| |
| for (i = 1; i < argc; i++) { |
| dev = strtoul(argv[i], NULL, 0); |
| |
| printf("0x%08x = %s\n", (unsigned int)dev, bdevname(dev)); |
| } |
| |
| return 0; |
| } |
| |
| #endif /* TEST */ |