lkml.org 
[lkml]   [2004]   [Nov]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[PATCH] gen_init_cpio-slink_pipe_sock
From
Date
This patch makes gen_init_cpio more complete by adding symlink, pipe and
socket support. It updates scripts/gen_initramfs_list.sh to support the
new types. The patch applies to the recent mm series that already have
the updated gen_init_cpio and gen_initramfs_list.sh.


--
Thayne Harbaugh
Linux Networx
diff -ur linux-2.6.10-rc1.orig/Documentation/early-userspace/README linux-2.6.10-rc1/Documentation/early-userspace/README
--- linux-2.6.10-rc1.orig/Documentation/early-userspace/README 2004-11-12 11:16:29.752012328 -0700
+++ linux-2.6.10-rc1/Documentation/early-userspace/README 2004-11-12 11:48:57.415922408 -0700
@@ -1,7 +1,7 @@
Early userspace support
=======================

-Last update: 2003-08-21
+Last update: 2004-11-12


"Early userspace" is a set of libraries and programs that provide
@@ -17,14 +17,22 @@
- initramfs, a chunk of code that unpacks the compressed cpio image
midway through the kernel boot process.
- klibc, a userspace C library, currently packaged separately, that is
- optimised for correctness and small size.
+ optimized for correctness and small size.

The cpio file format used by initramfs is the "newc" (aka "cpio -c")
-format, and is documented in the file "buffer-format.txt". If you
-want to generate your own cpio files directly instead of hacking on
-gen_init_cpio, you will need to short-circuit the build process in
-usr/ so that gen_init_cpio does not get run, then simply pop your own
-initramfs_data.cpio.gz file into place.
+format, and is documented in the file "buffer-format.txt". There are
+three ways to add an early userspace filesystem:
+
+1) Put your gzip'ed cpio in usr/initramfs_data.cpio.gz.
+
+2) Set CONFIG_INITRAMFS_SOURCE to the filename of a gen_init_cpio
+input file. This provides the most flexibility and allows creation of
+archives with files not owned by the build user. This means that an
+unprivileged user can create an early userspace with files owned by
+root.
+
+3) Set CONFIG_INITRAMFS_SOURCE to point to a directory containing the
+files for your filesystem.


Where's this all leading?
diff -ur linux-2.6.10-rc1.orig/drivers/block/Kconfig linux-2.6.10-rc1/drivers/block/Kconfig
--- linux-2.6.10-rc1.orig/drivers/block/Kconfig 2004-11-12 11:03:52.657108248 -0700
+++ linux-2.6.10-rc1/drivers/block/Kconfig 2004-11-12 11:07:28.458301480 -0700
@@ -363,10 +363,14 @@
file <name> <location> <mode> <uid> <gid>
dir <name> <mode> <uid> <gid>
nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>
+ slink <name> <target> <mode> <uid> <gid>
+ pipe <name> <mode> <uid> <gid>
+ sock <name> <mode> <uid> <gid>

Where:
- <name> name of the file/dir/nod in the archive
+ <name> name of the file/dir/nod/etc in the archive
<location> location of the file in the current filesystem
+ <target> link target
<mode> mode/permissions of the file
<uid> user id (0=root)
<gid> group id (0=root)
diff -ur linux-2.6.10-rc1.orig/scripts/gen_initramfs_list.sh linux-2.6.10-rc1/scripts/gen_initramfs_list.sh
--- linux-2.6.10-rc1.orig/scripts/gen_initramfs_list.sh 2004-11-12 08:39:48.558211024 -0700
+++ linux-2.6.10-rc1/scripts/gen_initramfs_list.sh 2004-11-12 11:00:14.697243184 -0700
@@ -9,8 +9,6 @@
#
# The output is suitable for gen_init_cpio as found in usr/Makefile.
#
-# TODO: Add support for symlinks, sockets and pipes when gen_init_cpio
-# supports them.

