1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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[32];
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
|