Subject: Re: pax-as-tar extract to stdout patch
To: Simon Burge <simonb@wasabisystems.com>
From: James Chacon <jmc@netbsd.org>
List: tech-userlevel
Date: 06/16/2003 00:04:32
Please commit this. (It makes things like the distrib/cdrom Makefile a lot
simpler to deal with for instance as it extracts one-off files from the 
tarballs for some cd images).

James


>Hi folks,
>
>The following patch adds support for pax-as-tar to extract files to
>stdout (the -O option from GNU tar).  Anyone see any problems with
>this patch?
>
>Simon.
>--
>Simon Burge                                   <simonb@wasabisystems.com>
>NetBSD Development, Support and Service:   http://www.wasabisystems.com/
>
>Index: ar_subs.c
>===================================================================
>RCS file: /cvsroot/src/bin/pax/ar_subs.c,v
>retrieving revision 1.24
>diff -d -p -u -r1.24 ar_subs.c
>--- ar_subs.c	2003/03/31 20:06:33	1.24
>+++ ar_subs.c	2003/06/15 08:37:30
>@@ -308,7 +308,8 @@ extract(void)
> 		/*
> 		 * if required, chdir around.
> 		 */
>-		if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
>+		if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL) &&
>+		    !to_stdout)
> 			if (chdir(arcn->pat->chdname) != 0)
> 				syswarn(1, errno, "Cannot chdir to %s",
> 				    arcn->pat->chdname);
>@@ -336,22 +337,28 @@ extract(void)
> 			}
> 			continue;
> 		}
>-		/*
>-		 * we have a file with data here. If we can not create it, skip
>-		 * over the data and purge the name from hard link table
>-		 */
>-		if ((fd = file_creat(arcn)) < 0) {
>-			(void)fflush(listf);
>-			(void)rd_skip(arcn->skip + arcn->pad);
>-			purg_lnk(arcn);
>-			continue;
>+		if (to_stdout)
>+			fd = STDOUT_FILENO;
>+		else {
>+			/*
>+			 * we have a file with data here. If we can not create
>+			 * it, skip over the data and purge the name from hard
>+			 * link table
>+			 */
>+			if ((fd = file_creat(arcn)) < 0) {
>+				(void)fflush(listf);
>+				(void)rd_skip(arcn->skip + arcn->pad);
>+				purg_lnk(arcn);
>+				continue;
>+			}
> 		}
> 		/*
> 		 * extract the file from the archive and skip over padding and
> 		 * any unprocessed data
> 		 */
> 		res = (*frmt->rd_data)(arcn, fd, &cnt);
>-		file_close(arcn, fd);
>+		if (!to_stdout)
>+			file_close(arcn, fd);
> 		if (vflag && vfpart) {
> 			(void)putc('\n', listf);
> 			vfpart = 0;
>Index: extern.h
>===================================================================
>RCS file: /cvsroot/src/bin/pax/extern.h,v
>retrieving revision 1.37
>diff -d -p -u -r1.37 extern.h
>--- extern.h	2003/02/25 13:36:59	1.37
>+++ extern.h	2003/06/15 08:37:31
>@@ -251,6 +251,7 @@ extern int pids;
> extern int rmleadslash;
> extern int exit_val;
> extern int docrc;
>+extern int to_stdout;
> extern char *dirptr;
> extern char *ltmfrmt;
> extern char *argv0;
>Index: options.c
>===================================================================
>RCS file: /cvsroot/src/bin/pax/options.c,v
>retrieving revision 1.64
>diff -d -p -u -r1.64 options.c
>--- options.c	2003/04/08 15:13:10	1.64
>+++ options.c	2003/06/15 08:37:32
>@@ -709,6 +709,7 @@ struct option tar_longopts[] = {
> 	{ "gunzip",		no_argument,		0,	'z' },
> 	{ "read-full-blocks",	no_argument,		0,	'B' },
> 	{ "directory",		required_argument,	0,	'C' },
>+	{ "to-stdout",		no_argument,		0,	'O' },
> 	{ "absolute-paths",	no_argument,		0,	'P' },
> 	{ "files-from",		required_argument,	0,	'T' },
> 	{ "exclude-from",	required_argument,	0,	'X' },
>@@ -749,7 +750,6 @@ struct option tar_longopts[] = {
> 	{ "multi-volume",	no_argument,		0,	'M' },
> 	{ "after-date",		required_argument,	0,	'N' },
> 	{ "newer",		required_argument,	0,	'N' },
>-	{ "to-stdout",		no_argument,		0,	'O' },
> 	{ "record-number",	no_argument,		0,	'R' },
> 	{ "remove-files",	no_argument,		0,
> 						OPT_REMOVE_FILES },
>@@ -1076,9 +1076,17 @@ tar_options(int argc, char **argv)
> 	if (act == ARCHIVE || act == APPND)
> 		frmt = &(fsub[Oflag ? F_TAR : F_USTAR]);
> 	else if (Oflag) {
>-		tty_warn(1, "The -O/-o options are only valid when writing an archive");
>-		tar_usage();		/* only valid when writing */
>+		if (act == EXTRACT)
>+			to_stdout = 1;
>+		else {
>+			tty_warn(1, "The -O/-o options are only valid when "
>+			    "writing or extracting an archive");
>+			tar_usage();
>+		}
> 	}
>+
>+	if (act == EXTRACT && Oflag)
>+		to_stdout = 1;
> 
> 	/*
> 	 * process the args as they are interpreted by the operation mode
>Index: pax.c
>===================================================================
>RCS file: /cvsroot/src/bin/pax/pax.c,v
>retrieving revision 1.26
>diff -d -p -u -r1.26 pax.c
>--- pax.c	2003/03/03 11:42:36	1.26
>+++ pax.c	2003/06/15 08:37:32
>@@ -107,6 +107,7 @@ int	pids;			/* preserve file uid/gid */
> int	rmleadslash = 0;	/* remove leading '/' from pathnames */
> int	exit_val;		/* exit value */
> int	docrc;			/* check/create file crc */
>+int	to_stdout;		/* extract to stdout */
> char	*dirptr;		/* destination dir in a copy */
> char	*ltmfrmt;		/* -v locale time format (if any) */
> char	*argv0;			/* root of argv[0] */
>Index: tar.1
>===================================================================
>RCS file: /cvsroot/src/bin/pax/tar.1,v
>retrieving revision 1.11
>diff -d -p -u -r1.11 tar.1
>--- tar.1	2003/04/10 06:07:40	1.11
>+++ tar.1	2003/06/15 08:37:33
>@@ -124,7 +124,8 @@ Do not cross filesystems.
> .It Fl m , -modification-time
> Do not preserve modification time.
> .It Fl O
>-Write old-style (non-POSIX) archives.
>+When creating and appending to an archive, write old-style (non-POSIX) archives.
>+When extracting from an archive, extract to standard output.
> .It Fl o , -portability , -old-archive
> Don't write directory information that the older (V7) style
> .Nm
>
>
>