aboutsummaryrefslogtreecommitdiff
path: root/util-linux/mdev.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-19 21:37:07 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-19 21:37:07 +0000
commit3798db58cfa0e939d0fc1822c9864355c1422cd0 (patch)
tree99f44bad59ccf82f4c1defa3bd81f09078eea8a0 /util-linux/mdev.c
parentf66fe9af89e3d0f8a92894c59b6808f9202c0e86 (diff)
downloadbusybox-w32-3798db58cfa0e939d0fc1822c9864355c1422cd0.tar.gz
busybox-w32-3798db58cfa0e939d0fc1822c9864355c1422cd0.tar.bz2
busybox-w32-3798db58cfa0e939d0fc1822c9864355c1422cd0.zip
mdev: support $ENVVAR=regex
Diffstat (limited to 'util-linux/mdev.c')
-rw-r--r--util-linux/mdev.c69
1 files changed, 42 insertions, 27 deletions
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index a3275f881..ea1edcc40 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -89,15 +89,11 @@ static char *build_alias(char *alias, const char *device_name)
89/* 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! */
90static void make_device(char *path, int delete) 90static void make_device(char *path, int delete)
91{ 91{
92 const char *device_name; 92 char *device_name;
93 int major, minor, type, len; 93 int major, minor, type, len;
94 int mode; 94 int mode;
95 char *dev_maj_min = path + strlen(path);
96 parser_t *parser; 95 parser_t *parser;
97 96
98 /* Force the configuration file settings exactly. */
99 umask(0);
100
101 /* Try to read major/minor string. Note that the kernel puts \n after 97 /* Try to read major/minor string. Note that the kernel puts \n after
102 * the data, so we don't need to worry about null terminating the string 98 * the data, so we don't need to worry about null terminating the string
103 * because sscanf() will stop at the first nondigit, which \n is. 99 * because sscanf() will stop at the first nondigit, which \n is.
@@ -105,21 +101,23 @@ static void make_device(char *path, int delete)
105 */ 101 */
106 major = -1; 102 major = -1;
107 if (!delete) { 103 if (!delete) {
104 char *dev_maj_min = path + strlen(path);
105
108 strcpy(dev_maj_min, "/dev"); 106 strcpy(dev_maj_min, "/dev");
109 len = open_read_close(path, dev_maj_min + 1, 64); 107 len = open_read_close(path, dev_maj_min + 1, 64);
110 *dev_maj_min++ = '\0'; 108 *dev_maj_min = '\0';
111 if (len < 1) { 109 if (len < 1) {
112 if (!ENABLE_FEATURE_MDEV_EXEC) 110 if (!ENABLE_FEATURE_MDEV_EXEC)
113 return; 111 return;
114 /* no "dev" file, so just try to run script */ 112 /* no "dev" file, but we can still run scripts
115 *dev_maj_min = '\0'; 113 * based on device name */
116 } else if (sscanf(dev_maj_min, "%u:%u", &major, &minor) != 2) { 114 } else if (sscanf(++dev_maj_min, "%u:%u", &major, &minor) != 2) {
117 major = -1; 115 major = -1;
118 } 116 }
119 } 117 }
120 118
121 /* Determine device name, type, major and minor */ 119 /* Determine device name, type, major and minor */
122 device_name = bb_basename(path); 120 device_name = (char*) bb_basename(path);
123 /* http://kernel.org/doc/pending/hotplug.txt says that only 121 /* http://kernel.org/doc/pending/hotplug.txt says that only
124 * "/sys/block/..." is for block devices. "/sys/bus" etc is not. 122 * "/sys/block/..." is for block devices. "/sys/bus" etc is not.
125 * But since 2.6.25 block devices are also in /sys/class/block, 123 * But since 2.6.25 block devices are also in /sys/class/block,
@@ -139,9 +137,7 @@ static void make_device(char *path, int delete)
139 parser = config_open2("/etc/mdev.conf", fopen_for_read); 137 parser = config_open2("/etc/mdev.conf", fopen_for_read);
140 138
141 do { 139 do {
142 regmatch_t off[1 + 9 * ENABLE_FEATURE_MDEV_RENAME_REGEXP];
143 int keep_matching; 140 int keep_matching;
144 char *val, *name;
145 struct bb_uidgid_t ugid; 141 struct bb_uidgid_t ugid;
146 char *tokens[4]; 142 char *tokens[4];
147 char *command = NULL; 143 char *command = NULL;
@@ -156,19 +152,22 @@ static void make_device(char *path, int delete)
156 if (ENABLE_FEATURE_MDEV_CONF 152 if (ENABLE_FEATURE_MDEV_CONF
157 && config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL) 153 && config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)
158 ) { 154 ) {
155 char *val;
156 char *str_to_match;
157 regmatch_t off[1 + 9 * ENABLE_FEATURE_MDEV_RENAME_REGEXP];
158
159 val = tokens[0]; 159 val = tokens[0];
160 keep_matching = ('-' == val[0]); 160 keep_matching = ('-' == val[0]);
161 val += keep_matching; /* swallow leading dash */ 161 val += keep_matching; /* swallow leading dash */
162 162
163 /* Match against either "subsystem/device_name" 163 /* Match against either "subsystem/device_name"
164 * or "device_name" alone */ 164 * or "device_name" alone */
165 name = strchr(val, '/') ? path : (char *) device_name; 165 str_to_match = strchr(val, '/') ? path : device_name;
166 166
167 /* Fields: regex uid:gid mode [alias] [cmd] */ 167 /* Fields: regex uid:gid mode [alias] [cmd] */
168 168
169 /* 1st field: @<numeric maj,min>... */
170 if (val[0] == '@') { 169 if (val[0] == '@') {
171 /* @major,minor[-last] */ 170 /* @major,minor[-minor2] */
172 /* (useful when name is ambiguous: 171 /* (useful when name is ambiguous:
173 * "/sys/class/usb/lp0" and 172 * "/sys/class/usb/lp0" and
174 * "/sys/class/printer/lp0") */ 173 * "/sys/class/printer/lp0") */
@@ -182,15 +181,29 @@ static void make_device(char *path, int delete)
182 ) { 181 ) {
183 continue; /* this line doesn't match */ 182 continue; /* this line doesn't match */
184 } 183 }
185 } else { /* ... or regex to match device name */ 184 goto line_matches;
185 }
186 if (val[0] == '$') {
187 /* regex to match an environment variable */
188 char *eq = strchr(++val, '=');
189 if (!eq)
190 continue;
191 *eq = '\0';
192 str_to_match = getenv(val);
193 if (!str_to_match)
194 continue;
195 str_to_match -= strlen(val) + 1;
196 *eq = '=';
197 }
198 /* else: regex to match [subsystem/]device_name */
199
200 {
186 regex_t match; 201 regex_t match;
187 int result; 202 int result;
188 203
189 /* Is this it? */
190 xregcomp(&match, val, REG_EXTENDED); 204 xregcomp(&match, val, REG_EXTENDED);
191 result = regexec(&match, name, ARRAY_SIZE(off), off, 0); 205 result = regexec(&match, str_to_match, ARRAY_SIZE(off), off, 0);
192 regfree(&match); 206 regfree(&match);
193
194 //bb_error_msg("matches:"); 207 //bb_error_msg("matches:");
195 //for (int i = 0; i < ARRAY_SIZE(off); i++) { 208 //for (int i = 0; i < ARRAY_SIZE(off); i++) {
196 // if (off[i].rm_so < 0) continue; 209 // if (off[i].rm_so < 0) continue;
@@ -199,17 +212,17 @@ static void make_device(char *path, int delete)
199 // device_name + off[i].rm_so); 212 // device_name + off[i].rm_so);
200 //} 213 //}
201 214
202 /* If not this device, skip rest of line */ 215 /* If no match, skip rest of line */
203 /* (regexec returns whole pattern as "range" 0) */ 216 /* (regexec returns whole pattern as "range" 0) */
204 if (result || off[0].rm_so 217 if (result || off[0].rm_so
205 || ((int)off[0].rm_eo != (int)strlen(name)) 218 || ((int)off[0].rm_eo != (int)strlen(str_to_match))
206 ) { 219 ) {
207 continue; /* this line doesn't match */ 220 continue; /* this line doesn't match */
208 } 221 }
209 } 222 }
210 223 line_matches:
211 /* This line matches: stop parsing the file after parsing 224 /* This line matches. Stop parsing after parsing
212 * the rest of fields unless keep_matching == 1 */ 225 * the rest the line unless keep_matching == 1 */
213 226
214 /* 2nd field: uid:gid - device ownership */ 227 /* 2nd field: uid:gid - device ownership */
215 parse_chown_usergroup_or_die(&ugid, tokens[1]); 228 parse_chown_usergroup_or_die(&ugid, tokens[1]);
@@ -243,7 +256,7 @@ static void make_device(char *path, int delete)
243 if (*s++ == '%') 256 if (*s++ == '%')
244 n++; 257 n++;
245 258
246 p = alias = xzalloc(strlen(a) + n * strlen(name)); 259 p = alias = xzalloc(strlen(a) + n * strlen(str_to_match));
247 s = a + 1; 260 s = a + 1;
248 while (*s) { 261 while (*s) {
249 *p = *s; 262 *p = *s;
@@ -251,7 +264,7 @@ static void make_device(char *path, int delete)
251 i = (s[1] - '0'); 264 i = (s[1] - '0');
252 if (i <= 9 && off[i].rm_so >= 0) { 265 if (i <= 9 && off[i].rm_so >= 0) {
253 n = off[i].rm_eo - off[i].rm_so; 266 n = off[i].rm_eo - off[i].rm_so;
254 strncpy(p, name + off[i].rm_so, n); 267 strncpy(p, str_to_match + off[i].rm_so, n);
255 p += n - 1; 268 p += n - 1;
256 s++; 269 s++;
257 } 270 }
@@ -447,9 +460,11 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
447 460
448 /* We can be called as hotplug helper */ 461 /* We can be called as hotplug helper */
449 /* Kernel cannot provide suitable stdio fds for us, do it ourself */ 462 /* Kernel cannot provide suitable stdio fds for us, do it ourself */
450
451 bb_sanitize_stdio(); 463 bb_sanitize_stdio();
452 464
465 /* Force the configuration file settings exactly */
466 umask(0);
467
453 xchdir("/dev"); 468 xchdir("/dev");
454 469
455 if (argv[1] && strcmp(argv[1], "-s") == 0) { 470 if (argv[1] && strcmp(argv[1], "-s") == 0) {