simple_initramfs() {
cat <<-EOF
@@ -25,12 +23,19 @@
filetype() {
local argv1="$1"

- if [ -f "${argv1}" ]; then
+ # symlink test must come before file test
+ if [ -L "${argv1}" ]; then
+ echo "slink"
+ elif [ -f "${argv1}" ]; then
echo "file"
elif [ -d "${argv1}" ]; then
echo "dir"
elif [ -b "${argv1}" -o -c "${argv1}" ]; then
echo "nod"
+ elif [ -p "${argv1}" ]; then
+ echo "pipe"
+ elif [ -S "${argv1}" ]; then
+ echo "sock"
else
echo "invalid"
fi
@@ -52,6 +57,8 @@
parse() {
local location="$1"
local name="${location/${srcdir}//}"
+ # change '//' into '/'
+ name="${name//\/\///}"
local mode="$2"
local uid="$3"
local gid="$4"
@@ -79,6 +86,11 @@
fi
str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}"
;;
+ "slink")
+ local target=$(LC_ALL=C ls -l "${location}" | \
+ gawk '{print $11}')
+ str="${ftype} ${name} ${target} ${str}"
+ ;;
*)
str="${ftype} ${name} ${str}"
;;
diff -ur linux-2.6.10-rc1.orig/usr/gen_init_cpio.c linux-2.6.10-rc1/usr/gen_init_cpio.c
--- linux-2.6.10-rc1.orig/usr/gen_init_cpio.c 2004-11-12 08:39:18.988706272 -0700
+++ linux-2.6.10-rc1/usr/gen_init_cpio.c 2004-11-12 11:07:23.920991256 -0700
@@ -10,13 +10,19 @@
#include <ctype.h>
#include <limits.h>

+/*
+ * Original work by Jeff Garzick
+ *
+ * External file lists, symlink, pipe and fifo support by Thayne Harbaugh
+ */
+
#define xstr(s) #s
#define str(s) xstr(s)

static unsigned int offset;
static unsigned int ino = 721;

-struct file_type {
+struct file_handler {
const char *type;
int (*handler)(const char *line);
};
@@ -91,7 +97,55 @@
}
}

-static int cpio_mkdir(const char *name, unsigned int mode,
+static int cpio_mkslink(const char *name, const char *target,
+ unsigned int mode, uid_t uid, gid_t gid)
+{
+ char s[256];
+ time_t mtime = time(NULL);
+
+ sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
+ "%08X%08X%08X%08X%08X%08X%08X",
+ "070701", /* magic */
+ ino++, /* ino */
+ S_IFLNK | mode, /* mode */
+ (long) uid, /* uid */
+ (long) gid, /* gid */
+ 1, /* nlink */
+ (long) mtime, /* mtime */
+ strlen(target) + 1, /* filesize */
+ 3, /* major */
+ 1, /* minor */
+ 0, /* rmajor */
+ 0, /* rminor */
+ (unsigned)strlen(name) + 1,/* namesize */
+ 0); /* chksum */
+ push_hdr(s);
+ push_string(name);
+ push_pad();
+ push_string(target);
+ push_pad();
+ return 0;
+}
+
+static int cpio_mkslink_line(const char *line)
+{
+ char name[PATH_MAX + 1];
+ char target[PATH_MAX + 1];
+ unsigned int mode;
+ int uid;
+ int gid;
+ int rc = -1;
+
+ if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, target, &mode, &uid, &gid)) {
+ fprintf(stderr, "Unrecognized dir format '%s'", line);
+ goto fail;
+ }
+ rc = cpio_mkslink(name, target, mode, uid, gid);
+ fail:
+ return rc;
+}
+
+static int cpio_mkgeneric(const char *name, unsigned int mode,
uid_t uid, gid_t gid)
{
char s[256];
@@ -101,7 +155,7 @@
"%08X%08X%08X%08X%08X%08X%08X",
"070701", /* magic */
ino++, /* ino */
- S_IFDIR | mode, /* mode */
+ mode, /* mode */
(long) uid, /* uid */
(long) gid, /* gid */
2, /* nlink */
@@ -118,7 +172,33 @@
return 0;
}

