Exemplo n.º 1
0
/*
 * This function builds a list of dependency rules from /lib/modules/`uname -r`\modules.dep.
 * It then fills every modules and aliases with their default options, found by parsing
 * modprobe.conf (or modules.conf, or conf.modules).
 */
static struct dep_t *build_dep ( void )
{
	int fd;
	struct utsname un;
	struct dep_t *first = 0;
	struct dep_t *current = 0;
	char buffer[2048];
	char *filename;
	int continuation_line = 0;
	int k_version;

	k_version = 0;
	if ( uname ( &un ))
		bb_error_msg_and_die("can't determine kernel version");

	if (un.release[0] == '2') {
		k_version = un.release[2] - '0';
	}

	filename = bb_xasprintf("/lib/modules/%s/modules.dep", un.release );
	fd = open ( filename, O_RDONLY );
	if (ENABLE_FEATURE_CLEAN_UP)
		free(filename);
	if (fd < 0) {
		/* Ok, that didn't work.  Fall back to looking in /lib/modules */
		if (( fd = open ( "/lib/modules/modules.dep", O_RDONLY )) < 0 ) {
			return 0;
		}
	}

	while ( reads ( fd, buffer, sizeof( buffer ))) {
		int l = strlen ( buffer );
		char *p = 0;

		while ( l > 0 && isspace ( buffer [l-1] )) {
			buffer [l-1] = 0;
			l--;
		}

		if ( l == 0 ) {
			continuation_line = 0;
			continue;
		}

		/* Is this a new module dep description? */
		if ( !continuation_line ) {
			/* find the dep beginning */
			char *col = strchr ( buffer, ':' );
			char *dot = col;

			if ( col ) {
				/* This line is a dep description */
				char *mods;
				char *modpath;
				char *mod;

				/* Find the beginning of the module file name */
				*col = 0;
				mods = strrchr ( buffer, '/' );

				if ( !mods )
					mods = buffer; /* no path for this module */
				else
					mods++; /* there was a path for this module... */

				/* find the path of the module */
				modpath = strchr ( buffer, '/' ); /* ... and this is the path */
				if ( !modpath )
					modpath = buffer; /* module with no path */
				/* find the end of the module name in the file name */
				if ( ENABLE_FEATURE_2_6_MODULES &&
				     (k_version > 4) && ( *(col-3) == '.' ) &&
				     ( *(col-2) == 'k' ) && ( *(col-1) == 'o' ) )
					dot = col - 3;
				else
					if (( *(col-2) == '.' ) && ( *(col-1) == 'o' ))
						dot = col - 2;

				mod = bb_xstrndup ( mods, dot - mods );

				/* enqueue new module */
				if ( !current ) {
					first = current = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
				}
				else {
					current-> m_next = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
					current = current-> m_next;
				}
				current-> m_name  = mod;
				current-> m_path  = bb_xstrdup(modpath);
				current-> m_options = NULL;
				current-> m_isalias = 0;
				current-> m_depcnt  = 0;
				current-> m_deparr  = 0;
				current-> m_next    = 0;

				p = col + 1;
			}
			else
				/* this line is not a dep description */
				p = 0;
		}
		else
			/* It's a dep description continuation */
			p = buffer;

		while ( p && *p && isblank(*p))
			p++;

		/* p points to the first dependable module; if NULL, no dependable module */
		if ( p && *p ) {
			char *end = &buffer [l-1];
			char *deps;
			char *dep;
			char *next;
			int ext = 0;

			while ( isblank ( *end ) || ( *end == '\\' ))
				end--;

			do
			{
				/* search the end of the dependency */
				next = strchr (p, ' ' );
				if (next)
				{
					*next = 0;
					next--;
				}
				else
					next = end;

				/* find the beginning of the module file name */
				deps = strrchr ( p, '/' );

				if ( !deps || ( deps < p )) {
					deps = p;

					while ( isblank ( *deps ))
						deps++;
				}
				else
					deps++;

				/* find the end of the module name in the file name */
				if ( ENABLE_FEATURE_2_6_MODULES &&
				     (k_version > 4) && ( *(next-2) == '.' ) &&
				     ( *(next-1) == 'k' )  && ( *next == 'o' ) )
					ext = 3;
				else
					if (( *(next-1) == '.' ) && ( *next == 'o' ))
						ext = 2;

				/* Cope with blank lines */
				if ((next-deps-ext+1) <= 0)
					continue;
				dep = bb_xstrndup ( deps, next - deps - ext + 1 );

				/* Add the new dependable module name */
				current-> m_depcnt++;
				current-> m_deparr = (char **) xrealloc ( current-> m_deparr,
						sizeof ( char *) * current-> m_depcnt );
				current-> m_deparr [current-> m_depcnt - 1] = dep;

				p = next + 2;
			} while (next < end);
		}

		/* is there other dependable module(s) ? */
		if ( buffer [l-1] == '\\' )
			continuation_line = 1;
		else
			continuation_line = 0;
	}
	close ( fd );

