wok rev 5345

Added gen-init-cpio. Its a program to compress initramfs images.
author Christopher Rogers <slaxemulator@gmail.com>
date Wed Apr 28 01:10:50 2010 +0000 (2010-04-28)
parents 703e2a93043d
children cb56d4ced18c
files gen-init-cpio/receipt gen-init-cpio/stuff/Makefile gen-init-cpio/stuff/gen_init_cpio.c
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gen-init-cpio/receipt	Wed Apr 28 01:10:50 2010 +0000
     1.3 @@ -0,0 +1,30 @@
     1.4 +# SliTaz package receipt.
     1.5 +
     1.6 +PACKAGE="gen-init-cpio"
     1.7 +VERSION="2.6.32"
     1.8 +CATEGORY="base-system"
     1.9 +MAINTAINER="devel@slitaz.org"
    1.10 +SHORT_DESC="Program to compress initramfs images"
    1.11 +WEB_SITE="http://www.kernel.org/"
    1.12 +DEPENDS="glibc-base"
    1.13 +BUILD_DEPENDS=""
    1.14 +TARBALL=""
    1.15 +WGET_URL=""
    1.16 +TAGS=""
    1.17 +
    1.18 +# Rules to configure and make the package.
    1.19 +
    1.20 +compile_rules()
    1.21 +{
    1.22 +  mkdir -p $PACKAGE-$VERSION
    1.23 +  cp -f stuff/* $PACKAGE-$VERSION
    1.24 +  cd $PACKAGE-$VERSION
    1.25 +  make 
    1.26 +  make DESTDIR=$PWD/_pkg install
    1.27 +}
    1.28 +
    1.29 +# Rules to gen a SliTaz package suitable for Tazpkg.
    1.30 +genpkg_rules()
    1.31 +{
    1.32 +	cp -a $_pkg/sbin $fs
    1.33 +}
    1.34 \ No newline at end of file
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/gen-init-cpio/stuff/Makefile	Wed Apr 28 01:10:50 2010 +0000
     2.3 @@ -0,0 +1,43 @@
     2.4 +
     2.5 +DESTDIR =
     2.6 +PREFIX = /
     2.7 +
     2.8 +MKDIR = /bin/mkdir
     2.9 +INSTALL = /bin/install -c -m 755
    2.10 +
    2.11 +CC   = /usr/bin/gcc 
    2.12 +LD   = /usr/bin/gcc
    2.13 +
    2.14 +CFLAGS += -Wall -Wstrict-prototypes -Wsign-compare -Wchar-subscripts \
    2.15 +           -Wpointer-arith -Wcast-align -Wsign-compare
    2.16 +
    2.17 +#pretty print!
    2.18 +E = @echo
    2.19 +Q = @
    2.20 +
    2.21 +all: gen_init_cpio
    2.22 +.PHONY: all
    2.23 +.DEFAULT: all
    2.24 +
    2.25 +%.o: %.c
    2.26 +	$(E) "  compile " $@
    2.27 +	$(Q) $(CC) -c $(CFLAGS) $< -o $@
    2.28 +
    2.29 +gen_init_cpio: gen_init_cpio.o
    2.30 +	$(E) ">>build   " $@
    2.31 +	$(Q) $(LD) $(LDFLAGS) $@.o -o $@ $(LIB_OBJS)
    2.32 +
    2.33 +clean:
    2.34 +	$(E) "  clean   "
    2.35 +	$(Q) rm -f gen_init_cpio *.o
    2.36 +.PHONY: clean
    2.37 +
    2.38 +install: all
    2.39 +	$(MKDIR) -p $(DESTDIR)$(PREFIX)sbin/
    2.40 +	cp gen_init_cpio $(DESTDIR)$(PREFIX)sbin/
    2.41 +	chmod -R 755 ${DESTDIR}${PREFIX}sbin/
    2.42 +.PHONY: install
    2.43 +
    2.44 +uninstall:
    2.45 +	rm $(DESTDIR)$(PREFIX)sbin/gen_init_cpio
    2.46 +.PHONY: uninstall
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/gen-init-cpio/stuff/gen_init_cpio.c	Wed Apr 28 01:10:50 2010 +0000
     3.3 @@ -0,0 +1,592 @@
     3.4 +#include <stdio.h>
     3.5 +#include <stdlib.h>
     3.6 +#include <sys/types.h>
     3.7 +#include <sys/stat.h>
     3.8 +#include <string.h>
     3.9 +#include <unistd.h>
    3.10 +#include <time.h>
    3.11 +#include <fcntl.h>
    3.12 +#include <errno.h>
    3.13 +#include <ctype.h>
    3.14 +#include <limits.h>
    3.15 +
    3.16 +/*
    3.17 + * Original work by Jeff Garzik
    3.18 + *
    3.19 + * External file lists, symlink, pipe and fifo support by Thayne Harbaugh
    3.20 + * Hard link support by Luciano Rocha
    3.21 + */
    3.22 +
    3.23 +#define xstr(s) #s
    3.24 +#define str(s) xstr(s)
    3.25 +
    3.26 +static unsigned int offset;
    3.27 +static unsigned int ino = 721;
    3.28 +
    3.29 +struct file_handler {
    3.30 +	const char *type;
    3.31 +	int (*handler)(const char *line);
    3.32 +};
    3.33 +
    3.34 +static void push_string(const char *name)
    3.35 +{
    3.36 +	unsigned int name_len = strlen(name) + 1;
    3.37 +
    3.38 +	fputs(name, stdout);
    3.39 +	putchar(0);
    3.40 +	offset += name_len;
    3.41 +}
    3.42 +
    3.43 +static void push_pad (void)
    3.44 +{
    3.45 +	while (offset & 3) {
    3.46 +		putchar(0);
    3.47 +		offset++;
    3.48 +	}
    3.49 +}
    3.50 +
    3.51 +static void push_rest(const char *name)
    3.52 +{
    3.53 +	unsigned int name_len = strlen(name) + 1;
    3.54 +	unsigned int tmp_ofs;
    3.55 +
    3.56 +	fputs(name, stdout);
    3.57 +	putchar(0);
    3.58 +	offset += name_len;
    3.59 +
    3.60 +	tmp_ofs = name_len + 110;
    3.61 +	while (tmp_ofs & 3) {
    3.62 +		putchar(0);
    3.63 +		offset++;
    3.64 +		tmp_ofs++;
    3.65 +	}
    3.66 +}
    3.67 +
    3.68 +static void push_hdr(const char *s)
    3.69 +{
    3.70 +	fputs(s, stdout);
    3.71 +	offset += 110;
    3.72 +}
    3.73 +
    3.74 +static void cpio_trailer(void)
    3.75 +{
    3.76 +	char s[256];
    3.77 +	const char name[] = "TRAILER!!!";
    3.78 +
    3.79 +	sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
    3.80 +	       "%08X%08X%08X%08X%08X%08X%08X",
    3.81 +		"070701",		/* magic */
    3.82 +		0,			/* ino */
    3.83 +		0,			/* mode */
    3.84 +		(long) 0,		/* uid */
    3.85 +		(long) 0,		/* gid */
    3.86 +		1,			/* nlink */
    3.87 +		(long) 0,		/* mtime */
    3.88 +		0,			/* filesize */
    3.89 +		0,			/* major */
    3.90 +		0,			/* minor */
    3.91 +		0,			/* rmajor */
    3.92 +		0,			/* rminor */
    3.93 +		(unsigned)strlen(name)+1, /* namesize */
    3.94 +		0);			/* chksum */
    3.95 +	push_hdr(s);
    3.96 +	push_rest(name);
    3.97 +
    3.98 +	while (offset % 512) {
    3.99 +		putchar(0);
   3.100 +		offset++;
   3.101 +	}
   3.102 +}
   3.103 +
   3.104 +static int cpio_mkslink(const char *name, const char *target,
   3.105 +			 unsigned int mode, uid_t uid, gid_t gid)
   3.106 +{
   3.107 +	char s[256];
   3.108 +	time_t mtime = time(NULL);
   3.109 +
   3.110 +	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
   3.111 +	       "%08X%08X%08X%08X%08X%08X%08X",
   3.112 +		"070701",		/* magic */
   3.113 +		ino++,			/* ino */
   3.114 +		S_IFLNK | mode,		/* mode */
   3.115 +		(long) uid,		/* uid */
   3.116 +		(long) gid,		/* gid */
   3.117 +		1,			/* nlink */
   3.118 +		(long) mtime,		/* mtime */
   3.119 +		(unsigned)strlen(target)+1, /* filesize */
   3.120 +		3,			/* major */
   3.121 +		1,			/* minor */
   3.122 +		0,			/* rmajor */
   3.123 +		0,			/* rminor */
   3.124 +		(unsigned)strlen(name) + 1,/* namesize */
   3.125 +		0);			/* chksum */
   3.126 +	push_hdr(s);
   3.127 +	push_string(name);
   3.128 +	push_pad();
   3.129 +	push_string(target);
   3.130 +	push_pad();
   3.131 +	return 0;
   3.132 +}
   3.133 +
   3.134 +static int cpio_mkslink_line(const char *line)
   3.135 +{
   3.136 +	char name[PATH_MAX + 1];
   3.137 +	char target[PATH_MAX + 1];
   3.138 +	unsigned int mode;
   3.139 +	int uid;
   3.140 +	int gid;
   3.141 +	int rc = -1;
   3.142 +
   3.143 +	if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, target, &mode, &uid, &gid)) {
   3.144 +		fprintf(stderr, "Unrecognized dir format '%s'", line);
   3.145 +		goto fail;
   3.146 +	}
   3.147 +	rc = cpio_mkslink(name, target, mode, uid, gid);
   3.148 + fail:
   3.149 +	return rc;
   3.150 +}
   3.151 +
   3.152 +static int cpio_mkgeneric(const char *name, unsigned int mode,
   3.153 +		       uid_t uid, gid_t gid)
   3.154 +{
   3.155 +	char s[256];
   3.156 +	time_t mtime = time(NULL);
   3.157 +
   3.158 +	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
   3.159 +	       "%08X%08X%08X%08X%08X%08X%08X",
   3.160 +		"070701",		/* magic */
   3.161 +		ino++,			/* ino */
   3.162 +		mode,			/* mode */
   3.163 +		(long) uid,		/* uid */
   3.164 +		(long) gid,		/* gid */
   3.165 +		2,			/* nlink */
   3.166 +		(long) mtime,		/* mtime */
   3.167 +		0,			/* filesize */
   3.168 +		3,			/* major */
   3.169 +		1,			/* minor */
   3.170 +		0,			/* rmajor */
   3.171 +		0,			/* rminor */
   3.172 +		(unsigned)strlen(name) + 1,/* namesize */
   3.173 +		0);			/* chksum */
   3.174 +	push_hdr(s);
   3.175 +	push_rest(name);
   3.176 +	return 0;
   3.177 +}
   3.178 +
   3.179 +enum generic_types {
   3.180 +	GT_DIR,
   3.181 +	GT_PIPE,
   3.182 +	GT_SOCK
   3.183 +};
   3.184 +
   3.185 +struct generic_type {
   3.186 +	const char *type;
   3.187 +	mode_t mode;
   3.188 +};
   3.189 +
   3.190 +static struct generic_type generic_type_table[] = {
   3.191 +	[GT_DIR] = {
   3.192 +		.type = "dir",
   3.193 +		.mode = S_IFDIR
   3.194 +	},
   3.195 +	[GT_PIPE] = {
   3.196 +		.type = "pipe",
   3.197 +		.mode = S_IFIFO
   3.198 +	},
   3.199 +	[GT_SOCK] = {
   3.200 +		.type = "sock",
   3.201 +		.mode = S_IFSOCK
   3.202 +	}
   3.203 +};
   3.204 +
   3.205 +static int cpio_mkgeneric_line(const char *line, enum generic_types gt)
   3.206 +{
   3.207 +	char name[PATH_MAX + 1];
   3.208 +	unsigned int mode;
   3.209 +	int uid;
   3.210 +	int gid;
   3.211 +	int rc = -1;
   3.212 +
   3.213 +	if (4 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d", name, &mode, &uid, &gid)) {
   3.214 +		fprintf(stderr, "Unrecognized %s format '%s'",
   3.215 +			line, generic_type_table[gt].type);
   3.216 +		goto fail;
   3.217 +	}
   3.218 +	mode |= generic_type_table[gt].mode;
   3.219 +	rc = cpio_mkgeneric(name, mode, uid, gid);
   3.220 + fail:
   3.221 +	return rc;
   3.222 +}
   3.223 +
   3.224 +static int cpio_mkdir_line(const char *line)
   3.225 +{
   3.226 +	return cpio_mkgeneric_line(line, GT_DIR);
   3.227 +}
   3.228 +
   3.229 +static int cpio_mkpipe_line(const char *line)
   3.230 +{
   3.231 +	return cpio_mkgeneric_line(line, GT_PIPE);
   3.232 +}
   3.233 +
   3.234 +static int cpio_mksock_line(const char *line)
   3.235 +{
   3.236 +	return cpio_mkgeneric_line(line, GT_SOCK);
   3.237 +}
   3.238 +
   3.239 +static int cpio_mknod(const char *name, unsigned int mode,
   3.240 +		       uid_t uid, gid_t gid, char dev_type,
   3.241 +		       unsigned int maj, unsigned int min)
   3.242 +{
   3.243 +	char s[256];
   3.244 +	time_t mtime = time(NULL);
   3.245 +
   3.246 +	if (dev_type == 'b')
   3.247 +		mode |= S_IFBLK;
   3.248 +	else
   3.249 +		mode |= S_IFCHR;
   3.250 +
   3.251 +	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
   3.252 +	       "%08X%08X%08X%08X%08X%08X%08X",
   3.253 +		"070701",		/* magic */
   3.254 +		ino++,			/* ino */
   3.255 +		mode,			/* mode */
   3.256 +		(long) uid,		/* uid */
   3.257 +		(long) gid,		/* gid */
   3.258 +		1,			/* nlink */
   3.259 +		(long) mtime,		/* mtime */
   3.260 +		0,			/* filesize */
   3.261 +		3,			/* major */
   3.262 +		1,			/* minor */
   3.263 +		maj,			/* rmajor */
   3.264 +		min,			/* rminor */
   3.265 +		(unsigned)strlen(name) + 1,/* namesize */
   3.266 +		0);			/* chksum */
   3.267 +	push_hdr(s);
   3.268 +	push_rest(name);
   3.269 +	return 0;
   3.270 +}
   3.271 +
   3.272 +static int cpio_mknod_line(const char *line)
   3.273 +{
   3.274 +	char name[PATH_MAX + 1];
   3.275 +	unsigned int mode;
   3.276 +	int uid;
   3.277 +	int gid;
   3.278 +	char dev_type;
   3.279 +	unsigned int maj;
   3.280 +	unsigned int min;
   3.281 +	int rc = -1;
   3.282 +
   3.283 +	if (7 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d %c %u %u",
   3.284 +			 name, &mode, &uid, &gid, &dev_type, &maj, &min)) {
   3.285 +		fprintf(stderr, "Unrecognized nod format '%s'", line);
   3.286 +		goto fail;
   3.287 +	}
   3.288 +	rc = cpio_mknod(name, mode, uid, gid, dev_type, maj, min);
   3.289 + fail:
   3.290 +	return rc;
   3.291 +}
   3.292 +
   3.293 +static int cpio_mkfile(const char *name, const char *location,
   3.294 +			unsigned int mode, uid_t uid, gid_t gid,
   3.295 +			unsigned int nlinks)
   3.296 +{
   3.297 +	char s[256];
   3.298 +	char *filebuf = NULL;
   3.299 +	struct stat buf;
   3.300 +	long size;
   3.301 +	int file = -1;
   3.302 +	int retval;
   3.303 +	int rc = -1;
   3.304 +	int namesize;
   3.305 +	int i;
   3.306 +
   3.307 +	mode |= S_IFREG;
   3.308 +
   3.309 +	retval = stat (location, &buf);
   3.310 +	if (retval) {
   3.311 +		fprintf (stderr, "File %s could not be located\n", location);
   3.312 +		goto error;
   3.313 +	}
   3.314 +
   3.315 +	file = open (location, O_RDONLY);
   3.316 +	if (file < 0) {
   3.317 +		fprintf (stderr, "File %s could not be opened for reading\n", location);
   3.318 +		goto error;
   3.319 +	}
   3.320 +
   3.321 +	filebuf = malloc(buf.st_size);
   3.322 +	if (!filebuf) {
   3.323 +		fprintf (stderr, "out of memory\n");
   3.324 +		goto error;
   3.325 +	}
   3.326 +
   3.327 +	retval = read (file, filebuf, buf.st_size);
   3.328 +	if (retval < 0) {
   3.329 +		fprintf (stderr, "Can not read %s file\n", location);
   3.330 +		goto error;
   3.331 +	}
   3.332 +
   3.333 +	size = 0;
   3.334 +	for (i = 1; i <= nlinks; i++) {
   3.335 +		/* data goes on last link */
   3.336 +		if (i == nlinks) size = buf.st_size;
   3.337 +
   3.338 +		namesize = strlen(name) + 1;
   3.339 +		sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
   3.340 +		       "%08lX%08X%08X%08X%08X%08X%08X",
   3.341 +			"070701",		/* magic */
   3.342 +			ino,			/* ino */
   3.343 +			mode,			/* mode */
   3.344 +			(long) uid,		/* uid */
   3.345 +			(long) gid,		/* gid */
   3.346 +			nlinks,			/* nlink */
   3.347 +			(long) buf.st_mtime,	/* mtime */
   3.348 +			size,			/* filesize */
   3.349 +			3,			/* major */
   3.350 +			1,			/* minor */
   3.351 +			0,			/* rmajor */
   3.352 +			0,			/* rminor */
   3.353 +			namesize,		/* namesize */
   3.354 +			0);			/* chksum */
   3.355 +		push_hdr(s);
   3.356 +		push_string(name);
   3.357 +		push_pad();
   3.358 +
   3.359 +		if (size) {
   3.360 +			fwrite(filebuf, size, 1, stdout);
   3.361 +			offset += size;
   3.362 +			push_pad();
   3.363 +		}
   3.364 +
   3.365 +		name += namesize;
   3.366 +	}
   3.367 +	ino++;
   3.368 +	rc = 0;
   3.369 +	
   3.370 +error:
   3.371 +	if (filebuf) free(filebuf);
   3.372 +	if (file >= 0) close(file);
   3.373 +	return rc;
   3.374 +}
   3.375 +
   3.376 +static char *cpio_replace_env(char *new_location)
   3.377 +{
   3.378 +       char expanded[PATH_MAX + 1];
   3.379 +       char env_var[PATH_MAX + 1];
   3.380 +       char *start;
   3.381 +       char *end;
   3.382 +
   3.383 +       for (start = NULL; (start = strstr(new_location, "${")); ) {
   3.384 +               end = strchr(start, '}');
   3.385 +               if (start < end) {
   3.386 +                       *env_var = *expanded = '\0';
   3.387 +                       strncat(env_var, start + 2, end - start - 2);
   3.388 +                       strncat(expanded, new_location, start - new_location);
   3.389 +                       strncat(expanded, getenv(env_var), PATH_MAX);
   3.390 +                       strncat(expanded, end + 1, PATH_MAX);
   3.391 +                       strncpy(new_location, expanded, PATH_MAX);
   3.392 +               } else
   3.393 +                       break;
   3.394 +       }
   3.395 +
   3.396 +       return new_location;
   3.397 +}
   3.398 +
   3.399 +
   3.400 +static int cpio_mkfile_line(const char *line)
   3.401 +{
   3.402 +	char name[PATH_MAX + 1];
   3.403 +	char *dname = NULL; /* malloc'ed buffer for hard links */
   3.404 +	char location[PATH_MAX + 1];
   3.405 +	unsigned int mode;
   3.406 +	int uid;
   3.407 +	int gid;
   3.408 +	int nlinks = 1;
   3.409 +	int end = 0, dname_len = 0;
   3.410 +	int rc = -1;
   3.411 +
   3.412 +	if (5 > sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX)
   3.413 +				"s %o %d %d %n",
   3.414 +				name, location, &mode, &uid, &gid, &end)) {
   3.415 +		fprintf(stderr, "Unrecognized file format '%s'", line);
   3.416 +		goto fail;
   3.417 +	}
   3.418 +	if (end && isgraph(line[end])) {
   3.419 +		int len;
   3.420 +		int nend;
   3.421 +
   3.422 +		dname = malloc(strlen(line));
   3.423 +		if (!dname) {
   3.424 +			fprintf (stderr, "out of memory (%d)\n", dname_len);
   3.425 +			goto fail;
   3.426 +		}
   3.427 +
   3.428 +		dname_len = strlen(name) + 1;
   3.429 +		memcpy(dname, name, dname_len);
   3.430 +
   3.431 +		do {
   3.432 +			nend = 0;
   3.433 +			if (sscanf(line + end, "%" str(PATH_MAX) "s %n",
   3.434 +					name, &nend) < 1)
   3.435 +				break;
   3.436 +			len = strlen(name) + 1;
   3.437 +			memcpy(dname + dname_len, name, len);
   3.438 +			dname_len += len;
   3.439 +			nlinks++;
   3.440 +			end += nend;
   3.441 +		} while (isgraph(line[end]));
   3.442 +	} else {
   3.443 +		dname = name;
   3.444 +	}
   3.445 +	rc = cpio_mkfile(dname, cpio_replace_env(location),
   3.446 +	                 mode, uid, gid, nlinks);
   3.447 + fail:
   3.448 +	if (dname_len) free(dname);
   3.449 +	return rc;
   3.450 +}
   3.451 +
   3.452 +static void usage(const char *prog)
   3.453 +{
   3.454 +	fprintf(stderr, "Usage:\n"
   3.455 +		"\t%s <cpio_list>\n"
   3.456 +		"\n"
   3.457 +		"<cpio_list> is a file containing newline separated entries that\n"
   3.458 +		"describe the files to be included in the initramfs archive:\n"
   3.459 +		"\n"
   3.460 +		"# a comment\n"
   3.461 +		"file <name> <location> <mode> <uid> <gid> [<hard links>]\n"
   3.462 +		"dir <name> <mode> <uid> <gid>\n"
   3.463 +		"nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n"
   3.464 +		"slink <name> <target> <mode> <uid> <gid>\n"
   3.465 +		"pipe <name> <mode> <uid> <gid>\n"
   3.466 +		"sock <name> <mode> <uid> <gid>\n"
   3.467 +		"\n"
   3.468 +		"<name>       name of the file/dir/nod/etc in the archive\n"
   3.469 +		"<location>   location of the file in the current filesystem\n"
   3.470 +		"             expands shell variables quoted with ${}\n"
   3.471 +		"<target>     link target\n"
   3.472 +		"<mode>       mode/permissions of the file\n"
   3.473 +		"<uid>        user id (0=root)\n"
   3.474 +		"<gid>        group id (0=root)\n"
   3.475 +		"<dev_type>   device type (b=block, c=character)\n"
   3.476 +		"<maj>        major number of nod\n"
   3.477 +		"<min>        minor number of nod\n"
   3.478 +		"<hard links> space separated list of other links to file\n"
   3.479 +		"\n"
   3.480 +		"example:\n"
   3.481 +		"# A simple initramfs\n"
   3.482 +		"dir /dev 0755 0 0\n"
   3.483 +		"nod /dev/console 0600 0 0 c 5 1\n"
   3.484 +		"dir /root 0700 0 0\n"
   3.485 +		"dir /sbin 0755 0 0\n"
   3.486 +		"file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n",
   3.487 +		prog);
   3.488 +}
   3.489 +
   3.490 +struct file_handler file_handler_table[] = {
   3.491 +	{
   3.492 +		.type    = "file",
   3.493 +		.handler = cpio_mkfile_line,
   3.494 +	}, {
   3.495 +		.type    = "nod",
   3.496 +		.handler = cpio_mknod_line,
   3.497 +	}, {
   3.498 +		.type    = "dir",
   3.499 +		.handler = cpio_mkdir_line,
   3.500 +	}, {
   3.501 +		.type    = "slink",
   3.502 +		.handler = cpio_mkslink_line,
   3.503 +	}, {
   3.504 +		.type    = "pipe",
   3.505 +		.handler = cpio_mkpipe_line,
   3.506 +	}, {
   3.507 +		.type    = "sock",
   3.508 +		.handler = cpio_mksock_line,
   3.509 +	}, {
   3.510 +		.type    = NULL,
   3.511 +		.handler = NULL,
   3.512 +	}
   3.513 +};
   3.514 +
   3.515 +#define LINE_SIZE (2 * PATH_MAX + 50)
   3.516 +
   3.517 +int main (int argc, char *argv[])
   3.518 +{
   3.519 +	FILE *cpio_list;
   3.520 +	char line[LINE_SIZE];
   3.521 +	char *args, *type;
   3.522 +	int ec = 0;
   3.523 +	int line_nr = 0;
   3.524 +
   3.525 +	if (2 != argc) {
   3.526 +		usage(argv[0]);
   3.527 +		exit(1);
   3.528 +	}
   3.529 +
   3.530 +	if (!strcmp(argv[1], "-"))
   3.531 +		cpio_list = stdin;
   3.532 +	else if (! (cpio_list = fopen(argv[1], "r"))) {
   3.533 +		fprintf(stderr, "ERROR: unable to open '%s': %s\n\n",
   3.534 +			argv[1], strerror(errno));
   3.535 +		usage(argv[0]);
   3.536 +		exit(1);
   3.537 +	}
   3.538 +
   3.539 +	while (fgets(line, LINE_SIZE, cpio_list)) {
   3.540 +		int type_idx;
   3.541 +		size_t slen = strlen(line);
   3.542 +
   3.543 +		line_nr++;
   3.544 +
   3.545 +		if ('#' == *line) {
   3.546 +			/* comment - skip to next line */
   3.547 +			continue;
   3.548 +		}
   3.549 +
   3.550 +		if (! (type = strtok(line, " \t"))) {
   3.551 +			fprintf(stderr,
   3.552 +				"ERROR: incorrect format, could not locate file type line %d: '%s'\n",
   3.553 +				line_nr, line);
   3.554 +			ec = -1;
   3.555 +			break;
   3.556 +		}
   3.557 +
   3.558 +		if ('\n' == *type) {
   3.559 +			/* a blank line */
   3.560 +			continue;
   3.561 +		}
   3.562 +
   3.563 +		if (slen == strlen(type)) {
   3.564 +			/* must be an empty line */
   3.565 +			continue;
   3.566 +		}
   3.567 +
   3.568 +		if (! (args = strtok(NULL, "\n"))) {
   3.569 +			fprintf(stderr,
   3.570 +				"ERROR: incorrect format, newline required line %d: '%s'\n",
   3.571 +				line_nr, line);
   3.572 +			ec = -1;
   3.573 +		}
   3.574 +
   3.575 +		for (type_idx = 0; file_handler_table[type_idx].type; type_idx++) {
   3.576 +			int rc;
   3.577 +			if (! strcmp(line, file_handler_table[type_idx].type)) {
   3.578 +				if ((rc = file_handler_table[type_idx].handler(args))) {
   3.579 +					ec = rc;
   3.580 +					fprintf(stderr, " line %d\n", line_nr);
   3.581 +				}
   3.582 +				break;
   3.583 +			}
   3.584 +		}
   3.585 +
   3.586 +		if (NULL == file_handler_table[type_idx].type) {
   3.587 +			fprintf(stderr, "unknown file type line %d: '%s'\n",
   3.588 +				line_nr, line);
   3.589 +		}
   3.590 +	}
   3.591 +	if (ec == 0)
   3.592 +		cpio_trailer();
   3.593 +
   3.594 +	exit(ec);
   3.595 +}