[oe] [PATCH 1/4] klibc: add 1.5.17

Eric Benard eric at eukrea.com
Sat Apr 24 13:14:45 UTC 2010


Tested only on x86, with kernel 2.6.33 and 2.6.32

Signed-off-by: Eric Benard <eric at eukrea.com>
---
 recipes/klibc/klibc-1.5.17/modprobe.patch | 1993 +++++++++++++++++++++++++++++
 recipes/klibc/klibc-1.5.17/wc.patch       |  245 ++++
 recipes/klibc/klibc_1.5.17.bb             |    9 +
 recipes/klibc/klibc_1.5.17.inc            |  185 +++
 4 files changed, 2432 insertions(+), 0 deletions(-)
 create mode 100644 recipes/klibc/klibc-1.5.17/modprobe.patch
 create mode 100644 recipes/klibc/klibc-1.5.17/wc.patch
 create mode 100644 recipes/klibc/klibc_1.5.17.bb
 create mode 100644 recipes/klibc/klibc_1.5.17.inc

diff --git a/recipes/klibc/klibc-1.5.17/modprobe.patch b/recipes/klibc/klibc-1.5.17/modprobe.patch
new file mode 100644
index 0000000..d89010c
--- /dev/null
+++ b/recipes/klibc/klibc-1.5.17/modprobe.patch
@@ -0,0 +1,1993 @@
+---
+ usr/utils/Kbuild     |    4 +-
+ usr/utils/list.h     |  238 +++++++
+ usr/utils/modprobe.c | 1710 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 1951 insertions(+), 1 deletions(-)
+ create mode 100644 usr/utils/list.h
+ create mode 100644 usr/utils/modprobe.c
+
+diff --git a/usr/utils/Kbuild b/usr/utils/Kbuild
+index 57e2d08..a52ea61 100644
+--- a/usr/utils/Kbuild
++++ b/usr/utils/Kbuild
+@@ -4,7 +4,7 @@
+ 
+ progs := chroot dd mkdir mkfifo mknod mount pivot_root umount
+ progs += true false sleep ln nuke minips cat ls losetup
+-progs += uname halt kill readlink cpio sync dmesg
++progs += uname halt kill readlink cpio sync dmesg modprobe
+ 
+ static-y := $(addprefix static/, $(progs))
+ shared-y := $(addprefix shared/, $(progs))
+@@ -58,6 +58,8 @@ static/sync-y       := sync.o
+ shared/sync-y       := sync.o
+ static/losetup-y    := losetup.o
+ shared/losetup-y    := losetup.o
++static/modprobe-y   := modprobe.o
++shared/modprobe-y   := modprobe.o
+ 
+ # Additionally linked targets
+ always := static/reboot static/poweroff shared/reboot shared/poweroff
+diff --git a/usr/utils/list.h b/usr/utils/list.h
+new file mode 100644
+index 0000000..511303d
+--- /dev/null
++++ b/usr/utils/list.h
+@@ -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
+diff --git a/usr/utils/modprobe.c b/usr/utils/modprobe.c
+new file mode 100644
+index 0000000..8e8a437
+--- /dev/null
++++ b/usr/utils/modprobe.c
+@@ -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;
++
++	/* Is this the module we are looking for? */
++	*ptr = '\0';
++	if (strrchr(line, '/'))
++		modname = strrchr(line, '/') + 1;
++	else
++		modname = line;
++
++	len = strlen(modname);
++	if (strchr(modname, '.'))
++		len = strchr(modname, '.') - modname;
++	if (!modname_equal(modname, name, len))
++		return 0;
++
++	/* Create the list. */
++	add_module(line, ptr - line, list);
++
++	ptr++;
++	for(;;) {
++		char *dep_start;
++		ptr += strspn(ptr, " \t");
++		if (*ptr == '\0')
++			break;
++		dep_start = ptr;
++		ptr += strcspn(ptr, " \t");
++		add_module(dep_start, ptr - dep_start, list);
++	}
++	return 1;
++}
++
++static void read_depends(const char *dirname,
++			 const char *start_name,
++			 struct list_head *list)
++{
++	char *modules_dep_name;
++	char *line;
++	FILE *modules_dep;
++	int done = 0;
++
++	asprintf(&modules_dep_name, "%s/%s", dirname, "modules.dep");
++	modules_dep = fopen(modules_dep_name, "r");
++	if (!modules_dep)
++		fatal("Could not load %s: %s\n",
++		      modules_dep_name, strerror(errno));
++
++	/* Stop at first line, as we can have duplicates (eg. symlinks
++           from boot/ */
++	while (!done && (line = getline_wrapped(modules_dep, NULL)) != NULL) {
++		done = add_modules_dep_line(line, start_name, list);
++		free(line);
++	}
++	fclose(modules_dep);
++	free(modules_dep_name);
++}
++
++/* We use error numbers in a loose translation... */
++static const char *insert_moderror(int err)
++{
++	switch (err) {
++	case ENOEXEC:
++		return "Invalid module format";
++	case ENOENT:
++		return "Unknown symbol in module, or unknown parameter (see dmesg)";
++	case ENOSYS:
++		return "Kernel does not have module support";
++	default:
++		return strerror(err);
++	}
++}
++
++static const char *remove_moderror(int err)
++{
++	switch (err) {
++	case ENOENT:
++		return "No such module";
++	case ENOSYS:
++		return "Kernel does not have module unloading support";
++	default:
++		return strerror(err);
++	}
++}
++
++/* Is module in /proc/modules?  If so, fill in usecount if not NULL. 
++   0 means no, 1 means yes, -1 means unknown.
++ */
++static int module_in_kernel(const char *modname, unsigned int *usecount)
++{
++	FILE *proc_modules;
++	char *line;
++
++again:
++	/* Might not be mounted yet.  Don't fail. */
++	proc_modules = fopen("/proc/modules", "r");
++	if (!proc_modules)
++		return -1;
++
++	while ((line = getline_wrapped(proc_modules, NULL)) != NULL) {
++		char *entry = strtok(line, " \n");
++
++		if (entry && streq(entry, modname)) {
++			/* If it exists, usecount is the third entry. */
++			if (!strtok(NULL, " \n"))
++				goto out;
++
++			if (!(entry = strtok(NULL, " \n"))) /* usecount */
++				goto out;
++			else
++				if (usecount)
++					*usecount = atoi(entry);
++
++			/* Followed by - then status. */
++			if (strtok(NULL, " \n")
++			    && (entry = strtok(NULL, " \n")) != NULL) {
++				/* Locking will fail on ro fs, we might hit
++				 * cases where module is in flux.  Spin. */
++				if (streq(entry, "Loading")
++				    || streq(entry, "Unloading")) {
++					usleep(100000);
++					free(line);
++					fclose(proc_modules);
++					goto again;
++				}
++			}
++
++		out:
++			free(line);
++			fclose(proc_modules);
++			return 1;
++		}
++		free(line);
++	}
++	fclose(proc_modules);
++	return 0;
++}
++
++static void replace_modname(struct module *module,
++			    void *mem, unsigned long len,
++			    const char *oldname, const char *newname)
++{
++	char *p;
++
++	/* 64 - sizeof(unsigned long) - 1 */
++	if (strlen(newname) > 55)
++		fatal("New name %s is too long\n", newname);
++
++	/* Find where it is in the module structure.  Don't assume layout! */
++	for (p = mem; p < (char *)mem + len - strlen(oldname); p++) {
++		if (memcmp(p, oldname, strlen(oldname)) == 0) {
++			strcpy(p, newname);
++			return;
++		}
++	}
++
++	warn("Could not find old name in %s to replace!\n", module->filename);
++}
++
++static void *get_section32(void *file,
++			   unsigned long size,
++			   const char *name,
++			   unsigned long *secsize)
++{
++	Elf32_Ehdr *hdr = file;
++	Elf32_Shdr *sechdrs = file + hdr->e_shoff;
++	const char *secnames;
++	unsigned int i;
++
++	/* Too short? */
++	if (size < sizeof(*hdr))
++		return NULL;
++	if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0]))
++		return NULL;
++	if (size < sechdrs[hdr->e_shstrndx].sh_offset)
++		return NULL;
++		
++	secnames = file + sechdrs[hdr->e_shstrndx].sh_offset;
++	for (i = 1; i < hdr->e_shnum; i++)
++		if (strcmp(secnames + sechdrs[i].sh_name, name) == 0) {
++			*secsize = sechdrs[i].sh_size;
++			return file + sechdrs[i].sh_offset;
++		}
++	return NULL;
++}
++
++static void *get_section64(void *file,
++			   unsigned long size,
++			   const char *name,
++			   unsigned long *secsize)
++{
++	Elf64_Ehdr *hdr = file;
++	Elf64_Shdr *sechdrs = file + hdr->e_shoff;
++	const char *secnames;
++	unsigned int i;
++
++	/* Too short? */
++	if (size < sizeof(*hdr))
++		return NULL;
++	if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0]))
++		return NULL;
++	if (size < sechdrs[hdr->e_shstrndx].sh_offset)
++		return NULL;
++		
++	secnames = file + sechdrs[hdr->e_shstrndx].sh_offset;
++	for (i = 1; i < hdr->e_shnum; i++)
++		if (strcmp(secnames + sechdrs[i].sh_name, name) == 0) {
++			*secsize = sechdrs[i].sh_size;
++			return file + sechdrs[i].sh_offset;
++		}
++	return NULL;
++}
++
++static int elf_ident(void *mod, unsigned long size)
++{
++	/* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
++	char *ident = mod;
++
++	if (size < EI_CLASS || memcmp(mod, ELFMAG, SELFMAG) != 0)
++		return ELFCLASSNONE;
++	return ident[EI_CLASS];
++}
++
++static void *get_section(void *file,
++			 unsigned long size,
++			 const char *name,
++			 unsigned long *secsize)
++{
++	switch (elf_ident(file, size)) {
++	case ELFCLASS32:
++		return get_section32(file, size, name, secsize);
++	case ELFCLASS64:
++		return get_section64(file, size, name, secsize);
++	default:
++		return NULL;
++	}
++}
++
++static void rename_module(struct module *module,
++			  void *mod,
++			  unsigned long len,
++			  const char *newname)
++{
++	void *modstruct;
++	unsigned long modstruct_len;
++
++	/* Old-style */
++	modstruct = get_section(mod, len, ".gnu.linkonce.this_module",
++				&modstruct_len);
++	/* New-style */
++	if (!modstruct)
++		modstruct = get_section(mod, len, "__module", &modstruct_len);
++	if (!modstruct)
++		warn("Could not find module name to change in %s\n",
++		     module->filename);
++	else
++		replace_modname(module, modstruct, modstruct_len,
++				module->modname, newname);
++}
++
++/* Kernel told to ignore these sections if SHF_ALLOC not set. */
++static void invalidate_section32(void *mod, const char *secname)
++{
++	Elf32_Ehdr *hdr = mod;
++	Elf32_Shdr *sechdrs = mod + hdr->e_shoff;
++	const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset;
++	unsigned int i;
++
++	for (i = 1; i < hdr->e_shnum; i++)
++		if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0)
++			sechdrs[i].sh_flags &= ~SHF_ALLOC;
++}
++
++static void invalidate_section64(void *mod, const char *secname)
++{
++	Elf64_Ehdr *hdr = mod;
++	Elf64_Shdr *sechdrs = mod + hdr->e_shoff;
++	const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset;
++	unsigned int i;
++
++	for (i = 1; i < hdr->e_shnum; i++)
++		if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0)
++			sechdrs[i].sh_flags &= ~(unsigned long long)SHF_ALLOC;
++}
++
++static void strip_section(struct module *module,
++			  void *mod,
++			  unsigned long len,
++			  const char *secname)
++{
++	switch (elf_ident(mod, len)) {
++	case ELFCLASS32:
++		invalidate_section32(mod, secname);
++		break;
++	case ELFCLASS64:
++		invalidate_section64(mod, secname);
++		break;
++	default:
++		warn("Unknown module format in %s: not forcing version\n",
++		     module->filename);
++	}
++}
++
++static const char *next_string(const char *string, unsigned long *secsize)
++{
++	/* Skip non-zero chars */
++	while (string[0]) {
++		string++;
++		if ((*secsize)-- <= 1)
++			return NULL;
++	}
++
++	/* Skip any zero padding. */
++	while (!string[0]) {
++		string++;
++		if ((*secsize)-- <= 1)
++			return NULL;
++	}
++	return string;
++}
++
++static void clear_magic(struct module *module, void *mod, unsigned long len)
++{
++	const char *p;
++	unsigned long modlen;
++
++	/* Old-style: __vermagic section */
++	strip_section(module, mod, len, "__vermagic");
++
++	/* New-style: in .modinfo section */
++	for (p = get_section(mod, len, ".modinfo", &modlen);
++	     p;
++	     p = next_string(p, &modlen)) {
++		if (strncmp(p, "vermagic=", strlen("vermagic=")) == 0) {
++			memset((char *)p, 0, strlen(p));
++			return;
++		}
++	}
++}
++
++struct module_options
++{
++	struct module_options *next;
++	char *modulename;
++	char *options;
++};
++
++struct module_command
++{
++	struct module_command *next;
++	char *modulename;
++	char *command;
++};
++
++struct module_alias
++{
++	struct module_alias *next;
++	char *module;
++};
++
++struct module_blacklist
++{
++	struct module_blacklist *next;
++	char *modulename;
++};
++
++/* Link in a new option line from the config file. */
++static struct module_options *
++add_options(const char *modname,
++	    const char *option,
++	    struct module_options *options)
++{
++	struct module_options *new;
++	char *tab; 
++
++	new = NOFAIL(malloc(sizeof(*new)));
++	new->modulename = NOFAIL(strdup(modname));
++	new->options = NOFAIL(strdup(option));
++	/* We can handle tabs, kernel can't. */
++	for (tab = strchr(new->options, '\t'); tab; tab = strchr(tab, '\t'))
++		*tab = ' ';
++	new->next = options;
++	return new;
++}
++
++/* Link in a new install line from the config file. */
++static struct module_command *
++add_command(const char *modname,
++	       const char *command,
++	       struct module_command *commands)
++{
++	struct module_command *new;
++
++	new = NOFAIL(malloc(sizeof(*new)));
++	new->modulename = NOFAIL(strdup(modname));
++	new->command = NOFAIL(strdup(command));
++	new->next = commands;
++	return new;
++}
++
++/* Link in a new alias line from the config file. */
++static struct module_alias *
++add_alias(const char *modname, struct module_alias *aliases)
++{
++	struct module_alias *new;
++
++	new = NOFAIL(malloc(sizeof(*new)));
++	new->module = NOFAIL(strdup(modname));
++	new->next = aliases;
++	return new;
++}
++
++/* Link in a new blacklist line from the config file. */
++static struct module_blacklist *
++add_blacklist(const char *modname, struct module_blacklist *blacklist)
++{
++	struct module_blacklist *new;
++
++	new = NOFAIL(malloc(sizeof(*new)));
++	new->modulename = NOFAIL(strdup(modname));
++	new->next = blacklist;
++	return new;
++}
++
++/* Find blacklist commands if any. */
++static  int
++find_blacklist(const char *modname, const struct module_blacklist *blacklist)
++{
++	while (blacklist) {
++		if (strcmp(blacklist->modulename, modname) == 0)
++			return 1;
++		blacklist = blacklist->next;
++	}
++	return 0;
++}
++
++/* return a new alias list, with backlisted elems filtered out */
++static struct module_alias *
++apply_blacklist(const struct module_alias *aliases,
++		const struct module_blacklist *blacklist)
++{
++	struct module_alias *result = NULL;
++	while (aliases) {
++		char *modname = aliases->module;
++		if (!find_blacklist(modname, blacklist))
++			result = add_alias(modname, result);
++		aliases = aliases->next;
++	}
++	return result;
++}
++
++/* Find install commands if any. */
++static const char *find_command(const char *modname,
++				const struct module_command *commands)
++{
++	while (commands) {
++		if (fnmatch(commands->modulename, modname, 0) == 0)
++			return commands->command;
++		commands = commands->next;
++	}
++	return NULL;
++}
++
++static char *append_option(char *options, const char *newoption)
++{
++	options = NOFAIL(realloc(options, strlen(options) + 1
++				 + strlen(newoption) + 1));
++	if (strlen(options)) strcat(options, " ");
++	strcat(options, newoption);
++	return options;
++}
++
++/* Add to options */
++static char *add_extra_options(const char *modname,
++			       char *optstring,
++			       const struct module_options *options)
++{
++	while (options) {
++		if (strcmp(options->modulename, modname) == 0)
++			optstring = append_option(optstring, options->options);
++		options = options->next;
++	}
++	return optstring;
++}
++
++/* If we don't flush, then child processes print before we do */
++static void verbose_printf(int verbose, const char *fmt, ...)
++{
++	va_list arglist;
++
++	if (verbose) {
++		va_start(arglist, fmt);
++		vprintf(fmt, arglist);
++		fflush(stdout);
++		va_end(arglist);
++	}
++}
++
++/* Do an install/remove command: replace $CMDLINE_OPTS if it's specified. */
++static void do_command(const char *modname,
++		       const char *command,
++		       int verbose, int dry_run,
++		       errfn_t error,
++		       const char *type,
++		       const char *cmdline_opts)
++{
++	int ret;
++	char *p, *replaced_cmd = NOFAIL(strdup(command));
++
++	while ((p = strstr(replaced_cmd, "$CMDLINE_OPTS")) != NULL) {
++		char *new;
++		asprintf(&new, "%.*s%s%s",
++			 p - replaced_cmd, replaced_cmd, cmdline_opts,
++			 p + strlen("$CMDLINE_OPTS"));
++		NOFAIL(new);
++		free(replaced_cmd);
++		replaced_cmd = new;
++	}
++
++	verbose_printf(verbose, "%s %s\n", type, replaced_cmd);
++	if (dry_run)
++		return;
++
++	setenv("MODPROBE_MODULE", modname, 1);
++	ret = system(replaced_cmd);
++	if (ret == -1 || WEXITSTATUS(ret))
++		error("Error running %s command for %s\n", type, modname);
++	free(replaced_cmd);
++}
++
++/* Actually do the insert.  Frees second arg. */
++static void insmod(struct list_head *list,
++		   char *optstring,
++		   const char *newname,
++		   int first_time,
++		   errfn_t error,
++		   int dry_run,
++		   int verbose,
++		   const struct module_options *options,
++		   const struct module_command *commands,
++		   int ignore_commands,
++		   int ignore_proc,
++		   int strip_vermagic,
++		   int strip_modversion,
++		   const char *cmdline_opts)
++{
++	int ret, fd;
++	unsigned long len;
++	void *map;
++	const char *command;
++	struct module *mod = list_entry(list->next, struct module, list);
++
++	/* Take us off the list. */
++	list_del(&mod->list);
++
++	/* Do things we (or parent) depend on first, but don't die if
++	 * they fail. */
++	if (!list_empty(list)) {
++		insmod(list, NOFAIL(strdup("")), NULL, 0, warn,
++		       dry_run, verbose, options, commands, 0, ignore_proc,
++		       strip_vermagic, strip_modversion, cmdline_opts);
++	}
++
++	/* Lock before we look, in case it's initializing. */
++	fd = lock_file(mod->filename);
++	if (fd < 0) {
++		error("Could not open '%s': %s\n",
++		      mod->filename, strerror(errno));
++		goto out_optstring;
++	}
++
++	/* Don't do ANYTHING if already in kernel. */
++	if (!ignore_proc
++	    && module_in_kernel(newname ?: mod->modname, NULL) == 1) {
++		if (first_time)
++			error("Module %s already in kernel.\n",
++			      newname ?: mod->modname);
++		goto out_unlock;
++	}
++
++	command = find_command(mod->modname, commands);
++	if (command && !ignore_commands) {
++		/* It might recurse: unlock. */
++		unlock_file(fd);
++		do_command(mod->modname, command, verbose, dry_run, error,
++			   "install", cmdline_opts);
++		goto out_optstring;
++	}
++
++	map = grab_fd(fd, &len);
++	if (!map) {
++		error("Could not read '%s': %s\n",
++		      mod->filename, strerror(errno));
++		goto out_unlock;
++	}
++
++	/* Rename it? */
++	if (newname)
++		rename_module(mod, map, len, newname);
++
++	if (strip_modversion)
++		strip_section(mod, map, len, "__versions");
++	if (strip_vermagic)
++		clear_magic(mod, map, len);
++
++	/* Config file might have given more options */
++	optstring = add_extra_options(mod->modname, optstring, options);
++
++	verbose_printf(verbose, "insmod %s %s\n", mod->filename, optstring);
++
++	if (dry_run)
++		goto out;
++
++	ret = init_module(map, len, optstring);
++	if (ret != 0) {
++		if (errno == EEXIST) {
++			if (first_time)
++				error("Module %s already in kernel.\n",
++				      newname ?: mod->modname);
++			goto out_unlock;
++		}
++		error("Error inserting %s (%s): %s\n",
++		      mod->modname, mod->filename, insert_moderror(errno));
++	}
++ out:
++	release_file(map, len);
++ out_unlock:
++	unlock_file(fd);
++ out_optstring:
++	free(optstring);
++	return;
++}
++
++/* Do recursive removal. */
++static void rmmod(struct list_head *list,
++		  const char *name,
++		  int first_time,
++		  errfn_t error,
++		  int dry_run,
++		  int verbose,
++		  struct module_command *commands,
++		  int ignore_commands,
++		  int ignore_inuse,
++		  const char *cmdline_opts)
++{
++	const char *command;
++	unsigned int usecount = 0;
++	int lock;
++	struct module *mod = list_entry(list->next, struct module, list);
++
++	/* Take first one off the list. */
++	list_del(&mod->list);
++
++	/* Ignore failure; it's best effort here. */
++	lock = lock_file(mod->filename);
++
++	if (!name)
++		name = mod->modname;
++
++	/* Even if renamed, find commands to orig. name. */
++	command = find_command(mod->modname, commands);
++	if (command && !ignore_commands) {
++		/* It might recurse: unlock. */
++		unlock_file(lock);
++		do_command(mod->modname, command, verbose, dry_run, error,
++			   "remove", cmdline_opts);
++		goto remove_rest_no_unlock;
++	}
++
++	if (module_in_kernel(name, &usecount) == 0)
++		goto nonexistent_module;
++
++	if (usecount != 0) {
++		if (!ignore_inuse)
++			error("Module %s is in use.\n", name);
++		goto remove_rest;
++	}
++
++	verbose_printf(verbose, "rmmod %s\n", mod->filename);
++
++	if (dry_run)
++		goto remove_rest;
++
++	if (delete_module(name, O_EXCL) != 0) {
++		if (errno == ENOENT)
++			goto nonexistent_module;
++		error("Error removing %s (%s): %s\n",
++		      name, mod->filename,
++		      remove_moderror(errno));
++	}
++
++ remove_rest:
++	unlock_file(lock);
++ remove_rest_no_unlock:
++	/* Now do things we depend. */
++	if (!list_empty(list))
++		rmmod(list, NULL, 0, warn, dry_run, verbose, commands,
++		      0, 1, cmdline_opts);
++	return;
++
++nonexistent_module:
++	if (first_time)
++		fatal("Module %s is not in kernel.\n", mod->modname);
++	goto remove_rest;
++}
++
++/* Does path contain directory(s) subpath? */
++static int type_matches(const char *path, const char *subpath)
++{
++	char *subpath_with_slashes;
++	int ret;
++
++	asprintf(&subpath_with_slashes, "/%s/", subpath);
++	NOFAIL(subpath_with_slashes);
++
++	ret = (strstr(path, subpath_with_slashes) != NULL);
++	free(subpath_with_slashes);
++	return ret;
++}
++
++static char *underscores(char *string)
++{
++	if (string) {
++		unsigned int i;
++		for (i = 0; string[i]; i++)
++			if (string[i] == '-')
++				string[i] = '_';
++	}
++	return string;
++}
++
++static int do_wildcard(const char *dirname,
++		       const char *type,
++		       const char *wildcard)
++{
++	char modules_dep_name[strlen(dirname) + sizeof("modules.dep") + 1];
++	char *line, *wcard;
++	FILE *modules_dep;
++
++	/* Canonicalize wildcard */
++	wcard = strdup(wildcard);
++	underscores(wcard);
++
++	sprintf(modules_dep_name, "%s/%s", dirname, "modules.dep");
++	modules_dep = fopen(modules_dep_name, "r");
++	if (!modules_dep)
++		fatal("Could not load %s: %s\n",
++		      modules_dep_name, strerror(errno));
++
++	while ((line = getline_wrapped(modules_dep, NULL)) != NULL) {
++		char *ptr;
++
++		/* Ignore lines without : or which start with a # */
++		ptr = strchr(line, ':');
++		if (ptr == NULL || line[strspn(line, "\t ")] == '#')
++			goto next;
++		*ptr = '\0';
++
++		/* "type" must match complete directory component(s). */
++		if (!type || type_matches(line, type)) {
++			char modname[strlen(line)+1];
++
++			filename2modname(modname, line);
++			if (fnmatch(wcard, modname, 0) == 0)
++				printf("%s\n", line);
++		}
++	next:
++		free(line);
++	}
++
++	free(wcard);
++	return 0;
++}
++
++static char *strsep_skipspace(char **string, char *delim)
++{
++	if (!*string)
++		return NULL;
++	*string += strspn(*string, delim);
++	return strsep(string, delim);
++}
++
++/* Recursion */
++static int read_config(const char *filename,
++		       const char *name,
++		       int dump_only,
++		       int removing,
++		       struct module_options **options,
++		       struct module_command **commands,
++		       struct module_alias **alias,
++		       struct module_blacklist **blacklist);
++
++/* FIXME: Maybe should be extended to "alias a b [and|or c]...". --RR */
++static int read_config_file(const char *filename,
++			    const char *name,
++			    int dump_only,
++			    int removing,
++			    struct module_options **options,
++			    struct module_command **commands,
++			    struct module_alias **aliases,
++			    struct module_blacklist **blacklist)
++{
++	char *line;
++	unsigned int linenum = 0;
++	FILE *cfile;
++
++	cfile = fopen(filename, "r");
++	if (!cfile)
++		return 0;
++
++	while ((line = getline_wrapped(cfile, &linenum)) != NULL) {
++		char *ptr = line;
++		char *cmd, *modname;
++
++		if (dump_only)
++			printf("%s\n", line);
++
++		cmd = strsep_skipspace(&ptr, "\t ");
++		if (cmd == NULL || cmd[0] == '#' || cmd[0] == '\0')
++			continue;
++
++		if (strcmp(cmd, "alias") == 0) {
++			char *wildcard
++				= underscores(strsep_skipspace(&ptr, "\t "));
++			char *realname
++				= underscores(strsep_skipspace(&ptr, "\t "));
++
++			if (!wildcard || !realname)
++				grammar(cmd, filename, linenum);
++			else if (fnmatch(wildcard,name,0) == 0)
++				*aliases = add_alias(realname, *aliases);
++		} else if (strcmp(cmd, "include") == 0) {
++			struct module_alias *newalias = NULL;
++			char *newfilename;
++
++			newfilename = strsep_skipspace(&ptr, "\t ");
++			if (!newfilename)
++				grammar(cmd, filename, linenum);
++			else {
++				if (!read_config(newfilename, name,
++						 dump_only, removing,
++						 options, commands, &newalias,
++						 blacklist))
++					warn("Failed to open included"
++					      " config file %s: %s\n",
++					      newfilename, strerror(errno));
++
++				/* Files included override aliases,
++				   etc that was already set ... */
++				if (newalias)
++					*aliases = newalias;
++			}
++		} else if (strcmp(cmd, "options") == 0) {
++			modname = strsep_skipspace(&ptr, "\t ");
++			if (!modname || !ptr)
++				grammar(cmd, filename, linenum);
++			else {
++				ptr += strspn(ptr, "\t ");
++				*options = add_options(underscores(modname),
++						       ptr, *options);
++			}
++		} else if (strcmp(cmd, "install") == 0) {
++			modname = strsep_skipspace(&ptr, "\t ");
++			if (!modname || !ptr)
++				grammar(cmd, filename, linenum);
++			else if (!removing) {
++				ptr += strspn(ptr, "\t ");
++				*commands = add_command(underscores(modname),
++							ptr, *commands);
++			}
++		} else if (strcmp(cmd, "blacklist") == 0) {
++			modname = strsep_skipspace(&ptr, "\t ");
++			if (!modname)
++				grammar(cmd, filename, linenum);
++			else if (!removing) {
++				*blacklist = add_blacklist(underscores(modname),
++							*blacklist);
++			}
++		} else if (strcmp(cmd, "remove") == 0) {
++			modname = strsep_skipspace(&ptr, "\t ");
++			if (!modname || !ptr)
++				grammar(cmd, filename, linenum);
++			else if (removing) {
++				ptr += strspn(ptr, "\t ");
++				*commands = add_command(underscores(modname),
++							ptr, *commands);
++			}
++		} else
++			grammar(cmd, filename, linenum);
++
++		free(line);
++	}
++	fclose(cfile);
++	return 1;
++}
++
++/* Simple format, ignore lines starting with #, one command per line.
++   Returns true or false. */
++static int read_config(const char *filename,
++		       const char *name,
++		       int dump_only,
++		       int removing,
++		       struct module_options **options,
++		       struct module_command **commands,
++		       struct module_alias **aliases,
++		       struct module_blacklist **blacklist)
++{
++	DIR *dir;
++	int ret = 0;
++
++	/* ignore everything in this directory */
++	if (streq(filename, "/etc/modprobe.d/arch"))
++		return 1;
++
++	/* Reiser4 has file/directory duality: treat it as both. */
++	dir = opendir(filename);
++	if (dir) {
++		struct dirent *i;
++		while ((i = readdir(dir)) != NULL) {
++			if (!streq(i->d_name,".") && !streq(i->d_name,"..")) {
++				char sub[strlen(filename) + 1
++					 + strlen(i->d_name) + 1];
++
++				sprintf(sub, "%s/%s", filename, i->d_name);
++				if (!read_config(sub, name,
++						 dump_only, removing, options,
++						 commands, aliases, blacklist))
++					warn("Failed to open"
++					     " config file %s: %s\n",
++					     sub, strerror(errno));
++			}
++		}
++		closedir(dir);
++		ret = 1;
++	}
++
++	if (read_config_file(filename, name, dump_only, removing,
++			     options, commands, aliases, blacklist))
++		ret = 1;
++
++	return ret;
++}
++
++static const char *default_configs[] = 
++{
++	"/etc/modprobe.conf",
++	"/etc/modprobe.d",
++};
++
++static void read_toplevel_config(const char *filename,
++				 const char *name,
++				 int dump_only,
++				 int removing,
++				 struct module_options **options,
++				 struct module_command **commands,
++				 struct module_alias **aliases,
++				 struct module_blacklist **blacklist)
++{
++	unsigned int i;
++
++	if (filename) {
++		if (!read_config(filename, name, dump_only, removing,
++				 options, commands, aliases, blacklist))
++			fatal("Failed to open config file %s: %s\n",
++			      filename, strerror(errno));
++		return;
++	}
++
++	/* Try defaults. */
++	for (i = 0; i < ARRAY_SIZE(default_configs); i++) {
++		if (read_config(default_configs[i], name, dump_only, removing,
++				options, commands, aliases, blacklist))
++			return;
++	}
++}
++
++static void add_to_env_var(const char *option)
++{
++	const char *oldenv;
++
++	if ((oldenv = getenv("MODPROBE_OPTIONS")) != NULL) {
++		char *newenv;
++		asprintf(&newenv, "%s %s", oldenv, option);
++		setenv("MODPROBE_OPTIONS", newenv, 1);
++	} else
++		setenv("MODPROBE_OPTIONS", option, 1);
++}
++
++/* Prepend options from environment. */
++static char **merge_args(char *args, char *argv[], int *argc)
++{
++	char *arg, *argstring;
++	char **newargs = NULL;
++	unsigned int i, num_env = 0;
++
++	if (!args)
++		return argv;
++
++	argstring = NOFAIL(strdup(args));
++	for (arg = strtok(argstring, " "); arg; arg = strtok(NULL, " ")) {
++		num_env++;
++		newargs = NOFAIL(realloc(newargs,
++					 sizeof(newargs[0])
++					 * (num_env + *argc + 1)));
++		newargs[num_env] = arg;
++	}
++
++	/* Append commandline args */
++	newargs[0] = argv[0];
++	for (i = 1; i <= *argc; i++)
++		newargs[num_env+i] = argv[i];
++
++	*argc += num_env;
++	return newargs;
++}
++
++static char *gather_options(char *argv[])
++{
++	char *optstring = NOFAIL(strdup(""));
++
++	/* Rest is module options */
++	while (*argv) {
++		/* Quote value if it contains spaces. */
++		unsigned int eq = strcspn(*argv, "=");
++
++		if (strchr(*argv+eq, ' ') && !strchr(*argv, '"')) {
++			char quoted[strlen(*argv) + 3];
++			(*argv)[eq] = '\0';
++			sprintf(quoted, "%s=\"%s\"", *argv, *argv+eq+1);
++			optstring = append_option(optstring, quoted);
++		} else
++			optstring = append_option(optstring, *argv);
++		argv++;
++	}
++	return optstring;
++}
++
++static void handle_module(const char *modname,
++			  struct list_head *todo_list,
++			  const char *newname,
++			  int remove,
++			  char *options,
++			  int first_time,
++			  errfn_t error,
++			  int dry_run,
++			  int verbose,
++			  struct module_options *modoptions,
++			  struct module_command *commands,
++			  int ignore_commands,
++			  int ignore_proc,
++			  int strip_vermagic,
++			  int strip_modversion,
++			  int unknown_silent,
++			  const char *cmdline_opts)
++{
++	if (list_empty(todo_list)) {
++		const char *command;
++
++		/* The dependencies have to be real modules, but
++		   handle case where the first is completely bogus. */
++		command = find_command(modname, commands);
++		if (command && !ignore_commands) {
++			do_command(modname, command, verbose, dry_run, error,
++				   remove ? "remove":"install", cmdline_opts);
++			return;
++		}
++
++		if (unknown_silent)
++			exit(1);
++		error("Module %s not found.\n", modname);
++		return;
++	}
++
++	if (remove)
++		rmmod(todo_list, newname, first_time, error, dry_run, verbose,
++		      commands, ignore_commands, 0, cmdline_opts);
++	else
++		insmod(todo_list, NOFAIL(strdup(options)), newname,
++		       first_time, error, dry_run, verbose, modoptions,
++		       commands, ignore_commands, ignore_proc, strip_vermagic,
++		       strip_modversion, cmdline_opts);
++}
++
++static struct option options[] = { { "verbose", 0, NULL, 'v' },
++				   { "version", 0, NULL, 'V' },
++				   { "config", 1, NULL, 'C' },
++				   { "name", 1, NULL, 'o' },
++				   { "remove", 0, NULL, 'r' },
++				   { "showconfig", 0, NULL, 'c' },
++				   { "autoclean", 0, NULL, 'k' },
++				   { "quiet", 0, NULL, 'q' },
++				   { "show", 0, NULL, 'n' },
++				   { "dry-run", 0, NULL, 'n' },
++				   { "syslog", 0, NULL, 's' },
++				   { "type", 1, NULL, 't' },
++				   { "list", 0, NULL, 'l' },
++				   { "all", 0, NULL, 'a' },
++				   { "ignore-install", 0, NULL, 'i' },
++				   { "ignore-remove", 0, NULL, 'i' },
++				   { "force", 0, NULL, 'f' },
++				   { "force-vermagic", 0, NULL, 1 },
++				   { "force-modversion", 0, NULL, 2 },
++				   { "set-version", 1, NULL, 'S' },
++				   { "show-depends", 0, NULL, 'D' },
++				   { "first-time", 0, NULL, 3 },
++				   { "use-blacklist", 0, NULL, 'b' },
++				   { NULL, 0, NULL, 0 } };
++
++#define MODPROBE_DEVFSD_CONF "/etc/modprobe.devfs"
++
++/* This is a horrible hack to allow devfsd, which calls modprobe with
++   -C /etc/modules.conf or /etc/modules.devfs, to work.  FIXME. */
++/* Modern devfsd or variants should use -q explicitly in 2.6. */
++static int is_devfs_call(char *argv[])
++{
++	unsigned int i;
++
++	/* Look for "/dev" arg */
++	for (i = 1; argv[i]; i++) {
++		if (strncmp(argv[i], "/dev/", 5) == 0)
++			return 1;
++	}
++	return 0;
++}
++
++int main(int argc, char *argv[])
++{
++	struct utsname buf;
++	struct stat statbuf;
++	int opt;
++	int dump_only = 0;
++	int dry_run = 0;
++	int remove = 0;
++	int verbose = 0;
++	int unknown_silent = 0;
++	int list_only = 0;
++	int all = 0;
++	int ignore_commands = 0;
++	int strip_vermagic = 0;
++	int strip_modversion = 0;
++	int ignore_proc = 0;
++	int first_time = 0;
++	int use_blacklist = 0;
++	unsigned int i, num_modules;
++	char *type = NULL;
++	const char *config = NULL;
++	char *dirname, *optstring;
++	char *newname = NULL;
++	char *aliasfilename, *symfilename;
++	errfn_t error = fatal;
++
++	/* Prepend options from environment. */
++	argv = merge_args(getenv("MODPROBE_OPTIONS"), argv, &argc);
++
++	/* --set-version overrides version, and disables backwards compat. */
++	for (opt = 1; opt < argc; opt++)
++		if (strncmp(argv[opt],"--set-version",strlen("--set-version"))
++		    == 0)
++			break;
++
++	if (opt == argc)
++		try_old_version("modprobe", argv);
++
++	uname(&buf);
++	while ((opt = getopt_long(argc, argv, "vVC:o:rknqQsclt:aifb", options, NULL)) != -1){
++		switch (opt) {
++		case 'v':
++			add_to_env_var("-v");
++			verbose = 1;
++			break;
++		case 'V':
++			puts("module-init-tools version 3.2.2");
++			exit(0);
++		case 'S':
++			strncpy(buf.release, optarg, sizeof(buf.release));
++			buf.release[sizeof(buf.release)-1] = '\0';
++			break;
++		case 'C':
++			if (is_devfs_call(argv)) {
++				if (streq("/etc/modules.devfs", optarg)) {
++					config = MODPROBE_DEVFSD_CONF;
++					add_to_env_var("-C");
++					add_to_env_var(config);
++					/* Fall thru to -q */
++				} else if (streq("/etc/modules.conf", optarg))
++					/* Ignore config, fall thru to -q */
++					;
++				else {
++					/* False alarm.  Treat as normal. */
++					config = optarg;
++					add_to_env_var("-C");
++					add_to_env_var(config);
++					break;
++				}
++			} else {
++				config = optarg;
++				add_to_env_var("-C");
++				add_to_env_var(config);
++				break;
++			}
++		case 'q':
++			unknown_silent = 1;
++			add_to_env_var("-q");
++			break;
++		case 'D':
++			dry_run = 1;
++			ignore_proc = 1;
++			verbose = 1;
++			add_to_env_var("-D");
++			break;
++		case 'o':
++			newname = optarg;
++			break;
++		case 'r':
++			remove = 1;
++			break;
++		case 'c':
++			dump_only = 1;
++			break;
++		case 't':
++			type = optarg;
++			break;
++		case 'l':
++			list_only = 1;
++			break;
++		case 'a':
++			all = 1;
++			error = warn;
++			break;
++		case 'k':
++			/* FIXME: This should actually do something */
++			break;
++		case 'n':
++			dry_run = 1;
++			break;
++		case 's':
++			add_to_env_var("-s");
++			log = 1;
++			break;
++		case 'i':
++			ignore_commands = 1;
++			break;
++		case 'f':
++			strip_vermagic = 1;
++			strip_modversion = 1;
++			break;
++		case 'b':
++			use_blacklist = 1;
++			break;
++		case 1:
++			strip_vermagic = 1;
++			break;
++		case 2:
++			strip_modversion = 1;
++			break;
++		case 3:
++			first_time = 1;
++			break;
++		default:
++			print_usage(argv[0]);
++		}
++	}
++
++	/* If stderr not open, go to syslog */
++	if (log || fstat(STDERR_FILENO, &statbuf) != 0) {
++		openlog("modprobe", LOG_CONS, LOG_DAEMON);
++		log = 1;
++	}
++
++	if (argc < optind + 1 && !dump_only && !list_only && !remove)
++		print_usage(argv[0]);
++
++	dirname = NOFAIL(malloc(strlen(buf.release) + sizeof(MODULE_DIR) + 1));
++	sprintf(dirname, "%s/%s", MODULE_DIR, buf.release);
++	aliasfilename = NOFAIL(malloc(strlen(dirname)
++				      + sizeof("/modules.alias")));
++	sprintf(aliasfilename, "%s/modules.alias", dirname);
++	symfilename = NOFAIL(malloc(strlen(dirname)
++				    + sizeof("/modules.symbols")));
++	sprintf(symfilename, "%s/modules.symbols", dirname);
++
++	/* Old-style -t xxx wildcard?  Only with -l. */
++	if (list_only) {
++		if (optind+1 < argc)
++			fatal("Can't have multiple wildcards\n");
++		/* fprintf(stderr, "man find\n"); return 1; */
++		return do_wildcard(dirname, type, argv[optind]?:"*");
++	}
++	if (type)
++		fatal("-t only supported with -l");
++
++	if (dump_only) {
++		struct module_command *commands = NULL;
++		struct module_options *modoptions = NULL;
++		struct module_alias *aliases = NULL;
++		struct module_blacklist *blacklist = NULL;
++
++		read_toplevel_config(config, "", 1, 0,
++			     &modoptions, &commands, &aliases, &blacklist);
++		read_config(aliasfilename, "", 1, 0,&modoptions, &commands,
++			    &aliases, &blacklist);
++		read_config(symfilename, "", 1, 0, &modoptions, &commands,
++			    &aliases, &blacklist);
++		exit(0);
++	}
++
++	if (remove || all) {
++		num_modules = argc - optind;
++		optstring = NOFAIL(strdup(""));
++	} else {
++		num_modules = 1;
++		optstring = gather_options(argv+optind+1);
++	}
++
++	/* num_modules is always 1 except for -r or -a. */
++	for (i = 0; i < num_modules; i++) {
++		struct module_command *commands = NULL;
++		struct module_options *modoptions = NULL;
++		struct module_alias *aliases = NULL;
++		struct module_blacklist *blacklist = NULL;
++		LIST_HEAD(list);
++		char *modulearg = argv[optind + i];
++
++		/* Convert name we are looking for */
++		underscores(modulearg);
++
++		/* Returns the resolved alias, options */
++		read_toplevel_config(config, modulearg, 0,
++		     remove, &modoptions, &commands, &aliases, &blacklist);
++
++		/* No luck?  Try symbol names, if starts with symbol:. */
++		if (!aliases
++		    && strncmp(modulearg, "symbol:", strlen("symbol:")) == 0)
++			read_config(symfilename, modulearg, 0,
++			    remove, &modoptions, &commands,
++			    	&aliases, &blacklist);
++
++		if (!aliases) {
++			/* We only use canned aliases as last resort. */
++			read_depends(dirname, modulearg, &list);
++
++			if (list_empty(&list)
++			    && !find_command(modulearg, commands))
++			{
++				read_config(aliasfilename, modulearg, 0,
++					    remove, &modoptions, &commands,
++					    &aliases, &blacklist);
++				aliases = apply_blacklist(aliases, blacklist);
++			}
++		}
++
++		if (aliases) {
++			errfn_t err = error;
++
++			/* More than one alias?  Don't bail out on failure. */
++			if (aliases->next)
++				err = warn;
++			while (aliases) {
++				/* Add the options for this alias. */
++				char *opts = NOFAIL(strdup(optstring));
++				opts = add_extra_options(modulearg,
++							 opts, modoptions);
++
++				read_depends(dirname, aliases->module, &list);
++				handle_module(aliases->module, &list, newname,
++					      remove, opts, first_time, err,
++					      dry_run, verbose, modoptions,
++					      commands, ignore_commands,
++					      ignore_proc, strip_vermagic,
++					      strip_modversion,
++					      unknown_silent,
++					      optstring);
++
++				aliases = aliases->next;
++				INIT_LIST_HEAD(&list);
++			}
++		} else {
++			if (use_blacklist
++			    && find_blacklist(modulearg, blacklist))
++				continue;
++
++			handle_module(modulearg, &list, newname, remove,
++				      optstring, first_time, error, dry_run,
++				      verbose, modoptions, commands,
++				      ignore_commands, ignore_proc,
++				      strip_vermagic, strip_modversion,
++				      unknown_silent, optstring);
++		}
++	}
++	if (log)
++		closelog();
++
++	return 0;
++}
+-- 
+1.6.3.3
+
diff --git a/recipes/klibc/klibc-1.5.17/wc.patch b/recipes/klibc/klibc-1.5.17/wc.patch
new file mode 100644
index 0000000..9063a5a
--- /dev/null
+++ b/recipes/klibc/klibc-1.5.17/wc.patch
@@ -0,0 +1,245 @@
+---
+ usr/utils/Kbuild |    4 +-
+ usr/utils/wc.c   |  208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 211 insertions(+), 1 deletions(-)
+ create mode 100644 usr/utils/wc.c
+
+diff --git a/usr/utils/Kbuild b/usr/utils/Kbuild
+index a52ea61..7c8ccfb 100644
+--- a/usr/utils/Kbuild
++++ b/usr/utils/Kbuild
+@@ -3,7 +3,7 @@
+ #
+ 
+ progs := chroot dd mkdir mkfifo mknod mount pivot_root umount
+-progs += true false sleep ln nuke minips cat ls losetup
++progs += true false sleep ln nuke minips cat ls losetup wc
+ progs += uname halt kill readlink cpio sync dmesg modprobe
+ 
+ static-y := $(addprefix static/, $(progs))
+@@ -60,6 +60,8 @@ static/losetup-y    := losetup.o
+ shared/losetup-y    := losetup.o
+ static/modprobe-y   := modprobe.o
+ shared/modprobe-y   := modprobe.o
++static/wc-y	    := wc.o
++shared/wc-y	    := wc.o
+ 
+ # Additionally linked targets
+ always := static/reboot static/poweroff shared/reboot shared/poweroff
+diff --git a/usr/utils/wc.c b/usr/utils/wc.c
+new file mode 100644
+index 0000000..f5059fc
+--- /dev/null
++++ b/usr/utils/wc.c
+@@ -0,0 +1,208 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * wc implementation for busybox
++ *
++ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
++ *
++ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
++ */
++
++/* BB_AUDIT SUSv3 _NOT_ compliant -- option -m is not currently supported. */
++/* http://www.opengroup.org/onlinepubs/007904975/utilities/wc.html */
++
++/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
++ *
++ * Rewritten to fix a number of problems and do some size optimizations.
++ * Problems in the previous busybox implementation (besides bloat) included:
++ *  1) broken 'wc -c' optimization (read note below)
++ *  2) broken handling of '-' args
++ *  3) no checking of ferror on EOF returns
++ *  4) isprint() wasn't considered when word counting.
++ *
++ * TODO:
++ *
++ * When locale support is enabled, count multibyte chars in the '-m' case.
++ *
++ * NOTES:
++ *
++ * The previous busybox wc attempted an optimization using stat for the
++ * case of counting chars only.  I omitted that because it was broken.
++ * It didn't take into account the possibility of input coming from a
++ * pipe, or input from a file with file pointer not at the beginning.
++ *
++ * To implement such a speed optimization correctly, not only do you
++ * need the size, but also the file position.  Note also that the
++ * file position may be past the end of file.  Consider the example
++ * (adapted from example in gnu wc.c)
++ *
++ *      echo hello > /tmp/testfile &&
++ *      (dd ibs=1k skip=1 count=0 &> /dev/null; wc -c) < /tmp/testfile
++ *
++ * for which 'wc -c' should output '0'.
++ */
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#undef isspace
++#undef isprint
++#define isspace(c) ((((c) == ' ') || (((unsigned int)((c) - 9)) <= (13 - 9))))
++#define isprint(c) (((unsigned int)((c) - 0x20)) <= (0x7e - 0x20))
++#define isspace_given_isprint(c) ((c) == ' ')
++
++#define COUNT_T unsigned long
++#define COUNT_FMT "u"
++#define optind 1
++FILE *fopen_or_warn_stdin(const char *filename)
++{
++        FILE *fp = stdin;
++
++        if (filename[0]) {
++                fp = fopen(filename, "r");
++        }
++
++        return fp;
++}
++
++enum {
++	WC_LINES	= 0,
++	WC_WORDS	= 1,
++	WC_CHARS	= 2,
++	WC_LENGTH	= 3
++};
++
++int main(int argc, char **argv)
++{
++	FILE *fp;
++	const char *s, *arg;
++	const char *start_fmt = "%9"COUNT_FMT;
++	const char *fname_fmt = " %s\n";
++	COUNT_T *pcounts;
++	COUNT_T counts[4];
++	COUNT_T totals[4];
++	unsigned linepos;
++	unsigned u;
++	int num_files = 0;
++	int c;
++	signed char status = EXIT_SUCCESS;
++	signed char in_word;
++	unsigned print_type;
++
++	print_type = getopt(argc, argv, "lwcL");
++
++	if (print_type == 0) {
++		print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS);
++	}
++
++	argv += optind;
++	if (!argv[0]) {
++		*--argv = (char *) "wc";
++		fname_fmt = "\n";
++		if (!((print_type-1) & print_type)) /* exactly one option? */
++			start_fmt = "%"COUNT_FMT;
++	}
++
++	memset(totals, 0, sizeof(totals));
++
++	pcounts = counts;
++
++	while ((arg = *argv++) != 0) {
++		++num_files;
++		fp = fopen_or_warn_stdin(arg);
++		if (!fp) {
++			status = EXIT_FAILURE;
++			continue;
++		}
++
++		memset(counts, 0, sizeof(counts));
++		linepos = 0;
++		in_word = 0;
++
++		do {
++			/* Our -w doesn't match GNU wc exactly... oh well */
++
++			++counts[WC_CHARS];
++			c = getc(fp);
++			if (isprint(c)) {
++				++linepos;
++				if (!isspace_given_isprint(c)) {
++					in_word = 1;
++					continue;
++				}
++			} else if (((unsigned int)(c - 9)) <= 4) {
++				/* \t  9
++				 * \n 10
++				 * \v 11
++				 * \f 12
++				 * \r 13
++				 */
++				if (c == '\t') {
++					linepos = (linepos | 7) + 1;
++				} else {			/* '\n', '\r', '\f', or '\v' */
++				DO_EOF:
++					if (linepos > counts[WC_LENGTH]) {
++						counts[WC_LENGTH] = linepos;
++					}
++					if (c == '\n') {
++						++counts[WC_LINES];
++					}
++					if (c != '\v') {
++						linepos = 0;
++					}
++				}
++			} else if (c == EOF) {
++/*				if (ferror(fp)) {
++					status = EXIT_FAILURE;
++				}
++*/				--counts[WC_CHARS];
++				goto DO_EOF;		/* Treat an EOF as '\r'. */
++			} else {
++				continue;
++			}
++
++			counts[WC_WORDS] += in_word;
++			in_word = 0;
++			if (c == EOF) {
++				break;
++			}
++		} while (1);
++
++		if (totals[WC_LENGTH] < counts[WC_LENGTH]) {
++			totals[WC_LENGTH] = counts[WC_LENGTH];
++		}
++		totals[WC_LENGTH] -= counts[WC_LENGTH];
++
++		if(fp != stdin)
++			fclose(fp);
++
++	OUTPUT:
++		/* coreutils wc tries hard to print pretty columns
++		 * (saves results for all files, find max col len etc...)
++		 * we won't try that hard, it will bloat us too much */
++		s = start_fmt;
++		u = 0;
++		do {
++			if (print_type & (1 << u)) {
++				printf(s, pcounts[u]);
++				s = " %9"COUNT_FMT; /* Ok... restore the leading space. */
++			}
++			totals[u] += pcounts[u];
++		} while (++u < 4);
++		printf(fname_fmt, arg);
++	}
++
++	/* If more than one file was processed, we want the totals.  To save some
++	 * space, we set the pcounts ptr to the totals array.  This has the side
++	 * effect of trashing the totals array after outputting it, but that's
++	 * irrelavent since we no longer need it. */
++	if (num_files > 1) {
++		num_files = 0;				/* Make sure we don't get here again. */
++		arg = "total";
++		pcounts = totals;
++		--argv;
++		goto OUTPUT;
++	}
++
++	fflush(stdout);
++	exit(status);
++}
+-- 
+1.6.3.3
+
diff --git a/recipes/klibc/klibc_1.5.17.bb b/recipes/klibc/klibc_1.5.17.bb
new file mode 100644
index 0000000..09844b3
--- /dev/null
+++ b/recipes/klibc/klibc_1.5.17.bb
@@ -0,0 +1,9 @@
+require klibc_1.5.17.inc
+PR = "r1"
+
+DEFAULT_PREFERENCE = "-1"
+DEFAULT_PREFERENCE_aquides = "1"
+
+SRC_URI[md5sum] = "5ac5b944223f63ed037350795924d1b9"
+SRC_URI[sha256sum] = "a67b976db1958a66bb4887d70c45f83f63751a287b5a715c929fb69bdcd7b1ca"
+
diff --git a/recipes/klibc/klibc_1.5.17.inc b/recipes/klibc/klibc_1.5.17.inc
new file mode 100644
index 0000000..6dd7e13
--- /dev/null
+++ b/recipes/klibc/klibc_1.5.17.inc
@@ -0,0 +1,185 @@
+require klibc-common.inc
+
+SRC_URI += "file://fstype-sane-vfat-and-jffs2-for-1.5.patch;patch=1 \
+            file://modprobe.patch;patch=1 \
+            file://dash_readopt.patch;patch=1 \
+            file://wc.patch;patch=1 \
+            file://klibc_kexecsyscall.patch;patch=1 \
+            file://mntproc-definitions.patch;patch=1 \
+            file://isystem.patch;patch=1 \
+	    "
+
+DEFAULT_PREFERENCE = "-1"
+
+KLIBC_ARCH_x86 = 'x86'
+KLIBC_ARCH_i486 = 'x86'
+KLIBC_ARCH_i586 = 'x86'
+KLIBC_ARCH_i686 = 'x86'
+KLIBC_ARCH_pentium = 'x86'
+
+EXTRA_OEMAKE = "'KLIBCARCH=${KLIBC_ARCH}' \
+                'CROSS_COMPILE=${TARGET_PREFIX}' \
+		'KLIBCKERNELSRC=${STAGING_KERNEL_DIR}' \
+                "
+
+do_configure () {
+	ln -sf ${STAGING_KERNEL_DIR} linux
+	cd ${S}/usr/klibc/arch/
+	ln -s i386 x86
+	cd ${S}/usr/include/arch/
+	ln -s i386 x86
+	cd ${S}
+}
+
+# we want only the shared programms and the lib so we chose them manually
+do_install() {
+        install -d ${D}${base_bindir}
+        install -m 755 usr/dash/sh.shared ${D}${base_bindir}/sh
+        install -m 755 usr/gzip/gzip ${D}${base_bindir}
+        install -m 755 usr/kinit/kinit.shared ${D}${base_bindir}/kinit
+        install -m 755 usr/kinit/fstype/shared/fstype ${D}${base_bindir}
+        install -m 755 usr/kinit/ipconfig/shared/ipconfig ${D}${base_bindir}
+        install -m 755 usr/kinit/nfsmount/shared/nfsmount ${D}${base_bindir}
+        install -m 755 usr/kinit/resume/shared/resume ${D}${base_bindir}
+        install -m 755 usr/kinit/run-init/shared/run-init ${D}${base_bindir}
+        install -m 755 usr/utils/shared/cat ${D}${base_bindir}
+        install -m 755 usr/utils/shared/chroot ${D}${base_bindir}
+        install -m 755 usr/utils/shared/cpio ${D}${base_bindir}
+        install -m 755 usr/utils/shared/dd ${D}${base_bindir}
+        install -m 755 usr/utils/shared/dmesg ${D}${base_bindir}
+        install -m 755 usr/utils/shared/false ${D}${base_bindir}
+        install -m 755 usr/utils/shared/halt ${D}${base_bindir}
+        install -m 755 usr/utils/shared/kill ${D}${base_bindir}
+        install -m 755 usr/utils/shared/ln ${D}${base_bindir}
+        install -m 755 usr/utils/shared/minips ${D}${base_bindir}
+        install -m 755 usr/utils/shared/mkdir ${D}${base_bindir}
+        install -m 755 usr/utils/shared/mkfifo ${D}${base_bindir}
+        install -m 755 usr/utils/shared/mknod ${D}${base_bindir}
+        install -m 755 usr/utils/shared/mount ${D}${base_bindir}
+        install -m 755 usr/utils/shared/nuke ${D}${base_bindir}
+        install -m 755 usr/utils/shared/pivot_root ${D}${base_bindir}
+        install -m 755 usr/utils/shared/poweroff ${D}${base_bindir}
+        install -m 755 usr/utils/shared/readlink ${D}${base_bindir}
+        install -m 755 usr/utils/shared/reboot ${D}${base_bindir}
+        install -m 755 usr/utils/shared/sleep ${D}${base_bindir}
+        install -m 755 usr/utils/shared/sync ${D}${base_bindir}
+        install -m 755 usr/utils/shared/true ${D}${base_bindir}
+        install -m 755 usr/utils/shared/umount ${D}${base_bindir}
+        install -m 755 usr/utils/shared/uname ${D}${base_bindir}
+        install -m 755 usr/utils/shared/modprobe ${D}${base_bindir}
+        install -m 755 usr/utils/shared/losetup ${D}${base_bindir}
+        install -m 755 usr/utils/shared/wc ${D}${base_bindir}
+        install -m 755 usr/utils/shared/ls ${D}${base_bindir}
+
+        install -d ${D}${base_libdir}
+        install -m 755 usr/klibc/klibc-*.so ${D}${base_libdir}
+        cd ${D}${base_libdir}
+        ln -s klibc-*.so klibc.so
+        cd -
+        cd ${D}${base_bindir}
+        ln -s gzip gunzip
+        ln -s gzip zcat
+        cd -
+}
+
+EXTRA_OEMAKE += "INSTALLROOT=${STAGING_DIR_TARGET}"
+do_stage() {
+        oe_runmake  install
+        cp '${STAGING_DIR_TARGET}/bin/klcc'  '${CROSS_DIR}/bin/${TARGET_PREFIX}klcc'
+}
+
+PACKAGES = "${PN} ${PN}-dev klibc-utils-sh klibc-utils-kinit \
+        klibc-utils-fstype klibc-utils-ipconfig \
+        klibc-utils-nfsmount klibc-utils-resume \
+        klibc-utils-run-init klibc-utils-cat \
+        klibc-utils-chroot klibc-utils-cpio \
+        klibc-utils-dd klibc-utils-dmesg \
+        klibc-utils-false klibc-utils-halt \
+        klibc-utils-kill klibc-utils-ln \
+        klibc-utils-minips klibc-utils-mkdir \
+        klibc-utils-mkfifo klibc-utils-mknod \
+        klibc-utils-mount klibc-utils-nuke \
+        klibc-utils-pivot-root klibc-utils-poweroff \
+        klibc-utils-readlink klibc-utils-reboot \
+        klibc-utils-sleep \
+        klibc-utils-sync klibc-utils-true \
+        klibc-utils-umount klibc-utils-uname \
+        klibc-utils-gzip klibc-utils-modprobe \
+        klibc-utils-losetup klibc-utils-wc \
+        klibc-utils-ls"
+
+FILES_${PN} = "${base_libdir}/klibc-*.so"
+FILES_${PN}-dev = "${base_libdir}/klibc.so"
+FILES_klibc-utils-sh = "${base_bindir}/sh"
+FILES_klibc-utils-gzip = "${base_bindir}/gzip ${base_bindir}/gunzip ${base_bindir}/zcat"
+FILES_klibc-utils-kinit = "${base_bindir}/kinit"
+FILES_klibc-utils-fstype = "${base_bindir}/fstype"
+FILES_klibc-utils-ipconfig = "${base_bindir}/ipconfig"
+FILES_klibc-utils-nfsmount = "${base_bindir}/nfsmount"
+FILES_klibc-utils-resume = "${base_bindir}/resume"
+FILES_klibc-utils-run-init = "${base_bindir}/run-init"
+FILES_klibc-utils-cat = "${base_bindir}/cat"
+FILES_klibc-utils-chroot = "${base_bindir}/chroot"
+FILES_klibc-utils-cpio = "${base_bindir}/cpio"
+FILES_klibc-utils-dd = "${base_bindir}/dd"
+FILES_klibc-utils-dmesg = "${base_bindir}/dmesg"
+FILES_klibc-utils-false = "${base_bindir}/false"
+FILES_klibc-utils-halt = "${base_bindir}/halt"
+FILES_klibc-utils-kill = "${base_bindir}/kill"
+FILES_klibc-utils-ln = "${base_bindir}/ln"
+FILES_klibc-utils-minips = "${base_bindir}/minips"
+FILES_klibc-utils-mkdir = "${base_bindir}/mkdir"
+FILES_klibc-utils-mkfifo = "${base_bindir}/mkfifo"
+FILES_klibc-utils-mknod = "${base_bindir}/mknod"
+FILES_klibc-utils-mount = "${base_bindir}/mount"
+FILES_klibc-utils-nuke = "${base_bindir}/nuke"
+FILES_klibc-utils-pivot-root = "${base_bindir}/pivot_root"
+FILES_klibc-utils-poweroff = "${base_bindir}/poweroff"
+FILES_klibc-utils-readlink = "${base_bindir}/readlink"
+FILES_klibc-utils-reboot = "${base_bindir}/reboot"
+FILES_klibc-utils-sleep = "${base_bindir}/sleep"
+FILES_klibc-utils-sync = "${base_bindir}/sync"
+FILES_klibc-utils-true = "${base_bindir}/true"
+FILES_klibc-utils-umount = "${base_bindir}/umount"
+FILES_klibc-utils-uname = "${base_bindir}/uname"
+FILES_klibc-utils-modprobe = "${base_bindir}/modprobe"
+FILES_klibc-utils-losetup = "${base_bindir}/losetup"
+FILES_klibc-utils-wc = "${base_bindir}/wc"
+FILES_klibc-utils-ls = "${base_bindir}/ls"
+
+# Yes we want exactly the klibc that was compiled with the utils
+RDEPENDS_klibc-utils-sh = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-kinit = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-fstype = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-ipconfig = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-nfsmount = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-resume = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-run-init = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-cat = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-chroot = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-cpio = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-dd = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-dmesg = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-false = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-halt = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-kill = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-ln = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-minips = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-mkdir = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-mkfifo = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-mknod = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-mount = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-nuke = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-pivot-root = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-poweroff = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-readlink = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-reboot = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-sleep = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-sync = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-true = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-umount = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-uname = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-modprobe = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-losetup = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-wc = "${PN} (=${PV}-${PR})"
+RDEPENDS_klibc-utils-ls = "${PN} (=${PV}-${PR})"
-- 
1.6.3.3





More information about the Openembedded-devel mailing list