]> Dogcows Code - chaz/tar/blobdiff - src/tar.c
New option --full-time.
[chaz/tar] / src / tar.c
index 0c59352dc2216432f43387b980e1a7a86508a5a0..21c396d56601ca0c0ed9e2edd497a457bea14610 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -214,9 +214,10 @@ subcommand_string (enum subcommand c)
     case UPDATE_SUBCOMMAND:
       return "-u";
 
-    default:
-      abort ();
+    case TEST_LABEL_SUBCOMMAND:
+      return "--test-label";
     }
+  abort ();
 }
 
 void
@@ -273,6 +274,7 @@ enum
   EXCLUDE_TAG_ALL_OPTION,
   EXCLUDE_VCS_OPTION,
   FORCE_LOCAL_OPTION,
+  FULL_TIME_OPTION,
   GROUP_OPTION,
   IGNORE_CASE_OPTION,
   IGNORE_COMMAND_ERROR_OPTION,
@@ -280,6 +282,7 @@ enum
   INDEX_FILE_OPTION,
   KEEP_NEWER_FILES_OPTION,
   LEVEL_OPTION,
+  LZIP_OPTION,
   LZMA_OPTION,
   LZOP_OPTION,
   MODE_OPTION,
@@ -614,23 +617,19 @@ static struct argp_option options[] = {
   {"no-auto-compress", NO_AUTO_COMPRESS_OPTION, 0, 0,
    N_("do not use archive suffix to determine the compression program"),
    GRID+1 },
-  {"bzip2", 'j', 0, 0,
-   N_("filter the archive through bzip2"), GRID+1 },
-  {"gzip", 'z', 0, 0,
-   N_("filter the archive through gzip"), GRID+1 },
+  {"use-compress-program", 'I', N_("PROG"), 0,
+   N_("filter through PROG (must accept -d)"), GRID+1 },
+  /* Note: docstrings for the options below are generated by tar_help_filter */
+  {"bzip2", 'j', 0, 0, NULL, GRID+1 },
+  {"gzip", 'z', 0, 0, NULL, GRID+1 },
   {"gunzip", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
   {"ungzip", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
-  {"compress", 'Z', 0, 0,
-   N_("filter the archive through compress"), GRID+1 },
+  {"compress", 'Z', 0, 0, NULL, GRID+1 },
   {"uncompress", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
-  {"lzma", LZMA_OPTION, 0, 0,
-   N_("filter the archive through lzma"), GRID+1 },
-  {"lzop", LZOP_OPTION, 0, 0,
-   N_("filter the archive through lzop"), GRID+8 },
-  {"xz", 'J', 0, 0,
-   N_("filter the archive through xz"), GRID+8 },
-  {"use-compress-program", 'I', N_("PROG"), 0,
-   N_("filter through PROG (must accept -d)"), GRID+1 },
+  {"lzip", LZIP_OPTION, 0, 0, NULL, GRID+1 },
+  {"lzma", LZMA_OPTION, 0, 0, NULL, GRID+1 },
+  {"lzop", LZOP_OPTION, 0, 0, NULL, GRID+1 },
+  {"xz", 'J', 0, 0, NULL, GRID+1 },
 #undef GRID
   
 #define GRID 100
@@ -754,7 +753,9 @@ static struct argp_option options[] = {
       "Allowed signals are: SIGHUP, SIGQUIT, SIGINT, SIGUSR1 and SIGUSR2; "
       "the names without SIG prefix are also accepted"), GRID+1 },
   {"utc", UTC_OPTION, 0, 0,
-   N_("print file modification dates in UTC"), GRID+1 },
+   N_("print file modification times in UTC"), GRID+1 },
+  {"full-time", FULL_TIME_OPTION, 0, 0,
+   N_("print file time to its full resolution"), GRID+1 },
   {"index-file", INDEX_FILE_OPTION, N_("FILE"), 0,
    N_("send verbose output to FILE"), GRID+1 },
   {"block-number", 'R', 0, 0,
@@ -903,9 +904,7 @@ add_exclude_array (char const * const * fv)
 static char *
 format_default_settings (void)
 {
-  char *s;
-  
-  asprintf (&s,
+  return xasprintf (
            "--format=%s -f%s -b%d --quoting-style=%s --rmt-command=%s"
 #ifdef REMOTE_SHELL
            " --rsh-command=%s"
@@ -914,12 +913,11 @@ format_default_settings (void)
            archive_format_string (DEFAULT_ARCHIVE_FORMAT), 
            DEFAULT_ARCHIVE, DEFAULT_BLOCKING,              
            quoting_style_args[DEFAULT_QUOTING_STYLE],
-           DEFAULT_RMT_COMMAND,
+           DEFAULT_RMT_COMMAND
 #ifdef REMOTE_SHELL
-           REMOTE_SHELL
+           REMOTE_SHELL
 #endif
            );
-  return s;
 }
 
 \f
@@ -929,7 +927,7 @@ set_subcommand_option (enum subcommand subcommand)
   if (subcommand_option != UNKNOWN_SUBCOMMAND
       && subcommand_option != subcommand)
     USAGE_ERROR ((0, 0,
-                 _("You may not specify more than one `-Acdtrux' option")));
+                 _("You may not specify more than one `-Acdtrux' or `--test-label' option")));
   
   subcommand_option = subcommand;
 }
@@ -1002,12 +1000,12 @@ set_stat_signal (const char *name)
 struct textual_date
 {
   struct textual_date *next;
-  struct timespec *ts;
+  struct timespec ts;
   const char *option;
-  const char *date;
+  char *date;
 };
 
-static void
+static int
 get_date_or_file (struct tar_args *args, const char *option,
                  const char *str, struct timespec *ts)
 {
@@ -1030,17 +1028,19 @@ get_date_or_file (struct tar_args *args, const char *option,
          WARN ((0, 0, _("Substituting %s for unknown date format %s"),
                 tartime (*ts, false), quote (str)));
          ts->tv_nsec = 0;
+         return 1;
        }
       else
        {
          struct textual_date *p = xmalloc (sizeof (*p));
-         p->ts = ts;
+         p->ts = *ts;
          p->option = option;
-         p->date = str;
+         p->date = xstrdup (str);
          p->next = args->textual_date;
          args->textual_date = p;
        }
     }
+  return 0;
 }
 
 static void
