From: th.ought <[email protected]>

---
 tar.1 |  3 +++
 tar.c | 35 ++++++++++++++++++++++++++---------
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/tar.1 b/tar.1
index be2ebea..67242dd 100644
--- a/tar.1
+++ b/tar.1
@@ -9,6 +9,7 @@
 .Op Fl C Ar dir
 .Op Fl J | Fl Z | Fl a | Fl j | Fl z
 .Fl x Op Fl m | Fl t
+.Op Fl O
 .Op Fl f Ar file
 .Op Ar file ...
 .Nm
@@ -40,6 +41,8 @@ Do not preserve modification time.
 List all files in the archive.
 .It Fl x
 Extract archive.
+.It Fl O
+Extract files to standard output.
 .It Fl h
 Always dereference symbolic links while recursively traversing directories.
 .It Fl J | Fl Z | Fl a | Fl j | Fl z
diff --git a/tar.c b/tar.c
index b74c134..1c25ae5 100644
--- a/tar.c
+++ b/tar.c
@@ -63,7 +63,7 @@ static int tarfd;
 static ino_t tarinode;
 static dev_t tardev;
 
-static int mflag, vflag;
+static int mflag, vflag, Oflag;
 static int filtermode;
 static const char *filtertool;
 
@@ -251,6 +251,21 @@ archive(const char *path)
        return 0;
 }
 
+static int
+writefile(int fd, ssize_t l, char b[BLKSIZ])
+{
+       for (; l > 0; l -= BLKSIZ)
+               if (eread(tarfd, b, BLKSIZ) > 0)
+                       ewrite(fd, b, MIN(l, BLKSIZ));
+       return 0;
+}
+
+static int
+printfile(char *fname, ssize_t l, char b[BLKSIZ])
+{
+    return writefile(STDOUT_FILENO, l, b);
+}
+
 static int
 unarchive(char *fname, ssize_t l, char b[BLKSIZ])
 {
@@ -323,9 +338,7 @@ unarchive(char *fname, ssize_t l, char b[BLKSIZ])
                eprintf("strtol %s: invalid number\n", h->gid);
 
        if (fd != -1) {
-               for (; l > 0; l -= BLKSIZ)
-                       if (eread(tarfd, b, BLKSIZ) > 0)
-                               ewrite(fd, b, MIN(l, BLKSIZ));
+        writefile(fd, l, b);
                close(fd);
        }
 
@@ -360,7 +373,7 @@ skipblk(ssize_t l)
 }
 
 static int
-print(char *fname, ssize_t l, char b[BLKSIZ])
+printfname(char *fname, ssize_t l, char b[BLKSIZ])
 {
        puts(fname);
        skipblk(l);
@@ -451,7 +464,8 @@ xt(int argc, char *argv[], int mode)
        struct dirtime *dirtime;
        long size;
        int i, n;
-       int (*fn)(char *, ssize_t, char[BLKSIZ]) = (mode == 'x') ? unarchive : 
print;
+       int (*fn)(char *, ssize_t, char[BLKSIZ]) = (mode == 'x') ?
+               (Oflag ? printfile : unarchive) : printfname;
 
        while (eread(tarfd, b, BLKSIZ) > 0 && h->name[0]) {
                chktar(h);
@@ -486,7 +500,7 @@ xt(int argc, char *argv[], int mode)
 
                fn(fname, size, b);
                if (vflag && mode != 't')
-                       puts(fname);
+                       fprintf(Oflag ? stderr : stdout, "%s\n", fname);
        }
 
        if (mode == 'x' && !mflag) {
@@ -505,7 +519,7 @@ xt(int argc, char *argv[], int mode)
 static void
 usage(void)
 {
-       eprintf("usage: %s [-C dir] [-J | -Z | -a | -j | -z] -x [-m | -t] "
+       eprintf("usage: %s [-C dir] [-J | -Z | -a | -j | -z] -x [-m | -t] [-O] "
                "[-f file] [file ...]\n"
                "       %s [-C dir] [-J | -Z | -a | -j | -z] [-h] -c path ... "
                "[-f file]\n", argv0, argv0);
@@ -534,6 +548,9 @@ main(int argc, char *argv[])
        case 'm':
                mflag = 1;
                break;
+       case 'O':
+               Oflag = 1;
+               break;
        case 'J':
        case 'Z':
        case 'a':
@@ -555,7 +572,7 @@ main(int argc, char *argv[])
        if (!mode)
                usage();
        if (mode == 'c')
-               if (!argc)
+               if (!argc || Oflag)
                        usage();
 
        switch (mode) {
-- 
2.30.2


Reply via email to