diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-13 23:18:52 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-13 23:18:52 +0000 |
| commit | f2b39e088d6ccbf4a540c741059c2f661eebc9ac (patch) | |
| tree | b375683a37729c04af06f71047cba19e162ac27e | |
| parent | 065c7147914bf545ede2dbdbc07c48386d750c77 (diff) | |
| download | busybox-w32-f2b39e088d6ccbf4a540c741059c2f661eebc9ac.tar.gz busybox-w32-f2b39e088d6ccbf4a540c741059c2f661eebc9ac.tar.bz2 busybox-w32-f2b39e088d6ccbf4a540c741059c2f661eebc9ac.zip | |
mdev: add support for - "dont stop here" char
function old new delta
make_device 1340 1362 +22
packed_usage 26291 26299 +8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 30/0) Total: 30 bytes
| -rw-r--r-- | include/usage.h | 2 | ||||
| -rw-r--r-- | util-linux/mdev.c | 179 |
2 files changed, 98 insertions, 83 deletions
diff --git a/include/usage.h b/include/usage.h index 7111e90bc..d3bf7849e 100644 --- a/include/usage.h +++ b/include/usage.h | |||
| @@ -2560,7 +2560,7 @@ | |||
| 2560 | " echo /bin/mdev >/proc/sys/kernel/hotplug\n" \ | 2560 | " echo /bin/mdev >/proc/sys/kernel/hotplug\n" \ |
| 2561 | USE_FEATURE_MDEV_CONF( \ | 2561 | USE_FEATURE_MDEV_CONF( \ |
| 2562 | "It uses /etc/mdev.conf with lines\n" \ | 2562 | "It uses /etc/mdev.conf with lines\n" \ |
| 2563 | "DEVNAME UID:GID PERM" \ | 2563 | "[-]DEVNAME UID:GID PERM" \ |
| 2564 | USE_FEATURE_MDEV_RENAME(" [>|=PATH]") \ | 2564 | USE_FEATURE_MDEV_RENAME(" [>|=PATH]") \ |
| 2565 | USE_FEATURE_MDEV_EXEC(" [@|$|*COMMAND]") \ | 2565 | USE_FEATURE_MDEV_EXEC(" [@|$|*COMMAND]") \ |
| 2566 | ) \ | 2566 | ) \ |
diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 3b0ef351e..b1f3d051c 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c | |||
| @@ -57,21 +57,12 @@ static char *build_alias(char *alias, const char *device_name) | |||
| 57 | /* NB: "mdev -s" may call us many times, do not leak memory/fds! */ | 57 | /* NB: "mdev -s" may call us many times, do not leak memory/fds! */ |
| 58 | static void make_device(char *path, int delete) | 58 | static void make_device(char *path, int delete) |
| 59 | { | 59 | { |
| 60 | const char *device_name; | ||
| 61 | int major, minor, type, len; | ||
| 62 | int mode = 0660; | ||
| 63 | #if ENABLE_FEATURE_MDEV_CONF | 60 | #if ENABLE_FEATURE_MDEV_CONF |
| 64 | struct bb_uidgid_t ugid = { 0, 0 }; | ||
| 65 | parser_t *parser; | 61 | parser_t *parser; |
| 66 | char *tokens[5]; | ||
| 67 | # if ENABLE_FEATURE_MDEV_EXEC | ||
| 68 | char *command = NULL; | ||
| 69 | # endif | ||
| 70 | # if ENABLE_FEATURE_MDEV_RENAME | ||
| 71 | char *alias = NULL; | ||
| 72 | char aliaslink = aliaslink; /* for compiler */ | ||
| 73 | # endif | ||
| 74 | #endif | 62 | #endif |
| 63 | const char *device_name; | ||
| 64 | int major, minor, type, len; | ||
| 65 | int mode; | ||
| 75 | char *dev_maj_min = path + strlen(path); | 66 | char *dev_maj_min = path + strlen(path); |
| 76 | 67 | ||
| 77 | /* Force the configuration file settings exactly. */ | 68 | /* Force the configuration file settings exactly. */ |
| @@ -111,14 +102,37 @@ static void make_device(char *path, int delete) | |||
| 111 | parser = config_open2("/etc/mdev.conf", fopen_for_read); | 102 | parser = config_open2("/etc/mdev.conf", fopen_for_read); |
| 112 | 103 | ||
| 113 | /* If we have config file, look up user settings */ | 104 | /* If we have config file, look up user settings */ |
| 114 | while (config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)) { | 105 | while (1) { |
| 115 | regmatch_t off[1 + 9*ENABLE_FEATURE_MDEV_RENAME_REGEXP]; | 106 | regmatch_t off[1 + 9*ENABLE_FEATURE_MDEV_RENAME_REGEXP]; |
| 116 | char *val = tokens[0]; | 107 | int keep_matching; |
| 108 | char *val; | ||
| 109 | struct bb_uidgid_t ugid; | ||
| 110 | char *tokens[4]; | ||
| 111 | # if ENABLE_FEATURE_MDEV_EXEC | ||
| 112 | char *command = NULL; | ||
| 113 | # endif | ||
| 114 | # if ENABLE_FEATURE_MDEV_RENAME | ||
| 115 | char *alias = NULL; | ||
| 116 | char aliaslink = aliaslink; /* for compiler */ | ||
| 117 | # endif | ||
| 118 | /* Defaults in case we won't match any line */ | ||
| 119 | ugid.uid = ugid.gid = 0; | ||
| 120 | keep_matching = 0; | ||
| 121 | mode = 0660; | ||
| 122 | |||
| 123 | if (!config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)) { | ||
| 124 | /* End of file, create dev node with default params */ | ||
| 125 | goto line_matches; | ||
| 126 | } | ||
| 127 | |||
| 128 | val = tokens[0]; | ||
| 129 | keep_matching = ('-' == val[0]); | ||
| 130 | val += keep_matching; /* swallow leading dash */ | ||
| 117 | 131 | ||
| 118 | /* Fields: regex uid:gid mode [alias] [cmd] */ | 132 | /* Fields: regex uid:gid mode [alias] [cmd] */ |
| 119 | 133 | ||
| 120 | /* 1st field: @<numeric maj,min>... */ | 134 | /* 1st field: @<numeric maj,min>... */ |
| 121 | if (tokens[0][0] == '@') { | 135 | if (val[0] == '@') { |
| 122 | /* @major,minor[-last] */ | 136 | /* @major,minor[-last] */ |
| 123 | /* (useful when name is ambiguous: | 137 | /* (useful when name is ambiguous: |
| 124 | * "/sys/class/usb/lp0" and | 138 | * "/sys/class/usb/lp0" and |
| @@ -126,12 +140,12 @@ static void make_device(char *path, int delete) | |||
| 126 | int cmaj, cmin0, cmin1, sc; | 140 | int cmaj, cmin0, cmin1, sc; |
| 127 | if (major < 0) | 141 | if (major < 0) |
| 128 | continue; /* no dev, no match */ | 142 | continue; /* no dev, no match */ |
| 129 | sc = sscanf(tokens[0], "@%u,%u-%u", &cmaj, &cmin0, &cmin1); | 143 | sc = sscanf(val, "@%u,%u-%u", &cmaj, &cmin0, &cmin1); |
| 130 | if (sc < 1 || major != cmaj | 144 | if (sc < 1 || major != cmaj |
| 131 | || (sc == 2 && minor != cmin0) | 145 | || (sc == 2 && minor != cmin0) |
| 132 | || (sc == 3 && (minor < cmin0 || minor > cmin1)) | 146 | || (sc == 3 && (minor < cmin0 || minor > cmin1)) |
| 133 | ) { | 147 | ) { |
| 134 | continue; /* no match */ | 148 | continue; /* this line doesn't match */ |
| 135 | } | 149 | } |
| 136 | } else { /* ... or regex to match device name */ | 150 | } else { /* ... or regex to match device name */ |
| 137 | regex_t match; | 151 | regex_t match; |
| @@ -160,12 +174,12 @@ static void make_device(char *path, int delete) | |||
| 160 | if (result || off[0].rm_so | 174 | if (result || off[0].rm_so |
| 161 | || ((int)off[0].rm_eo != (int)strlen(dev_name_or_subsystem)) | 175 | || ((int)off[0].rm_eo != (int)strlen(dev_name_or_subsystem)) |
| 162 | ) { | 176 | ) { |
| 163 | continue; | 177 | continue; /* this line doesn't match */ |
| 164 | } | 178 | } |
| 165 | } | 179 | } |
| 166 | 180 | ||
| 167 | /* This line matches: stop parsing the file | 181 | /* This line matches: stop parsing the file after parsing |
| 168 | * after parsing the rest of fields */ | 182 | * the rest of fields unless keep_matching == 1 */ |
| 169 | 183 | ||
| 170 | /* 2nd field: uid:gid - device ownership */ | 184 | /* 2nd field: uid:gid - device ownership */ |
| 171 | parse_chown_usergroup_or_die(&ugid, tokens[1]); | 185 | parse_chown_usergroup_or_die(&ugid, tokens[1]); |
| @@ -174,24 +188,25 @@ static void make_device(char *path, int delete) | |||
| 174 | mode = strtoul(tokens[2], NULL, 8); | 188 | mode = strtoul(tokens[2], NULL, 8); |
| 175 | 189 | ||
| 176 | val = tokens[3]; | 190 | val = tokens[3]; |
| 177 | /* 4th field (opt): >alias */ | 191 | /* 4th field (opt): >|=alias */ |
| 178 | # if ENABLE_FEATURE_MDEV_RENAME | 192 | # if ENABLE_FEATURE_MDEV_RENAME |
| 179 | if (!val) | 193 | if (!val) |
| 180 | break; | 194 | goto line_matches; |
| 181 | aliaslink = *val; | 195 | aliaslink = val[0]; |
| 182 | if (aliaslink == '>' || aliaslink == '=') { | 196 | if (aliaslink == '>' || aliaslink == '=') { |
| 183 | char *s, *st; | 197 | char *a, *s, *st; |
| 184 | # if ENABLE_FEATURE_MDEV_RENAME_REGEXP | 198 | # if ENABLE_FEATURE_MDEV_RENAME_REGEXP |
| 185 | char *p; | 199 | char *p; |
| 186 | unsigned i, n; | 200 | unsigned i, n; |
| 187 | # endif | 201 | # endif |
| 188 | char *a = val; | 202 | a = val; |
| 189 | s = strchrnul(val, ' '); | 203 | s = strchrnul(val, ' '); |
| 190 | st = strchrnul(val, '\t'); | 204 | st = strchrnul(val, '\t'); |
| 191 | if (st < s) | 205 | if (st < s) |
| 192 | s = st; | 206 | s = st; |
| 193 | val = (s[0] && s[1]) ? s+1 : NULL; | 207 | val = (s[0] && s[1]) ? s+1 : NULL; |
| 194 | s[0] = '\0'; | 208 | s[0] = '\0'; |
| 209 | |||
| 195 | # if ENABLE_FEATURE_MDEV_RENAME_REGEXP | 210 | # if ENABLE_FEATURE_MDEV_RENAME_REGEXP |
| 196 | /* substitute %1..9 with off[1..9], if any */ | 211 | /* substitute %1..9 with off[1..9], if any */ |
| 197 | n = 0; | 212 | n = 0; |
| @@ -223,12 +238,12 @@ static void make_device(char *path, int delete) | |||
| 223 | # endif /* ENABLE_FEATURE_MDEV_RENAME */ | 238 | # endif /* ENABLE_FEATURE_MDEV_RENAME */ |
| 224 | 239 | ||
| 225 | # if ENABLE_FEATURE_MDEV_EXEC | 240 | # if ENABLE_FEATURE_MDEV_EXEC |
| 226 | /* The rest (opt): command to run */ | 241 | /* The rest (opt): @|$|*command */ |
| 227 | if (!val) | 242 | if (!val) |
| 228 | break; | 243 | goto line_matches; |
| 229 | { | 244 | { |
| 230 | const char *s = "@$*"; | 245 | const char *s = "@$*"; |
| 231 | const char *s2 = strchr(s, *val); | 246 | const char *s2 = strchr(s, val[0]); |
| 232 | 247 | ||
| 233 | if (!s2) | 248 | if (!s2) |
| 234 | bb_error_msg_and_die("bad line %u", parser->lineno); | 249 | bb_error_msg_and_die("bad line %u", parser->lineno); |
| @@ -244,71 +259,71 @@ static void make_device(char *path, int delete) | |||
| 244 | } | 259 | } |
| 245 | } | 260 | } |
| 246 | # endif | 261 | # endif |
| 247 | /* end of field parsing */ | 262 | /* End of field parsing */ |
| 248 | break; /* we found matching line, stop */ | 263 | line_matches: |
| 249 | } /* end of "while line is read from /etc/mdev.conf" */ | ||
| 250 | |||
| 251 | config_close(parser); | ||
| 252 | #endif /* ENABLE_FEATURE_MDEV_CONF */ | 264 | #endif /* ENABLE_FEATURE_MDEV_CONF */ |
| 253 | 265 | ||
| 254 | if (!delete && major >= 0) { | 266 | /* "Execute" the line we found */ |
| 255 | |||
| 256 | if (ENABLE_FEATURE_MDEV_RENAME) | ||
| 257 | unlink(device_name); | ||
| 258 | |||
| 259 | if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST) | ||
| 260 | bb_perror_msg_and_die("mknod %s", device_name); | ||
| 261 | |||
| 262 | if (major == root_major && minor == root_minor) | ||
| 263 | symlink(device_name, "root"); | ||
| 264 | 267 | ||
| 268 | if (!delete && major >= 0) { | ||
| 269 | if (ENABLE_FEATURE_MDEV_RENAME) | ||
| 270 | unlink(device_name); | ||
| 271 | if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST) | ||
| 272 | bb_perror_msg_and_die("mknod %s", device_name); | ||
| 273 | if (major == root_major && minor == root_minor) | ||
| 274 | symlink(device_name, "root"); | ||
| 265 | #if ENABLE_FEATURE_MDEV_CONF | 275 | #if ENABLE_FEATURE_MDEV_CONF |
| 266 | chown(device_name, ugid.uid, ugid.gid); | 276 | chown(device_name, ugid.uid, ugid.gid); |
| 267 | |||
| 268 | # if ENABLE_FEATURE_MDEV_RENAME | 277 | # if ENABLE_FEATURE_MDEV_RENAME |
| 269 | if (alias) { | 278 | if (alias) { |
| 270 | alias = build_alias(alias, device_name); | 279 | alias = build_alias(alias, device_name); |
| 271 | 280 | /* move the device, and optionally | |
| 272 | /* move the device, and optionally | 281 | * make a symlink to moved device node */ |
| 273 | * make a symlink to moved device node */ | 282 | if (rename(device_name, alias) == 0 && aliaslink == '>') |
| 274 | if (rename(device_name, alias) == 0 && aliaslink == '>') | 283 | symlink(alias, device_name); |
| 275 | symlink(alias, device_name); | 284 | free(alias); |
| 276 | 285 | } | |
| 277 | free(alias); | ||
| 278 | } | ||
| 279 | # endif | 286 | # endif |
| 280 | #endif | 287 | #endif |
| 281 | } | 288 | } |
| 282 | |||
| 283 | #if ENABLE_FEATURE_MDEV_EXEC | 289 | #if ENABLE_FEATURE_MDEV_EXEC |
| 284 | if (command) { | 290 | if (command) { |
| 285 | /* setenv will leak memory, use putenv/unsetenv/free */ | 291 | /* setenv will leak memory, use putenv/unsetenv/free */ |
| 286 | char *s = xasprintf("%s=%s", "MDEV", device_name); | 292 | char *s = xasprintf("%s=%s", "MDEV", device_name); |
| 287 | char *s1 = xasprintf("%s=%s", "SUBSYSTEM", subsystem); | 293 | char *s1 = xasprintf("%s=%s", "SUBSYSTEM", subsystem); |
| 288 | putenv(s); | 294 | putenv(s); |
| 289 | putenv(s1); | 295 | putenv(s1); |
| 290 | if (system(command) == -1) | 296 | if (system(command) == -1) |
| 291 | bb_perror_msg_and_die("can't run '%s'", command); | 297 | bb_perror_msg_and_die("can't run '%s'", command); |
| 292 | unsetenv("SUBSYSTEM"); | 298 | unsetenv("SUBSYSTEM"); |
| 293 | free(s1); | 299 | free(s1); |
| 294 | unsetenv("MDEV"); | 300 | unsetenv("MDEV"); |
| 295 | free(s); | 301 | free(s); |
| 296 | free(command); | 302 | free(command); |
| 297 | } | 303 | } |
| 298 | #endif | 304 | #endif |
| 299 | 305 | if (delete) { | |
| 300 | if (delete) { | 306 | unlink(device_name); |
| 301 | unlink(device_name); | 307 | /* At creation time, device might have been moved |
| 302 | /* At creation time, device might have been moved | 308 | * and a symlink might have been created. Undo that. */ |
| 303 | * and a symlink might have been created. Undo that. */ | ||
| 304 | #if ENABLE_FEATURE_MDEV_RENAME | 309 | #if ENABLE_FEATURE_MDEV_RENAME |
| 305 | if (alias) { | 310 | if (alias) { |
| 306 | alias = build_alias(alias, device_name); | 311 | alias = build_alias(alias, device_name); |
| 307 | unlink(alias); | 312 | unlink(alias); |
| 308 | free(alias); | 313 | free(alias); |
| 309 | } | 314 | } |
| 310 | #endif | 315 | #endif |
| 311 | } | 316 | } |
| 317 | |||
| 318 | #if ENABLE_FEATURE_MDEV_CONF | ||
| 319 | /* We found matching line. | ||
| 320 | * Stop unless it was prefixed with '-' */ | ||
| 321 | if (!keep_matching) | ||
| 322 | break; | ||
| 323 | } /* end of "while line is read from /etc/mdev.conf" */ | ||
| 324 | |||
| 325 | config_close(parser); | ||
| 326 | #endif /* ENABLE_FEATURE_MDEV_CONF */ | ||
| 312 | } | 327 | } |
| 313 | 328 | ||
| 314 | /* File callback for /sys/ traversal */ | 329 | /* File callback for /sys/ traversal */ |
