Home | History | Annotate | Download | only in other
      1 /* insmod.c - Load a module into the Linux kernel.
      2  *
      3  * Copyright 2012 Elie De Brauwer <eliedebrauwer (at) gmail.com>
      4 
      5 USE_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
      6 
      7 config INSMOD
      8   bool "insmod"
      9   default y
     10   help
     11     usage: insmod MODULE [MODULE_OPTIONS]
     12 
     13     Load the module named MODULE passing options if given.
     14 */
     15 
     16 #include "toys.h"
     17 
     18 #include <sys/syscall.h>
     19 #define finit_module(fd, opts, flags) syscall(SYS_finit_module, fd, opts, flags)
     20 #define init_module(mod, len, opts) syscall(SYS_init_module, mod, len, opts)
     21 
     22 void insmod_main(void)
     23 {
     24   int fd = !strcmp(*toys.optargs, "-") ? 0 : xopen(*toys.optargs, O_RDONLY);
     25   int i, rc;
     26 
     27   i = 1;
     28   while (toys.optargs[i] &&
     29     strlen(toybuf) + strlen(toys.optargs[i]) + 2 < sizeof(toybuf))
     30   {
     31     strcat(toybuf, toys.optargs[i++]);
     32     strcat(toybuf, " ");
     33   }
     34 
     35   // finit_module was new in Linux 3.8, and doesn't work on stdin,
     36   // so we fall back to init_module if necessary.
     37   rc = finit_module(fd, toybuf, 0);
     38   if (rc && (fd == 0 || errno == ENOSYS)) {
     39     off_t len = 0;
     40     char *path = !strcmp(*toys.optargs, "-") ? "/dev/stdin" : *toys.optargs;
     41     char *buf = readfileat(AT_FDCWD, path, NULL, &len);
     42 
     43     rc = init_module(buf, len, toybuf);
     44     if (CFG_TOYBOX_FREE) free(buf);
     45   }
     46 
     47   if (rc) perror_exit("failed to load %s", toys.optargs[0]);
     48 
     49   if (CFG_TOYBOX_FREE) close(fd);
     50 }
     51