diff options
author | Elliott Hughes <enh@google.com> | 2016-02-18 16:24:02 -0800 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2016-02-19 17:59:40 -0600 |
commit | 81f31e463bd982a8344ea8681938eb43c9114652 (patch) | |
tree | 3288839ae781d82a48283f284afd277828688f63 /toys | |
parent | 5ec9f52a39c0f5a631cd60f12560698033eba7dc (diff) | |
download | toybox-81f31e463bd982a8344ea8681938eb43c9114652.tar.gz |
Implement "insmod -".
Also use finit_module if available. Given that "insmod -" requires
init_module, maybe this isn't a worthwhile optimization. Given that
"insmod /actual/file.ko" is the common use case, maybe it is.
Fix a bug in readfileat where *plen would be corrupted if you didn't supply
your own buffer (because ibuf is 0 in that case, not a pointer to the start
of the allocated space).
Diffstat (limited to 'toys')
-rw-r--r-- | toys/other/insmod.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/toys/other/insmod.c b/toys/other/insmod.c index cb222a54..098d2cfa 100644 --- a/toys/other/insmod.c +++ b/toys/other/insmod.c @@ -16,31 +16,35 @@ config INSMOD #include "toys.h" #include <sys/syscall.h> -#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts) +#define finit_module(fd, opts, flags) syscall(SYS_finit_module, fd, opts, flags) +#define init_module(mod, len, opts) syscall(SYS_init_module, mod, len, opts) void insmod_main(void) { - char * buf = NULL; - int len, res, i; - int fd = xopen(*toys.optargs, O_RDONLY); - - len = fdlength(fd); - buf = xmalloc(len); - xreadall(fd, buf, len); + int fd = !strcmp(*toys.optargs, "-") ? 0 : xopen(*toys.optargs, O_RDONLY); + int i, rc; i = 1; - while(toys.optargs[i] && + while (toys.optargs[i] && strlen(toybuf) + strlen(toys.optargs[i]) + 2 < sizeof(toybuf)) { strcat(toybuf, toys.optargs[i++]); strcat(toybuf, " "); } - res = init_module(buf, len, toybuf); - if (CFG_TOYBOX_FREE) { - if (buf != toybuf) free(buf); - close(fd); + // finit_module was new in Linux 3.8, and doesn't work on stdin, + // so we fall back to init_module if necessary. + rc = finit_module(fd, toybuf, 0); + if (rc && (fd == 0 || errno == ENOSYS)) { + off_t len = 0; + char *path = !strcmp(*toys.optargs, "-") ? "/dev/stdin" : *toys.optargs; + char *buf = readfileat(AT_FDCWD, path, NULL, &len); + + rc = init_module(buf, len, toybuf); + if (CFG_TOYBOX_FREE) free(buf); } - if (res) perror_exit("failed to load %s", toys.optargs[0]); + if (rc) perror_exit("failed to load %s", toys.optargs[0]); + + if (CFG_TOYBOX_FREE) close(fd); } |