	/*
	 * First parse system-specific options and aliases
	 * as they take precedence over the kernel ones.
	 */
	if (!ENABLE_FEATURE_2_6_MODULES
			|| ( fd = open ( "/etc/modprobe.conf", O_RDONLY )) < 0 )
		if (( fd = open ( "/etc/modules.conf", O_RDONLY )) < 0 )
			fd = open ( "/etc/conf.modules", O_RDONLY );

	if (fd >= 0) {
		include_conf (&first, &current, buffer, sizeof(buffer), fd);
		close(fd);
	}

	/* Only 2.6 has a modules.alias file */
	if (ENABLE_FEATURE_2_6_MODULES) {
		/* Parse kernel-declared aliases */
		filename = bb_xasprintf("/lib/modules/%s/modules.alias", un.release);
		if ((fd = open ( filename, O_RDONLY )) < 0) {
			/* Ok, that didn't work.  Fall back to looking in /lib/modules */
			fd = open ( "/lib/modules/modules.alias", O_RDONLY );
		}
		if (ENABLE_FEATURE_CLEAN_UP)
			free(filename);

		if (fd >= 0) {
			include_conf (&first, &current, buffer, sizeof(buffer), fd);
			close(fd);
		}
	}

	return first;
}
Exemplo n.º 2
0
/*
 * This function builds a list of dependency rules from /lib/modules/`uname -r`/modules.dep.
 * It then fills every modules and aliases with their default options, found by parsing
 * modprobe.conf (or modules.conf, or conf.modules).
 */
static struct dep_t *build_dep(void)
{
	int fd;
	struct utsname un;
	struct dep_t *first = NULL;
	struct dep_t *current = NULL;
	char *filename;
	int continuation_line = 0;
	int k_version;

	if (uname(&un))
		bb_error_msg_and_die("can't determine kernel version");

	k_version = 0;
	if (un.release[0] == '2') {
		k_version = un.release[2] - '0';
	}

	filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/"CONFIG_DEFAULT_DEPMOD_FILE, un.release);
	fd = open(filename, O_RDONLY);
	if (ENABLE_FEATURE_CLEAN_UP)
		free(filename);
	if (fd < 0) {
		/* Ok, that didn't work.  Fall back to looking in /lib/modules */
		fd = open(CONFIG_DEFAULT_MODULES_DIR"/"CONFIG_DEFAULT_DEPMOD_FILE, O_RDONLY);
		if (fd < 0) {
			bb_error_msg_and_die("cannot parse " CONFIG_DEFAULT_DEPMOD_FILE);
		}
	}