@@ -1050,10 +1050,14 @@ report_textual_dates (struct tar_args *args)
   for (p = args->textual_date; p; )
     {
       struct textual_date *next = p->next;
-      char const *treated_as = tartime (*p->ts, true);
-      if (strcmp (p->date, treated_as) != 0)
-       WARN ((0, 0, _("Option %s: Treating date `%s' as %s"),
-              p->option, p->date, treated_as));
+      if (verbose_option)
+       {
+         char const *treated_as = tartime (p->ts, true);
+         if (strcmp (p->date, treated_as) != 0)
+           WARN ((0, 0, _("Option %s: Treating date `%s' as %s"),
+                  p->option, p->date, treated_as));
+       }
+      free (p->date);
       free (p);
       p = next;
     }
@@ -1253,25 +1257,112 @@ tar_help_filter (int key, const char *text, void *input)
 {
   struct obstack stk;
   char *s;
+  
+  switch (key)
+    {
+    default:
+      s = (char*) text;
+      break;
+      
+    case 'j':
+      s = xasprintf (_("filter the archive through %s"), BZIP2_PROGRAM);
+      break;
+      
+    case 'z':
+      s = xasprintf (_("filter the archive through %s"), GZIP_PROGRAM);
+      break;
+      
+    case 'Z':
+      s = xasprintf (_("filter the archive through %s"), COMPRESS_PROGRAM);
+      break;
 
-  if (key != ARGP_KEY_HELP_EXTRA)
-    return (char*) text;
-
+    case LZIP_OPTION:
+      s = xasprintf (_("filter the archive through %s"), LZIP_PROGRAM);
+      break;
+      
+    case LZMA_OPTION:
+      s = xasprintf (_("filter the archive through %s"), LZMA_PROGRAM);
+      break;
+      
+    case 'J':
+      s = xasprintf (_("filter the archive through %s"), XZ_PROGRAM);
+      break;
+      
+    case ARGP_KEY_HELP_EXTRA:
+      {
+       const char *tstr;
+
+       obstack_init (&stk);
+       tstr = _("Valid arguments for the --quoting-style option are:");
+       obstack_grow (&stk, tstr, strlen (tstr));
+       obstack_grow (&stk, "\n\n", 2);
+       tar_list_quoting_styles (&stk, "  ");
+       tstr = _("\n*This* tar defaults to:\n");
+       obstack_grow (&stk, tstr, strlen (tstr));
+       s = format_default_settings ();
+       obstack_grow (&stk, s, strlen (s));
+       obstack_1grow (&stk, '\n');
+       obstack_1grow (&stk, 0);
+       s = xstrdup (obstack_finish (&stk));
+       obstack_free (&stk, NULL);
+      }
+    }
+  return s;
+}
+\f
+static char *
+expand_pax_option (struct tar_args *targs, const char *arg)
+{
+  struct obstack stk;
+  char *res;
+  
   obstack_init (&stk);
-  s = _("Valid arguments for the --quoting-style option are:");
-  obstack_grow (&stk, s, strlen (s));
-  obstack_grow (&stk, "\n\n", 2);
-  tar_list_quoting_styles (&stk, "  ");
-  s = _("\n*This* tar defaults to:\n");
-  obstack_grow (&stk, s, strlen (s));
-  s = format_default_settings ();
-  obstack_grow (&stk, s, strlen (s));
-  obstack_1grow (&stk, '\n');
+  while (*arg)
+    {
+      size_t seglen = strcspn (arg, ",");
+      char *p = memchr (arg, '=', seglen);
+      if (p)
+       {
+         size_t len = p - arg + 1;
+         obstack_grow (&stk, arg, len);
+         len = seglen - len;
+         for (++p; *p && isspace ((unsigned char) *p); p++)
+           len--;
+         if (*p == '{' && p[len-1] == '}')
+           {
+             struct timespec ts;
+             char *tmp = xmalloc (len);
+             memcpy (tmp, p + 1, len-2);
+             tmp[len-2] = 0;
+             if (get_date_or_file (targs, "--pax-option", tmp, &ts) == 0)
+               {
+                 char buf[UINTMAX_STRSIZE_BOUND], *s;
+                 s = umaxtostr (ts.tv_sec, buf);
+                 obstack_grow (&stk, s, strlen (s));
+               }
+             else
+               obstack_grow (&stk, p, len);
+             free (tmp);
+           }
+         else
+           obstack_grow (&stk, p, len);
+       }
+      else
+       obstack_grow (&stk, arg, seglen);
+
+      arg += seglen;
+      if (*arg)
+       {
+         obstack_1grow (&stk, *arg);
+         arg++;
+       }
+    }
   obstack_1grow (&stk, 0);
-  s = xstrdup (obstack_finish (&stk));
+  res = xstrdup (obstack_finish (&stk));
   obstack_free (&stk, NULL);
-  return s;
+  return res;
 }
