modprobe-small: add depfile creation
This commit is contained in:
parent
784369987f
commit
7f950a93ff
@ -43,6 +43,7 @@ typedef struct module_info {
|
||||
struct globals {
|
||||
module_info *modinfo;
|
||||
char *module_load_options;
|
||||
smallint dep_bb_seen;
|
||||
int module_count;
|
||||
int module_found_idx;
|
||||
int stringbuf_idx;
|
||||
@ -51,6 +52,7 @@ struct globals {
|
||||
};
|
||||
#define G (*ptr_to_globals)
|
||||
#define modinfo (G.modinfo )
|
||||
#define dep_bb_seen (G.dep_bb_seen )
|
||||
#define module_count (G.module_count )
|
||||
#define module_found_idx (G.module_found_idx )
|
||||
#define module_load_options (G.module_load_options)
|
||||
@ -320,13 +322,28 @@ static FAST_FUNC int fileAction(const char *pathname,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void load_dep_bb(void)
|
||||
static int load_dep_bb(void)
|
||||
{
|
||||
char *line;
|
||||
FILE *fp = fopen(DEPFILE_BB, "r");
|
||||
|
||||
if (!fp)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
dep_bb_seen = 1;
|
||||
dbg1_error_msg("loading "DEPFILE_BB);
|
||||
|
||||
/* Why? There is a rare scenario: we did not find modprobe.dep.bb,
|
||||
* we scanned the dir and found no module by name, then we search
|
||||
* for alias (full scan), and we decided to generate modprobe.dep.bb.
|
||||
* But we see modprobe.dep.bb.new! Other modprobe is at work!
|
||||
* We wait and other modprobe renames it to modprobe.dep.bb.
|
||||
* Now we can use it.
|
||||
* But we already have modinfo[] filled, and "module_count = 0"
|
||||
* makes us start anew. Yes, we leak modinfo[].xxx pointers -
|
||||
* there is not much of data there anyway. */
|
||||
module_count = 0;
|
||||
memset(&modinfo[0], 0, sizeof(modinfo[0]));
|
||||
|
||||
while ((line = xmalloc_fgetline(fp)) != NULL) {
|
||||
char* space;
|
||||
@ -355,13 +372,74 @@ static void load_dep_bb(void)
|
||||
free(line);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int start_dep_bb_writeout(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(DEPFILE_BB".new", O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0644);
|
||||
if (fd < 0) {
|
||||
if (errno == EEXIST) {
|
||||
int count = 5 * 20;
|
||||
dbg1_error_msg(DEPFILE_BB".new exists, waiting for "DEPFILE_BB);
|
||||
while (1) {
|
||||
usleep(1000*1000 / 20);
|
||||
if (load_dep_bb()) {
|
||||
dbg1_error_msg(DEPFILE_BB" appeared");
|
||||
return -2; /* magic number */
|
||||
}
|
||||
if (!--count)
|
||||
break;
|
||||
}
|
||||
bb_error_msg("deleting stale %s", DEPFILE_BB".new");
|
||||
fd = open_or_warn(DEPFILE_BB".new", O_WRONLY | O_CREAT | O_TRUNC);
|
||||
}
|
||||
}
|
||||
dbg1_error_msg("opened "DEPFILE_BB".new:%d", fd);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void write_out_dep_bb(int fd)
|
||||
{
|
||||
int i;
|
||||
FILE *fp;
|
||||
|
||||
/* We want good error reporting. fdprintf is not good enough. */
|
||||
fp = fdopen(fd, "w");
|
||||
if (!fp) {
|
||||
close(fd);
|
||||
goto err;
|
||||
}
|
||||
i = 0;
|
||||
while (modinfo[i].pathname) {
|
||||
fprintf(fp, "%s%s%s\n" "%s%s\n",
|
||||
modinfo[i].pathname, modinfo[i].aliases[0] ? " " : "", modinfo[i].aliases,
|
||||
modinfo[i].deps, modinfo[i].deps[0] ? "\n" : "");
|
||||
i++;
|
||||
}
|
||||
/* Badly formatted depfile is a no-no. Be paranoid. */
|
||||
errno = 0;
|
||||
if (ferror(fp) | fclose(fp))
|
||||
goto err;
|
||||
if (rename(DEPFILE_BB".new", DEPFILE_BB) != 0) {
|
||||
err:
|
||||
bb_perror_msg("can't create %s", DEPFILE_BB);
|
||||
unlink(DEPFILE_BB".new");
|
||||
} else {
|
||||
dbg1_error_msg("created "DEPFILE_BB);
|
||||
}
|
||||
}
|
||||
|
||||
static module_info* find_alias(const char *alias)
|
||||
{
|
||||
int i;
|
||||
int dep_bb_fd;
|
||||
module_info *result;
|
||||
dbg1_error_msg("find_alias('%s')", alias);
|
||||
|
||||
try_again:
|
||||
/* First try to find by name (cheaper) */
|
||||
i = 0;
|
||||
while (modinfo[i].pathname) {
|
||||
@ -376,13 +454,22 @@ static module_info* find_alias(const char *alias)
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Ok, we definitely have to scan module bodies. This is a good
|
||||
* moment to generate modprobe.dep.bb, if it does not exist yet */
|
||||
dep_bb_fd = dep_bb_seen ? -1 : start_dep_bb_writeout();
|
||||
if (dep_bb_fd == -2) /* modprobe.dep.bb appeared? */
|
||||
goto try_again;
|
||||
|
||||
/* Scan all module bodies, extract modinfo (it contains aliases) */
|
||||
i = 0;
|
||||
result = NULL;
|
||||
while (modinfo[i].pathname) {
|
||||
char *desc, *s;
|
||||
if (!modinfo[i].aliases) {
|
||||
parse_module(&modinfo[i], modinfo[i].pathname);
|
||||
}
|
||||
if (result)
|
||||
continue;
|
||||
/* "alias1 symbol:sym1 alias2 symbol:sym2" */
|
||||
desc = str_2_list(modinfo[i].aliases);
|
||||
/* Does matching substring exist? */
|
||||
@ -392,17 +479,25 @@ static module_info* find_alias(const char *alias)
|
||||
* "pci:v000010DEd000000D9sv*sd*bc*sc*i*".
|
||||
* Plain strcmp() won't catch that */
|
||||
if (fnmatch(s, alias, 0) == 0) {
|
||||
free(desc);
|
||||
dbg1_error_msg("found alias '%s' in module '%s'",
|
||||
alias, modinfo[i].pathname);
|
||||
return &modinfo[i];
|
||||
result = &modinfo[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(desc);
|
||||
if (result && dep_bb_fd < 0)
|
||||
return result;
|
||||
i++;
|
||||
}
|
||||
dbg1_error_msg("find_alias '%s' returns NULL", alias);
|
||||
return NULL;
|
||||
|
||||
/* Create module.dep.bb if needed */
|
||||
if (dep_bb_fd >= 0) {
|
||||
write_out_dep_bb(dep_bb_fd);
|
||||
}
|
||||
|
||||
dbg1_error_msg("find_alias '%s' returns %p", alias, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if ENABLE_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
|
||||
@ -497,7 +592,7 @@ static void process_module(char *name, const char *cmdline_options)
|
||||
|
||||
/* rmmod? unload it by name */
|
||||
if (is_rmmod) {
|
||||
if (delete_module(name, O_NONBLOCK|O_EXCL) != 0
|
||||
if (delete_module(name, O_NONBLOCK | O_EXCL) != 0
|
||||
&& !(option_mask32 & OPT_q)
|
||||
) {
|
||||
bb_perror_msg("remove '%s'", name);
|
||||
@ -511,6 +606,8 @@ static void process_module(char *name, const char *cmdline_options)
|
||||
}
|
||||
|
||||
if (!info) { /* both dirscan and find_alias found nothing */
|
||||
bb_error_msg("module '%s' not found", name);
|
||||
//TODO: _and_die()?
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -637,6 +734,10 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
|
||||
argv[1] = NULL;
|
||||
#endif
|
||||
|
||||
/* Prevent ugly corner cases with no modules at all */
|
||||
modinfo = xzalloc(sizeof(modinfo[0]));
|
||||
|
||||
/* Try to load modprobe.dep.bb */
|
||||
load_dep_bb();
|
||||
|
||||
/* Load/remove modules.
|
||||
|
Loading…
Reference in New Issue
Block a user