summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/klibc/files/losetup.patch571
-rw-r--r--packages/klibc/files/modprobe.patch1985
-rw-r--r--packages/klibc/klibc-common.inc2
-rw-r--r--packages/klibc/klibc-utils-static_1.5.bb10
-rw-r--r--packages/klibc/klibc.inc11
-rw-r--r--packages/klibc/klibc_1.5.bb2
6 files changed, 2575 insertions, 6 deletions
diff --git a/packages/klibc/files/losetup.patch b/packages/klibc/files/losetup.patch
new file mode 100644
index 0000000000..77049bd05f
--- /dev/null
+++ b/packages/klibc/files/losetup.patch
@@ -0,0 +1,571 @@
+Index: klibc-1.5/usr/utils/losetup.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ klibc-1.5/usr/utils/losetup.c 2008-03-07 23:13:38.635692852 +0100
+@@ -0,0 +1,485 @@
++/* Originally from Ted's losetup.c */
++
++#define LOOPMAJOR 7
++
++/*
++ * losetup.c - setup and control loop devices
++ */
++
++#include <stdio.h>
++#include <string.h>
++#include <ctype.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <sys/ioctl.h>
++#include <sys/stat.h>
++#include <sys/mman.h>
++#include <sys/sysmacros.h>
++#include <string.h>
++
++#include "loop.h"
++
++extern int verbose;
++extern char *progname;
++extern char *xstrdup (const char *s); /* not: #include "sundries.h" */
++extern void error (const char *fmt, ...); /* idem */
++
++/* caller guarantees n > 0 */
++void
++xstrncpy(char *dest, const char *src, size_t n) {
++ strncpy(dest, src, n-1);
++ dest[n-1] = 0;
++}
++
++
++static int
++loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info)
++{
++ memset(info, 0, sizeof(*info));
++ info->lo_number = info64->lo_number;
++ info->lo_device = info64->lo_device;
++ info->lo_inode = info64->lo_inode;
++ info->lo_rdevice = info64->lo_rdevice;
++ info->lo_offset = info64->lo_offset;
++ info->lo_encrypt_type = info64->lo_encrypt_type;
++ info->lo_encrypt_key_size = info64->lo_encrypt_key_size;
++ info->lo_flags = info64->lo_flags;
++ info->lo_init[0] = info64->lo_init[0];
++ info->lo_init[1] = info64->lo_init[1];
++ if (info->lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
++ memcpy(info->lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
++ else
++ memcpy(info->lo_name, info64->lo_file_name, LO_NAME_SIZE);
++ memcpy(info->lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
++
++ /* error in case values were truncated */
++ if (info->lo_device != info64->lo_device ||
++ info->lo_rdevice != info64->lo_rdevice ||
++ info->lo_inode != info64->lo_inode ||
++ info->lo_offset != info64->lo_offset)
++ return -EOVERFLOW;
++
++ return 0;
++}
++
++
++static int
++show_loop(char *device) {
++ struct loop_info loopinfo;
++ struct loop_info64 loopinfo64;
++ int fd, errsv;
++
++ if ((fd = open(device, O_RDONLY)) < 0) {
++ int errsv = errno;
++ fprintf(stderr, "loop: can't open device %s: %s\n",
++ device, strerror (errsv));
++ return 2;
++ }
++
++ if (ioctl(fd, LOOP_GET_STATUS64, &loopinfo64) == 0) {
++
++ loopinfo64.lo_file_name[LO_NAME_SIZE-2] = '*';
++ loopinfo64.lo_file_name[LO_NAME_SIZE-1] = 0;
++ loopinfo64.lo_crypt_name[LO_NAME_SIZE-1] = 0;
++
++ printf("%s: [%04llx]:%llu (%s)",
++ device, loopinfo64.lo_device, loopinfo64.lo_inode,
++ loopinfo64.lo_file_name);
++
++ if (loopinfo64.lo_offset)
++ printf(", offset %lld", loopinfo64.lo_offset);
++
++ if (loopinfo64.lo_sizelimit)
++ printf(", sizelimit %lld", loopinfo64.lo_sizelimit);
++
++ if (loopinfo64.lo_encrypt_type ||
++ loopinfo64.lo_crypt_name[0]) {
++ char *e = loopinfo64.lo_crypt_name;
++
++ if (*e == 0 && loopinfo64.lo_encrypt_type == 1)
++ e = "XOR";
++ printf(", encryption %s (type %d)",
++ e, loopinfo64.lo_encrypt_type);
++ }
++ printf("\n");
++ close (fd);
++ return 0;
++ }
++
++ if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) == 0) {
++ printf ("%s: [%04x]:%ld (%s)",
++ device, loopinfo.lo_device, loopinfo.lo_inode,
++ loopinfo.lo_name);
++
++ if (loopinfo.lo_offset)
++ printf(", offset %d", loopinfo.lo_offset);
++
++ if (loopinfo.lo_encrypt_type)
++ printf(", encryption type %d\n",
++ loopinfo.lo_encrypt_type);
++
++ printf("\n");
++ close (fd);
++ return 0;
++ }
++
++ errsv = errno;
++ fprintf(stderr, "loop: can't get info on device %s: %s\n",
++ device, strerror (errsv));
++ close (fd);
++ return 1;
++}
++
++int
++is_loop_device (const char *device) {
++ struct stat statbuf;
++
++ return (stat(device, &statbuf) == 0 &&
++ S_ISBLK(statbuf.st_mode) &&
++ major(statbuf.st_rdev) == LOOPMAJOR);
++}
++
++#define SIZE(a) (sizeof(a)/sizeof(a[0]))
++
++char *
++find_unused_loop_device (void) {
++ /* Just creating a device, say in /tmp, is probably a bad idea -
++ people might have problems with backup or so.
++ So, we just try /dev/loop[0-7]. */
++ char dev[20];
++ char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
++ int i, j, fd, somedev = 0, someloop = 0, permission = 0;
++ struct stat statbuf;
++ struct loop_info loopinfo;
++
++ for (j = 0; j < SIZE(loop_formats); j++) {
++ for(i = 0; i < 256; i++) {
++ sprintf(dev, loop_formats[j], i);
++ if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
++ somedev++;
++ fd = open (dev, O_RDONLY);
++ if (fd >= 0) {
++ if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
++ someloop++; /* in use */
++ else if (errno == ENXIO) {
++ close (fd);
++ return xstrdup(dev);/* probably free */
++ }
++ close (fd);
++ } else if (errno == EACCES)
++ permission++;
++
++ continue;/* continue trying as long as devices exist */
++ }
++ break;
++ }
++ }
++
++ if (!somedev)
++ error("%s: could not find any device /dev/loop#", progname);
++ else if (!someloop && permission)
++ error("%s: no permission to look at /dev/loop#", progname);
++ else if (!someloop)
++ error(
++ "%s: Could not find any loop device. Maybe this kernel "
++ "does not know\n"
++ " about the loop device? (If so, recompile or "
++ "`modprobe loop'.)", progname);
++ else
++ error("%s: could not find any free loop device", progname);
++ return 0;
++}
++
++/*
++ * A function to read the passphrase either from the terminal or from
++ * an open file descriptor.
++ */
++static char *
++xgetpass(int pfd, const char *prompt) {
++ char *pass;
++ int buflen, i;
++
++ pass = NULL;
++ buflen = 0;
++ for (i=0; ; i++) {
++ if (i >= buflen-1) {
++ /* we're running out of space in the buffer.
++ * Make it bigger: */
++ char *tmppass = pass;
++ buflen += 128;
++ pass = realloc(tmppass, buflen);
++ if (pass == NULL) {
++ /* realloc failed. Stop reading. */
++ error("Out of memory while reading passphrase");
++ pass = tmppass; /* the old buffer hasn't changed */
++ break;
++ }
++ }
++ if (read(pfd, pass+i, 1) != 1 ||
++ pass[i] == '\n' || pass[i] == 0)
++ break;
++ }
++
++ if (pass == NULL)
++ return "";
++
++ pass[i] = 0;
++ return pass;
++}
++
++static int
++digits_only(const char *s) {
++ while (*s)
++ if (!isdigit(*s++))
++ return 0;
++ return 1;
++}
++
++int
++set_loop(const char *device, const char *file, unsigned long long offset,
++ const char *encryption, int pfd, int *loopro) {
++ struct loop_info64 loopinfo64;
++ int fd, ffd, mode, i;
++ char *pass;
++
++ mode = (*loopro ? O_RDONLY : O_RDWR);
++ if ((ffd = open(file, mode)) < 0) {
++ if (!*loopro && errno == EROFS)
++ ffd = open(file, mode = O_RDONLY);
++ if (ffd < 0) {
++ perror(file);
++ return 1;
++ }
++ }
++ if ((fd = open(device, mode)) < 0) {
++ perror (device);
++ return 1;
++ }
++ *loopro = (mode == O_RDONLY);
++
++ memset(&loopinfo64, 0, sizeof(loopinfo64));
++
++ xstrncpy(loopinfo64.lo_file_name, file, LO_NAME_SIZE);
++
++ if (encryption && *encryption) {
++ if (digits_only(encryption)) {
++ loopinfo64.lo_encrypt_type = atoi(encryption);
++ } else {
++ loopinfo64.lo_encrypt_type = LO_CRYPT_CRYPTOAPI;
++ snprintf(loopinfo64.lo_crypt_name, LO_NAME_SIZE,
++ "%s", encryption);
++ }
++ }
++
++ loopinfo64.lo_offset = offset;
++
++
++ switch (loopinfo64.lo_encrypt_type) {
++ case LO_CRYPT_NONE:
++ loopinfo64.lo_encrypt_key_size = 0;
++ break;
++ case LO_CRYPT_XOR:
++ pass = xgetpass(pfd, "Password: ");
++ goto gotpass;
++ default:
++ pass = xgetpass(pfd, "Password: ");
++ gotpass:
++ memset(loopinfo64.lo_encrypt_key, 0, LO_KEY_SIZE);
++ xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
++ memset(pass, 0, strlen(pass));
++ loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE;
++ }
++
++ if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
++ perror("ioctl: LOOP_SET_FD");
++ return 1;
++ }
++ close (ffd);
++
++ i = ioctl(fd, LOOP_SET_STATUS64, &loopinfo64);
++ if (i) {
++ struct loop_info loopinfo;
++ int errsv = errno;
++
++ i = loop_info64_to_old(&loopinfo64, &loopinfo);
++ if (i) {
++ errno = errsv;
++ perror("ioctl: LOOP_SET_STATUS64");
++ } else {
++ i = ioctl(fd, LOOP_SET_STATUS, &loopinfo);
++ if (i)
++ perror("ioctl: LOOP_SET_STATUS");
++ }
++ memset(&loopinfo, 0, sizeof(loopinfo));
++ }
++ memset(&loopinfo64, 0, sizeof(loopinfo64));
++
++ if (i) {
++ ioctl (fd, LOOP_CLR_FD, 0);
++ close (fd);
++ return 1;
++ }
++ close (fd);
++
++ if (verbose > 1)
++ printf("set_loop(%s,%s,%llu): success\n",
++ device, file, offset);
++ return 0;
++}
++
++int
++del_loop (const char *device) {
++ int fd;
++
++ if ((fd = open (device, O_RDONLY)) < 0) {
++ int errsv = errno;
++ fprintf(stderr, "loop: can't delete device %s: %s\n",
++ device, strerror (errsv));
++ return 1;
++ }
++ if (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
++ perror ("ioctl: LOOP_CLR_FD");
++ return 1;
++ }
++ close (fd);
++ if (verbose > 1)
++ printf("del_loop(%s): success\n", device);
++ return 0;
++}
++
++
++#include <getopt.h>
++#include <stdarg.h>
++
++int verbose = 0;
++char *progname;
++
++static void
++usage(void) {
++ fprintf(stderr, "usage:\n\
++ %s loop_device # give info\n\
++ %s -d loop_device # delete\n\
++ %s -f # find unused\n\
++ %s [-e encryption] [-o offset] {-f|loop_device} file # setup\n",
++ progname, progname, progname, progname);
++ exit(1);
++}
++
++char *
++xstrdup (const char *s) {
++ char *t;
++
++ if (s == NULL)
++ return NULL;
++
++ t = strdup (s);
++
++ if (t == NULL) {
++ fprintf(stderr, "not enough memory");
++ exit(1);
++ }
++
++ return t;
++}
++
++void
++error (const char *fmt, ...) {
++ va_list args;
++
++ va_start (args, fmt);
++ vfprintf (stderr, fmt, args);
++ va_end (args);
++ fprintf (stderr, "\n");
++}
++
++int
++main(int argc, char **argv) {
++ char *p, *offset, *encryption, *passfd, *device, *file;
++ int delete, find, c;
++ int res = 0;
++ int ro = 0;
++ int pfd = -1;
++ unsigned long long off;
++
++
++ delete = find = 0;
++ off = 0;
++ offset = encryption = passfd = NULL;
++
++ progname = argv[0];
++ if ((p = strrchr(progname, '/')) != NULL)
++ progname = p+1;
++
++ while ((c = getopt(argc, argv, "de:E:fo:p:v")) != -1) {
++ switch (c) {
++ case 'd':
++ delete = 1;
++ break;
++ case 'E':
++ case 'e':
++ encryption = optarg;
++ break;
++ case 'f':
++ find = 1;
++ break;
++ case 'o':
++ offset = optarg;
++ break;
++ case 'p':
++ passfd = optarg;
++ break;
++ case 'v':
++ verbose = 1;
++ break;
++ default:
++ usage();
++ }
++ }
++
++ if (argc == 1) {
++ usage();
++ } else if (delete) {
++ if (argc != optind+1 || encryption || offset || find)
++ usage();
++ } else if (find) {
++ if (argc < optind || argc > optind+1)
++ usage();
++ } else {
++ if (argc < optind+1 || argc > optind+2)
++ usage();
++ }
++
++ if (find) {
++ device = find_unused_loop_device();
++ if (device == NULL)
++ return -1;
++ if (verbose)
++ printf("Loop device is %s\n", device);
++ if (argc == optind) {
++ printf("%s\n", device);
++ return 0;
++ }
++ file = argv[optind];
++ } else {
++ device = argv[optind];
++ if (argc == optind+1)
++ file = NULL;
++ else
++ file = argv[optind+1];
++ }
++
++ if (delete)
++ res = del_loop(device);
++ else if (file == NULL)
++ res = show_loop(device);
++ else {
++ if (offset && sscanf(offset, "%llu", &off) != 1)
++ usage();
++ if (passfd && sscanf(passfd, "%d", &pfd) != 1)
++ usage();
++ res = set_loop(device, file, off, encryption, pfd, &ro);
++ }
++ return res;
++}
+Index: klibc-1.5/usr/utils/loop.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ klibc-1.5/usr/utils/loop.h 2008-03-07 23:01:49.336694297 +0100
+@@ -0,0 +1,51 @@
++#define LO_CRYPT_NONE 0
++#define LO_CRYPT_XOR 1
++#define LO_CRYPT_DES 2
++#define LO_CRYPT_CRYPTOAPI 18
++
++#define LOOP_SET_FD 0x4C00
++#define LOOP_CLR_FD 0x4C01
++#define LOOP_SET_STATUS 0x4C02
++#define LOOP_GET_STATUS 0x4C03
++#define LOOP_SET_STATUS64 0x4C04
++#define LOOP_GET_STATUS64 0x4C05
++
++#define LO_NAME_SIZE 64
++#define LO_KEY_SIZE 32
++
++#include "my_dev_t.h"
++
++struct loop_info {
++ int lo_number;
++ my_dev_t lo_device;
++ unsigned long lo_inode;
++ my_dev_t lo_rdevice;
++ int lo_offset;
++ int lo_encrypt_type;
++ int lo_encrypt_key_size;
++ int lo_flags;
++ char lo_name[LO_NAME_SIZE];
++ unsigned char lo_encrypt_key[LO_KEY_SIZE];
++ unsigned long lo_init[2];
++ char reserved[4];
++};
++
++/*
++ * Where to get __u8, __u32, __u64? Let us use unsigned char/int/long long
++ * and get punished when someone comes with 128-bit long longs.
++ */
++struct loop_info64 {
++ unsigned long long lo_device;
++ unsigned long long lo_inode;
++ unsigned long long lo_rdevice;
++ unsigned long long lo_offset;
++ unsigned long long lo_sizelimit; /* bytes, 0 == max available */
++ unsigned int lo_number;
++ unsigned int lo_encrypt_type;
++ unsigned int lo_encrypt_key_size;
++ unsigned int lo_flags;
++ unsigned char lo_file_name[LO_NAME_SIZE];
++ unsigned char lo_crypt_name[LO_NAME_SIZE];
++ unsigned char lo_encrypt_key[LO_KEY_SIZE];
++ unsigned long long lo_init[2];
++};
+Index: klibc-1.5/usr/utils/my_dev_t.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ klibc-1.5/usr/utils/my_dev_t.h 2008-03-07 23:03:45.148693283 +0100
+@@ -0,0 +1,20 @@
++/* silliness to get dev_t defined as the kernel defines it */
++/* glibc uses a different dev_t */
++
++#include <linux/posix_types.h>
++#include <linux/version.h>
++
++#ifndef KERNEL_VERSION
++#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(1,3,78)
++/* for i386 - alpha uses unsigned int */
++#define my_dev_t unsigned short
++#else
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)
++#define my_dev_t __kernel_dev_t
++#else
++#define my_dev_t __kernel_old_dev_t
++#endif
++#endif
diff --git a/packages/klibc/files/modprobe.patch b/packages/klibc/files/modprobe.patch
new file mode 100644
index 0000000000..074b0b6311
--- /dev/null
+++ b/packages/klibc/files/modprobe.patch
@@ -0,0 +1,1985 @@
+Index: klibc-1.5/usr/utils/Kbuild
+===================================================================
+--- klibc-1.5.orig/usr/utils/Kbuild 2008-03-07 22:01:45.223695348 +0100
++++ klibc-1.5/usr/utils/Kbuild 2008-03-07 22:48:44.660783243 +0100
+@@ -3,8 +3,8 @@
+ #
+
+ progs := chroot dd mkdir mkfifo mknod mount pivot_root umount
+-progs += true false sleep ln nuke minips cat
+-progs += insmod uname halt kill readlink cpio
++progs += true false sleep ln nuke minips cat losetup
++progs += insmod uname halt kill readlink cpio modprobe
+
+ static-y := $(addprefix static/, $(progs))
+ shared-y := $(addprefix shared/, $(progs))
+@@ -52,7 +52,10 @@
+ shared/readlink-y := readlink.o
+ static/cpio-y := cpio.o
+ shared/cpio-y := cpio.o
+-
++static/modprobe-y := modprobe.o
++shared/modprobe-y := modprobe.o
++static/losetup-y := losetup.o
++shared/losetup-y := losetup.o
+ # Additionally linked targets
+ always := static/reboot static/poweroff shared/reboot shared/poweroff
+
+Index: klibc-1.5/usr/utils/list.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ klibc-1.5/usr/utils/list.h 2008-03-07 22:33:22.287688586 +0100
+@@ -0,0 +1,238 @@
++/* Stolen from Linux Kernel Source's list.h -- GPL. */
++#ifndef _MODINITTOOLS_LIST_H
++#define _MODINITTOOLS_LIST_H
++
++#undef offsetof
++#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
++
++/**
++ * container_of - cast a member of a structure out to the containing structure
++ *
++ * @ptr: the pointer to the member.
++ * @type: the type of the container struct this is embedded in.
++ * @member: the name of the member within the struct.
++ *
++ */
++#define container_of(ptr, type, member) ({ \
++ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
++ (type *)( (char *)__mptr - offsetof(type,member) );})
++
++/*
++ * Simple doubly linked list implementation.
++ *
++ * Some of the internal functions ("__xxx") are useful when
++ * manipulating whole lists rather than single entries, as
++ * sometimes we already know the next/prev entries and we can
++ * generate better code by using them directly rather than
++ * using the generic single-entry routines.
++ */
++
++struct list_head {
++ struct list_head *next, *prev;
++};
++
++#define LIST_HEAD_INIT(name) { &(name), &(name) }
++
++#define LIST_HEAD(name) \
++ struct list_head name = LIST_HEAD_INIT(name)
++
++#define INIT_LIST_HEAD(ptr) do { \
++ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
++} while (0)
++
++/*
++ * Insert a new entry between two known consecutive entries.
++ *
++ * This is only for internal list manipulation where we know
++ * the prev/next entries already!
++ */
++static inline void __list_add(struct list_head *new,
++ struct list_head *prev,
++ struct list_head *next)
++{
++ next->prev = new;
++ new->next = next;
++ new->prev = prev;
++ prev->next = new;
++}
++
++/**
++ * list_add - add a new entry
++ * @new: new entry to be added
++ * @head: list head to add it after
++ *
++ * Insert a new entry after the specified head.
++ * This is good for implementing stacks.
++ */
++static inline void list_add(struct list_head *new, struct list_head *head)
++{
++ __list_add(new, head, head->next);
++}
++
++/**
++ * list_add_tail - add a new entry
++ * @new: new entry to be added
++ * @head: list head to add it before
++ *
++ * Insert a new entry before the specified head.
++ * This is useful for implementing queues.
++ */
++static inline void list_add_tail(struct list_head *new, struct list_head *head)
++{
++ __list_add(new, head->prev, head);
++}
++
++/*
++ * Delete a list entry by making the prev/next entries
++ * point to each other.
++ *
++ * This is only for internal list manipulation where we know
++ * the prev/next entries already!
++ */
++static inline void __list_del(struct list_head * prev, struct list_head * next)
++{
++ next->prev = prev;
++ prev->next = next;
++}
++
++/**
++ * list_del - deletes entry from list.
++ * @entry: the element to delete from the list.
++ * Note: list_empty on entry does not return true after this, the entry is
++ * in an undefined state.
++ */
++static inline void list_del(struct list_head *entry)
++{
++ __list_del(entry->prev, entry->next);
++}
++
++/**
++ * list_del_init - deletes entry from list and reinitialize it.
++ * @entry: the element to delete from the list.
++ */
++static inline void list_del_init(struct list_head *entry)
++{
++ __list_del(entry->prev, entry->next);
++ INIT_LIST_HEAD(entry);
++}
++
++/**
++ * list_move - delete from one list and add as another's head
++ * @list: the entry to move
++ * @head: the head that will precede our entry
++ */
++static inline void list_move(struct list_head *list, struct list_head *head)
++{
++ __list_del(list->prev, list->next);
++ list_add(list, head);
++}
++
++/**
++ * list_move_tail - delete from one list and add as another's tail
++ * @list: the entry to move
++ * @head: the head that will follow our entry
++ */
++static inline void list_move_tail(struct list_head *list,
++ struct list_head *head)
++{
++ __list_del(list->prev, list->next);
++ list_add_tail(list, head);
++}
++
++/**
++ * list_empty - tests whether a list is empty
++ * @head: the list to test.
++ */
++static inline int list_empty(struct list_head *head)
++{
++ return head->next == head;
++}
++
++static inline void __list_splice(struct list_head *list,
++ struct list_head *head)
++{
++ struct list_head *first = list->next;
++ struct list_head *last = list->prev;
++ struct list_head *at = head->next;
++
++ first->prev = head;
++ head->next = first;
++
++ last->next = at;
++ at->prev = last;
++}
++
++/**
++ * list_splice - join two lists
++ * @list: the new list to add.
++ * @head: the place to add it in the first list.
++ */
++static inline void list_splice(struct list_head *list, struct list_head *head)
++{
++ if (!list_empty(list))
++ __list_splice(list, head);
++}
++
++/**
++ * list_splice_init - join two lists and reinitialise the emptied list.
++ * @list: the new list to add.
++ * @head: the place to add it in the first list.
++ *
++ * The list at @list is reinitialised
++ */
++static inline void list_splice_init(struct list_head *list,
++ struct list_head *head)
++{
++ if (!list_empty(list)) {
++ __list_splice(list, head);
++ INIT_LIST_HEAD(list);
++ }
++}
++
++/**
++ * list_entry - get the struct for this entry
++ * @ptr: the &struct list_head pointer.
++ * @type: the type of the struct this is embedded in.
++ * @member: the name of the list_struct within the struct.
++ */
++#define list_entry(ptr, type, member) \
++ container_of(ptr, type, member)
++
++/**
++ * list_for_each - iterate over a list
++ * @pos: the &struct list_head to use as a loop counter.
++ * @head: the head for your list.
++ */
++#define list_for_each(pos, head) \
++ for (pos = (head)->next; pos != (head); pos = pos->next)
++
++/**
++ * list_for_each_prev - iterate over a list backwards
++ * @pos: the &struct list_head to use as a loop counter.
++ * @head: the head for your list.
++ */
++#define list_for_each_prev(pos, head) \
++ for (pos = (head)->prev; pos != (head); pos = pos->prev)
++
++/**
++ * list_for_each_safe - iterate over a list safe against removal of list entry
++ * @pos: the &struct list_head to use as a loop counter.
++ * @n: another &struct list_head to use as temporary storage
++ * @head: the head for your list.
++ */
++#define list_for_each_safe(pos, n, head) \
++ for (pos = (head)->next, n = pos->next; pos != (head); \
++ pos = n, n = pos->next)
++
++/**
++ * list_for_each_entry - iterate over list of given type
++ * @pos: the type * to use as a loop counter.
++ * @head: the head for your list.
++ * @member: the name of the list_struct within the struct.
++ */
++#define list_for_each_entry(pos, head, member) \
++ for (pos = list_entry((head)->next, typeof(*pos), member); \
++ &pos->member != (head); \
++ pos = list_entry(pos->member.next, typeof(*pos), member))
++
++#endif
+Index: klibc-1.5/usr/utils/modprobe.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ klibc-1.5/usr/utils/modprobe.c 2008-03-08 03:05:51.847688952 +0100
+@@ -0,0 +1,1710 @@
++/* modprobe.c: insert a module into the kernel, intelligently.
++ Copyright (C) 2001 Rusty Russell.
++ Copyright (C) 2002, 2003 Rusty Russell, IBM Corporation.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++#define _GNU_SOURCE /* asprintf */
++
++#include <sys/utsname.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/mman.h>
++#include <fcntl.h>
++#include <stdarg.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <ctype.h>
++#include <string.h>
++#include <errno.h>
++#include <unistd.h>
++#include <dirent.h>
++#include <limits.h>
++#include <elf.h>
++#include <getopt.h>
++#include <fnmatch.h>
++#include <asm/unistd.h>
++#include <sys/wait.h>
++#include <syslog.h>
++#include <zlib.h>
++
++#define streq(a,b) (strcmp((a),(b)) == 0)
++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
++
++#include "list.h"
++static inline void try_old_version(const char *progname, char *argv[])
++{
++}
++extern long init_module(void *, unsigned long, const char *);
++extern long delete_module(const char *, unsigned int);
++
++struct module {
++ struct list_head list;
++ char *modname;
++ char filename[0];
++};
++
++#ifndef MODULE_DIR
++#define MODULE_DIR "/lib/modules"
++#endif
++
++typedef void (*errfn_t)(const char *fmt, ...);
++
++/* Do we use syslog or stderr for messages? */
++static int log;
++
++static void message(const char *prefix, const char *fmt, va_list *arglist)
++{
++ char *buf, *buf2;
++
++ vasprintf(&buf, fmt, *arglist);
++ asprintf(&buf2, "%s%s", prefix, buf);
++
++ if (log)
++ syslog(LOG_NOTICE, "%s", buf2);
++ else
++ fprintf(stderr, "%s", buf2);
++ free(buf2);
++ free(buf);
++}
++void *grab_contents(gzFile *gzfd, unsigned long *size)
++{
++ unsigned int max = 16384;
++ void *buffer = malloc(max);
++ int ret;
++
++ if (!buffer)
++ return NULL;
++
++ *size = 0;
++ while ((ret = gzread(gzfd, buffer + *size, max - *size)) > 0) {
++ *size += ret;
++ if (*size == max) {
++ buffer = realloc(buffer, max *= 2);
++ if (!buffer)
++ return NULL;
++ }
++ }
++ if (ret < 0) {
++ free(buffer);
++ buffer = NULL;
++ }
++ return buffer;
++}
++
++void *grab_fd(int fd, unsigned long *size)
++{
++ gzFile gzfd;
++
++ gzfd = gzdopen(fd, "rb");
++ if (!gzfd)
++ return NULL;
++
++ /* gzclose(gzfd) would close fd, which would drop locks.
++ Don't blame zlib: POSIX locking semantics are so horribly
++ broken that they should be ripped out. */
++ return grab_contents(gzfd, size);
++}
++void release_file(void *data, unsigned long size)
++{
++ free(data);
++}
++
++
++static int warned = 0;
++static void warn(const char *fmt, ...)
++{
++ va_list arglist;
++ warned++;
++ va_start(arglist, fmt);
++ message("WARNING: ", fmt, &arglist);
++ va_end(arglist);
++}
++
++static void fatal(const char *fmt, ...)
++{
++ va_list arglist;
++ va_start(arglist, fmt);
++ message("FATAL: ", fmt, &arglist);
++ va_end(arglist);
++ exit(1);
++}
++
++
++static void grammar(const char *cmd, const char *filename, unsigned int line)
++{
++ warn("%s line %u: ignoring bad line starting with '%s'\n",
++ filename, line, cmd);
++}
++
++static void *do_nofail(void *ptr, const char *file, int line, const char *expr)
++{
++ if (!ptr) {
++ fatal("Memory allocation failure %s line %d: %s.\n",
++ file, line, expr);
++ }
++ return ptr;
++}
++
++#define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__, #ptr)
++
++static void print_usage(const char *progname)
++{
++ fprintf(stderr,
++ "Usage: %s [-v] [-V] [-C config-file] [-n] [-i] [-q] [-b] [-o <modname>] <modname> [parameters...]\n"
++ "%s -r [-n] [-i] [-v] <modulename> ...\n"
++ "%s -l -t <dirname> [ -a <modulename> ...]\n",
++ progname, progname, progname);
++ exit(1);
++}
++
++static int fgetc_wrapped(FILE *file, unsigned int *linenum)
++{
++ for (;;) {
++ int ch = fgetc(file);
++ if (ch != '\\')
++ return ch;
++ ch = fgetc(file);
++ if (ch != '\n')
++ return ch;
++ if (linenum)
++ (*linenum)++;
++ }
++}
++
++static char *getline_wrapped(FILE *file, unsigned int *linenum)
++{
++ int size = 1024;
++ int i = 0;
++ char *buf = NOFAIL(malloc(size));
++ for(;;) {
++ int ch = fgetc_wrapped(file, linenum);
++ if (i == size) {
++ size *= 2;
++ buf = NOFAIL(realloc(buf, size));
++ }
++ if (ch < 0 && i == 0) {
++ free(buf);
++ return NULL;
++ }
++ if (ch < 0 || ch == '\n') {
++ if (linenum)
++ (*linenum)++;
++ buf[i] = '\0';
++ return NOFAIL(realloc(buf, i+1));
++ }
++ buf[i++] = ch;
++ }
++}
++
++static struct module *find_module(const char *filename, struct list_head *list)
++{
++ struct module *i;
++
++ list_for_each_entry(i, list, list) {
++ if (strcmp(i->filename, filename) == 0)
++ return i;
++ }
++ return NULL;
++}
++
++/* Convert filename to the module name. Works if filename == modname, too. */
++static void filename2modname(char *modname, const char *filename)
++{
++ const char *afterslash;
++ unsigned int i;
++
++ afterslash = strrchr(filename, '/');
++ if (!afterslash)
++ afterslash = filename;
++ else
++ afterslash++;
++
++ /* Convert to underscores, stop at first . */
++ for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) {
++ if (afterslash[i] == '-')
++ modname[i] = '_';
++ else
++ modname[i] = afterslash[i];
++ }
++ modname[i] = '\0';
++}
++
++static int lock_file(const char *filename)
++{
++ int fd = open(filename, O_RDWR, 0);
++
++ if (fd >= 0) {
++ struct flock lock;
++ lock.l_type = F_WRLCK;
++ lock.l_whence = SEEK_SET;
++ lock.l_start = 0;
++ lock.l_len = 1;
++ fcntl(fd, F_SETLKW, &lock);
++ } else
++ /* Read-only filesystem? There goes locking... */
++ fd = open(filename, O_RDONLY, 0);
++ return fd;
++}
++
++static void unlock_file(int fd)
++{
++ /* Valgrind is picky... */
++ close(fd);
++}
++
++static void add_module(char *filename, int namelen, struct list_head *list)
++{
++ struct module *mod;
++
++ /* If it's a duplicate: move it to the end, so it gets
++ inserted where it is *first* required. */
++ mod = find_module(filename, list);
++ if (mod)
++ list_del(&mod->list);
++ else {
++ /* No match. Create a new module. */
++ mod = NOFAIL(malloc(sizeof(struct module) + namelen + 1));
++ memcpy(mod->filename, filename, namelen);
++ mod->filename[namelen] = '\0';
++ mod->modname = NOFAIL(malloc(namelen + 1));
++ filename2modname(mod->modname, mod->filename);
++ }
++
++ list_add_tail(&mod->list, list);
++}
++
++/* Compare len chars of a to b, with _ and - equivalent. */
++static int modname_equal(const char *a, const char *b, unsigned int len)
++{
++ unsigned int i;
++
++ if (strlen(b) != len)
++ return 0;
++
++ for (i = 0; i < len; i++) {
++ if ((a[i] == '_' || a[i] == '-')
++ && (b[i] == '_' || b[i] == '-'))
++ continue;
++ if (a[i] != b[i])
++ return 0;
++ }
++ return 1;
++}
++
++/* Fills in list of modules if this is the line we want. */
++static int add_modules_dep_line(char *line,
++ const char *name,
++ struct list_head *list)
++{
++ char *ptr;
++ int len;
++ char *modname;
++
++ /* Ignore lines without : or which start with a # */
++ ptr = strchr(line, ':');
++ if (ptr == NULL || line[strspn(line, "\t ")] == '#')
++ return 0;
++