Magellan Linux

Annotation of /tags/mkinitrd-6_1_8/nash/name_to_dev_t.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 916 - (hide annotations) (download)
Wed Oct 28 00:17:50 2009 UTC (14 years, 7 months ago) by niro
File MIME type: text/plain
File size: 3437 byte(s)
tagged 'mkinitrd-6_1_8'
1 niro 532 #include <stdlib.h>
2     #include <string.h>
3     #include <unistd.h>
4     #include <ctype.h>
5     #include <stdio.h>
6     #include <fcntl.h>
7     #include <sys/stat.h>
8    
9     #include "name_to_dev_t.h"
10    
11     static dev_t
12     try_name(char *name, int part)
13     {
14     char path[64];
15     char buf[32];
16     int range;
17     dev_t res;
18     char *s;
19     int len;
20     int fd;
21     unsigned int maj, min;
22     struct stat sb;
23    
24     /* read device number from .../dev */
25    
26     sprintf(path, "/sys/block/%s/dev", name);
27     fd = open(path, O_RDONLY);
28     if (fd < 0)
29     goto fail;
30     len = read(fd, buf, 32);
31     close(fd);
32     if (len <= 0 || len == 32 || buf[len - 1] != '\n')
33     goto fail;
34     buf[len - 1] = '\0';
35     if (sscanf(buf, "%u:%u", &maj, &min) != 2)
36     goto fail;
37     res = makedev(maj, min);
38     if (maj != major(res) || min != minor(res))
39     goto fail;
40    
41     /* if it's there and we are not looking for a partition - that's it */
42     if (!part)
43     return res;
44    
45     /* otherwise read range from .../range */
46     snprintf(path, 64, "/sys/block/%s/range", name);
47     fd = open(path, O_RDONLY);
48     if (fd < 0)
49     goto fail;
50     len = read(fd, buf, 32);
51     close(fd);
52     if (len <= 0 || len == 32 || buf[len - 1] != '\n')
53     goto fail;
54     buf[len - 1] = '\0';
55     range = strtoul(buf, &s, 10);
56     if (*s)
57     goto fail;
58    
59     /* if partition is within range - we got it */
60     if (part < range)
61     return res + part;
62     fail:
63     sprintf(path, "/dev/%s", name);
64     if (!stat(path, &sb)) {
65     if (S_ISBLK(sb.st_mode))
66     return sb.st_rdev;
67     }
68     return 0;
69     }
70    
71     /*
72     * Convert a name into device number. We accept the following variants:
73     *
74     * 1) device number in hexadecimal represents itself
75     * 2) /dev/nfs represents Root_NFS (0xff)
76     * 3) /dev/<disk_name> represents the device number of disk
77     * 4) /dev/<disk_name><decimal> represents the device number
78     * of partition - device number of disk plus the partition number
79     * 5) /dev/<disk_name>p<decimal> - same as the above, that form is
80     * used when disk name of partitioned disk ends on a digit.
81     *
82     * If name doesn't have fall into the categories above, we return 0.
83     * sysfs is used to check if something is a disk name - it has
84     * all known disks under bus/block/devices. If the disk name
85     * contains slashes, name of driverfs node has them replaced with
86     * bangs. try_name() does the actual checks, assuming that sysfs
87     * is mounted on /sys.
88     *
89     * Note that cases (1) and (2) are already handled by the kernel,
90     * so we can ifdef them out, provided that we check real-root-dev
91     * first.
92     */
93    
94     dev_t
95     name_to_dev_t(char *name)
96     {
97     char s[32];
98     char *p;
99     dev_t res = 0;
100     int part;
101    
102     if (strncmp(name, "/dev/", 5) != 0) {
103     #if 1 /* kernel used to do this */
104     unsigned maj, min;
105    
106     if (sscanf(name, "%u:%u", &maj, &min) == 2) {
107     res = makedev(maj, min);
108     if (maj != major(res) || min != minor(res))
109     return 0;
110     } else {
111     res = strtoul(name, &p, 16);
112     if (*p)
113     return 0;
114     }
115     #endif
116     return res;
117     }
118    
119     name += 5;
120    
121     #if 1 /* kernel used to do this */
122     if (strcmp(name, "nfs") == 0)
123     return makedev(0, 255);
124     #endif
125     if (strchr(name, '/')) {
126     res = try_name(name, 1);
127     if (res)
128     return res;
129     }
130    
131     if (strlen(name) > 31)
132     return 0;
133     strcpy(s, name);
134     for (p = s; *p; p++)
135     if (*p == '/')
136     *p = '!';
137     res = try_name(s, 0);
138     if (res)
139     return res;
140    
141     while (p > s && isdigit(p[-1]))
142     p--;
143     if (p == s || !*p || *p == '0')
144     return 0;
145     part = strtoul(p, NULL, 10);
146     *p = '\0';
147     res = try_name(s, part);
148     if (res)
149     return res;
150    
151     if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
152     return 0;
153     p[-1] = '\0';
154     return try_name(s, part);
155     }