[klibc] klibc insmod for recent kernels

Arnd Bergmann arnd@bergmann-dalldorf.de
Fri, 3 Jan 2003 17:26:42 +0100


--------------Boundary-00=_ICC5RTAS62ISKWMJ8RPQ
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 8bit

On Wednesday 25 December 2002 22:29, H. Peter Anvin wrote:

> That's not necessarily true.  Remember that an initramfs can be
> synthetically constructed, and it should be possible to inject a new
> driver at boot time, which may need to have dependencies resolved.

Right. So we actually need the full set of module-init-tools (or a fork
of them) to compile against klibc.

The attached patch against module-init-tools-0.9.7 gets us somewhat closer 
there. It removes the need for the 'index' and 'syscall' functions,
replacing them with 'strchr' and '_syscall#', which are part of 
klibc.
I also added another Makefile because klibc's MCONFIG does not
work well with automake.

The other patch adds the functions system, strerror, fgetc and fgets
to klibc. This might not be a good idea, since the fgets implementation
is about as slow as it gets and someone might be tempted to use it,
but it does the job for module-init-tools.

	Arnd <><
--------------Boundary-00=_ICC5RTAS62ISKWMJ8RPQ
Content-Type: text/x-diff;
  charset="iso-8859-1";
  name="klibc-0.70-mit.diff"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="klibc-0.70-mit.diff"

diff -urN -x '*.d' klibc-0.70-vanilla/klibc/Makefile klibc-0.70/klibc/Makefile
--- klibc-0.70-vanilla/klibc/Makefile	2002-11-15 06:07:50.000000000 +0100
+++ klibc-0.70/klibc/Makefile	2003-01-03 15:25:51.000000000 +0100
@@ -17,8 +17,10 @@
 	  strtoimax.o strtoumax.o \
 	  globals.o exitc.o atexit.o onexit.o \
 	  execl.o execle.o execv.o execvpe.o execvp.o execlp.o execlpe.o \
+	  system.o \
 	  fork.o wait.o wait3.o waitpid.o setpgrp.o \
 	  printf.o vprintf.o fprintf.o vfprintf.o perror.o \
+	  strerror.o fgetc.o fgets.o \
 	  fopen.o fread.o fread2.o fwrite.o fwrite2.o fputc.o fputs.o puts.o \
 	  sleep.o usleep.o raise.o abort.o assert.o alarm.o pause.o \
 	  signal.o siglist.o siglongjmp.o \
