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).
---
 lib/lib.c           |  4 ++--
 toys/other/insmod.c | 32 ++++++++++++++++++--------------
 2 files changed, 20 insertions(+), 16 deletions(-)
From e29c7c3468fda078ef42a8126db6388678b2ad3f Mon Sep 17 00:00:00 2001
From: Elliott Hughes <[email protected]>
Date: Thu, 18 Feb 2016 16:24:02 -0800
Subject: [PATCH] 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).
---
 lib/lib.c           |  4 ++--
 toys/other/insmod.c | 32 ++++++++++++++++++--------------
 2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/lib/lib.c b/lib/lib.c
index e80b8b1..43db2e3 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -475,12 +475,12 @@ char *readfileat(int dirfd, char *name, char *ibuf, off_t *plen)
     rbuf = buf+rlen;
     len -= rlen;
   }
-  *plen = len = rlen+(buf-ibuf);
+  *plen = len = rlen+(rbuf-buf);
   close(fd);
 
   if (rlen<0) {
     if (ibuf != buf) free(buf);
-    buf =  0;
+    buf = 0;
   } else buf[len] = 0;
 
   return buf;
diff --git a/toys/other/insmod.c b/toys/other/insmod.c
index cb222a5..098d2cf 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);
 }
-- 
2.7.0.rc3.207.g0ac5344

_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to