	while (reads(fd, line_buffer, sizeof(line_buffer))) {
		int l = strlen(line_buffer);
		char *p = 0;

		while (l > 0 && isspace(line_buffer[l-1])) {
			line_buffer[l-1] = '\0';
			l--;
		}

		if (l == 0) {
			continuation_line = 0;
			continue;
		}

		/* Is this a new module dep description? */
		if (!continuation_line) {
			/* find the dep beginning */
			char *col = strchr(line_buffer, ':');
			char *dot = col;

			if (col) {
				/* This line is a dep description */
				const char *mods;
				char *modpath;
				char *mod;

				/* Find the beginning of the module file name */
				*col = '\0';
				mods = bb_basename(line_buffer);

				/* find the path of the module */
				modpath = strchr(line_buffer, '/'); /* ... and this is the path */
				if (!modpath)
					modpath = line_buffer; /* module with no path */
				/* find the end of the module name in the file name */
				if (ENABLE_FEATURE_2_6_MODULES &&
				    (k_version > 4) && (col[-3] == '.') &&
				    (col[-2] == 'k') && (col[-1] == 'o'))
					dot = col - 3;
				else if ((col[-2] == '.') && (col[-1] == 'o'))
					dot = col - 2;

				mod = xstrndup(mods, dot - mods);

				/* enqueue new module */
				if (!current) {
					first = current = xzalloc(sizeof(struct dep_t));
				} else {
					current->m_next = xzalloc(sizeof(struct dep_t));
					current = current->m_next;
				}
				current->m_name = mod;
				current->m_path = xstrdup(modpath);
				/*current->m_options = NULL; - xzalloc did it*/
				/*current->m_isalias = 0;*/
				/*current->m_depcnt = 0;*/
				/*current->m_deparr = 0;*/
				/*current->m_next = 0;*/

				p = col + 1;
			} else
				/* this line is not a dep description */
				p = NULL;
		} else
			/* It's a dep description continuation */
			p = line_buffer;

		/* p points to the first dependable module; if NULL, no dependable module */
		if (p && (p = skip_whitespace(p))[0] != '\0') {
			char *end = &line_buffer[l-1];
			const char *deps;
			char *dep;
			char *next;
			int ext = 0;

			while (isblank(*end) || (*end == '\\'))
				end--;

			do {
				/* search the end of the dependency */
				next = strchr(p, ' ');
				if (next) {
					*next = '\0';
					next--;
				} else
					next = end;

				/* find the beginning of the module file name */
				deps = bb_basename(p);
				if (deps == p)
					deps = skip_whitespace(deps);

				/* find the end of the module name in the file name */
				if (ENABLE_FEATURE_2_6_MODULES
				 && (k_version > 4) && (next[-2] == '.')
				 && (next[-1] == 'k') && (next[0] == 'o'))
					ext = 3;
				else if ((next[-1] == '.') && (next[0] == 'o'))
					ext = 2;

				/* Cope with blank lines */
				if ((next-deps-ext+1) <= 0)
					continue;
				dep = xstrndup(deps, next - deps - ext + 1);

				/* Add the new dependable module name */
				current->m_depcnt++;
				current->m_deparr = xrealloc(current->m_deparr,
						sizeof(char *) * current->m_depcnt);
				current->m_deparr[current->m_depcnt - 1] = dep;

				p = next + 2;
			} while (next < end);
		}

		/* is there other dependable module(s) ? */
		continuation_line = (line_buffer[l-1] == '\\');
	} /* while (reads(...)) */
	close(fd);

	/*
	 * First parse system-specific options and aliases
	 * as they take precedence over the kernel ones.
	 * >=2.6: we only care about modprobe.conf
	 * <=2.4: we care about modules.conf and conf.modules
	 */
	if (ENABLE_FEATURE_2_6_MODULES
	 && (fd = open("/etc/modprobe.conf", O_RDONLY)) < 0)
		if (ENABLE_FEATURE_2_4_MODULES
		 && (fd = open("/etc/modules.conf", O_RDONLY)) < 0)
			if (ENABLE_FEATURE_2_4_MODULES)
				fd = open("/etc/conf.modules", O_RDONLY);

