Add the capability to extract to stdout. Relevant parts from: https://github.com/mackyle/xar/commit/312a71a77dff76c4bf6ebc8d7a9e64ca1322d8dd 2012-09-15T07:10 https://github.com/mackyle/xar/commit/ba57887b34af69e786b35b34762ab06f17135e2b 2012-09-15T07:29 https://github.com/mackyle/xar/commit/ddea2e4b53b6b2cfdd0d13c6beaac0978330c2a2 2012-09-15T07:33 --- include/xar.h.in.orig 2019-02-14 18:05:37.000000000 -0600 +++ include/xar.h.in 2022-03-10 06:07:31.000000000 -0600 @@ -134,6 +134,8 @@ #define XAR_OPT_VAL_TRUE "true" #define XAR_OPT_VAL_FALSE "false" +#define XAR_OPT_EXTRACTSTDOUT "extract-stdout" /* Extract data to stdout instead of file (true/false) */ + /* xar signing algorithms */ #define XAR_SIG_SHA1RSA 1 --- lib/archive.c.orig 2022-03-14 05:57:47.000000000 -0500 +++ lib/archive.c 2022-03-14 06:03:01.000000000 -0500 @@ -886,6 +886,9 @@ if( (strcmp(option, XAR_OPT_TOCCKSUM) == 0) ) { XAR(x)->heap_offset = xar_io_get_toc_checksum_length_for_type(value); } + if ((strcmp(option, XAR_OPT_EXTRACTSTDOUT) == 0)) { + XAR(x)->tostdout = strcmp(value, XAR_OPT_VAL_TRUE) == 0; + } /* This was an edit from xar-1.4 Looks like we would only allow one definition for a particular key in this list @@ -1499,33 +1502,46 @@ xar_file_t tmpf; uint32_t result = -1; - if( (strstr(XAR_FILE(f)->fspath, "/") != NULL) && (stat(XAR_FILE(f)->fspath, &sb)) && (XAR_FILE(f)->parent_extracted == 0) ) { - tmp1 = strdup(XAR_FILE(f)->fspath); - dname = xar_safe_dirname(tmp1); - tmpf = xar_file_find(XAR(x)->files, dname); - free(dname); - free(tmp1); - if( !tmpf ) { - xar_err_set_string(x, "Unable to find file"); - xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); - return -1; - } + if (XAR(x)->tostdout) { + char *buffer = NULL; + size_t bsize = 0; + int32_t result; + if ((result = xar_extract_tobuffersz(x, f, &buffer, &bsize)) != 0) + return result; + if (bsize && buffer && fwrite(buffer, bsize, 1, stdout) != 1) + result = -1; + free(buffer); + return result; + } + else { + if( (strstr(XAR_FILE(f)->fspath, "/") != NULL) && (stat(XAR_FILE(f)->fspath, &sb)) && (XAR_FILE(f)->parent_extracted == 0) ) { + tmp1 = strdup(XAR_FILE(f)->fspath); + dname = xar_safe_dirname(tmp1); + tmpf = xar_file_find(XAR(x)->files, dname); + free(dname); + free(tmp1); + if( !tmpf ) { + xar_err_set_string(x, "Unable to find file"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } - XAR_FILE(f)->parent_extracted++; - result = xar_extract(x, tmpf); + XAR_FILE(f)->parent_extracted++; + result = xar_extract(x, tmpf); - if (result < 0) - return result; + if (result < 0) + return result; - } + } - char* safe_path = xar_get_safe_path(f); - if (safe_path) { - result = xar_extract_tofile(x, f, safe_path); - free(safe_path); - } + char* safe_path = xar_get_safe_path(f); + if (safe_path) { + result = xar_extract_tofile(x, f, safe_path); + free(safe_path); + } - return result; + return result; + } } int32_t xar_verify_progress(xar_t x, xar_file_t f, xar_progress_callback p) { --- lib/archive.h.orig 2022-03-10 05:12:27.000000000 -0600 +++ lib/archive.h 2022-03-10 05:45:47.000000000 -0600 @@ -101,6 +101,7 @@ int toc_hash_size; /* size of toc hash that was copied during archive open */ void *toc_hash; /* copy of the toc hash copied during archive open */ int skipwarn; + int tostdout; struct stat sbcache; }; --- src/xar.c.orig 2022-03-10 05:12:27.000000000 -0600 +++ src/xar.c 2022-03-10 05:39:41.000000000 -0600 @@ -53,8 +53,10 @@ #include "config.h" #include "../lib/filetree.h" #include "util.h" +#include "xar.h" #define SYMBOLIC 1 #define NUMERIC 2 +#define XAR_OPT_EXTRACTSTDOUT "extract-stdout" /* Extract data to stdout instead of file (true/false) */ static int Perms = 0; static int Local = 0; static char *Subdoc = NULL; @@ -73,6 +73,7 @@ static int LinkSame = 0; static int NoOverwrite = 0; static int SaveSuid = 0; +static int ToStdout = 0; struct lnode { char *str; @@ -383,6 +384,9 @@ if( SaveSuid ) { xar_opt_set(x, XAR_OPT_SAVESUID, XAR_OPT_VAL_TRUE); } + if (ToStdout) { + xar_opt_set(x, XAR_OPT_EXTRACTSTDOUT, XAR_OPT_VAL_TRUE); + } iter = xar_iter_new(); if( !iter ) { @@ -457,24 +461,28 @@ if( matched ) { struct stat sb; - if( NoOverwrite && (lstat(path, &sb) == 0) ) { + if( !ToStdout && NoOverwrite && (lstat(path, &sb) == 0) ) { printf("%s already exists, not overwriting\n", path); } else { const char *prop = NULL; int deferred = 0; if( xar_prop_get(f, "type", &prop) == 0 && prop != NULL ) { if( strcmp(prop, "directory") == 0 ) { - struct lnode *tmpl = calloc(sizeof(struct lnode),1); - tmpl->str = (char *)f; - tmpl->next = dirs; - dirs = tmpl; - deferred = 1; + if (!ToStdout) { + struct lnode *tmpl = calloc(sizeof(struct lnode),1); + tmpl->str = (char *)f; + tmpl->next = dirs; + dirs = tmpl; + deferred = 1; + } } } if( ! deferred ) { - files_extracted++; print_file(x, f); - xar_extract(x, f); + if (xar_extract(x, f) == 0) + files_extracted++; + else if (!ToStdout) + fprintf(stderr, "Unable to extract file %s\n", path); } } } @@ -859,6 +867,8 @@ fprintf(stderr, "\t to a document in cwd named .xml\n"); fprintf(stderr, "\t--exclude POSIX regular expression of files to \n"); fprintf(stderr, "\t ignore while archiving.\n"); + fprintf(stderr, "\t--to-stdout Write file contents to standard out when extracting\n"); + fprintf(stderr, "\t-O Synonym for \"--to-stdout\"\n"); fprintf(stderr, "\t--rsize Specifies the size of the buffer used\n"); fprintf(stderr, "\t for read IO operations in bytes.\n"); fprintf(stderr, "\t--coalesce-heap When archived files are identical, only store one copy\n"); @@ -917,6 +927,7 @@ {"keep-existing", no_argument, 0, 15}, {"keep-setuid", no_argument, 0, 16}, {"compression-args", required_argument, 0, 17}, + {"to-stdout", no_argument, 0, 'O'}, { 0, 0, 0, 0} }; @@ -925,7 +936,7 @@ exit(1); } - while( (c = getopt_long(argc, argv, "axcC:vtjzf:hpPln:s:d:vk", o, &loptind)) != -1 ) { + while( (c = getopt_long(argc, argv, "axcOC:vtjzf:hpPln:s:d:vk", o, &loptind)) != -1 ) { switch(c) { case 1 : // toc-cksum if( !optarg ) { @@ -1150,6 +1161,9 @@ case 'l': // stay on local device Local = 1; break; + case 'O': + ToStdout = 1; + break; case 'n': // provide subdocument name SubdocName = optarg; break; --- src/xar.1.orig 2020-05-12 22:28:17.000000000 -0500 +++ src/xar.1 2022-03-09 19:52:00.000000000 -0600 @@ -103,6 +103,13 @@ the archive during creation or from being extracted during extraction. This option can be specified multiple times. .TP +\-\-to\-stdout +Instead of creating files during extraction, write the file contents to standard output. +Only the file data will be written to standard output. All extended attributes, resource forks and other file properties are ignored with this option. +.TP +\-O +Synonym for \-\-to\-stdout +.TP \-\-rsize Specifies a size (in bytes) for the internal libxar read buffer while performing I/O. .TP