-static int cpio_mkdir_line(const char *line)
+enum generic_types {
+ GT_DIR,
+ GT_PIPE,
+ GT_SOCK
+};
+
+struct generic_type {
+ const char *type;
+ mode_t mode;
+};
+
+static struct generic_type generic_type_table[] = {
+ [GT_DIR] = {
+ .type = "dir",
+ .mode = S_IFDIR
+ },
+ [GT_PIPE] = {
+ .type = "pipe",
+ .mode = S_IFIFO
+ },
+ [GT_SOCK] = {
+ .type = "sock",
+ .mode = S_IFSOCK
+ }
+};
+
+static int cpio_mkgeneric_line(const char *line, enum generic_types gt)
{
char name[PATH_MAX + 1];
unsigned int mode;
@@ -127,14 +207,31 @@
int rc = -1;

if (4 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d", name, &mode, &uid, &gid)) {
- fprintf(stderr, "Unrecognized dir format '%s'", line);
+ fprintf(stderr, "Unrecognized %s format '%s'",
+ line, generic_type_table[gt].type);
goto fail;
}
- rc = cpio_mkdir(name, mode, uid, gid);
+ mode |= generic_type_table[gt].mode;
+ rc = cpio_mkgeneric(name, mode, uid, gid);
fail:
return rc;
}

+static int cpio_mkdir_line(const char *line)
+{
+ return cpio_mkgeneric_line(line, GT_DIR);
+}
+
+static int cpio_mkpipe_line(const char *line)
+{
+ return cpio_mkgeneric_line(line, GT_PIPE);
+}
+
+static int cpio_mksock_line(const char *line)
+{
+ return cpio_mkgeneric_line(line, GT_SOCK);
+}
+
static int cpio_mknod(const char *name, unsigned int mode,
uid_t uid, gid_t gid, char dev_type,
unsigned int maj, unsigned int min)
@@ -286,12 +383,16 @@
"describe the files to be included in the initramfs archive:\n"
"\n"
"# a comment\n"
- "file <name> <location> <mode> <uid> <gid> \n"
+ "file <name> <location> <mode> <uid> <gid>\n"
"dir <name> <mode> <uid> <gid>\n"
"nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n"
+ "slink <name> <target> <mode> <uid> <gid>\n"
+ "pipe <name> <mode> <uid> <gid>\n"
+ "sock <name> <mode> <uid> <gid>\n"
"\n"
- "<name> name of the file/dir/nod in the archive\n"
+ "<name> name of the file/dir/nod/etc in the archive\n"
"<location> location of the file in the current filesystem\n"
+ "<target> link target\n"
"<mode> mode/permissions of the file\n"
"<uid> user id (0=root)\n"
"<gid> group id (0=root)\n"
@@ -309,7 +410,7 @@
prog);
}

-struct file_type file_type_table[] = {
+struct file_handler file_handler_table[] = {
{
.type = "file",
.handler = cpio_mkfile_line,
@@ -320,6 +421,15 @@
.type = "dir",
.handler = cpio_mkdir_line,
}, {
+ .type = "slink",
+ .handler = cpio_mkslink_line,
+ }, {
+ .type = "pipe",
+ .handler = cpio_mkpipe_line,
+ }, {
+ .type = "sock",
+ .handler = cpio_mksock_line,
+ }, {
.type = NULL,
.handler = NULL,
}
@@ -382,10 +492,10 @@
ec = -1;
}

- for (type_idx = 0; file_type_table[type_idx].type; type_idx++) {
+ for (type_idx = 0; file_handler_table[type_idx].type; type_idx++) {
int rc;
- if (! strcmp(line, file_type_table[type_idx].type)) {
- if ((rc = file_type_table[type_idx].handler(args))) {
+ if (! strcmp(line, file_handler_table[type_idx].type)) {
+ if ((rc = file_handler_table[type_idx].handler(args))) {
ec = rc;
fprintf(stderr, " line %d\n", line_nr);
}
@@ -393,7 +503,7 @@
}
}

- if (NULL == file_type_table[type_idx].type) {
+ if (NULL == file_handler_table[type_idx].type) {
fprintf(stderr, "unknown file type line %d: '%s'\n",
line_nr, line);
}
\
 
 \ /
  Last update: 2005-03-22 14:08    [W:0.478 / U:0.880 seconds]
©2003-2014 Jasper Spaans. Advertise on this site