diff --git a/tools/ChangeLog b/tools/ChangeLog index 5599ff578..65bb6f6e2 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2010-08-09 Werner Koch + + * gpgtar.c (main): Add options -T and --null. + * gpgtar-create.c (gpgtar_create): Implement option --null. + 2010-07-16 Werner Koch * gpgtar-create.c: Rewrite to better support W32. diff --git a/tools/gpgtar-create.c b/tools/gpgtar-create.c index 2b2c441fe..7568c153a 100644 --- a/tools/gpgtar-create.c +++ b/tools/gpgtar-create.c @@ -736,27 +736,88 @@ write_eof_mark (estream_t stream) +/* Create a new tarball using the names in the array INPATTERN. If + INPATTERN is NULL take the pattern as null terminated strings from + stdin. */ void gpgtar_create (char **inpattern) { gpg_error_t err = 0; - const char *pattern; struct scanctrl_s scanctrl_buffer; scanctrl_t scanctrl = &scanctrl_buffer; tar_header_t hdr, *start_tail; estream_t outstream = NULL; + int eof_seen = 0; + + if (!inpattern) + es_set_binary (es_stdin); memset (scanctrl, 0, sizeof *scanctrl); scanctrl->flist_tail = &scanctrl->flist; - for (; (pattern = *inpattern); inpattern++) + while (!eof_seen) { char *pat, *p; + int skip_this = 0; - if (!*pattern) - continue; + if (inpattern) + { + const char *pattern = *inpattern; + + if (!pattern) + break; /* End of array. */ + inpattern++; + + if (!*pattern) + continue; + + pat = xtrystrdup (pattern); + } + else /* Read null delimited pattern from stdin. */ + { + int c; + char namebuf[4096]; + size_t n = 0; + + for (;;) + { + if ((c = es_getc (es_stdin)) == EOF) + { + if (es_ferror (es_stdin)) + { + err = gpg_error_from_syserror (); + log_error ("error reading `%s': %s\n", + "[stdin]", strerror (errno)); + goto leave; + } + /* Note: The Nul is a delimiter and not a terminator. */ + c = 0; + eof_seen = 1; + } + if (n >= sizeof namebuf - 1) + { + if (!skip_this) + { + skip_this = 1; + log_error ("error reading `%s': %s\n", + "[stdin]", "filename too long"); + } + } + else + namebuf[n++] = c; + if (!c) + { + namebuf[n] = 0; + break; + } + } + + if (skip_this || n < 2) + continue; + + pat = xtrystrdup (namebuf); + } - pat = xtrystrdup (pattern); if (!pat) { err = gpg_error_from_syserror (); @@ -771,7 +832,7 @@ gpgtar_create (char **inpattern) log_info ("scanning `%s'\n", pat); start_tail = scanctrl->flist_tail; - if (!pattern_valid_p (pat)) + if (skip_this || !pattern_valid_p (pat)) log_error ("skipping invalid name `%s'\n", pat); else if (!add_entry (pat, NULL, scanctrl) && *start_tail && ((*start_tail)->typeflag & TF_DIRECTORY)) diff --git a/tools/gpgtar.c b/tools/gpgtar.c index 8a9aaaf9b..4ea9e73bf 100644 --- a/tools/gpgtar.c +++ b/tools/gpgtar.c @@ -55,12 +55,14 @@ enum cmd_and_opt_values oOutput = 'o', oQuiet = 'q', oVerbose = 'v', + oFilesFrom = 'T', oNoVerbose = 500, aSignEncrypt, oSkipCrypto, oSetFilename, - aList + aList, + oNull }; @@ -84,6 +86,10 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")), ARGPARSE_s_n (oSkipCrypto, "skip-crypto", N_("skip the crypto processing")), ARGPARSE_s_s (oSetFilename, "set-filename", "@"), + ARGPARSE_s_s (oFilesFrom, "files-from", + N_("|FILE|get names to create from FILE")), + ARGPARSE_s_n (oNull, "null", N_("-T reads null-terminated names")), + ARGPARSE_end () }; @@ -157,6 +163,8 @@ main (int argc, char **argv) int no_more_options = 0; enum cmd_and_opt_values cmd = 0; int skip_crypto = 0; + const char *files_from = NULL; + int null_names = 0; assert (sizeof (struct ustar_raw_header) == 512); @@ -181,6 +189,8 @@ main (int argc, char **argv) case oQuiet: opt.quiet = 1; break; case oVerbose: opt.verbose++; break; case oNoVerbose: opt.verbose = 0; break; + case oFilesFrom: files_from = pargs.r.ret_str; break; + case oNull: null_names = 1; break; case aList: case aDecrypt: @@ -202,6 +212,11 @@ main (int argc, char **argv) } } + if ((files_from && !null_names) || (!files_from && null_names)) + log_error ("--files-from and --null may only be used in conjunction\n"); + if (files_from && strcmp (files_from, "-")) + log_error ("--files-from only supports argument \"-\"\n"); + if (log_get_errorcount (0)) exit (2); @@ -213,6 +228,8 @@ main (int argc, char **argv) fname = argc ? *argv : NULL; if (opt.filename) log_info ("note: ignoring option --set-filename\n"); + if (files_from) + log_info ("note: ignoring option --files-from\n"); if (skip_crypto) gpgtar_list (fname); else @@ -220,14 +237,15 @@ main (int argc, char **argv) break; case aEncrypt: - if (!argc) + if ((!argc && !null_names) + || (argc && null_names)) usage (1); if (opt.filename) log_info ("note: ignoring option --set-filename\n"); if (skip_crypto) - gpgtar_create (argv); + gpgtar_create (null_names? NULL :argv); else - tar_and_encrypt (argv); + tar_and_encrypt (null_names? NULL : argv); break; case aDecrypt: @@ -235,6 +253,8 @@ main (int argc, char **argv) usage (1); if (opt.outfile) log_info ("note: ignoring option --output\n"); + if (files_from) + log_info ("note: ignoring option --files-from\n"); fname = argc ? *argv : NULL; if (skip_crypto) gpgtar_extract (fname);