Re: [Toybox] [New Toy] - modprobe
On Thu, Dec 19, 2013 at 11:28:17AM +0530, Ashwini Sharma wrote: > Hi, > > comments inline... > > attached is the modified file. > this also includes the fix for alias loading. There was an error in > modprobe_main(). > > llist_pop() returns the struct ag_list*, whereas this was assigned to > char*, which is modified > as below. > > char *real = ((struct arg_list*)llist_pop(&module->rnames))->arg; > struct module_s *m2 = get_mod(real, 0); > > regards, > Ashwini Looks good for a first version. And yes, it fixes alias loading. Thanks, Isaac Dunham ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] [New Toy] - modprobe
On Tue, Dec 17, 2013 at 04:39:39PM +0530, Ashwini Sharma wrote: > Hi List, > > An implementation for modprobe is attached. > go thru the same and let me know your inputs. > > regards, > Ashwini It doesn't quite work. Specifically, when I try loading by alias: modprobe -v $ALIAS I get the message: "probing $ALIAS by realname" Which indicates that no alias is matched; presumably this is because get_mod always returns NULL in this case. Using resolve_modalias, I can get the real module name and then load it manually. The source for resolve_modalias is attached. The only config files presemt are modules.alias, modules.dep, and modules.symbols. Thanks, Isaac Dunham > > /* > * Returns struct module_s from the data base if found, NULL otherwise. > * if ps - create module entry, add it to data base and return the same mod. > */ > static struct module_s *get_mod(char *mod, uint8_t ps) > { > char name[MODNAME_LEN]; > struct module_s *modentry; > struct arg_list *temp; > unsigned i, hash = 0; > > path2mod(mod, name); > for (i = 0; name[i]; i++) hash = ((hash*31) + hash) + name[i]; > hash %= DBASE_SIZE; > for (temp = TT.dbase[hash]; temp; temp = temp->next) { > modentry = (struct module_s *) temp->arg; > if (!strcmp(modentry->name, name)) return modentry; > } > if (!ps) return NULL; This line is the problem, but I'm not sure what's the right fix. > modentry = xzalloc(sizeof(*modentry)); > modentry->name = xstrdup(name); > llist_add(&TT.dbase[hash], modentry); > return modentry; > } > > /* > * Action to be taken on all config files in default directories > * checks for aliases, options, install, remove and blacklist > */ > static int config_action(struct dirtree *node) > { > FILE *fc; > char *filename, *tokens[3], *line, *linecp; > struct module_s *modent; > int tcount = 0; > > if (!dirtree_notdotdot(node)) return 0; > if (S_ISDIR(node->st.st_mode)) return DIRTREE_RECURSE; > > if (!S_ISREG(node->st.st_mode)) return 0; // process only regular file > filename = dirtree_path(node, NULL); > if (!(fc = fopen(filename, "r"))) { > free(filename); > return 0; > } > for (line = linecp = NULL; read_line(fc, &line) > 0; > free(line), free(linecp), line = linecp = NULL) { > char *tk = NULL; > > if (!strlen(line)) continue; > linecp = xstrdup(line); > for (tk = strtok(linecp, "# \t"), tcount = 0; tk; > tk = strtok(NULL, "# \t"), tcount++) { > tokens[tcount] = tk; > if (tcount == 2) { > tokens[2] = line + strlen(tokens[0]) + strlen(tokens[1]) + 2; > break; > } > } > if (!tk) continue; > // process the tokens[0] contains first word of config line. > if (!strcmp(tokens[0], "alias")) { > struct arg_list *temp; > char aliase[MODNAME_LEN], *realname; > > if (!tokens[2]) continue; > path2mod(tokens[1], aliase); > for (temp = TT.probes; temp; temp = temp->next) { > modent = (struct module_s *) temp->arg; > if (fnmatch(aliase, modent->name, 0)) continue; > realname = path2mod(tokens[2], NULL); > llist_add(&modent->rnames, realname); > if (modent->flags & MOD_NDDEPS) { > modent->flags &= ~MOD_NDDEPS; > TT.nudeps--; > } > modent = get_mod(realname, 1); > if (!(modent->flags & MOD_NDDEPS)) { > modent->flags |= MOD_NDDEPS; > TT.nudeps++; > } > } > } else if (!strcmp(tokens[0], "options")) { > if (!tokens[2]) continue; > modent = get_mod(tokens[1], 1); > modent->opts = add_opts(modent->opts, tokens[2]); > } else if (!strcmp(tokens[0], "include")) > dirtree_read(tokens[1], config_action); > else if (!strcmp(tokens[0], "blacklist")) > get_mod(tokens[1], 1)->flags |= MOD_BLACKLIST; > else if (!strcmp(tokens[0], "install")) continue; > else if (!strcmp(tokens[0], "remove")) continue; > else error_msg("Invalid option %s found in file %s", tokens[0], filename); > } > fclose(fc); > free(filename); > return 0; > } > > void modprobe_main(void) > { > struct utsname uts; > char **argv = toys.optargs, *procline = NULL; > FILE *fs; > struct module_s *module; > unsigned flags = toys.optflags; > > dbg = dummy; > if (flags & FLAG_v) dbg = xprintf; > > if ((toys.optc < 1) && (((flags & FLAG_r) && (flags & FLAG_l)) > ||(!((flags & FLAG_r)||(flags & FLAG_l) { > toys.exithelp++; > error_exit(" Syntex Error."); > } > // Check for -r flag without arg if yes then do auto remove. > if ((flags & FLAG_r) && (!toys.optc)) { > if (rm_mod(NULL, O_NONBLOCK | O_EXCL) != 0) perror_exit("rmmod"); > return; > } > > // change directory to /lib/modules// > xchdir("/lib/modules"); > uname(&uts); > xchdir(uts.release); > > // modules.dep processing for dependency check. > if (flags & FLAG_l) { > if (depmode_read_entry(to
Re: [Toybox] [New Toy] - modprobe
On Tue, Dec 17, 2013 at 04:39:39PM +0530, Ashwini Sharma wrote: > Hi List, > > An implementation for modprobe is attached. > go thru the same and let me know your inputs. > > regards, > Ashwini For comments see below. No big issues with style that I can see, except that it should be default n until Rob's looked over it. At 575 lines, it's largeish, but it seems reasonable to me... except perhaps for use of modules.dep: http://lists.landley.net/pipermail/toybox-landley.net/2013-August/001294.html http://lists.landley.net/pipermail/toybox-landley.net/2013-August/001297.html > /* modprobe.c - modprobe utility. > * > * Copyright 2012 Madhur Verma > * Copyright 2013 Kyungwan Han > * > * No Standard. > > USE_MODPROBE(NEWTOY(modprobe, "alrqvsDb", TOYFLAG_SBIN)) > > config MODPROBE > bool "modprobe" > default y > help > usage: modprobe [-alrqvsDb] MODULE [symbol=value][...] > > modprobe utility - inserts modules and dependencies. > > -a Load multiple MODULEs > -l List (MODULE is a pattern) > -r Remove MODULE (stacks) or do autoclean > -q Quiet > -v Verbose > -s Log to syslog > -D Show dependencies > -b Apply blacklist to module names too > */ > #define FOR_modprobe > #include "toys.h" > #include > #include > > GLOBALS( > struct arg_list *probes; > struct arg_list *dbase[256]; > char *cmdopts; > int nudeps; > uint8_t symreq; > ) > > /* Note: if "#define DBASE_SIZE" modified, > * Please update GLOBALS dbase[256] accordingly. > */ > #define DBASE_SIZE 256 > #define MODNAME_LEN 256 Any reason not to use sizeof(TT.dbase)? > > // Modules flag definations > #define MOD_ALOADED 0x0001 > #define MOD_BLACKLIST 0x0002 > #define MOD_FNDDEPMOD 0x0004 > #define MOD_NDDEPS0x0008 I can see using the macros, but I seem to remember Rob mentioning somewhere before that defining things just before you need them can clarify the code a little. That would mean moving them just above config_action(). > static void (*dbg)(char *format, ...); > // dummy interface for debugging. > static void dummy(char *format, ...) > { > } > > // Current probing modules info > struct module_s { > uint32_t flags; > char *cmdname, *name, *depent, *opts; > struct arg_list *rnames, *dep; > }; > > // Converts path name FILE to module name. > static char *path2mod(char *file, char *mod) > { > int i; > char *from, *lslash; > > if (!file) return NULL; > if (!mod) mod = xmalloc(MODNAME_LEN); > > lslash = strrchr(file, '/'); > if (!lslash || (lslash == file && !lslash[1])) from = file; > else from = lslash + 1; A home-made basename()? > for (i = 0; i < (MODNAME_LEN-1) && from[i] && from[i] != '.'; i++) > mod[i] = (from[i] == '-') ? '_' : from[i]; > mod[i] = '\0'; > return mod; > } I presume you are only using this part for display. modprobe dm_crypt or dm-crypt will load dm-crypt.ko modprobe micheal-mic or micheal_mic will load micheal_mic.ko Whatever you do, either gets displayed with an '_' > // locate character in string. > static char *strchr_nul(char *s, int c) > { > while(*s != '\0' && *s != c) s++; > return (char*)s; > } I'm guessing this is because strchrnul is a non-standard glibc extension? I don't know about uclibc or newlib (if the latter is relevant), but musl does include it. $ nm /opt/musl/lib/libc.a |grep strchrnul U __strchrnul U __strchrnul strchrnul.o: T __strchrnul W strchrnul U __strchrnul > // Add options in opts from toadd. > static char *add_opts(char *opts, char *toadd) > { > if (toadd) { > int optlen = 0; > > if (opts) optlen = strlen(opts); > opts = xrealloc(opts, optlen + strlen(toadd) + 2); > sprintf(opts + optlen, " %s", toadd); > } > return opts; > } > > // Remove first element from the list and return it. > static void *llist_popme(struct arg_list **head) > { > char *data = NULL; > struct arg_list *temp = *head; > > if (temp) { > data = temp->arg; > *head = temp->next; > free(temp); > } > return data; > } > > // Add new node at the beginning of the list. > static void llist_add(struct arg_list **old, void *data) > { > struct arg_list *new = xmalloc(sizeof(struct arg_list)); > > new->arg = (char*)data; > new->next = *old; > *old = new; > } > > // Add new node at tail of list. > static void llist_add_tail(struct arg_list **head, void *data) > { > while (*head) head = &(*head)->next; > *head = xzalloc(sizeof(struct arg_list)); > (*head)->arg = (char*)data; > } > > // Reverse list order. > static struct arg_list *llist_rev(struct arg_list *list) > { > struct arg_list *rev = NULL; > > while (list) { > struct arg_list *next = list->next; > > list->next = rev; > rev = list; > list = next; > } > return rev; > } > > /* > * Returns struct module_s from the data base if found, NULL otherwise. > * if ps - create module entry, ad
[Toybox] [New Toy] - modprobe
Hi List, An implementation for modprobe is attached. go thru the same and let me know your inputs. regards, Ashwini /* modprobe.c - modprobe utility. * * Copyright 2012 Madhur Verma * Copyright 2013 Kyungwan Han * * No Standard. USE_MODPROBE(NEWTOY(modprobe, "alrqvsDb", TOYFLAG_SBIN)) config MODPROBE bool "modprobe" default y help usage: modprobe [-alrqvsDb] MODULE [symbol=value][...] modprobe utility - inserts modules and dependencies. -a Load multiple MODULEs -l List (MODULE is a pattern) -r Remove MODULE (stacks) or do autoclean -q Quiet -v Verbose -s Log to syslog -D Show dependencies -b Apply blacklist to module names too */ #define FOR_modprobe #include "toys.h" #include #include GLOBALS( struct arg_list *probes; struct arg_list *dbase[256]; char *cmdopts; int nudeps; uint8_t symreq; ) /* Note: if "#define DBASE_SIZE" modified, * Please update GLOBALS dbase[256] accordingly. */ #define DBASE_SIZE 256 #define MODNAME_LEN 256 // Modules flag definations #define MOD_ALOADED 0x0001 #define MOD_BLACKLIST 0x0002 #define MOD_FNDDEPMOD 0x0004 #define MOD_NDDEPS0x0008 static void (*dbg)(char *format, ...); // dummy interface for debugging. static void dummy(char *format, ...) { } // Current probing modules info struct module_s { uint32_t flags; char *cmdname, *name, *depent, *opts; struct arg_list *rnames, *dep; }; // Converts path name FILE to module name. static char *path2mod(char *file, char *mod) { int i; char *from, *lslash; if (!file) return NULL; if (!mod) mod = xmalloc(MODNAME_LEN); lslash = strrchr(file, '/'); if (!lslash || (lslash == file && !lslash[1])) from = file; else from = lslash + 1; for (i = 0; i < (MODNAME_LEN-1) && from[i] && from[i] != '.'; i++) mod[i] = (from[i] == '-') ? '_' : from[i]; mod[i] = '\0'; return mod; } // locate character in string. static char *strchr_nul(char *s, int c) { while(*s != '\0' && *s != c) s++; return (char*)s; } // Add options in opts from toadd. static char *add_opts(char *opts, char *toadd) { if (toadd) { int optlen = 0; if (opts) optlen = strlen(opts); opts = xrealloc(opts, optlen + strlen(toadd) + 2); sprintf(opts + optlen, " %s", toadd); } return opts; } // Remove first element from the list and return it. static void *llist_popme(struct arg_list **head) { char *data = NULL; struct arg_list *temp = *head; if (temp) { data = temp->arg; *head = temp->next; free(temp); } return data; } // Add new node at the beginning of the list. static void llist_add(struct arg_list **old, void *data) { struct arg_list *new = xmalloc(sizeof(struct arg_list)); new->arg = (char*)data; new->next = *old; *old = new; } // Add new node at tail of list. static void llist_add_tail(struct arg_list **head, void *data) { while (*head) head = &(*head)->next; *head = xzalloc(sizeof(struct arg_list)); (*head)->arg = (char*)data; } // Reverse list order. static struct arg_list *llist_rev(struct arg_list *list) { struct arg_list *rev = NULL; while (list) { struct arg_list *next = list->next; list->next = rev; rev = list; list = next; } return rev; } /* * Returns struct module_s from the data base if found, NULL otherwise. * if ps - create module entry, add it to data base and return the same mod. */ static struct module_s *get_mod(char *mod, uint8_t ps) { char name[MODNAME_LEN]; struct module_s *modentry; struct arg_list *temp; unsigned i, hash = 0; path2mod(mod, name); for (i = 0; name[i]; i++) hash = ((hash*31) + hash) + name[i]; hash %= DBASE_SIZE; for (temp = TT.dbase[hash]; temp; temp = temp->next) { modentry = (struct module_s *) temp->arg; if (!strcmp(modentry->name, name)) return modentry; } if (!ps) return NULL; modentry = xzalloc(sizeof(*modentry)); modentry->name = xstrdup(name); llist_add(&TT.dbase[hash], modentry); return modentry; } /* * Read a line from file with \ continuation and escape commented line. * Return the line in allocated string (*li) */ static int read_line(FILE *fl, char **li) { char *nxtline = NULL, *line; int len, nxtlen, linelen, nxtlinelen; while (1) { line = NULL; linelen = nxtlinelen = 0; len = getline(&line, (size_t*)&linelen, fl); if (len <= 0) return len; // checking for commented lines. if (line[0] != '#') break; free(line); } for (;;) { if (line[len - 1] == '\n') len--; // checking line continuation. if (!len || line[len - 1] != '\\') break; len--; nxtlen = getline(&nxtline, (size_t*)&nxtlinelen, fl); if (nxtlen <= 0) break; if (linelen < len + nxtlen + 1) { linelen = len + nxtlen + 1; line = xrealloc(line, linelen); } memcpy(&line[len], nxtline, nxtlen); len += nxtlen; } line[len] = '\0'; *li = xstrdup(line); if (line) free(line); if (nxtline) free(nxtline); return len; } /* * Action