Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/modutils/modprobe.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/modutils/modprobe.c
r902 r1770 12 12 */ 13 13 14 #include " busybox.h"14 #include "libbb.h" 15 15 #include <sys/utsname.h> 16 #include <sys/types.h>17 #include <sys/wait.h>18 #include <getopt.h>19 #include <stdlib.h>20 #include <unistd.h>21 #include <syslog.h>22 #include <string.h>23 #include <ctype.h>24 #include <fcntl.h>25 16 #include <fnmatch.h> 26 17 … … 32 23 struct dep_t { /* one-way list of dependency rules */ 33 24 /* a dependency rule */ 34 char * m_name; 35 char * m_path; 36 struct mod_opt_t * m_options; /* the module options */37 38 int m_isalias : 1; 39 int m_reserved : 15; 40 41 int m_depcnt : 16; 42 char ** m_deparr; 43 44 struct dep_t * m_next; 25 char * m_name; /* the module name*/ 26 char * m_path; /* the module file path */ 27 struct mod_opt_t * m_options; /* the module options */ 28 29 int m_isalias : 1; /* the module is an alias */ 30 int m_reserved : 15; /* stuffin' */ 31 32 int m_depcnt : 16; /* the number of dependable module(s) */ 33 char ** m_deparr; /* the list of dependable module(s) */ 34 35 struct dep_t * m_next; /* the next dependency rule */ 45 36 }; 46 37 47 38 struct mod_list_t { /* two-way list of modules to process */ 48 39 /* a module description */ 49 c har *m_name;50 char * 51 struct mod_opt_t * 40 const char * m_name; 41 char * m_path; 42 struct mod_opt_t * m_options; 52 43 53 44 struct mod_list_t * m_prev; … … 82 73 static int main_opts; 83 74 84 static int parse_tag_value ( char *buffer, char **ptag, char **pvalue)75 static int parse_tag_value(char *buffer, char **ptag, char **pvalue) 85 76 { 86 77 char *tag, *value; 87 78 88 while ( isspace ( *buffer )) 89 buffer++; 79 buffer = skip_whitespace(buffer); 90 80 tag = value = buffer; 91 while ( !isspace ( *value))81 while (!isspace(*value)) 92 82 if (!*value) return 0; 93 83 else value++; 94 84 *value++ = 0; 95 while ( isspace ( *value )) 96 value++; 85 value = skip_whitespace(value); 97 86 if (!*value) return 0; 98 87 … … 101 90 102 91 return 1; 103 }104 105 /* Jump through hoops to simulate how fgets() grabs just one line at a106 * time... Don't use any stdio since modprobe gets called from a kernel107 * thread and stdio junk can overflow the limited stack...108 */109 static char *reads ( int fd, char *buffer, size_t len )110 {111 int n = read ( fd, buffer, len );112 113 if ( n > 0 ) {114 char *p;115 116 buffer [len-1] = 0;117 p = strchr ( buffer, '\n' );118 119 if ( p ) {120 off_t offset;121 122 offset = lseek ( fd, 0L, SEEK_CUR ); // Get the current file descriptor offset123 lseek ( fd, offset-n + (p-buffer) + 1, SEEK_SET ); // Set the file descriptor offset to right after the \n124 125 p[1] = 0;126 }127 return buffer;128 }129 130 else131 return 0;132 92 } 133 93 … … 135 95 * This function appends an option to a list 136 96 */ 137 static struct mod_opt_t *append_option( struct mod_opt_t *opt_list, char *opt)97 static struct mod_opt_t *append_option(struct mod_opt_t *opt_list, char *opt) 138 98 { 139 99 struct mod_opt_t *ol = opt_list; 140 100 141 if ( ol) {142 while ( ol-> m_next) {143 ol = ol-> 144 } 145 ol-> m_next = xmalloc( sizeof( struct mod_opt_t ));146 ol = ol-> 101 if (ol) { 102 while (ol->m_next) { 103 ol = ol->m_next; 104 } 105 ol->m_next = xmalloc(sizeof(struct mod_opt_t)); 106 ol = ol->m_next; 147 107 } else { 148 ol = opt_list = xmalloc( sizeof( struct mod_opt_t ));149 } 150 151 ol-> m_opt_val = bb_xstrdup( opt);152 ol-> 108 ol = opt_list = xmalloc(sizeof(struct mod_opt_t)); 109 } 110 111 ol->m_opt_val = xstrdup(opt); 112 ol->m_next = NULL; 153 113 154 114 return opt_list; … … 156 116 157 117 #if ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS 158 /* static char* parse_command_string( char* src, char **dst);118 /* static char* parse_command_string(char* src, char **dst); 159 119 * src: pointer to string containing argument 160 120 * dst: pointer to where to store the parsed argument 161 121 * return value: the pointer to the first char after the parsed argument, 162 122 * NULL if there was no argument parsed (only trailing spaces). 163 * Note that memory is allocated with bb_xstrdup when a new argument was123 * Note that memory is allocated with xstrdup when a new argument was 164 124 * parsed. Don't forget to free it! 165 125 */ … … 167 127 #define ARG_IN_DQUOTES 0x01 168 128 #define ARG_IN_SQUOTES 0x02 169 static char *parse_command_string( char *src, char **dst)129 static char *parse_command_string(char *src, char **dst) 170 130 { 171 131 int opt_status = ARG_EMPTY; … … 173 133 174 134 /* Dumb you, I have nothing to do... */ 175 if ( src == NULL) return src;135 if (src == NULL) return src; 176 136 177 137 /* Skip leading spaces */ 178 while ( *src == ' ') {138 while (*src == ' ') { 179 139 src++; 180 140 } 181 141 /* Is the end of string reached? */ 182 if ( *src == '\0') {142 if (*src == '\0') { 183 143 return NULL; 184 144 } … … 186 146 * By the way, we duplicate a little too much 187 147 * here but what is too much is freed later. */ 188 *dst = tmp_str = bb_xstrdup( src);148 *dst = tmp_str = xstrdup(src); 189 149 /* Get to the end of that argument */ 190 while ( ( *tmp_str != '\0' )191 && ( ( *tmp_str != ' ')192 || ( opt_status & ( ARG_IN_DQUOTES | ARG_IN_SQUOTES ) ) )) {193 switch ( *tmp_str) {194 195 if( opt_status & ARG_IN_DQUOTES) {196 197 198 199 memmove( tmp_str, tmp_str + 1, strlen( tmp_str ));200 201 202 203 204 150 while (*tmp_str != '\0' 151 && (*tmp_str != ' ' || (opt_status & (ARG_IN_DQUOTES | ARG_IN_SQUOTES))) 152 ) { 153 switch (*tmp_str) { 154 case '\'': 155 if (opt_status & ARG_IN_DQUOTES) { 156 /* Already in double quotes, keep current char as is */ 157 } else { 158 /* shift left 1 char, until end of string: get rid of the opening/closing quotes */ 159 memmove(tmp_str, tmp_str + 1, strlen(tmp_str)); 160 /* mark me: we enter or leave single quotes */ 161 opt_status ^= ARG_IN_SQUOTES; 162 /* Back one char, as we need to re-scan the new char there. */ 163 tmp_str--; 164 } 205 165 break; 206 207 if( opt_status & ARG_IN_SQUOTES) {208 209 210 211 memmove( tmp_str, tmp_str + 1, strlen( tmp_str ));212 213 214 215 216 166 case '"': 167 if (opt_status & ARG_IN_SQUOTES) { 168 /* Already in single quotes, keep current char as is */ 169 } else { 170 /* shift left 1 char, until end of string: get rid of the opening/closing quotes */ 171 memmove(tmp_str, tmp_str + 1, strlen(tmp_str)); 172 /* mark me: we enter or leave double quotes */ 173 opt_status ^= ARG_IN_DQUOTES; 174 /* Back one char, as we need to re-scan the new char there. */ 175 tmp_str--; 176 } 217 177 break; 218 219 if( opt_status & ARG_IN_SQUOTES) {220 221 222 switch( *(tmp_str+1)) {223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 memmove( tmp_str, tmp_str + 1, strlen( tmp_str ));240 241 242 178 case '\\': 179 if (opt_status & ARG_IN_SQUOTES) { 180 /* Between single quotes: keep as is. */ 181 } else { 182 switch (*(tmp_str+1)) { 183 case 'a': 184 case 'b': 185 case 't': 186 case 'n': 187 case 'v': 188 case 'f': 189 case 'r': 190 case '0': 191 /* We escaped a special character. For now, keep 192 * both the back-slash and the following char. */ 193 tmp_str++; src++; 194 break; 195 default: 196 /* We escaped a space or a single or double quote, 197 * or a back-slash, or a non-escapable char. Remove 198 * the '\' and keep the new current char as is. */ 199 memmove(tmp_str, tmp_str + 1, strlen(tmp_str)); 200 break; 201 } 202 } 243 203 break; 244 245 246 247 248 249 250 251 252 204 /* Any other char that is special shall appear here. 205 * Example: $ starts a variable 206 case '$': 207 do_variable_expansion(); 208 break; 209 * */ 210 default: 211 /* any other char is kept as is. */ 212 break; 253 213 } 254 214 tmp_str++; /* Go to next char */ … … 256 216 } 257 217 /* End of string, but still no ending quote */ 258 if ( opt_status & ( ARG_IN_DQUOTES | ARG_IN_SQUOTES )) {259 bb_error_msg_and_die( "unterminated (single or double) quote in options list: %s", src);218 if (opt_status & (ARG_IN_DQUOTES | ARG_IN_SQUOTES)) { 219 bb_error_msg_and_die("unterminated (single or double) quote in options list: %s", src); 260 220 } 261 221 *tmp_str++ = '\0'; 262 *dst = xrealloc( *dst, (tmp_str - *dst ));222 *dst = xrealloc(*dst, (tmp_str - *dst)); 263 223 return src; 264 224 } … … 271 231 * (/etc/modprobe.conf syntax). It supports includes (only files, no directories). 272 232 */ 273 static void include_conf ( struct dep_t **first, struct dep_t **current, char *buffer, int buflen, int fd)233 static void include_conf(struct dep_t **first, struct dep_t **current, char *buffer, int buflen, int fd) 274 234 { 275 235 int continuation_line = 0; 276 236 277 // alias parsing is not 100% correct (no correct handling of continuation lines within an alias) 278 279 while ( reads (fd, buffer, buflen)) {237 // alias parsing is not 100% correct (no correct handling of continuation lines within an alias)! 238 239 while (reads(fd, buffer, buflen)) { 280 240 int l; 281 241 char *p; 282 242 283 p = strchr ( buffer, '#');284 if ( p)243 p = strchr(buffer, '#'); 244 if (p) 285 245 *p = 0; 286 246 287 l = strlen ( buffer);288 289 while ( l && isspace ( buffer [l-1])) {290 buffer 247 l = strlen(buffer); 248 249 while (l && isspace(buffer[l-1])) { 250 buffer[l-1] = 0; 291 251 l--; 292 252 } 293 253 294 if ( l == 0) {254 if (l == 0) { 295 255 continuation_line = 0; 296 256 continue; 297 257 } 298 258 299 if ( !continuation_line) {300 if (( strncmp ( buffer, "alias", 5 ) == 0 ) && isspace ( buffer [5])) {259 if (!continuation_line) { 260 if ((strncmp(buffer, "alias", 5) == 0) && isspace(buffer[5])) { 301 261 char *alias, *mod; 302 262 303 if ( parse_tag_value ( buffer + 6, &alias, &mod)) {263 if (parse_tag_value(buffer + 6, &alias, &mod)) { 304 264 /* handle alias as a module dependent on the aliased module */ 305 if ( !*current ) { 306 (*first) = (*current) = (struct dep_t *) xcalloc ( 1, sizeof ( struct dep_t )); 265 if (!*current) { 266 (*first) = (*current) = xzalloc(sizeof(struct dep_t)); 267 } else { 268 (*current)->m_next = xzalloc(sizeof(struct dep_t)); 269 (*current) = (*current)->m_next; 307 270 } 308 else { 309 (*current)-> m_next = (struct dep_t *) xcalloc ( 1, sizeof ( struct dep_t )); 310 (*current) = (*current)-> m_next; 271 (*current)->m_name = xstrdup(alias); 272 (*current)->m_isalias = 1; 273 274 if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) { 275 (*current)->m_depcnt = 0; 276 (*current)->m_deparr = 0; 277 } else { 278 (*current)->m_depcnt = 1; 279 (*current)->m_deparr = xmalloc(1 * sizeof(char *)); 280 (*current)->m_deparr[0] = xstrdup(mod); 311 281 } 312 (*current)-> m_name = bb_xstrdup ( alias ); 313 (*current)-> m_isalias = 1; 314 315 if (( strcmp ( mod, "off" ) == 0 ) || ( strcmp ( mod, "null" ) == 0 )) { 316 (*current)-> m_depcnt = 0; 317 (*current)-> m_deparr = 0; 318 } 319 else { 320 (*current)-> m_depcnt = 1; 321 (*current)-> m_deparr = xmalloc ( 1 * sizeof( char * )); 322 (*current)-> m_deparr[0] = bb_xstrdup ( mod ); 323 } 324 (*current)-> m_next = 0; 325 } 326 } 327 else if (( strncmp ( buffer, "options", 7 ) == 0 ) && isspace ( buffer [7] )) { 282 (*current)->m_next = 0; 283 } 284 } else if ((strncmp(buffer, "options", 7) == 0) && isspace(buffer[7])) { 328 285 char *mod, *opt; 329 286 330 287 /* split the line in the module/alias name, and options */ 331 if ( parse_tag_value ( buffer + 8, &mod, &opt)) {288 if (parse_tag_value(buffer + 8, &mod, &opt)) { 332 289 struct dep_t *dt; 333 290 334 291 /* find the corresponding module */ 335 for ( dt = *first; dt; dt = dt-> m_next) {336 if ( strcmp ( dt-> m_name, mod ) == 0)292 for (dt = *first; dt; dt = dt->m_next) { 293 if (strcmp(dt->m_name, mod) == 0) 337 294 break; 338 295 } 339 if ( dt) {340 if ( ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) {296 if (dt) { 297 if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) { 341 298 char* new_opt = NULL; 342 while ( ( opt = parse_command_string( opt, &new_opt ) )) {343 dt-> m_options = append_option( dt-> m_options, new_opt);299 while ((opt = parse_command_string(opt, &new_opt))) { 300 dt->m_options = append_option(dt->m_options, new_opt); 344 301 } 345 302 } else { 346 dt-> m_options = append_option( dt-> m_options, opt);303 dt->m_options = append_option(dt->m_options, opt); 347 304 } 348 305 } 349 306 } 350 } 351 else if (( strncmp ( buffer, "include", 7 ) == 0 ) && isspace ( buffer [7] )) { 352 353 int fdi; char *filename = buffer + 8; 354 355 while ( isspace ( *filename )) 356 filename++; 357 358 if (( fdi = open ( filename, O_RDONLY )) >= 0 ) { 307 } else if ((strncmp(buffer, "include", 7) == 0) && isspace(buffer[7])) { 308 int fdi; char *filename; 309 310 filename = skip_whitespace(buffer + 8); 311 312 if ((fdi = open(filename, O_RDONLY)) >= 0) { 359 313 include_conf(first, current, buffer, buflen, fdi); 360 314 close(fdi); … … 366 320 367 321 /* 368 * This function builds a list of dependency rules from /lib/modules/`uname -r` \modules.dep.322 * This function builds a list of dependency rules from /lib/modules/`uname -r`/modules.dep. 369 323 * It then fills every modules and aliases with their default options, found by parsing 370 324 * modprobe.conf (or modules.conf, or conf.modules). 371 325 */ 372 static struct dep_t *build_dep ( void)326 static struct dep_t *build_dep(void) 373 327 { 374 328 int fd; … … 381 335 int k_version; 382 336 337 if (uname(&un)) 338 bb_error_msg_and_die("can't determine kernel version"); 339 383 340 k_version = 0; 384 if ( uname ( &un ))385 bb_error_msg_and_die("can't determine kernel version");386 387 341 if (un.release[0] == '2') { 388 342 k_version = un.release[2] - '0'; 389 343 } 390 344 391 filename = bb_xasprintf("/lib/modules/%s/modules.dep", un.release);392 fd = open ( filename, O_RDONLY);345 filename = xasprintf("/lib/modules/%s/modules.dep", un.release); 346 fd = open(filename, O_RDONLY); 393 347 if (ENABLE_FEATURE_CLEAN_UP) 394 348 free(filename); 395 349 if (fd < 0) { 396 350 /* Ok, that didn't work. Fall back to looking in /lib/modules */ 397 if (( fd = open ( "/lib/modules/modules.dep", O_RDONLY )) < 0 ) { 351 fd = open("/lib/modules/modules.dep", O_RDONLY); 352 if (fd < 0) { 398 353 return 0; 399 354 } 400 355 } 401 356 402 while ( reads ( fd, buffer, sizeof( buffer))) {403 int l = strlen ( buffer);357 while (reads(fd, buffer, sizeof(buffer))) { 358 int l = strlen(buffer); 404 359 char *p = 0; 405 360 406 while ( l > 0 && isspace ( buffer [l-1])) {407 buffer 361 while (l > 0 && isspace(buffer[l-1])) { 362 buffer[l-1] = 0; 408 363 l--; 409 364 } 410 365 411 if ( l == 0) {366 if (l == 0) { 412 367 continuation_line = 0; 413 368 continue; … … 415 370 416 371 /* Is this a new module dep description? */ 417 if ( !continuation_line) {372 if (!continuation_line) { 418 373 /* find the dep beginning */ 419 char *col = strchr ( buffer, ':');374 char *col = strchr(buffer, ':'); 420 375 char *dot = col; 421 376 422 if ( col) {377 if (col) { 423 378 /* This line is a dep description */ 424 c har *mods;379 const char *mods; 425 380 char *modpath; 426 381 char *mod; … … 428 383 /* Find the beginning of the module file name */ 429 384 *col = 0; 430 mods = strrchr ( buffer, '/' ); 431 432 if ( !mods ) 433 mods = buffer; /* no path for this module */ 434 else 435 mods++; /* there was a path for this module... */ 385 mods = bb_basename(buffer); 436 386 437 387 /* find the path of the module */ 438 modpath = strchr ( buffer, '/'); /* ... and this is the path */439 if ( !modpath)388 modpath = strchr(buffer, '/'); /* ... and this is the path */ 389 if (!modpath) 440 390 modpath = buffer; /* module with no path */ 441 391 /* find the end of the module name in the file name */ 442 if ( 443 (k_version > 4) && ( *(col-3) == '.') &&444 ( *(col-2) == 'k' ) && ( *(col-1) == 'o' ))392 if (ENABLE_FEATURE_2_6_MODULES && 393 (k_version > 4) && (*(col-3) == '.') && 394 (*(col-2) == 'k') && (*(col-1) == 'o')) 445 395 dot = col - 3; 446 396 else 447 if (( *(col-2) == '.' ) && ( *(col-1) == 'o'))397 if ((*(col-2) == '.') && (*(col-1) == 'o')) 448 398 dot = col - 2; 449 399 450 mod = bb_xstrndup ( mods, dot - mods);400 mod = xstrndup(mods, dot - mods); 451 401 452 402 /* enqueue new module */ 453 if ( !current ) { 454 first = current = (struct dep_t *) xmalloc ( sizeof ( struct dep_t )); 455 } 456 else { 457 current-> m_next = (struct dep_t *) xmalloc ( sizeof ( struct dep_t )); 458 current = current-> m_next; 459 } 460 current-> m_name = mod; 461 current-> m_path = bb_xstrdup(modpath); 462 current-> m_options = NULL; 463 current-> m_isalias = 0; 464 current-> m_depcnt = 0; 465 current-> m_deparr = 0; 466 current-> m_next = 0; 403 if (!current) { 404 first = current = xmalloc(sizeof(struct dep_t)); 405 } else { 406 current->m_next = xmalloc(sizeof(struct dep_t)); 407 current = current->m_next; 408 } 409 current->m_name = mod; 410 current->m_path = xstrdup(modpath); 411 current->m_options = NULL; 412 current->m_isalias = 0; 413 current->m_depcnt = 0; 414 current->m_deparr = 0; 415 current->m_next = 0; 467 416 468 417 p = col + 1; 469 } 470 else 418 } else 471 419 /* this line is not a dep description */ 472 420 p = 0; 473 } 474 else 421 } else 475 422 /* It's a dep description continuation */ 476 423 p = buffer; 477 424 478 while ( 425 while (p && *p && isblank(*p)) 479 426 p++; 480 427 481 428 /* p points to the first dependable module; if NULL, no dependable module */ 482 if ( p && *p) {483 char *end = &buffer 484 c har *deps;429 if (p && *p) { 430 char *end = &buffer[l-1]; 431 const char *deps; 485 432 char *dep; 486 433 char *next; 487 434 int ext = 0; 488 435 489 while ( isblank ( *end ) || ( *end == '\\'))436 while (isblank(*end) || (*end == '\\')) 490 437 end--; 491 438 492 do 493 { 439 do { 494 440 /* search the end of the dependency */ 495 next = strchr (p, ' ' ); 496 if (next) 497 { 441 next = strchr(p, ' '); 442 if (next) { 498 443 *next = 0; 499 444 next--; 500 } 501 else 445 } else 502 446 next = end; 503 447 504 448 /* find the beginning of the module file name */ 505 deps = strrchr ( p, '/' ); 506 507 if ( !deps || ( deps < p )) { 508 deps = p; 509 510 while ( isblank ( *deps )) 449 deps = bb_basename(p); 450 if (deps == p) { 451 while (isblank(*deps)) 511 452 deps++; 512 453 } 513 else514 deps++;515 454 516 455 /* find the end of the module name in the file name */ 517 if ( ENABLE_FEATURE_2_6_MODULES &&518 (k_version > 4) && ( *(next-2) == '.' ) &&519 ( *(next-1) == 'k' ) && ( *next == 'o' ))456 if (ENABLE_FEATURE_2_6_MODULES 457 && (k_version > 4) && (*(next-2) == '.') 458 && (*(next-1) == 'k') && (*next == 'o')) 520 459 ext = 3; 521 460 else 522 if (( *(next-1) == '.' ) && ( *next == 'o'))461 if ((*(next-1) == '.') && (*next == 'o')) 523 462 ext = 2; 524 463 … … 526 465 if ((next-deps-ext+1) <= 0) 527 466 continue; 528 dep = bb_xstrndup ( deps, next - deps - ext + 1);467 dep = xstrndup(deps, next - deps - ext + 1); 529 468 530 469 /* Add the new dependable module name */ 531 current-> 532 current-> m_deparr = (char **) xrealloc ( current->m_deparr,533 sizeof ( char *) * current-> m_depcnt);534 current-> m_deparr [current->m_depcnt - 1] = dep;470 current->m_depcnt++; 471 current->m_deparr = xrealloc(current->m_deparr, 472 sizeof(char *) * current->m_depcnt); 473 current->m_deparr[current->m_depcnt - 1] = dep; 535 474 536 475 p = next + 2; … … 539 478 540 479 /* is there other dependable module(s) ? */ 541 if ( buffer [l-1] == '\\')480 if (buffer[l-1] == '\\') 542 481 continuation_line = 1; 543 482 else 544 483 continuation_line = 0; 545 484 } 546 close ( fd);485 close(fd); 547 486 548 487 /* 549 488 * First parse system-specific options and aliases 550 489 * as they take precedence over the kernel ones. 490 * >=2.6: we only care about modprobe.conf 491 * <=2.4: we care about modules.conf and conf.modules 551 492 */ 552 if (!ENABLE_FEATURE_2_6_MODULES 553 || ( fd = open ( "/etc/modprobe.conf", O_RDONLY )) < 0 ) 554 if (( fd = open ( "/etc/modules.conf", O_RDONLY )) < 0 ) 555 fd = open ( "/etc/conf.modules", O_RDONLY ); 493 if (ENABLE_FEATURE_2_6_MODULES 494 && (fd = open("/etc/modprobe.conf", O_RDONLY)) < 0) 495 if (ENABLE_FEATURE_2_4_MODULES 496 && (fd = open("/etc/modules.conf", O_RDONLY)) < 0) 497 if (ENABLE_FEATURE_2_4_MODULES) 498 fd = open("/etc/conf.modules", O_RDONLY); 556 499 557 500 if (fd >= 0) { 558 include_conf 501 include_conf(&first, ¤t, buffer, sizeof(buffer), fd); 559 502 close(fd); 560 503 } … … 562 505 /* Only 2.6 has a modules.alias file */ 563 506 if (ENABLE_FEATURE_2_6_MODULES) { 564 /* Parse kernel-declared aliases */ 565 filename = bb_xasprintf("/lib/modules/%s/modules.alias", un.release); 566 if ((fd = open ( filename, O_RDONLY )) < 0) { 507 /* Parse kernel-declared module aliases */ 508 filename = xasprintf("/lib/modules/%s/modules.alias", un.release); 509 fd = open(filename, O_RDONLY); 510 if (fd < 0) { 567 511 /* Ok, that didn't work. Fall back to looking in /lib/modules */ 568 fd = open ( "/lib/modules/modules.alias", O_RDONLY);512 fd = open("/lib/modules/modules.alias", O_RDONLY); 569 513 } 570 514 if (ENABLE_FEATURE_CLEAN_UP) … … 572 516 573 517 if (fd >= 0) { 574 include_conf 518 include_conf(&first, ¤t, buffer, sizeof(buffer), fd); 575 519 close(fd); 576 520 } 521 522 /* Parse kernel-declared symbol aliases */ 523 filename = xasprintf("/lib/modules/%s/modules.symbols", un.release); 524 fd = open(filename, O_RDONLY); 525 if (fd < 0) { 526 /* Ok, that didn't work. Fall back to looking in /lib/modules */ 527 fd = open("/lib/modules/modules.symbols", O_RDONLY); 528 } 529 if (ENABLE_FEATURE_CLEAN_UP) 530 free(filename); 531 532 if (fd >= 0) { 533 include_conf(&first, ¤t, buffer, sizeof(buffer), fd); 534 close(fd); 535 } 577 536 } 578 537 … … 581 540 582 541 /* return 1 = loaded, 0 = not loaded, -1 = can't tell */ 583 static int already_loaded 542 static int already_loaded(const char *name) 584 543 { 585 544 int fd, ret = 0; 586 545 char buffer[4096]; 587 546 588 fd = open 547 fd = open("/proc/modules", O_RDONLY); 589 548 if (fd < 0) 590 549 return -1; 591 550 592 while ( reads ( fd, buffer, sizeof( buffer))) {551 while (reads(fd, buffer, sizeof(buffer))) { 593 552 char *p; 594 553 … … 621 580 } 622 581 623 static int mod_process ( struct mod_list_t *list, int do_insert)582 static int mod_process(const struct mod_list_t *list, int do_insert) 624 583 { 625 584 int rc = 0; … … 629 588 int argc; 630 589 631 while ( list) {590 while (list) { 632 591 argc = 0; 633 if ( ENABLE_FEATURE_CLEAN_UP)592 if (ENABLE_FEATURE_CLEAN_UP) 634 593 argc_malloc = 0; 635 594 /* If CONFIG_FEATURE_CLEAN_UP is not defined, then we leak memory … … 644 603 * problem. */ 645 604 /* enough for minimal insmod (5 args + NULL) or rmmod (3 args + NULL) */ 646 argv = (char**) malloc( 6 * sizeof( char* ));647 if ( do_insert) {648 if (already_loaded 649 argv[argc++] = "insmod";605 argv = xmalloc(6 * sizeof(char*)); 606 if (do_insert) { 607 if (already_loaded(list->m_name) != 1) { 608 argv[argc++] = (char*)"insmod"; 650 609 if (ENABLE_FEATURE_2_4_MODULES) { 651 610 if (do_syslog) 652 argv[argc++] = "-s";611 argv[argc++] = (char*)"-s"; 653 612 if (autoclean) 654 argv[argc++] = "-k";613 argv[argc++] = (char*)"-k"; 655 614 if (quiet) 656 argv[argc++] = "-q";657 else if (verbose) /* verbose and quiet are mutually exclusive */658 argv[argc++] = "-v";659 } 660 argv[argc++] = list-> 661 if ( ENABLE_FEATURE_CLEAN_UP)615 argv[argc++] = (char*)"-q"; 616 else if (verbose) /* verbose and quiet are mutually exclusive */ 617 argv[argc++] = (char*)"-v"; 618 } 619 argv[argc++] = list->m_path; 620 if (ENABLE_FEATURE_CLEAN_UP) 662 621 argc_malloc = argc; 663 opts = list-> 664 while ( opts) {622 opts = list->m_options; 623 while (opts) { 665 624 /* Add one more option */ 666 625 argc++; 667 argv = (char**) xrealloc( argv, ( argc + 1 ) * sizeof( char* ));668 argv[argc-1] = opts-> 669 opts = opts-> 626 argv = xrealloc(argv,(argc + 1)* sizeof(char*)); 627 argv[argc-1] = opts->m_opt_val; 628 opts = opts->m_next; 670 629 } 671 630 } 672 631 } else { 673 632 /* modutils uses short name for removal */ 674 if (already_loaded 675 argv[argc++] = "rmmod";633 if (already_loaded(list->m_name) != 0) { 634 argv[argc++] = (char*)"rmmod"; 676 635 if (do_syslog) 677 argv[argc++] = "-s";678 argv[argc++] = list->m_name;679 if ( ENABLE_FEATURE_CLEAN_UP)636 argv[argc++] = (char*)"-s"; 637 argv[argc++] = (char*)list->m_name; 638 if (ENABLE_FEATURE_CLEAN_UP) 680 639 argc_malloc = argc; 681 640 } … … 685 644 if (argc) { 686 645 if (verbose) { 687 printf("%s module %s\n", do_insert?"Loading":"Unloading", list-> m_name);646 printf("%s module %s\n", do_insert?"Loading":"Unloading", list->m_name); 688 647 } 689 648 if (!show_only) { 690 int rc2 = wait4pid( bb_spawn(argv));649 int rc2 = wait4pid(spawn(argv)); 691 650 692 651 if (do_insert) { 693 652 rc = rc2; /* only last module matters */ 694 } 695 else if (!rc2) { 653 } else if (!rc2) { 696 654 rc = 0; /* success if remove any mod */ 697 655 } 698 656 } 699 if ( ENABLE_FEATURE_CLEAN_UP )657 if (ENABLE_FEATURE_CLEAN_UP) { 700 658 /* the last value in the array has index == argc, but 701 659 * it is the terminating NULL, so we must not free it. */ 702 while( argc_malloc < argc ) { 703 free( argv[argc_malloc++] ); 704 } 705 } 706 if( ENABLE_FEATURE_CLEAN_UP ) { 707 free( argv ); 660 while (argc_malloc < argc) { 661 free(argv[argc_malloc++]); 662 } 663 } 664 } 665 if (ENABLE_FEATURE_CLEAN_UP) { 666 free(argv); 708 667 argv = NULL; 709 668 } 710 list = do_insert ? list-> m_prev : list->m_next;669 list = do_insert ? list->m_prev : list->m_next; 711 670 } 712 671 return (show_only) ? 0 : rc; 672 } 673 674 /* 675 * Check the matching between a pattern and a module name. 676 * We need this as *_* is equivalent to *-*, even in pattern matching. 677 */ 678 static int check_pattern(const char* pat_src, const char* mod_src) 679 { 680 int ret; 681 682 if (ENABLE_FEATURE_MODPROBE_FANCY_ALIAS) { 683 char* pat; 684 char* mod; 685 char* p; 686 687 pat = xstrdup(pat_src); 688 mod = xstrdup(mod_src); 689 690 for (p = pat; (p = strchr(p, '-')); *p++ = '_'); 691 for (p = mod; (p = strchr(p, '-')); *p++ = '_'); 692 693 ret = fnmatch(pat, mod, 0); 694 695 if (ENABLE_FEATURE_CLEAN_UP) { 696 free(pat); 697 free(mod); 698 } 699 700 return ret; 701 } else { 702 return fnmatch(pat_src, mod_src, 0); 703 } 713 704 } 714 705 … … 718 709 * tail: the lowest module in the stack (first to insmod, last to rmmod) 719 710 */ 720 static void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t **tail)711 static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **tail) 721 712 { 722 713 struct mod_list_t *find; … … 730 721 * Of course if the name in the dependency rule is a plain string, 731 722 * then we consider it a pattern, and matching will still work. */ 732 for ( dt = depend; dt; dt = dt-> m_next) {733 if ( fnmatch ( dt-> m_name, mod, 0) == 0) {723 for (dt = depend; dt; dt = dt->m_next) { 724 if (check_pattern(dt->m_name, mod) == 0) { 734 725 break; 735 726 } 736 727 } 737 728 738 if ( !dt) {739 bb_error_msg ("module %s not found.", mod);729 if (!dt) { 730 bb_error_msg("module %s not found", mod); 740 731 return; 741 732 } 742 733 743 734 // resolve alias names 744 while ( dt-> m_isalias) {745 if ( dt-> m_depcnt == 1) {735 while (dt->m_isalias) { 736 if (dt->m_depcnt == 1) { 746 737 struct dep_t *adt; 747 738 748 for ( adt = depend; adt; adt = adt-> m_next) {749 if ( strcmp ( adt-> m_name, dt-> m_deparr [0] ) == 0)739 for (adt = depend; adt; adt = adt->m_next) { 740 if (check_pattern(adt->m_name, dt->m_deparr[0]) == 0) 750 741 break; 751 742 } 752 if ( adt) {743 if (adt) { 753 744 /* This is the module we are aliased to */ 754 struct mod_opt_t *opts = dt-> 745 struct mod_opt_t *opts = dt->m_options; 755 746 /* Option of the alias are appended to the options of the module */ 756 while ( opts) {757 adt-> m_options = append_option( adt-> m_options, opts-> m_opt_val);758 opts = opts-> 747 while (opts) { 748 adt->m_options = append_option(adt->m_options, opts->m_opt_val); 749 opts = opts->m_next; 759 750 } 760 751 dt = adt; 761 } 762 else { 763 bb_error_msg ("module %s not found.", mod); 752 } else { 753 bb_error_msg("module %s not found", mod); 764 754 return; 765 755 } 766 } 767 else { 768 bb_error_msg ("Bad alias %s", dt-> m_name); 756 } else { 757 bb_error_msg("bad alias %s", dt->m_name); 769 758 return; 770 759 } 771 760 } 772 761 773 mod = dt-> 774 path = dt-> 775 opt = dt-> 762 mod = dt->m_name; 763 path = dt->m_path; 764 opt = dt->m_options; 776 765 777 766 // search for duplicates 778 for ( find = *head; find; find = find-> m_next) {779 if ( !strcmp ( mod, find-> m_name)) {780 // found -> 781 782 if ( find-> m_prev)783 find-> m_prev-> m_next = find->m_next;767 for (find = *head; find; find = find->m_next) { 768 if (!strcmp(mod, find->m_name)) { 769 // found ->dequeue it 770 771 if (find->m_prev) 772 find->m_prev->m_next = find->m_next; 784 773 else 785 *head = find-> 786 787 if ( find-> m_next)788 find-> m_next-> m_prev = find->m_prev;774 *head = find->m_next; 775 776 if (find->m_next) 777 find->m_next->m_prev = find->m_prev; 789 778 else 790 *tail = find-> 779 *tail = find->m_prev; 791 780 792 781 break; // there can be only one duplicate … … 794 783 } 795 784 796 if ( !find) { // did not find a duplicate797 find = (struct mod_list_t *) xmalloc (sizeof(struct mod_list_t));798 find-> 799 find-> 800 find-> 785 if (!find) { // did not find a duplicate 786 find = xmalloc(sizeof(struct mod_list_t)); 787 find->m_name = mod; 788 find->m_path = path; 789 find->m_options = opt; 801 790 } 802 791 803 792 // enqueue at tail 804 if ( *tail)805 (*tail)-> 806 find-> m_prev= *tail;807 find-> m_next= 0;808 809 if ( !*head)793 if (*tail) 794 (*tail)->m_next = find; 795 find->m_prev = *tail; 796 find->m_next = 0; 797 798 if (!*head) 810 799 *head = find; 811 800 *tail = find; 812 801 813 if ( dt) {802 if (dt) { 814 803 int i; 815 804 816 805 /* Add all dependable module for that new module */ 817 for ( i = 0; i < dt-> m_depcnt; i++)818 check_dep ( dt-> m_deparr [i], head, tail);819 } 820 } 821 822 static int mod_insert ( char *mod, int argc, char **argv)823 { 824 struct mod_list_t *tail = 0;825 struct mod_list_t *head = 0;806 for (i = 0; i < dt->m_depcnt; i++) 807 check_dep(dt->m_deparr[i], head, tail); 808 } 809 } 810 811 static int mod_insert(char *mod, int argc, char **argv) 812 { 813 struct mod_list_t *tail = NULL; 814 struct mod_list_t *head = NULL; 826 815 int rc; 827 816 828 817 // get dep list for module mod 829 check_dep ( mod, &head, &tail ); 830 831 if ( head && tail ) { 832 if( argc ) { 818 check_dep(mod, &head, &tail); 819 820 rc = 1; 821 if (head && tail) { 822 if (argc) { 833 823 int i; 834 824 // append module args 835 for ( i = 0; i < argc; i++)836 head->m_options = append_option( head->m_options, argv[i]);825 for (i = 0; i < argc; i++) 826 head->m_options = append_option(head->m_options, argv[i]); 837 827 } 838 828 839 829 // process tail ---> head 840 if ((rc = mod_process ( tail, 1 )) != 0) { 830 rc = mod_process(tail, 1); 831 if (rc) { 841 832 /* 842 833 * In case of using udev, multiple instances of modprobe can be … … 845 836 * fail if the module was loaded, and not by us. 846 837 */ 847 if (already_loaded (mod))838 if (already_loaded(mod)) 848 839 rc = 0; 849 840 } 850 841 } 851 else852 rc = 1;853 854 842 return rc; 855 843 } 856 844 857 static int mod_remove ( char *mod)845 static int mod_remove(char *mod) 858 846 { 859 847 int rc; 860 static struct mod_list_t rm_a_dummy = { "-a", NULL, NULL, NULL, NULL };861 862 struct mod_list_t *head = 0;863 struct mod_list_t *tail = 0;864 865 if ( mod)866 check_dep ( mod, &head, &tail);848 static const struct mod_list_t rm_a_dummy = { "-a", NULL, NULL, NULL, NULL }; 849 850 struct mod_list_t *head = NULL; 851 struct mod_list_t *tail = NULL; 852 853 if (mod) 854 check_dep(mod, &head, &tail); 867 855 else // autoclean 868 head = tail = &rm_a_dummy; 869 870 if ( head && tail ) 871 rc = mod_process ( head, 0 ); // process head ---> tail 872 else 873 rc = 1; 856 head = tail = (struct mod_list_t*) &rm_a_dummy; 857 858 rc = 1; 859 if (head && tail) 860 rc = mod_process(head, 0); // process head ---> tail 874 861 return rc; 875 876 } 877 862 } 863 864 int modprobe_main(int argc, char** argv); 878 865 int modprobe_main(int argc, char** argv) 879 866 { … … 881 868 char *unused; 882 869 883 bb_opt_complementally = "?V-:q-v:v-q";884 main_opts = bb_getopt_ulflags(argc,argv, "acdklnqrst:vVC:",870 opt_complementary = "?V-:q-v:v-q"; 871 main_opts = getopt32(argv, "acdklnqrst:vVC:", 885 872 &unused, &unused); 886 if ((main_opts & (DUMP_CONF_EXIT | LIST_ALL)))887 888 if ((main_opts & (RESTRICT_DIR | CONFIG_FILE)))889 890 891 depend = build_dep ();892 893 if ( !depend)894 bb_error_msg_and_die ( "could not parse modules.dep");873 if (main_opts & (DUMP_CONF_EXIT | LIST_ALL)) 874 return EXIT_SUCCESS; 875 if (main_opts & (RESTRICT_DIR | CONFIG_FILE)) 876 bb_error_msg_and_die("-t and -C not supported"); 877 878 depend = build_dep(); 879 880 if (!depend) 881 bb_error_msg_and_die("cannot parse modules.dep"); 895 882 896 883 if (remove_opt) { 897 884 do { 898 if (mod_remove (optind < argc ?899 argv [optind] : NULL)) {900 bb_error_msg 901 argv [optind]);885 if (mod_remove(optind < argc ? 886 argv[optind] : NULL)) { 887 bb_error_msg("failed to remove module %s", 888 argv[optind]); 902 889 rc = EXIT_FAILURE; 903 890 } 904 } while ( ++optind < argc);891 } while (++optind < argc); 905 892 } else { 906 893 if (optind >= argc) 907 bb_error_msg_and_die ( "No module or pattern provided");908 909 if ( mod_insert ( argv [optind], argc - optind - 1, argv + optind + 1))910 bb_error_msg_and_die ( "failed to load module %s", argv [optind]);894 bb_error_msg_and_die("no module or pattern provided"); 895 896 if (mod_insert(argv[optind], argc - optind - 1, argv + optind + 1)) 897 bb_error_msg_and_die("failed to load module %s", argv[optind]); 911 898 } 912 899
Note:
See TracChangeset
for help on using the changeset viewer.