	if (fd >= 0) {
		include_conf(&first, &current, line_buffer, sizeof(line_buffer), fd);
		close(fd);
	}

	/* Only 2.6 has a modules.alias file */
	if (ENABLE_FEATURE_2_6_MODULES) {
		/* Parse kernel-declared module aliases */
		filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/modules.alias", un.release);
		fd = open(filename, O_RDONLY);
		if (fd < 0) {
			/* Ok, that didn't work.  Fall back to looking in /lib/modules */
			fd = open(CONFIG_DEFAULT_MODULES_DIR"/modules.alias", O_RDONLY);
		}
		if (ENABLE_FEATURE_CLEAN_UP)
			free(filename);

		if (fd >= 0) {
			include_conf(&first, &current, line_buffer, sizeof(line_buffer), fd);
			close(fd);
		}

		/* Parse kernel-declared symbol aliases */
		filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/modules.symbols", un.release);
		fd = open(filename, O_RDONLY);
		if (fd < 0) {
			/* Ok, that didn't work.  Fall back to looking in /lib/modules */
			fd = open(CONFIG_DEFAULT_MODULES_DIR"/modules.symbols", O_RDONLY);
		}
		if (ENABLE_FEATURE_CLEAN_UP)
			free(filename);

		if (fd >= 0) {
			include_conf(&first, &current, line_buffer, sizeof(line_buffer), fd);
			close(fd);
		}
	}

	return first;
}
Exemplo n.º 3
0
/*
 * This function reads aliases and default module options from a configuration file
 * (/etc/modprobe.conf syntax). It supports includes (only files, no directories).
 */
static void include_conf ( struct dep_t **first, struct dep_t **current, char *buffer, int buflen, int fd )
{
	int continuation_line = 0;

	// alias parsing is not 100% correct (no correct handling of continuation lines within an alias) !

	while ( reads ( fd, buffer, buflen)) {
		int l;
		char *p;

		p = strchr ( buffer, '#' );
		if ( p )
			*p = 0;

		l = strlen ( buffer );

		while ( l && isspace ( buffer [l-1] )) {
			buffer [l-1] = 0;
			l--;
		}

		if ( l == 0 ) {
			continuation_line = 0;
			continue;
		}

		if ( !continuation_line ) {
			if (( strncmp ( buffer, "alias", 5 ) == 0 ) && isspace ( buffer [5] )) {
				char *alias, *mod;

				if ( parse_tag_value ( buffer + 6, &alias, &mod )) {
					/* handle alias as a module dependent on the aliased module */
					if ( !*current ) {
						(*first) = (*current) = (struct dep_t *) xcalloc ( 1, sizeof ( struct dep_t ));
					}
					else {
						(*current)-> m_next = (struct dep_t *) xcalloc ( 1, sizeof ( struct dep_t ));
						(*current) = (*current)-> m_next;
					}
					(*current)-> m_name  = bb_xstrdup ( alias );
					(*current)-> m_isalias = 1;

					if (( strcmp ( mod, "off" ) == 0 ) || ( strcmp ( mod, "null" ) == 0 )) {
						(*current)-> m_depcnt = 0;
						(*current)-> m_deparr = 0;
					}
					else {
						(*current)-> m_depcnt  = 1;
						(*current)-> m_deparr  = xmalloc ( 1 * sizeof( char * ));
						(*current)-> m_deparr[0] = bb_xstrdup ( mod );
					}
					(*current)-> m_next    = 0;
				}
			}
			else if (( strncmp ( buffer, "options", 7 ) == 0 ) && isspace ( buffer [7] )) {
				char *mod, *opt;

				/* split the line in the module/alias name, and options */
				if ( parse_tag_value ( buffer + 8, &mod, &opt )) {
					struct dep_t *dt;

					/* find the corresponding module */
					for ( dt = *first; dt; dt = dt-> m_next ) {
						if ( strcmp ( dt-> m_name, mod ) == 0 )
							break;
					}
					if ( dt ) {
						if ( ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS ) {
							char* new_opt = NULL;
							while( ( opt = parse_command_string( opt, &new_opt ) ) ) {
								dt-> m_options = append_option( dt-> m_options, new_opt );
							}
						} else {
							dt-> m_options = append_option( dt-> m_options, opt );
						}
					}
				}
			}
			else if (( strncmp ( buffer, "include", 7 ) == 0 ) && isspace ( buffer [7] )) {

				int fdi; char *filename = buffer + 8;

				while ( isspace ( *filename ))
					filename++;

				if (( fdi = open ( filename, O_RDONLY )) >= 0 ) {
					include_conf(first, current, buffer, buflen, fdi);
					close(fdi);
				}
			}
		}
	}
}
Exemplo n.º 4
0
/*
 * This function reads aliases and default module options from a configuration file
 * (/etc/modprobe.conf syntax). It supports includes (only files, no directories).
 */
