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 #ifdef SYS_finit_module
     20 #define finit_module(fd, opts, flags) syscall(SYS_finit_module, fd, opts, flags)
     21 #else
     22 #define finit_module(a, b, c) (errno = ENOSYS)
     23 #endif
     24 #define init_module(mod, len, opts) syscall(SYS_init_module, mod, len, opts)
     25 
     26 void insmod_main(void)
     27 {
     28   int fd = xopenro(*toys.optargs);
     29   int i, rc;
     30 
     31   i = 1;
     32   while (toys.optargs[i] &&
     33     strlen(toybuf) + strlen(toys.optargs[i]) + 2 < sizeof(toybuf))
     34   {
     35     strcat(toybuf, toys.optargs[i++]);
     36     strcat(toybuf, " ");
     37   }
     38 
     39   // finit_module was new in Linux 3.8, and doesn't work on stdin,
     40   // so we fall back to init_module if necessary.
     41   rc = finit_module(fd, toybuf, 0);
     42   if (rc && (fd == 0 || errno == ENOSYS)) {
     43     off_t len = 0;
     44     char *path = !strcmp(*toys.optargs, "-") ? "/dev/stdin" : *toys.optargs;
     45     char *buf = readfileat(AT_FDCWD, path, NULL, &len);
     46 
     47     rc = init_module(buf, len, toybuf);
     48     if (CFG_TOYBOX_FREE) free(buf);
     49   }
     50 
     51   if (rc) perror_exit("failed to load %s", toys.optargs[0]);
     52 
     53   if (CFG_TOYBOX_FREE) close(fd);
     54 }
     55