diff -urN -x '*.d' klibc-0.70-vanilla/klibc/fgetc.c klibc-0.70/klibc/fgetc.c
--- klibc-0.70-vanilla/klibc/fgetc.c	1970-01-01 01:00:00.000000000 +0100
+++ klibc-0.70/klibc/fgetc.c	2003-01-03 15:24:34.000000000 +0100
@@ -0,0 +1,16 @@
+/*
+ * fgetc.c
+ *
+ * fgetc implemented with fread
+ */
+
+#define __NO_FREAD_FWRITE_INLINES
+#include <stdio.h>
+
+int fgetc(FILE *__f)
+{
+  char __c;
+  if (_fread(&__c, 1, __f))
+	  return __c;
+  return EOF;
+}
diff -urN -x '*.d' klibc-0.70-vanilla/klibc/fgets.c klibc-0.70/klibc/fgets.c
--- klibc-0.70-vanilla/klibc/fgets.c	1970-01-01 01:00:00.000000000 +0100
+++ klibc-0.70/klibc/fgets.c	2003-01-03 15:24:28.000000000 +0100
@@ -0,0 +1,33 @@
+/*
+ * fgets.c
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+
+char *fgets(char *buf, int count, FILE *f)
+{
+  ssize_t rv;
+  char *p = buf;
+
+  count--;
+  while ( count ) {
+    rv = read(fileno(f), p, 1);
+    if ( rv == -1 ) {
+      if ( errno == EINTR )
+	continue;
+      else
+	return 0;
+    } else if ( rv == 0 ) {
+      return 0;
+    }
+
+    count--;
+    if (*p++ == '\n')
+	    break;
+  }
+  *p = '\0';
+
+  return buf;
+}
diff -urN -x '*.d' klibc-0.70-vanilla/klibc/include/stdio.h klibc-0.70/klibc/include/stdio.h
--- klibc-0.70-vanilla/klibc/include/stdio.h	2002-08-26 06:54:53.000000000 +0200
+++ klibc-0.70/klibc/include/stdio.h	2003-01-03 15:23:07.000000000 +0100
@@ -72,6 +72,10 @@
 
 __extern size_t _fread(void *, size_t, FILE *);
 __extern size_t _fwrite(const void *, size_t, FILE *);
+__extern char *fgets(char *s, int size, FILE *stream);
+__extern int fgetc(FILE *__f);
+#define getc(f) fgetc(f)
+#define getchar() fgetc(stdin)
 
 #ifndef __NO_FREAD_FWRITE_INLINES
 static __inline__ size_t
diff -urN -x '*.d' klibc-0.70-vanilla/klibc/include/stdlib.h klibc-0.70/klibc/include/stdlib.h
--- klibc-0.70-vanilla/klibc/include/stdlib.h	2002-08-17 00:28:23.000000000 +0200
+++ klibc-0.70/klibc/include/stdlib.h	2003-01-03 15:23:07.000000000 +0100
@@ -42,6 +42,8 @@
 # define __attribute_malloc
 #endif
 
+__extern int system(const char *);
+
 __extern __attribute_malloc void *malloc(size_t);
 __extern __attribute_malloc void *calloc(size_t, size_t);
 __extern void *realloc(void *, size_t);
diff -urN -x '*.d' klibc-0.70-vanilla/klibc/include/sys/wait.h klibc-0.70/klibc/include/sys/wait.h
--- klibc-0.70-vanilla/klibc/include/sys/wait.h	2002-08-11 06:35:43.000000000 +0200
+++ klibc-0.70/klibc/include/sys/wait.h	2003-01-03 15:23:49.000000000 +0100
@@ -16,4 +16,7 @@
 __extern pid_t wait3(int *, int, struct rusage *);
 __extern pid_t wait4(pid_t, int *, int, struct rusage *);
 
+#define WIFEXITED(status)	(!(status & 0x7f))
+#define WEXITSTATUS(status)	((status >> 8 ) & 0xff)
+
 #endif /* _SYS_WAIT_H */
diff -urN -x '*.d' klibc-0.70-vanilla/klibc/include/syslog.h klibc-0.70/klibc/include/syslog.h
--- klibc-0.70-vanilla/klibc/include/syslog.h	2002-08-14 07:29:19.000000000 +0200
+++ klibc-0.70/klibc/include/syslog.h	2003-01-03 15:23:07.000000000 +0100
@@ -20,7 +20,14 @@
 #define LOG_PRIMASK	7
 #define LOG_PRI(x)	((x) & LOG_PRIMASK)
 
-
+/* options, unused */
+#define LOG_CONS	001
+#define LOG_NDELAY	002
+#define LOG_NOWAIT	004
+#define LOG_ODELAY	010
+#define LOG_PERROR	020
+#define LOG_PID		040
+														
 /* Facilities; not actually used */
 #define LOG_KERN	0000
 #define LOG_USER	0010
diff -urN -x '*.d' klibc-0.70-vanilla/klibc/strerror.c klibc-0.70/klibc/strerror.c
--- klibc-0.70-vanilla/klibc/strerror.c	2002-08-18 22:47:44.000000000 +0200
+++ klibc-0.70/klibc/strerror.c	2003-01-03 15:17:39.000000000 +0100
@@ -20,6 +20,7 @@
     errnum /= 10;
   } while ( errnum );
 
-  return (char *)memcpy(message+6, p, (numbuf+sizeof numbuf)-p);
+  memcpy(message+6, p, (numbuf+sizeof numbuf)-p);
+  return message;
 }
 