static void include_conf(struct dep_t **first, struct dep_t **current, char *buffer, int buflen, int fd)
{
	int continuation_line = 0;

	// alias parsing is not 100% correct (no correct handling of continuation lines within an alias)!

	while (reads(fd, buffer, buflen)) {
		int l;

		*strchrnul(buffer, '#') = '\0';

		l = strlen(buffer);

		while (l && isspace(buffer[l-1])) {
			buffer[l-1] = '\0';
			l--;
		}

		if (l == 0) {
			continuation_line = 0;
			continue;
		}

		if (continuation_line)
			continue;

		if (is_conf_command(buffer, "alias")) {
			char *alias, *mod;

			if (parse_tag_value(buffer + 6, &alias, &mod)) {
				/* handle alias as a module dependent on the aliased module */
				if (!*current) {
					(*first) = (*current) = xzalloc(sizeof(struct dep_t));
				} else {
					(*current)->m_next = xzalloc(sizeof(struct dep_t));
					(*current) = (*current)->m_next;
				}
				(*current)->m_name = xstrdup(alias);
				(*current)->m_isalias = 1;

				if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) {
					/*(*current)->m_depcnt = 0; - done by xzalloc */
					/*(*current)->m_deparr = 0;*/
				} else {
					(*current)->m_depcnt = 1;
					(*current)->m_deparr = xmalloc(sizeof(char *));
					(*current)->m_deparr[0] = xstrdup(mod);
				}
				/*(*current)->m_next = NULL; - done by xzalloc */
			}
		} else if (is_conf_command(buffer, "options")) {
			char *mod, *opt;

			/* split the line in the module/alias name, and options */
			if (parse_tag_value(buffer + 8, &mod, &opt)) {
				struct dep_t *dt;

				/* find the corresponding module */
				for (dt = *first; dt; dt = dt->m_next) {
					if (strcmp(dt->m_name, mod) == 0)
						break;
				}
				if (dt) {
					if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) {
						char* new_opt = NULL;
						while ((opt = parse_command_string(opt, &new_opt))) {
							dt->m_options = append_option(dt->m_options, new_opt);
						}
					} else {
						dt->m_options = append_option(dt->m_options, opt);
					}
				}
			}
		} else if (is_conf_command(buffer, "include")) {
			int fdi;
			char *filename;

			filename = skip_whitespace(buffer + 8);
			fdi = open(filename, O_RDONLY);
			if (fdi >= 0) {
				include_conf(first, current, buffer, buflen, fdi);
				close(fdi);
			}
		} else if (ENABLE_FEATURE_MODPROBE_BLACKLIST &&
				(is_conf_command(buffer, "blacklist"))) {
			char *mod;
			struct dep_t *dt;

			mod = skip_whitespace(buffer + 10);
			for (dt = *first; dt; dt = dt->m_next) {
				if (strcmp(dt->m_name, mod) == 0)
					break;
			}
			if (dt)
				dt->m_isblacklisted = 1;
		}
	} /* while (reads(...)) */
}