Commit 7a2398cc authored by Thayne Harbaugh's avatar Thayne Harbaugh Committed by Linus Torvalds

[PATCH] gen_init_cpio symlink, pipe and socket support

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.

From: William Lee Irwin III <wli@holomorphy.com>

The rest of gen_init_cpio.c seems to cast the result of strlen() to handle
this situation, so this patch follows suit while killing off size_t -related
printk() warnings.
Signed-off-by: default avatarWilliam Irwin <wli@holomorphy.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 4ceaf32b
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 @@ It consists of several major infrastructure components:
- 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?
......
......@@ -363,24 +363,9 @@ config INITRAMFS_SOURCE
default ""
help
This can be set to either a directory containing files, etc to be
included in the initramfs archive, or a file containing newline
separated entries.
If it is a file, it should be in the following format:
# a comment
file <name> <location> <mode> <uid> <gid>
dir <name> <mode> <uid> <gid>
nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>
Where:
<name> name of the file/dir/nod in the archive
<location> location of the file in the current filesystem
<mode> mode/permissions of the file
<uid> user id (0=root)
<gid> group id (0=root)
<dev_type> device type (b=block, c=character)
<maj> major number of nod
<min> minor number of nod
included in the initramfs archive, or a file containing entries
according to the format described by the "usr/gen_init_cpio"
program in the kernel tree.
If you are not sure, leave it blank.
......
......@@ -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 @@ simple_initramfs() {
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 @@ print_mtime() {
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 @@ parse() {
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}"
;;
......
......@@ -10,13 +10,19 @@
#include <ctype.h>
#include <limits.h>
/*
* Original work by Jeff Garzik
*
* 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);
};
......@@ -80,7 +86,7 @@ static void cpio_trailer(void)
0, /* minor */
0, /* rmajor */
0, /* rminor */
(unsigned)strlen(name) + 1, /* namesize */
(unsigned)strlen(name)+1, /* namesize */
0); /* chksum */
push_hdr(s);
push_rest(name);
......@@ -91,7 +97,55 @@ static void cpio_trailer(void)
}
}
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 */
(unsigned)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 @@ static int cpio_mkdir(const char *name, unsigned int mode,
"%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 @@ static int cpio_mkdir(const char *name, unsigned int mode,
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 @@ static int cpio_mkdir_line(const char *line)
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 @@ void usage(const char *prog)
"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 @@ void usage(const char *prog)
prog);
}
struct file_type file_type_table[] = {
struct file_handler file_handler_table[] = {
{
.type = "file",
.handler = cpio_mkfile_line,
......@@ -319,6 +420,15 @@ struct file_type file_type_table[] = {
}, {
.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 @@ int main (int argc, char *argv[])
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 @@ int main (int argc, char *argv[])
}
}
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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment