aboutsummaryrefslogtreecommitdiff
path: root/util-linux/mdev.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-19 01:27:20 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-19 01:27:20 +0000
commitc7cc5a9432d2224d4e0fe3cf8ae72abb7ef25e2c (patch)
tree103a6d3e66fd142e0f2b8d57a8156b87a6f590c9 /util-linux/mdev.c
parent885b6f29ae2740399231427dc2c6efe47db9a80d (diff)
downloadbusybox-w32-c7cc5a9432d2224d4e0fe3cf8ae72abb7ef25e2c.tar.gz
busybox-w32-c7cc5a9432d2224d4e0fe3cf8ae72abb7ef25e2c.tar.bz2
busybox-w32-c7cc5a9432d2224d4e0fe3cf8ae72abb7ef25e2c.zip
mdev: Rob's #if forest removal
*: remove superfluous conts in "f(type *const param)"
Diffstat (limited to 'util-linux/mdev.c')
-rw-r--r--util-linux/mdev.c324
1 files changed, 146 insertions, 178 deletions
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 003a27b56..a3275f881 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -52,7 +52,7 @@ struct globals {
52#define G (*(struct globals*)&bb_common_bufsiz1) 52#define G (*(struct globals*)&bb_common_bufsiz1)
53#define root_major (G.root_major) 53#define root_major (G.root_major)
54#define root_minor (G.root_minor) 54#define root_minor (G.root_minor)
55#define subsystem (G.subsystem) 55#define subsystem (G.subsystem )
56 56
57/* Prevent infinite loops in /sys symlinks */ 57/* Prevent infinite loops in /sys symlinks */
58#define MAX_SYSFS_DEPTH 3 58#define MAX_SYSFS_DEPTH 3
@@ -60,9 +60,9 @@ struct globals {
60/* We use additional 64+ bytes in make_device() */ 60/* We use additional 64+ bytes in make_device() */
61#define SCRATCH_SIZE 80 61#define SCRATCH_SIZE 80
62 62
63#if ENABLE_FEATURE_MDEV_RENAME
64/* Builds an alias path. 63/* Builds an alias path.
65 * This function potentionally reallocates the alias parameter. 64 * This function potentionally reallocates the alias parameter.
65 * Only used for ENABLE_FEATURE_MDEV_RENAME
66 */ 66 */
67static char *build_alias(char *alias, const char *device_name) 67static char *build_alias(char *alias, const char *device_name)
68{ 68{
@@ -84,19 +84,16 @@ static char *build_alias(char *alias, const char *device_name)
84 84
85 return alias; 85 return alias;
86} 86}
87#endif
88 87
89/* mknod in /dev based on a path like "/sys/block/hda/hda1" */ 88/* mknod in /dev based on a path like "/sys/block/hda/hda1" */
90/* NB: "mdev -s" may call us many times, do not leak memory/fds! */ 89/* NB: "mdev -s" may call us many times, do not leak memory/fds! */
91static void make_device(char *path, int delete) 90static void make_device(char *path, int delete)
92{ 91{
93#if ENABLE_FEATURE_MDEV_CONF
94 parser_t *parser;
95#endif
96 const char *device_name; 92 const char *device_name;
97 int major, minor, type, len; 93 int major, minor, type, len;
98 int mode; 94 int mode;
99 char *dev_maj_min = path + strlen(path); 95 char *dev_maj_min = path + strlen(path);
96 parser_t *parser;
100 97
101 /* Force the configuration file settings exactly. */ 98 /* Force the configuration file settings exactly. */
102 umask(0); 99 umask(0);
@@ -137,170 +134,153 @@ static void make_device(char *path, int delete)
137 else 134 else
138 path += sizeof("/sys/class/") - 1; 135 path += sizeof("/sys/class/") - 1;
139 136
140#if !ENABLE_FEATURE_MDEV_CONF
141 mode = 0660;
142#else
143 /* If we have config file, look up user settings */ 137 /* If we have config file, look up user settings */
144 parser = config_open2("/etc/mdev.conf", fopen_for_read); 138 if (ENABLE_FEATURE_MDEV_CONF)
145 while (1) { 139 parser = config_open2("/etc/mdev.conf", fopen_for_read);
140
141 do {
146 regmatch_t off[1 + 9 * ENABLE_FEATURE_MDEV_RENAME_REGEXP]; 142 regmatch_t off[1 + 9 * ENABLE_FEATURE_MDEV_RENAME_REGEXP];
147 int keep_matching; 143 int keep_matching;
148 char *val, *name; 144 char *val, *name;
149 struct bb_uidgid_t ugid; 145 struct bb_uidgid_t ugid;
150 char *tokens[4]; 146 char *tokens[4];
151# if ENABLE_FEATURE_MDEV_EXEC
152 char *command = NULL; 147 char *command = NULL;
153# endif
154# if ENABLE_FEATURE_MDEV_RENAME
155 char *alias = NULL; 148 char *alias = NULL;
156 char aliaslink = aliaslink; /* for compiler */ 149 char aliaslink = aliaslink; /* for compiler */
157# endif 150
158 /* Defaults in case we won't match any line */ 151 /* Defaults in case we won't match any line */
159 ugid.uid = ugid.gid = 0; 152 ugid.uid = ugid.gid = 0;
160 keep_matching = 0; 153 keep_matching = 0;
161 mode = 0660; 154 mode = 0660;
162 155
163 if (!config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)) { 156 if (ENABLE_FEATURE_MDEV_CONF
164 /* End of file, create dev node with default params */ 157 && config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)
165 goto line_matches; 158 ) {
166 } 159 val = tokens[0];
167 160 keep_matching = ('-' == val[0]);
168 val = tokens[0]; 161 val += keep_matching; /* swallow leading dash */
169 keep_matching = ('-' == val[0]); 162
170 val += keep_matching; /* swallow leading dash */ 163 /* Match against either "subsystem/device_name"
171 164 * or "device_name" alone */
172 /* Match against either "subsystem/device_name" 165 name = strchr(val, '/') ? path : (char *) device_name;
173 * or "device_name" alone */ 166
174 name = strchr(val, '/') ? path : (char *) device_name; 167 /* Fields: regex uid:gid mode [alias] [cmd] */
175 168
176 /* Fields: regex uid:gid mode [alias] [cmd] */ 169 /* 1st field: @<numeric maj,min>... */
177 170 if (val[0] == '@') {
178 /* 1st field: @<numeric maj,min>... */ 171 /* @major,minor[-last] */
179 if (val[0] == '@') { 172 /* (useful when name is ambiguous:
180 /* @major,minor[-last] */ 173 * "/sys/class/usb/lp0" and
181 /* (useful when name is ambiguous: 174 * "/sys/class/printer/lp0") */
182 * "/sys/class/usb/lp0" and 175 int cmaj, cmin0, cmin1, sc;
183 * "/sys/class/printer/lp0") */ 176 if (major < 0)
184 int cmaj, cmin0, cmin1, sc; 177 continue; /* no dev, no match */
185 if (major < 0) 178 sc = sscanf(val, "@%u,%u-%u", &cmaj, &cmin0, &cmin1);
186 continue; /* no dev, no match */ 179 if (sc < 1 || major != cmaj
187 sc = sscanf(val, "@%u,%u-%u", &cmaj, &cmin0, &cmin1); 180 || (sc == 2 && minor != cmin0)
188 if (sc < 1 || major != cmaj 181 || (sc == 3 && (minor < cmin0 || minor > cmin1))
189 || (sc == 2 && minor != cmin0) 182 ) {
190 || (sc == 3 && (minor < cmin0 || minor > cmin1)) 183 continue; /* this line doesn't match */
191 ) { 184 }
192 continue; /* this line doesn't match */ 185 } else { /* ... or regex to match device name */
193 } 186 regex_t match;
194 } else { /* ... or regex to match device name */ 187 int result;
195 regex_t match; 188
196 int result; 189 /* Is this it? */
197 190 xregcomp(&match, val, REG_EXTENDED);
198 /* Is this it? */ 191 result = regexec(&match, name, ARRAY_SIZE(off), off, 0);
199 xregcomp(&match, val, REG_EXTENDED); 192 regfree(&match);
200 result = regexec(&match, name, ARRAY_SIZE(off), off, 0); 193
201 regfree(&match); 194 //bb_error_msg("matches:");
202 195 //for (int i = 0; i < ARRAY_SIZE(off); i++) {
203 //bb_error_msg("matches:"); 196 // if (off[i].rm_so < 0) continue;
204 //for (int i = 0; i < ARRAY_SIZE(off); i++) { 197 // bb_error_msg("match %d: '%.*s'\n", i,
205 // if (off[i].rm_so < 0) continue; 198 // (int)(off[i].rm_eo - off[i].rm_so),
206 // bb_error_msg("match %d: '%.*s'\n", i, 199 // device_name + off[i].rm_so);
207 // (int)(off[i].rm_eo - off[i].rm_so), 200 //}
208 // device_name + off[i].rm_so); 201
209 //} 202 /* If not this device, skip rest of line */
210 203 /* (regexec returns whole pattern as "range" 0) */
211 /* If not this device, skip rest of line */ 204 if (result || off[0].rm_so
212 /* (regexec returns whole pattern as "range" 0) */ 205 || ((int)off[0].rm_eo != (int)strlen(name))
213 if (result || off[0].rm_so 206 ) {
214 || ((int)off[0].rm_eo != (int)strlen(name)) 207 continue; /* this line doesn't match */
215 ) { 208 }
216 continue; /* this line doesn't match */
217 } 209 }
218 }
219 210
220 /* This line matches: stop parsing the file after parsing 211 /* This line matches: stop parsing the file after parsing
221 * the rest of fields unless keep_matching == 1 */ 212 * the rest of fields unless keep_matching == 1 */
222 213
223 /* 2nd field: uid:gid - device ownership */ 214 /* 2nd field: uid:gid - device ownership */
224 parse_chown_usergroup_or_die(&ugid, tokens[1]); 215 parse_chown_usergroup_or_die(&ugid, tokens[1]);
225 216
226 /* 3rd field: mode - device permissions */ 217 /* 3rd field: mode - device permissions */
227 mode = strtoul(tokens[2], NULL, 8); 218 mode = strtoul(tokens[2], NULL, 8);
228 219
229 val = tokens[3]; 220 val = tokens[3];
230 /* 4th field (opt): >|=alias */ 221 /* 4th field (opt): >|=alias */
231# if ENABLE_FEATURE_MDEV_RENAME 222
232 if (!val) 223 if (ENABLE_FEATURE_MDEV_RENAME && val) {
233 goto line_matches; 224 aliaslink = val[0];
234 aliaslink = val[0]; 225 if (aliaslink == '>' || aliaslink == '=') {
235 if (aliaslink == '>' || aliaslink == '=') { 226 char *a, *s, *st;
236 char *a, *s, *st; 227 char *p;
237# if ENABLE_FEATURE_MDEV_RENAME_REGEXP 228 unsigned i, n;
238 char *p; 229
239 unsigned i, n; 230 a = val;
240# endif 231 s = strchrnul(val, ' ');
241 a = val; 232 st = strchrnul(val, '\t');
242 s = strchrnul(val, ' '); 233 if (st < s)
243 st = strchrnul(val, '\t'); 234 s = st;
244 if (st < s) 235 val = (s[0] && s[1]) ? s+1 : NULL;
245 s = st; 236 s[0] = '\0';
246 val = (s[0] && s[1]) ? s+1 : NULL; 237
247 s[0] = '\0'; 238 if (ENABLE_FEATURE_MDEV_RENAME_REGEXP) {
248 239 /* substitute %1..9 with off[1..9], if any */
249# if ENABLE_FEATURE_MDEV_RENAME_REGEXP 240 n = 0;
250 /* substitute %1..9 with off[1..9], if any */ 241 s = a;
251 n = 0; 242 while (*s)
252 s = a; 243 if (*s++ == '%')
253 while (*s) 244 n++;
254 if (*s++ == '%') 245
255 n++; 246 p = alias = xzalloc(strlen(a) + n * strlen(name));
256 247 s = a + 1;
257 p = alias = xzalloc(strlen(a) + n * strlen(name)); 248 while (*s) {
258 s = a + 1; 249 *p = *s;
259 while (*s) { 250 if ('%' == *s) {
260 *p = *s; 251 i = (s[1] - '0');
261 if ('%' == *s) { 252 if (i <= 9 && off[i].rm_so >= 0) {
262 i = (s[1] - '0'); 253 n = off[i].rm_eo - off[i].rm_so;
263 if (i <= 9 && off[i].rm_so >= 0) { 254 strncpy(p, name + off[i].rm_so, n);
264 n = off[i].rm_eo - off[i].rm_so; 255 p += n - 1;
265 strncpy(p, name + off[i].rm_so, n); 256 s++;
266 p += n - 1; 257 }
267 s++; 258 }
259 p++;
260 s++;
261 }
262 } else {
263 alias = xstrdup(a + 1);
268 } 264 }
269 } 265 }
270 p++;
271 s++;
272 } 266 }
273# else 267
274 alias = xstrdup(a + 1); 268 if (ENABLE_FEATURE_MDEV_EXEC && val) {
275# endif 269 const char *s = "$@*";
276 } 270 const char *s2 = strchr(s, val[0]);
277# endif /* ENABLE_FEATURE_MDEV_RENAME */ 271
278 272 if (!s2)
279# if ENABLE_FEATURE_MDEV_EXEC 273 bb_error_msg_and_die("bad line %u", parser->lineno);
280 /* The rest (opt): @|$|*command */ 274
281 if (!val) 275 /* Are we running this command now?
282 goto line_matches; 276 * Run $cmd on delete, @cmd on create, *cmd on both
283 { 277 */
284 const char *s = "@$*"; 278 if (s2-s != delete)
285 const char *s2 = strchr(s, val[0]); 279 command = xstrdup(val + 1);
286
287 if (!s2)
288 bb_error_msg_and_die("bad line %u", parser->lineno);
289
290 /* Correlate the position in the "@$*" with the delete
291 * step so that we get the proper behavior:
292 * @cmd: run on create
293 * $cmd: run on delete
294 * *cmd: run on both
295 */
296 if ((s2 - s + 1) /*1/2/3*/ & /*1/2*/ (1 + delete)) {
297 command = xstrdup(val + 1);
298 } 280 }
299 } 281 }
300# endif 282
301 /* End of field parsing */ 283 /* End of field parsing */
302 line_matches:
303#endif /* ENABLE_FEATURE_MDEV_CONF */
304 284
305 /* "Execute" the line we found */ 285 /* "Execute" the line we found */
306 286
@@ -311,11 +291,11 @@ static void make_device(char *path, int delete)
311 bb_perror_msg_and_die("mknod %s", device_name); 291 bb_perror_msg_and_die("mknod %s", device_name);
312 if (major == root_major && minor == root_minor) 292 if (major == root_major && minor == root_minor)
313 symlink(device_name, "root"); 293 symlink(device_name, "root");
314#if ENABLE_FEATURE_MDEV_CONF 294 if (ENABLE_FEATURE_MDEV_CONF) {
315 chmod(device_name, mode); 295 chmod(device_name, mode);
316 chown(device_name, ugid.uid, ugid.gid); 296 chown(device_name, ugid.uid, ugid.gid);
317# if ENABLE_FEATURE_MDEV_RENAME 297 }
318 if (alias) { 298 if (ENABLE_FEATURE_MDEV_RENAME && alias) {
319 alias = build_alias(alias, device_name); 299 alias = build_alias(alias, device_name);
320 /* move the device, and optionally 300 /* move the device, and optionally
321 * make a symlink to moved device node */ 301 * make a symlink to moved device node */
@@ -323,11 +303,9 @@ static void make_device(char *path, int delete)
323 symlink(alias, device_name); 303 symlink(alias, device_name);
324 free(alias); 304 free(alias);
325 } 305 }
326# endif
327#endif
328 } 306 }
329#if ENABLE_FEATURE_MDEV_EXEC 307
330 if (command) { 308 if (ENABLE_FEATURE_MDEV_EXEC && command) {
331 /* setenv will leak memory, use putenv/unsetenv/free */ 309 /* setenv will leak memory, use putenv/unsetenv/free */
332 char *s = xasprintf("%s=%s", "MDEV", device_name); 310 char *s = xasprintf("%s=%s", "MDEV", device_name);
333 char *s1 = xasprintf("%s=%s", "SUBSYSTEM", subsystem); 311 char *s1 = xasprintf("%s=%s", "SUBSYSTEM", subsystem);
@@ -341,29 +319,29 @@ static void make_device(char *path, int delete)
341 free(s); 319 free(s);
342 free(command); 320 free(command);
343 } 321 }
344#endif 322
345 if (delete) { 323 if (delete) {
346 unlink(device_name); 324 unlink(device_name);
347 /* At creation time, device might have been moved 325 /* At creation time, device might have been moved
348 * and a symlink might have been created. Undo that. */ 326 * and a symlink might have been created. Undo that. */
349#if ENABLE_FEATURE_MDEV_RENAME 327
350 if (alias) { 328 if (ENABLE_FEATURE_MDEV_RENAME && alias) {
351 alias = build_alias(alias, device_name); 329 alias = build_alias(alias, device_name);
352 unlink(alias); 330 unlink(alias);
353 free(alias); 331 free(alias);
354 } 332 }
355#endif
356 } 333 }
357 334
358#if ENABLE_FEATURE_MDEV_CONF
359 /* We found matching line. 335 /* We found matching line.
360 * Stop unless it was prefixed with '-' */ 336 * Stop unless it was prefixed with '-' */
361 if (!keep_matching) 337 if (ENABLE_FEATURE_MDEV_CONF && !keep_matching)
362 break; 338 break;
363 } /* end of "while line is read from /etc/mdev.conf" */
364 339
365 config_close(parser); 340 /* end of "while line is read from /etc/mdev.conf" */
366#endif /* ENABLE_FEATURE_MDEV_CONF */ 341 } while (ENABLE_FEATURE_MDEV_CONF);
342
343 if (ENABLE_FEATURE_MDEV_CONF)
344 config_close(parser);
367} 345}
368 346
369/* File callback for /sys/ traversal */ 347/* File callback for /sys/ traversal */
@@ -415,7 +393,7 @@ static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM,
415 * - userspace writes "0" (worked) or "-1" (failed) to /sys/$DEVPATH/loading 393 * - userspace writes "0" (worked) or "-1" (failed) to /sys/$DEVPATH/loading
416 * - kernel loads firmware into device 394 * - kernel loads firmware into device
417 */ 395 */
418static void load_firmware(const char *const firmware, const char *const sysfs_path) 396static void load_firmware(const char *firmware, const char *sysfs_path)
419{ 397{
420 int cnt; 398 int cnt;
421 int firmware_fd, loading_fd, data_fd; 399 int firmware_fd, loading_fd, data_fd;
@@ -469,18 +447,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
469 447
470 /* We can be called as hotplug helper */ 448 /* We can be called as hotplug helper */
471 /* Kernel cannot provide suitable stdio fds for us, do it ourself */ 449 /* Kernel cannot provide suitable stdio fds for us, do it ourself */
472#if 1 450
473 bb_sanitize_stdio(); 451 bb_sanitize_stdio();
474#else
475 /* Debug code */
476 /* Replace LOGFILE by other file or device name if you need */
477#define LOGFILE "/dev/console"
478 /* Just making sure fd 0 is not closed,
479 * we don't really intend to read from it */
480 xmove_fd(xopen("/", O_RDONLY), STDIN_FILENO);
481 xmove_fd(xopen(LOGFILE, O_WRONLY|O_APPEND), STDOUT_FILENO);
482 xmove_fd(xopen(LOGFILE, O_WRONLY|O_APPEND), STDERR_FILENO);
483#endif
484 452
485 xchdir("/dev"); 453 xchdir("/dev");
486 454