diff options
Diffstat (limited to 'mount/mount_guess_rootdev.c')
-rw-r--r-- | mount/mount_guess_rootdev.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/mount/mount_guess_rootdev.c b/mount/mount_guess_rootdev.c new file mode 100644 index 000000000..072c09fc4 --- /dev/null +++ b/mount/mount_guess_rootdev.c @@ -0,0 +1,90 @@ +/* + * Having the wrong rootdevice listed in mtab is slightly inconvenient. + * Try to guess what it could be... + * In case /proc/cmdline exists, and has the format + * stuff root=R more stuff... + * and we think we understand the number R, decode it as a root device. + * + * Another possibility: + * Erik Andersen writes: + * I did a similar find_real_root_device_name() in busybox some time back. + * Basically, do a stat("/", &rootstat) then walk /dev stat'ing each file + * and if (statbuf.st_rdev == rootstat.st_rdev) then you have a match. + * Works fine. + */ +#include <stdio.h> +#include <string.h> +#include "mount_guess_rootdev.h" + +#define PROC_CMDLINE "/proc/cmdline" + +static char * +rootdev(char *p) { + unsigned long devno; + char *ep; + char *type = "hd"; + char let; + int ma, mi; + char devname[8]; + + devno = strtoul(p, &ep, 16); + if ((ep == p+3 || ep == p+4) && (*ep == ' ' || *ep == 0)) { + ma = (devno >> 8); + mi = (devno & 0xff); + switch(ma) { + case 8: + type = "sd"; + let = 'a'+(mi/16); + mi = mi%16; + break; + case 3: + let = 'a'; break; + case 0x16: + let = 'c'; break; + case 0x21: + let = 'e'; break; + case 0x22: + let = 'g'; break; + case 0x38: + let = 'i'; break; + case 0x39: + let = 'k'; break; + default: + return NULL; + } + if (mi & 0x40) { + mi -= 0x40; + let++; + } + if (mi == 0) + sprintf(devname, "/dev/%s%c", type, let); + else + sprintf(devname, "/dev/%s%c%d", type, let, mi); + return strdup(devname); + } + return NULL; +} + +char * +mount_guess_rootdev() { + FILE *cf; + char line[1024]; + char *p; + + cf = fopen(PROC_CMDLINE, "r"); + if (cf && fgets(line, sizeof(line), cf)) { + for (p = line; *p; p++) + if (!strncmp(p, " root=", 6)) + return rootdev(p+6); + } + return NULL; +} + +#if 0 +main(){ + char *p = mount_guess_rootdev(); + if (!p) + p = "/dev/root"; + printf("%s\n", p); +} +#endif |