]> git.ipfire.org Git - ipfire-2.x.git/blob - src/nash/name_to_dev_t.c
PPOE Skript sollte den kill, CGI Fixes
[ipfire-2.x.git] / src / nash / name_to_dev_t.c
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
8 static dev_t try_name(char *name, int part)
9 {
10 char path[64];
11 char buf[32];
12 int range;
13 dev_t res;
14 char *s;
15 int len;
16 int fd;
17 unsigned int maj, min;
18
19 /* read device number from .../dev */
20
21 sprintf(path, "/sys/block/%s/dev", name);
22 fd = open(path, O_RDONLY);
23 if (fd < 0)
24 goto fail;
25 len = read(fd, buf, 32);
26 close(fd);
27 if (len <= 0 || len == 32 || buf[len - 1] != '\n')
28 goto fail;
29 buf[len - 1] = '\0';
30 if (sscanf(buf, "%u:%u", &maj, &min) != 2)
31 goto fail;
32 res = makedev(maj, min);
33 if (maj != major(res) || min != minor(res))
34 goto fail;
35
36 /* if it's there and we are not looking for a partition - that's it */
37 if (!part)
38 return res;
39
40 /* otherwise read range from .../range */
41 snprintf(path, 64, "/sys/block/%s/range", name);
42 fd = open(path, O_RDONLY);
43 if (fd < 0)
44 goto fail;
45 len = read(fd, buf, 32);
46 close(fd);
47 if (len <= 0 || len == 32 || buf[len - 1] != '\n')
48 goto fail;
49 buf[len - 1] = '\0';
50 range = strtoul(buf, &s, 10);
51 if (*s)
52 goto fail;
53
54 /* if partition is within range - we got it */
55 if (part < range)
56 return res + part;
57 fail:
58 return 0;
59 }
60
61 /*
62 * Convert a name into device number. We accept the following variants:
63 *
64 * 1) device number in hexadecimal represents itself
65 * 2) /dev/nfs represents Root_NFS (0xff)
66 * 3) /dev/<disk_name> represents the device number of disk
67 * 4) /dev/<disk_name><decimal> represents the device number
68 * of partition - device number of disk plus the partition number
69 * 5) /dev/<disk_name>p<decimal> - same as the above, that form is
70 * used when disk name of partitioned disk ends on a digit.
71 *
72 * If name doesn't have fall into the categories above, we return 0.
73 * sysfs is used to check if something is a disk name - it has
74 * all known disks under bus/block/devices. If the disk name
75 * contains slashes, name of driverfs node has them replaced with
76 * bangs. try_name() does the actual checks, assuming that sysfs
77 * is mounted on /sys.
78 *
79 * Note that cases (1) and (2) are already handled by the kernel,
80 * so we can ifdef them out, provided that we check real-root-dev
81 * first.
82 */
83
84 dev_t name_to_dev_t(char *name)
85 {
86 char s[32];
87 char *p;
88 dev_t res = 0;
89 int part;
90
91 if (strncmp(name, "/dev/", 5) != 0) {
92 #if 1 /* kernel used to do this */
93 unsigned maj, min;
94
95 if (sscanf(name, "%u:%u", &maj, &min) == 2) {
96 res = makedev(maj, min);
97 if (maj != major(res) || min != minor(res))
98 return 0;
99 } else {
100 res = strtoul(name, &p, 16);
101 if (*p)
102 return 0;
103 }
104 #endif
105 return res;
106 }
107
108 name += 5;
109
110 #if 1 /* kernel used to do this */
111 if (strcmp(name, "nfs") == 0)
112 return makedev(0, 255);
113 #endif
114
115 if (strlen(name) > 31)
116 return 0;
117 strcpy(s, name);
118 for (p = s; *p; p++)
119 if (*p == '/')
120 *p = '!';
121 res = try_name(s, 0);
122 if (res)
123 return res;
124
125 while (p > s && isdigit(p[-1]))
126 p--;
127 if (p == s || !*p || *p == '0')
128 return 0;
129 part = strtoul(p, NULL, 10);
130 *p = '\0';
131 res = try_name(s, part);
132 if (res)
133 return res;
134
135 if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
136 return 0;
137 p[-1] = '\0';
138 return try_name(s, part);
139 }