+
 \f
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
@@ -1349,6 +1440,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
       info_script_option = arg;
       multi_volume_option = true;
       break;
+
+    case FULL_TIME_OPTION:
+      full_time_option = true;
+      break;
       
     case 'g':
       listed_incremental_option = arg;
@@ -1381,11 +1476,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
       
     case 'j':
-      set_use_compress_program_option ("bzip2");
+      set_use_compress_program_option (BZIP2_PROGRAM);
       break;
       
     case 'J':
-      set_use_compress_program_option ("xz");
+      set_use_compress_program_option (XZ_PROGRAM);
       break;
       
     case 'k':
@@ -1428,12 +1523,16 @@ parse_opt (int key, char *arg, struct argp_state *state)
       }
       break;
       
+    case LZIP_OPTION:
+      set_use_compress_program_option (LZIP_PROGRAM);
+      break;
+      
     case LZMA_OPTION:
-      set_use_compress_program_option ("lzma");
+      set_use_compress_program_option (LZMA_PROGRAM);
       break;
       
     case LZOP_OPTION:
-      set_use_compress_program_option ("lzop");
+      set_use_compress_program_option (LZOP_PROGRAM);
       break;
       
     case 'm':
@@ -1535,8 +1634,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
       
     case TEST_LABEL_OPTION:
