[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--