diff -urN -x '*.d' klibc-0.70-vanilla/klibc/system.c klibc-0.70/klibc/system.c
--- klibc-0.70-vanilla/klibc/system.c	1970-01-01 01:00:00.000000000 +0100
+++ klibc-0.70/klibc/system.c	2003-01-03 15:24:23.000000000 +0100
@@ -0,0 +1,31 @@
+/*
+ * system.c
+ *
+ * run a shell command
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int system(const char *string)
+{
+  pid_t pid;
+  int status;
+
+  pid = fork();
+
+  if (pid == -1)
+	  return -1;
+
+  if (!pid)
+	  if (execl("/bin/sh", string, 0))
+		  exit(1);
+
+  pid = waitpid(pid, &status, 0);
+  if (pid == -1)
+	  return -1;
+
+  return status;
+}

--------------Boundary-00=_ICC5RTAS62ISKWMJ8RPQ
Content-Type: text/x-diff;
  charset="iso-8859-1";
  name="module-init-tools-0.9.7-klibc.diff"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="module-init-tools-0.9.7-klibc.diff"

diff -u -rN module-init-tools-0.9.7/Makefile.klibc.in module-init-tools-0.9.7-klibc/Makefile.klibc.in
--- module-init-tools-0.9.7/Makefile.klibc.in	1970-01-01 01:00:00.000000000 +0100
+++ module-init-tools-0.9.7-klibc/Makefile.klibc.in	2003-01-03 14:25:54.000000000 +0100
@@ -0,0 +1,26 @@
+PROGRAMS = insmod lsmod modprobe rmmod depmod
+
+depmod_OBJECTS = moduleops.o tables.o
+
+LD = ld
+CC = gcc
+DEFS =  @DEFS@ -DCONFIG_NO_BACKWARDS_COMPAT -DCONFIG_NO_BACKWARDS_COMPAT -DKLIBC
+CFLAGS = -O2 -Wall $(DEFS) $(REQFLAGS)
+
+SRCROOT = ..
+include $(SRCROOT)/MCONFIG
+
+all: $(PROGRAMS)
+
+%:	%.o
+	$(LD) -o $@ $(CRT0) $< $($@_OBJECTS) $(KLIBC) $(LIBGCC)
+
+depmod: $(depmod_OBJECTS)
+
+%.o:	%.c backwards_compat.c
+	$(CC) $(CFLAGS) -o $@ -c $< -s
+
+%:	%.c
+
+clean:
+	rm -f *.o $(PROGRAMS)
diff -u -rN module-init-tools-0.9.7/backwards_compat.c module-init-tools-0.9.7-klibc/backwards_compat.c
--- module-init-tools-0.9.7/backwards_compat.c	2002-12-28 07:25:34.000000000 +0100
+++ module-init-tools-0.9.7-klibc/backwards_compat.c	2003-01-03 14:25:19.000000000 +0100
@@ -11,13 +11,7 @@
 #include <string.h>
 #include <asm/unistd.h>
 
-#ifndef __ia64 /* breaks ia64. */
-_syscall2(long, create_module, const char *, name, size_t, size);
-#else
-#define create_module(name, size) \
-	syscall(__NR_create_module, (name), (size))
-#endif
-
+#include "system.h"
 #include "testing.h"
 
 static void exec_old(const char *progname, char *argv[])
diff -u -rN module-init-tools-0.9.7/configure.in module-init-tools-0.9.7-klibc/configure.in
--- module-init-tools-0.9.7/configure.in	2002-12-28 09:41:10.000000000 +0100
+++ module-init-tools-0.9.7-klibc/configure.in	2003-01-03 12:53:19.000000000 +0100
@@ -11,5 +11,5 @@
 *) AC_MSG_ERROR([Linux only, dude!]);;
 esac
 
-AC_OUTPUT([Makefile])
+AC_OUTPUT([Makefile Makefile.klibc])
 
diff -u -rN module-init-tools-0.9.7/depmod.c module-init-tools-0.9.7-klibc/depmod.c
--- module-init-tools-0.9.7/depmod.c	2002-12-28 06:25:26.000000000 +0100
+++ module-init-tools-0.9.7-klibc/depmod.c	2003-01-03 14:39:17.000000000 +0100
@@ -6,7 +6,6 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <getopt.h>
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
@@ -18,6 +17,7 @@
 #include <sys/utsname.h>
 #include <sys/mman.h>
 
+#include "system.h"
 #include "depmod.h"
 #include "moduleops.h"
 #include "tables.h"
diff -u -rN module-init-tools-0.9.7/insmod.c module-init-tools-0.9.7-klibc/insmod.c
--- module-init-tools-0.9.7/insmod.c	2002-12-21 07:34:27.000000000 +0100
+++ module-init-tools-0.9.7-klibc/insmod.c	2003-01-03 14:25:31.000000000 +0100
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <asm/unistd.h>
 
+#include "system.h"
 #include "backwards_compat.c"
 
 static void print_usage(const char *progname)
