Subject: pax-as-tar extract to stdout patch
To: None <tech-userlevel@netbsd.org>
From: Simon Burge <simonb@wasabisystems.com>
List: tech-userlevel
Date: 06/15/2003 18:39:50
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