summaryrefslogtreecommitdiffstats
path: root/mount/mount_guess_rootdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'mount/mount_guess_rootdev.c')
-rw-r--r--mount/mount_guess_rootdev.c90
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