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.h23 Mar 2020 20:04:19 - 1.60
+++ extern.h27 May 2022 00:30:36 -
@@ -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 - 1.55
+++ file_subs.c 27 May 2022 00:26:39 -
@@ -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 - 1.103
+++ options.c 27 May 2022 00:34:48 -
@@ -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 - 1.64
+++ tar.1 27 May 2022 00:33:25 -
@@ -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.