Contents of /tags/mkinitrd-6_0_4/mkinitrd-magellan/nash/name_to_dev_t.c
Parent Directory | Revision Log
Revision 674 -
(show annotations)
(download)
Fri Jan 25 11:12:53 2008 UTC (16 years, 8 months ago) by (unknown author)
File MIME type: text/plain
File size: 3437 byte(s)
Fri Jan 25 11:12:53 2008 UTC (16 years, 8 months ago) by (unknown author)
File MIME type: text/plain
File size: 3437 byte(s)
This commit was manufactured by cvs2svn to create tag 'mkinitrd-6_0_4'.
1 | #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 | } |