@@ -108,7 +109,7 @@
 		exit(1);
 	}
 
-	ret = syscall(__NR_init_module, map, len, options);
+	ret = init_module (map, len, options);
 	if (ret != 0) {
 		fprintf(stderr, "Error inserting '%s': %li %s\n",
 			filename, ret, moderror(errno));
diff -u -rN module-init-tools-0.9.7/modprobe.c module-init-tools-0.9.7-klibc/modprobe.c
--- module-init-tools-0.9.7/modprobe.c	2002-12-28 05:27:24.000000000 +0100
+++ module-init-tools-0.9.7-klibc/modprobe.c	2003-01-03 14:28:44.000000000 +0100
@@ -31,11 +31,10 @@
 #include <dirent.h>
 #include <limits.h>
 #include <elf.h>
-#include <getopt.h>
-#include <fnmatch.h>
 #include <asm/unistd.h>
 #include <sys/wait.h>
 
+#include "system.h"
 #include "list.h"
 #include "backwards_compat.c"
 
@@ -213,7 +212,7 @@
 	char *modname;
 
 	/* Ignore lines without : or which start with a # */
-	ptr = index(line, ':');
+	ptr = strchr(line, ':');
 	if (ptr == NULL || line[strspn(line, "\t ")] == '#')
 		return 0;
 
@@ -631,7 +630,7 @@
 	if (dry_run)
 		goto out;
 
-	ret = syscall(__NR_init_module, map, st.st_size, optstring);
+	ret = init_module (map, st.st_size, optstring);
 	if (ret != 0) {
 		if (dont_fail)
 			fatal("Error inserting %s (%s): %s\n",
@@ -687,7 +686,7 @@
 	if (dry_run)
 		goto remove_rest;
 
-	if (syscall(__NR_delete_module, mod->modname, O_EXCL) != 0) {
+	if (delete_module (mod->modname, O_EXCL) != 0) {
 		if (dont_fail)
 			fatal("Error removing %s (%s): %s\n",
 			      mod->modname, mod->filename,
diff -u -rN module-init-tools-0.9.7/rmmod.c module-init-tools-0.9.7-klibc/rmmod.c
--- module-init-tools-0.9.7/rmmod.c	2002-12-21 12:15:08.000000000 +0100
+++ module-init-tools-0.9.7-klibc/rmmod.c	2003-01-03 14:38:35.000000000 +0100
@@ -17,15 +17,16 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <asm/unistd.h>
 #include <stdarg.h>
-#include <getopt.h>
 #include <syslog.h>
 
+#include "system.h"
 #include "backwards_compat.c"
 
 #define error(log, fmt, ...) message(log, "ERROR: ", fmt , ## __VA_ARGS__)
@@ -184,7 +185,7 @@
 	     (flags & O_NONBLOCK) ? "no" : "yes",
 	     (flags & O_TRUNC) ? " force" : "");
 
-	ret = syscall(__NR_delete_module, name, flags);
+	ret = delete_module (name, flags);
 	if (ret != 0)
 		error(log, "Removing '%s': %s\n", name, strerror(errno));
 }
diff -u -rN module-init-tools-0.9.7/system.h module-init-tools-0.9.7-klibc/system.h
--- module-init-tools-0.9.7/system.h	1970-01-01 01:00:00.000000000 +0100
+++ module-init-tools-0.9.7-klibc/system.h	2003-01-03 14:56:39.000000000 +0100
@@ -0,0 +1,50 @@
+#ifndef _MODINITTOOLS_SYSTEM_H
+#define _MODINITTOOLS_SYSTEM_H
+
+#include <linux/unistd.h>
+
+#ifndef __ia64 /* breaks ia64 */
+static inline _syscall2(long, create_module, const char *, name, size_t, size);
+
+static inline _syscall3 (int, init_module, void *, map, unsigned long, len,
+			 char *, options);
+
+static inline _syscall2(long, delete_module, const char *, modname,
+			unsigned int, flags);
+#else
+
+#define create_module(name, size) \
+	syscall(__NR_create_module, (name), (size))
+
+#define init_module(map, len, options) \
+	syscall(__NR_init_module, (map), (len), (options))
+
+#define delete_module(modname, flags) \
+	syscall(__NR_delete_module, (modname), (flags))
+	
+#endif
+
+#ifndef KLIBC
+
+#include <fnmatch.h>
+#include <getopt.h>
+
+#else
+
+/* fnmatch and getopt_long are not implemented in klibc. Replacing them
+ * like this will disable some features, but keep the tools usable */
+#include <string.h>
+#define fnmatch(p,s,f) (strcmp((p),(s)) != 0)
+
+struct option {
+        const char *name;
+        int has_arg;
+        int *flag;
+        int val;
+};
+
+#define getopt_long(c,v,s,l,i) ((void)(l),getopt((c),(v),(s)))
+
+#endif
+
+#endif
diff -u -rN module-init-tools-0.9.7/testing.h module-init-tools-0.9.7-klibc/testing.h
--- module-init-tools-0.9.7/testing.h	2002-12-28 07:25:52.000000000 +0100
+++ module-init-tools-0.9.7-klibc/testing.h	2003-01-03 13:30:54.000000000 +0100
@@ -33,61 +33,38 @@
 	return -1;
 }
 
-static long int modtest_syscall(long int __sysno, ...)
+static int modtest_init_module(void * map, unsigned long size, char *optstring)
 {
-	va_list ap;
+	if (getenv("MODTEST_DUMP_INIT")) {
+		while (size) {
+			int ret;
+			ret = write(2, map, size);
+			if (ret < 0) exit(1);
+			size -= ret;
+			map += ret;
+		}
+	} else		
+		printf("INIT_MODULE: %u %s\n", size, optstring);
+	return 0;
+}
 
-	switch (__sysno) {
-	case __NR_init_module: {
-		void *map;
-		size_t size;
-		char *optstring;
-
-		va_start(ap, __sysno);
-		map = va_arg(ap, void *);
-		size = va_arg(ap, size_t);
-		optstring = va_arg(ap, char *);
-
-		if (getenv("MODTEST_DUMP_INIT")) {
-			while (size) {
-				int ret;
-				ret = write(2, map, size);
-				if (ret < 0) exit(1);
-				size -= ret;
-				map += ret;
-			}
-		} else		
-			printf("INIT_MODULE: %u %s\n", size, optstring);
-		break;
-	}
-	case __NR_delete_module: {
-		char *modname;
-		unsigned int flags;
-		char flagnames[100];
-
-		va_start(ap, __sysno);
-		modname = va_arg(ap, char *);
-		flags = va_arg(ap, unsigned int);
-
-		flagnames[0] = '\0';
-		if (flags & O_EXCL)
-			strcat(flagnames, "EXCL ");
-		if (flags & O_TRUNC)
-			strcat(flagnames, "TRUNC ");
-		if (flags & O_NONBLOCK)
-			strcat(flagnames, "NONBLOCK ");
-		if (flags & ~(O_EXCL|O_TRUNC|O_NONBLOCK))
-			strcat(flagnames, "UNKNOWN ");
+static long modtest_delete_module(const char * modname, unsigned int flags)
+{
+	char flagnames[100];
 
-		printf("DELETE_MODULE: %s %s\n", modname, flagnames);
-		break;
-	}
-	default:
-		printf("UNKNOWN SYSCALL: %lu\n", __sysno);
-		break;
-	}
+	flagnames[0] = '\0';
+	if (flags & O_EXCL)
+		strcat(flagnames, "EXCL ");
+	if (flags & O_TRUNC)
+		strcat(flagnames, "TRUNC ");
+	if (flags & O_NONBLOCK)
+		strcat(flagnames, "NONBLOCK ");
+	if (flags & ~(O_EXCL|O_TRUNC|O_NONBLOCK))
+		strcat(flagnames, "UNKNOWN ");
 
-	return 0;
+	printf("DELETE_MODULE: %s %s\n", modname, flagnames);
+
+	return 0;	
 }
 
 static const char *modtest_mapname(const char *path)
@@ -138,9 +115,12 @@
 /* create_module call */
 #undef create_module
 #define create_module modtest_create_module
+#undef init_module
+#define init_module modtest_init_module
+#undef delete_module
+#define delete_module modtest_delete_module
 
 #define uname modtest_uname
-#define syscall modtest_syscall
 #define open modtest_open
 #define fopen modtest_fopen
 #define stat(name, ptr) modtest_stat(name, ptr)

--------------Boundary-00=_ICC5RTAS62ISKWMJ8RPQ--