-      set_subcommand_option (LIST_SUBCOMMAND);
-      test_label_option = true;
+      set_subcommand_option (TEST_LABEL_SUBCOMMAND);
       break;
       
     case 'T':
@@ -1591,11 +1689,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
       
     case 'z':
-      set_use_compress_program_option ("gzip");
+      set_use_compress_program_option (GZIP_PROGRAM);
       break;
       
     case 'Z':
-      set_use_compress_program_option ("compress");
+      set_use_compress_program_option (COMPRESS_PROGRAM);
       break;
       
     case ANCHORED_OPTION:
@@ -1840,8 +1938,12 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
       
     case PAX_OPTION:
-      args->pax_option = true;
-      xheader_set_option (arg);
+      {
+       char *tmp = expand_pax_option (args, arg);
+       args->pax_option = true;
+       xheader_set_option (tmp);
+       free (tmp);
+      }
       break;
       
     case POSIX_OPTION:
@@ -2356,7 +2458,7 @@ decode_options (int argc, char **argv)
     old_files_option = UNLINK_FIRST_OLD_FILES;
 
 
-  if (test_label_option)
+  if (subcommand_option == TEST_LABEL_SUBCOMMAND)
     {
       /* --test-label is silent if the user has specified the label name to
         compare against. */
@@ -2391,6 +2493,7 @@ decode_options (int argc, char **argv)
     case EXTRACT_SUBCOMMAND:
     case LIST_SUBCOMMAND:
     case DIFF_SUBCOMMAND:
+    case TEST_LABEL_SUBCOMMAND:
       for (archive_name_cursor = archive_name_array;
           archive_name_cursor < archive_name_array + archive_names;
           archive_name_cursor++)
@@ -2440,8 +2543,7 @@ decode_options (int argc, char **argv)
 
   checkpoint_finish_compile ();
   
-  if (verbose_option)
-    report_textual_dates (&args);
+  report_textual_dates (&args);
 }
 
 \f
@@ -2475,8 +2577,6 @@ main (int argc, char **argv)
 
   obstack_init (&argv_stk);
 
-  /* Ensure default behavior for some signals */
-  signal (SIGPIPE, SIG_DFL);
   /* System V fork+wait does not work if SIGCHLD is ignored.  */
   signal (SIGCHLD, SIG_DFL);
 
@@ -2498,7 +2598,7 @@ main (int argc, char **argv)
     {
     case UNKNOWN_SUBCOMMAND:
       USAGE_ERROR ((0, 0,
-                   _("You must specify one of the `-Acdtrux' options")));
+                   _("You must specify one of the `-Acdtrux' or `--test-label'  options")));
 
     case CAT_SUBCOMMAND:
     case UPDATE_SUBCOMMAND:
@@ -2532,6 +2632,9 @@ main (int argc, char **argv)
       diff_init ();
       read_and (diff_archive);
       break;
+
+    case TEST_LABEL_SUBCOMMAND:
+      test_archive_label ();
     }
 
   if (totals_option)
This page took 0.031162 seconds and 4 git commands to generate.