Magellan Linux

Annotation of /trunk/mkinitrd-magellan/klibc/usr/kinit/name_to_dev.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1122 - (hide annotations) (download)
Wed Aug 18 21:11:40 2010 UTC (13 years, 9 months ago) by niro
File MIME type: text/plain
File size: 4564 byte(s)
-updated to klibc-1.5.19
1 niro 532 #include <ctype.h>
2     #include <errno.h>
3     #include <fcntl.h>
4     #include <sys/stat.h>
5     #include <stdio.h>
6     #include <stdlib.h>
7     #include <string.h>
8     #include <unistd.h>
9     #include <alloca.h>
10     #include <inttypes.h>
11    
12     #include "do_mounts.h"
13     #include "kinit.h"
14    
15     #define BUF_SZ 65536
16    
17     /* Find dev_t for e.g. "hda,NULL" or "hdb,2" */
18     static dev_t try_name(char *name, int part)
19     {
20     char path[BUF_SZ];
21     char buf[BUF_SZ];
22     int range;
23 niro 815 unsigned int major_num, minor_num;
24 niro 532 dev_t res;
25     char *s;
26     int len;
27     int fd;
28    
29     /* read device number from /sys/block/.../dev */
30     snprintf(path, sizeof(path), "/sys/block/%s/dev", name);
31     fd = open(path, 0, 0);
32     if (fd < 0)
33     goto fail;
34     len = read(fd, buf, BUF_SZ);
35     close(fd);
36    
37     if (len <= 0 || len == BUF_SZ || buf[len - 1] != '\n')
38     goto fail;
39     buf[len - 1] = '\0';
40 niro 815 major_num = strtoul(buf, &s, 10);
41 niro 532 if (*s != ':')
42     goto fail;
43 niro 815 minor_num = strtoul(s + 1, &s, 10);
44 niro 532 if (*s)
45     goto fail;
46 niro 815 res = makedev(major_num, minor_num);
47 niro 532
48     /* if it's there and we are not looking for a partition - that's it */
49     if (!part)
50     return res;
51    
52     /* otherwise read range from .../range */
53     snprintf(path, sizeof(path), "/sys/block/%s/range", name);
54     fd = open(path, 0, 0);
55     if (fd < 0)
56     goto fail;
57     len = read(fd, buf, 32);
58     close(fd);
59     if (len <= 0 || len == 32 || buf[len - 1] != '\n')
60     goto fail;
61     buf[len - 1] = '\0';
62     range = strtoul(buf, &s, 10);
63     if (*s)
64     goto fail;
65    
66     /* if partition is within range - we got it */
67     if (part < range) {
68 niro 1122 dprintf("kinit: try_name %s,%d = %s\n", name, part,
69     bdevname(res + part));
70 niro 532 return res + part;
71     }
72    
73     fail:
74     return (dev_t) 0;
75     }
76    
77     /*
78     * Convert a name into device number. We accept the following variants:
79     *
80     * 1) device number in hexadecimal represents itself
81     * 2) device number in major:minor decimal represents itself
82     * 3) /dev/nfs represents Root_NFS
83     * 4) /dev/<disk_name> represents the device number of disk
84     * 5) /dev/<disk_name><decimal> represents the device number
85     * of partition - device number of disk plus the partition number
86     * 6) /dev/<disk_name>p<decimal> - same as the above, that form is
87     * used when disk name of partitioned disk ends on a digit.
88     * 7) an actual block device node in the initramfs filesystem
89     *
90     * If name doesn't have fall into the categories above, we return 0.
91     * Driverfs is used to check if something is a disk name - it has
92     * all known disks under bus/block/devices. If the disk name
93     * contains slashes, name of driverfs node has them replaced with
94     * dots. try_name() does the actual checks, assuming that driverfs
95     * is mounted on rootfs /sys.
96     */
97    
98     static inline dev_t name_to_dev_t_real(const char *name)
99     {
100     char *p;
101     dev_t res = 0;
102     char *s;
103     int part;
104     struct stat st;
105     int len;
106     const char *devname;
107     char *cptr, *e1, *e2;
108 niro 815 int major_num, minor_num;
109 niro 532
110 niro 1122 /* Are we a multi root line? */
111     if (strchr(name, ','))
112     return Root_MULTI;
113 niro 532
114     if (name[0] == '/') {
115     devname = name;
116     } else {
117     char *dname = alloca(strlen(name) + 6);
118     sprintf(dname, "/dev/%s", name);
119     devname = dname;
120     }
121    
122     if (!stat(devname, &st) && S_ISBLK(st.st_mode))
123     return st.st_rdev;
124    
125     if (strncmp(name, "/dev/", 5)) {
126     if ((cptr = strchr(devname+5, ':')) &&
127     cptr[1] != '\0') {
128     /* Colon-separated decimal device number */
129     *cptr = '\0';
130 niro 815 major_num = strtoul(devname+5, &e1, 10);
131     minor_num = strtoul(cptr+1, &e2, 10);
132 niro 532 if (!*e1 && !*e2)
133 niro 815 return makedev(major_num, minor_num);
134 niro 532 *cptr = ':';
135     } else {
136     /* Hexadecimal device number */
137     res = (dev_t) strtoul(name, &p, 16);
138     if (!*p)
139     return res;
140     }
141     } else {
142     name += 5;
143     }
144    
145     if (!strcmp(name, "nfs"))
146     return Root_NFS;
147    
148     if (!strcmp(name, "ram")) /* /dev/ram - historic alias for /dev/ram0 */
149     return Root_RAM0;
150    
151     if (!strncmp(name, "mtd", 3))
152     return Root_MTD;
153    
154     len = strlen(name);
155     s = alloca(len + 1);
156     memcpy(s, name, len + 1);
157    
158     for (p = s; *p; p++)
159     if (*p == '/')
160     *p = '!';
161     res = try_name(s, 0);
162     if (res)
163     return res;
164    
165     while (p > s && isdigit(p[-1]))
166     p--;
167     if (p == s || !*p || *p == '0')
168     goto fail;
169     part = strtoul(p, NULL, 10);
170     *p = '\0';
171     res = try_name(s, part);
172     if (res)
173     return res;
174    
175     if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
176     goto fail;
177     p[-1] = '\0';
178     res = try_name(s, part);
179     return res;
180    
181     fail:
182     return (dev_t) 0;
183     }
184    
185     dev_t name_to_dev_t(const char *name)
186     {
187     dev_t dev = name_to_dev_t_real(name);
188    
189 niro 1122 dprintf("kinit: name_to_dev_t(%s) = %s\n", name, bdevname(dev));
190 niro 532 return dev;
191     }
192    
193     #ifdef TEST_NAMETODEV /* Standalone test */
194    
195     int main(int argc, char *argv[])
196     {
197     int i;
198    
199     for (i = 1; i < argc; i++)
200     name_to_dev_t(argv[i]);
201    
202     return 0;
203     }
204    
205     #endif