Add option --null
authorWerner Koch <wk@gnupg.org>
Mon, 9 Aug 2010 09:05:18 +0000 (09:05 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 9 Aug 2010 09:05:18 +0000 (09:05 +0000)
tools/ChangeLog
tools/gpgtar-create.c
tools/gpgtar.c

index 5599ff5..65bb6f6 100644 (file)
@@ -1,3 +1,8 @@
+2010-08-09  Werner Koch  <wk@g10code.com>
+
+       * gpgtar.c (main): Add options -T and --null.
+       * gpgtar-create.c (gpgtar_create): Implement option --null.
+
 2010-07-16  Werner Koch  <wk@g10code.com>
 
        * gpgtar-create.c: Rewrite to better support W32.
index 2b2c441..7568c15 100644 (file)
@@ -736,27 +736,88 @@ write_eof_mark (estream_t stream)
 
 
 \f
+/* 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 (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;
 
-      if (!*pattern)
-        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))
index 8a9aaaf..4ea9e73 100644 (file)
@@ -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);