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 /util-linux/mdev.c | |
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
Diffstat (limited to 'util-linux/mdev.c')
-rw-r--r-- | util-linux/mdev.c | 179 |
1 files changed, 97 insertions, 82 deletions
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 */ |