tar can read and write archive files from stdin/out, but cannot extract files
to stdout. This may be kinda esoteric, but there's a few uses. Archive of log
files, etc., where you want to check for something without extracting to a
tmp file.

I tried working around this by renaming to /dev/fd/1, but no dice. tar can't
unlink that file, and so refuses to write to it.

And so, a -S option to write extracted files to stdout. gtar has a similar
option, but uses -O for the letter (already taken here).

Kind of a weird edge case, but the diff is not so very much code, and it's
not easy to workaround. I'd rather not install gtar just for such cases.


Index: extern.h
===================================================================
RCS file: /home/cvs/src/bin/pax/extern.h,v
retrieving revision 1.60
diff -u -p -r1.60 extern.h
--- extern.h    23 Mar 2020 20:04:19 -0000      1.60
+++ extern.h    27 May 2022 00:30:36 -0000
@@ -284,7 +284,7 @@ u_int st_hash(const char *, int, int);
 /*
  * tar.c
  */
-extern int tar_nodir;
+extern int tar_nodir, write_stdout;
 extern char *gnu_name_string, *gnu_link_string;
 int tar_endwr(void);
 off_t tar_endrd(void);
Index: file_subs.c
===================================================================
RCS file: /home/cvs/src/bin/pax/file_subs.c,v
retrieving revision 1.55
diff -u -p -r1.55 file_subs.c
--- file_subs.c 23 Mar 2020 20:04:19 -0000      1.55
+++ file_subs.c 27 May 2022 00:26:39 -0000
@@ -68,6 +68,9 @@ file_creat(ARCHD *arcn)
        mode_t file_mode;
        int oerrno;
 
+       if (write_stdout)
+               return 1;
+
        /*
         * Assume file doesn't exist, so just try to create it, most times this
         * works. We have to take special handling when the file does exist. To
@@ -940,7 +943,7 @@ file_write(int fd, char *str, int cnt, i
                wcnt = MINIMUM(cnt, *rem);
                cnt -= wcnt;
                *rem -= wcnt;
-               if (*isempt) {
+               if (*isempt && !write_stdout) {
                        /*
                         * have not written to this block yet, so we keep
                         * looking for zero's
Index: options.c
===================================================================
RCS file: /home/cvs/src/bin/pax/options.c,v
retrieving revision 1.103
diff -u -p -r1.103 options.c
--- options.c   15 Nov 2019 20:34:17 -0000      1.103
+++ options.c   27 May 2022 00:34:48 -0000
@@ -731,7 +731,7 @@ tar_options(int argc, char **argv)
         * process option flags
         */
        while ((c = getoldopt(argc, argv,
-           "b:cef:hjmopqruts:vwxzBC:HI:LNOPXZ014578")) != -1) {
+           "b:cef:hjmopqruts:vwxzBC:HI:LNOPSXZ014578")) != -1) {
                switch (c) {
                case 'b':
                        /*
@@ -896,6 +896,9 @@ tar_options(int argc, char **argv)
                         */
                        rmleadslash = 0;
                        break;
+               case 'S':
+                       write_stdout = 1;
+                       break;
                case 'X':
                        /*
                         * do not pass over mount points in the file system
@@ -1694,10 +1697,10 @@ void
 tar_usage(void)
 {
        (void)fputs(
-           "usage: tar {crtux}[014578befHhjLmNOoPpqsvwXZz]\n"
+           "usage: tar {crtux}[014578befHhjLmNOoPpqSsvwXZz]\n"
            "           [blocking-factor | archive | replstr] [-C directory] 
[-I file]\n"
            "           [file ...]\n"
-           "       tar {-crtux} [-014578eHhjLmNOoPpqvwXZz] [-b 
blocking-factor]\n"
+           "       tar {-crtux} [-014578eHhjLmNOoPpqSvwXZz] [-b 
blocking-factor]\n"
            "           [-C directory] [-f archive] [-I file] [-s replstr] 
[file ...]\n",
            stderr);
        exit(1);
Index: tar.1
===================================================================
RCS file: /home/cvs/src/bin/pax/tar.1,v
retrieving revision 1.64
diff -u -p -r1.64 tar.1
--- tar.1       31 Mar 2022 17:27:14 -0000      1.64
+++ tar.1       27 May 2022 00:33:25 -0000
@@ -32,7 +32,7 @@
 .Sh SYNOPSIS
 .Nm tar
 .Sm off
-.No { Cm crtux No } Op Cm 014578befHhjLmNOoPpqsvwXZz
+.No { Cm crtux No } Op Cm 014578befHhjLmNOoPpqSsvwXZz
 .Sm on
 .Bk -words
 .Op Ar blocking-factor | archive | replstr
@@ -43,7 +43,7 @@
 .Nm tar
 .No { Ns Fl crtux Ns }
 .Bk -words
-.Op Fl 014578eHhjLmNOoPpqvwXZz
+.Op Fl 014578eHhjLmNOoPpqSvwXZz
 .Op Fl b Ar blocking-factor
 .Op Fl C Ar directory
 .Op Fl f Ar archive
@@ -206,6 +206,8 @@ No more than one archive member is match
 .Ar file .
 When members of type directory are matched, the file hierarchy rooted at that
 directory is also matched.
+.It Fl S
+Write output files to stdout instead of the file system when extracting.
 .It Fl s Ar replstr
 Modify the archive member names according to the substitution expression
 .Ar replstr ,
Index: tar.c
===================================================================
RCS file: /home/cvs/src/bin/pax/tar.c,v
retrieving revision 1.70
diff -u -p -r1.70 tar.c
--- tar.c       1 Mar 2022 21:19:11 -0000       1.70
+++ tar.c       27 May 2022 00:34:06 -0000
@@ -73,6 +73,7 @@ static gid_t gid_warn;
  */
 
 int tar_nodir;                         /* do not write dirs under old tar */
+int write_stdout;                      /* extract files to stdout */
 char *gnu_name_string;                 /* GNU ././@LongLink hackery name */
 char *gnu_link_string;                 /* GNU ././@LongLink hackery link */
 

Reply via email to