aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-07-26 18:35:10 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-07-26 18:35:10 +0000
commitdf96df9c7c78d0f19c8d1ac1aa3d8d80abbe16bb (patch)
tree7f8641e7a6fb7da86cac5b0a3dc0ca4456eecd95
parent48a9971bd41a6ad7fc2ee52dcc885b25012b5561 (diff)
downloadbusybox-w32-df96df9c7c78d0f19c8d1ac1aa3d8d80abbe16bb.tar.gz
busybox-w32-df96df9c7c78d0f19c8d1ac1aa3d8d80abbe16bb.tar.bz2
busybox-w32-df96df9c7c78d0f19c8d1ac1aa3d8d80abbe16bb.zip
mdev: do not complain if mdev.conf does not exist;
use #if to prevent gcc from generating dead code (sadly, it's more ugly this way)
-rw-r--r--docs/mdev.txt17
-rwxr-xr-xtestsuite/mdev.tests1
-rw-r--r--util-linux/mdev.c293
3 files changed, 166 insertions, 145 deletions
diff --git a/docs/mdev.txt b/docs/mdev.txt
index 555c2bf61..63ad40602 100644
--- a/docs/mdev.txt
+++ b/docs/mdev.txt
@@ -60,18 +60,23 @@ matched, then the default of 0:0 660 is used. To set your own default, simply
60create your own total match like so: 60create your own total match like so:
61 .* 1:1 777 61 .* 1:1 777
62 62
63You can rename/relocate device nodes by using the next optional field. 63You can rename/move device nodes by using the next optional field.
64 <device regex> <uid>:<gid> <octal permissions> [>path] 64 <device regex> <uid>:<gid> <octal permissions> [=path]
65So if you want to place the device node into a subdirectory, make sure the path 65So if you want to place the device node into a subdirectory, make sure the path
66has a trailing /. If you want to rename the device node, just place the name. 66has a trailing /. If you want to rename the device node, just place the name.
67 hda 0:3 660 >drives/ 67 hda 0:3 660 =drives/
68This will relocate "hda" into the drives/ subdirectory. 68This will move "hda" into the drives/ subdirectory.
69 hdb 0:3 660 >cdrom 69 hdb 0:3 660 =cdrom
70This will rename "hdb" to "cdrom". 70This will rename "hdb" to "cdrom".
71 71
72Similarly, ">path" renames/moves the device but it also creates
73a direct symlink /dev/DEVNAME to the renamed/moved device.
74
72If you also enable support for executing your own commands, then the file has 75If you also enable support for executing your own commands, then the file has
73the format: 76the format:
74 <device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>] 77 <device regex> <uid>:<gid> <octal permissions> [=path] [@|$|*<command>]
78 or
79 <device regex> <uid>:<gid> <octal permissions> [>path] [@|$|*<command>]
75The special characters have the meaning: 80The special characters have the meaning:
76 @ Run after creating the device. 81 @ Run after creating the device.
77 $ Run before removing the device. 82 $ Run before removing the device.
diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests
index 572609e11..5c65ffc46 100755
--- a/testsuite/mdev.tests
+++ b/testsuite/mdev.tests
@@ -29,7 +29,6 @@ testing "mdev add /block/sda" \
29 "env - ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; 29 "env - ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1;
30 ls -ln mdev.testdir/dev | $FILTER_LS" \ 30 ls -ln mdev.testdir/dev | $FILTER_LS" \
31"\ 31"\
32mdev: /etc/mdev.conf: No such file or directory
33brw-rw---- 1 0 0 8,0 sda 32brw-rw---- 1 0 0 8,0 sda
34" \ 33" \
35 "" "" 34 "" ""
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 461d3c8c1..f6440b190 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -25,6 +25,7 @@ struct globals {
25/* We use additional 64+ bytes in make_device() */ 25/* We use additional 64+ bytes in make_device() */
26#define SCRATCH_SIZE 80 26#define SCRATCH_SIZE 80
27 27
28#if ENABLE_FEATURE_MDEV_RENAME
28/* Builds an alias path. 29/* Builds an alias path.
29 * This function potentionally reallocates the alias parameter. 30 * This function potentionally reallocates the alias parameter.
30 */ 31 */
@@ -48,6 +49,7 @@ static char *build_alias(char *alias, const char *device_name)
48 49
49 return alias; 50 return alias;
50} 51}
52#endif
51 53
52/* mknod in /dev based on a path like "/sys/block/hda/hda1" */ 54/* mknod in /dev based on a path like "/sys/block/hda/hda1" */
53/* NB: "mdev -s" may call us many times, do not leak memory/fds! */ 55/* NB: "mdev -s" may call us many times, do not leak memory/fds! */
@@ -56,12 +58,20 @@ static void make_device(char *path, int delete)
56 const char *device_name; 58 const char *device_name;
57 int major, minor, type, len; 59 int major, minor, type, len;
58 int mode = 0660; 60 int mode = 0660;
61#if ENABLE_FEATURE_MDEV_CONF
59 uid_t uid = 0; 62 uid_t uid = 0;
60 gid_t gid = 0; 63 gid_t gid = 0;
61 char *dev_maj_min = path + strlen(path); 64 parser_t *parser;
65 char *tokens[5];
66#endif
67#if ENABLE_FEATURE_MDEV_EXEC
62 char *command = NULL; 68 char *command = NULL;
69#endif
70#if ENABLE_FEATURE_MDEV_RENAME
63 char *alias = NULL; 71 char *alias = NULL;
64 char aliaslink = aliaslink; /* for compiler */ 72 char aliaslink = aliaslink; /* for compiler */
73#endif
74 char *dev_maj_min = path + strlen(path);
65 75
66 /* Force the configuration file settings exactly. */ 76 /* Force the configuration file settings exactly. */
67 umask(0); 77 umask(0);
@@ -93,148 +103,149 @@ static void make_device(char *path, int delete)
93 if (strstr(path, "/block/")) 103 if (strstr(path, "/block/"))
94 type = S_IFBLK; 104 type = S_IFBLK;
95 105
96 if (ENABLE_FEATURE_MDEV_CONF) { 106#if ENABLE_FEATURE_MDEV_CONF
97 parser_t *parser = config_open("/etc/mdev.conf"); 107 parser = config_open2("/etc/mdev.conf", fopen_for_read);
98 char *tokens[5]; 108
99 109 /* If we have config file, look up user settings */
100 /* If we have config file, look up user settings */ 110 if (!parser)
101 if (!parser) 111 goto end_parse;
102 goto end_parse; 112
103 113 while (config_read(parser, tokens, 4, 3, "# \t", PARSE_LAST_IS_GREEDY)) {
104 while (config_read(parser, tokens, 4, 3, "# \t", PARSE_LAST_IS_GREEDY)) { 114 regmatch_t off[1 + 9*ENABLE_FEATURE_MDEV_RENAME_REGEXP];
105 regmatch_t off[1+9*ENABLE_FEATURE_MDEV_RENAME_REGEXP]; 115 char *val;
106 char *val; 116
107 117 /* Fields: regex uid:gid mode [alias] [cmd] */
108 /* Fields: regex uid:gid mode [alias] [cmd] */ 118
109 119 /* 1st field: regex to match this device */
110 /* 1st field: regex to match this device */ 120 {
111 { 121 regex_t match;
112 regex_t match; 122 int result;
113 int result; 123
114 124 /* Is this it? */
115 /* Is this it? */ 125 xregcomp(&match, tokens[0], REG_EXTENDED);
116 xregcomp(&match, tokens[0], REG_EXTENDED); 126 result = regexec(&match, device_name, ARRAY_SIZE(off), off, 0);
117 result = regexec(&match, device_name, ARRAY_SIZE(off), off, 0); 127 regfree(&match);
118 regfree(&match); 128
119 129 //bb_error_msg("matches:");
120 //bb_error_msg("matches:"); 130 //for (int i = 0; i < ARRAY_SIZE(off); i++) {
121 //for (int i = 0; i < ARRAY_SIZE(off); i++) { 131 // if (off[i].rm_so < 0) continue;
122 // if (off[i].rm_so < 0) continue; 132 // bb_error_msg("match %d: '%.*s'\n", i,
123 // bb_error_msg("match %d: '%.*s'\n", i, 133 // (int)(off[i].rm_eo - off[i].rm_so),
124 // (int)(off[i].rm_eo - off[i].rm_so), 134 // device_name + off[i].rm_so);
125 // device_name + off[i].rm_so); 135 //}
126 //} 136
127 137 /* If not this device, skip rest of line */
128 /* If not this device, skip rest of line */ 138 /* (regexec returns whole pattern as "range" 0) */
129 /* (regexec returns whole pattern as "range" 0) */ 139 if (result || off[0].rm_so
130 if (result || off[0].rm_so 140 || ((int)off[0].rm_eo != (int)strlen(device_name))
131 || ((int)off[0].rm_eo != (int)strlen(device_name)) 141 ) {
132 ) { 142 continue;
133 continue;
134 }
135 } 143 }
144 }
136 145
137 /* This line matches: stop parsing the file 146 /* This line matches: stop parsing the file
138 * after parsing the rest of fields */ 147 * after parsing the rest of fields */
139 148
140 /* 2nd field: uid:gid - device ownership */ 149 /* 2nd field: uid:gid - device ownership */
141 { 150 {
142 struct passwd *pass; 151 struct passwd *pass;
143 struct group *grp; 152 struct group *grp;
144 char *str_uid = tokens[1]; 153 char *str_uid = tokens[1];
145 char *str_gid = strchrnul(str_uid, ':'); 154 char *str_gid = strchrnul(str_uid, ':');
146 155
147 if (*str_gid) 156 if (*str_gid)
148 *str_gid++ = '\0'; 157 *str_gid++ = '\0';
149 /* Parse UID */ 158 /* Parse UID */
150 pass = getpwnam(str_uid); 159 pass = getpwnam(str_uid);
151 if (pass) 160 if (pass)
152 uid = pass->pw_uid; 161 uid = pass->pw_uid;
153 else 162 else
154 uid = strtoul(str_uid, NULL, 10); 163 uid = strtoul(str_uid, NULL, 10);
155 /* Parse GID */ 164 /* Parse GID */
156 grp = getgrnam(str_gid); 165 grp = getgrnam(str_gid);
157 if (grp) 166 if (grp)
158 gid = grp->gr_gid; 167 gid = grp->gr_gid;
159 else 168 else
160 gid = strtoul(str_gid, NULL, 10); 169 gid = strtoul(str_gid, NULL, 10);
161 } 170 }
162 171
163 /* 3rd field: mode - device permissions */ 172 /* 3rd field: mode - device permissions */
164 mode = strtoul(tokens[2], NULL, 8); 173 mode = strtoul(tokens[2], NULL, 8);
165 174
166 val = tokens[3]; 175 val = tokens[3];
167 /* 4th field (opt): >alias */ 176 /* 4th field (opt): >alias */
168#if ENABLE_FEATURE_MDEV_RENAME 177#if ENABLE_FEATURE_MDEV_RENAME
169 if (!val) 178 if (!val)
170 break; 179 break;
171 aliaslink = *val; 180 aliaslink = *val;
172 if (aliaslink == '>' || aliaslink == '=') { 181 if (aliaslink == '>' || aliaslink == '=') {
173 char *s; 182 char *s;
174#if ENABLE_FEATURE_MDEV_RENAME_REGEXP 183#if ENABLE_FEATURE_MDEV_RENAME_REGEXP
175 char *p; 184 char *p;
176 unsigned i, n; 185 unsigned i, n;
177#endif 186#endif
178 char *a = val; 187 char *a = val;
179 s = strchr(val, ' '); 188 s = strchr(val, ' ');
180 val = (s && s[1]) ? s+1 : NULL; 189 val = (s && s[1]) ? s+1 : NULL;
181#if ENABLE_FEATURE_MDEV_RENAME_REGEXP 190#if ENABLE_FEATURE_MDEV_RENAME_REGEXP
182 /* substitute %1..9 with off[1..9], if any */ 191 /* substitute %1..9 with off[1..9], if any */
183 n = 0; 192 n = 0;
184 s = a; 193 s = a;
185 while (*s) 194 while (*s)
186 if (*s++ == '%') 195 if (*s++ == '%')
187 n++; 196 n++;
188 197
189 p = alias = xzalloc(strlen(a) + n * strlen(device_name)); 198 p = alias = xzalloc(strlen(a) + n * strlen(device_name));
190 s = a + 1; 199 s = a + 1;
191 while (*s) { 200 while (*s) {
192 *p = *s; 201 *p = *s;
193 if ('%' == *s) { 202 if ('%' == *s) {
194 i = (s[1] - '0'); 203 i = (s[1] - '0');
195 if (i <= 9 && off[i].rm_so >= 0) { 204 if (i <= 9 && off[i].rm_so >= 0) {
196 n = off[i].rm_eo - off[i].rm_so; 205 n = off[i].rm_eo - off[i].rm_so;
197 strncpy(p, device_name + off[i].rm_so, n); 206 strncpy(p, device_name + off[i].rm_so, n);
198 p += n - 1; 207 p += n - 1;
199 s++; 208 s++;
200 }
201 } 209 }
202 p++;
203 s++;
204 } 210 }
211 p++;
212 s++;
213 }
205#else 214#else
206 alias = xstrdup(a + 1); 215 alias = xstrdup(a + 1);
207#endif 216#endif
208 } 217 }
209#endif /* ENABLE_FEATURE_MDEV_RENAME */ 218#endif /* ENABLE_FEATURE_MDEV_RENAME */
210 219
211 /* The rest (opt): command to run */ 220#if ENABLE_FEATURE_MDEV_EXEC
212 if (!val) 221 /* The rest (opt): command to run */
213 break; 222 if (!val)
214 if (ENABLE_FEATURE_MDEV_EXEC) { 223 break;
215 const char *s = "@$*"; 224 {
216 const char *s2 = strchr(s, *val); 225 const char *s = "@$*";
217 226 const char *s2 = strchr(s, *val);
218 if (!s2) 227
219 bb_error_msg_and_die("bad line %u", parser->lineno); 228 if (!s2)
220 229 bb_error_msg_and_die("bad line %u", parser->lineno);
221 /* Correlate the position in the "@$*" with the delete 230
222 * step so that we get the proper behavior: 231 /* Correlate the position in the "@$*" with the delete
223 * @cmd: run on create 232 * step so that we get the proper behavior:
224 * $cmd: run on delete 233 * @cmd: run on create
225 * *cmd: run on both 234 * $cmd: run on delete
226 */ 235 * *cmd: run on both
227 if ((s2 - s + 1) /*1/2/3*/ & /*1/2*/ (1 + delete)) { 236 */
228 command = xstrdup(val + 1); 237 if ((s2 - s + 1) /*1/2/3*/ & /*1/2*/ (1 + delete)) {
229 } 238 command = xstrdup(val + 1);
230 } 239 }
231 /* end of field parsing */ 240 }
232 break; /* we found matching line, stop */ 241#endif
233 } /* end of "while line is read from /etc/mdev.conf" */ 242 /* end of field parsing */
243 break; /* we found matching line, stop */
244 } /* end of "while line is read from /etc/mdev.conf" */
234 245
235 config_close(parser); 246 config_close(parser);
236 }
237 end_parse: 247 end_parse:
248#endif /* ENABLE_FEATURE_MDEV_CONF */
238 249
239 if (!delete && sscanf(dev_maj_min, "%u:%u", &major, &minor) == 2) { 250 if (!delete && sscanf(dev_maj_min, "%u:%u", &major, &minor) == 2) {
240 251
@@ -247,23 +258,26 @@ static void make_device(char *path, int delete)
247 if (major == root_major && minor == root_minor) 258 if (major == root_major && minor == root_minor)
248 symlink(device_name, "root"); 259 symlink(device_name, "root");
249 260
250 if (ENABLE_FEATURE_MDEV_CONF) { 261#if ENABLE_FEATURE_MDEV_CONF
251 chown(device_name, uid, gid); 262 chown(device_name, uid, gid);
252 263
253 if (ENABLE_FEATURE_MDEV_RENAME && alias) { 264#if ENABLE_FEATURE_MDEV_RENAME
254 alias = build_alias(alias, device_name); 265 if (alias) {
266 alias = build_alias(alias, device_name);
255 267
256 /* move the device, and optionally 268 /* move the device, and optionally
257 * make a symlink to moved device node */ 269 * make a symlink to moved device node */
258 if (rename(device_name, alias) == 0 && aliaslink == '>') 270 if (rename(device_name, alias) == 0 && aliaslink == '>')
259 symlink(alias, device_name); 271 symlink(alias, device_name);
260 272
261 free(alias); 273 free(alias);
262 }
263 } 274 }
275#endif
276#endif
264 } 277 }
265 278
266 if (ENABLE_FEATURE_MDEV_EXEC && command) { 279#if ENABLE_FEATURE_MDEV_EXEC
280 if (command) {
267 /* setenv will leak memory, use putenv/unsetenv/free */ 281 /* setenv will leak memory, use putenv/unsetenv/free */
268 char *s = xasprintf("MDEV=%s", device_name); 282 char *s = xasprintf("MDEV=%s", device_name);
269 putenv(s); 283 putenv(s);
@@ -274,16 +288,19 @@ static void make_device(char *path, int delete)
274 free(s); 288 free(s);
275 free(command); 289 free(command);
276 } 290 }
291#endif
277 292
278 if (delete) { 293 if (delete) {
279 unlink(device_name); 294 unlink(device_name);
280 /* At creation time, device might have been moved 295 /* At creation time, device might have been moved
281 * and a symlink might have been created. Undo that. */ 296 * and a symlink might have been created. Undo that. */
282 if (ENABLE_FEATURE_MDEV_RENAME && alias) { 297#if ENABLE_FEATURE_MDEV_RENAME
298 if (alias) {
283 alias = build_alias(alias, device_name); 299 alias = build_alias(alias, device_name);
284 unlink(alias); 300 unlink(alias);
285 free(alias); 301 free(alias);
286 } 302 }
303#endif
287 } 304 }
288} 305}
289 306