]> git.cworth.org Git - tar/blobdiff - tests/genfile.c
upstream: Fix extraction of device nodes.
[tar] / tests / genfile.c
index 1b338bce2f95a77635abe7f7f6926b53802d4395..8541be6c4d8e692b3f790989f7259f452fd977c9 100644 (file)
@@ -2,7 +2,7 @@
    Print statistics for existing files.
 
    Copyright (C) 1995, 1996, 1997, 2001, 2003, 2004, 2005, 2006, 2007,
-   2008 Free Software Foundation, Inc.
+   2008, 2009 Free Software Foundation, Inc.
 
    François Pinard <pinard@iro.umontreal.ca>, 1995.
    Sergey Poznyakoff <gray@mirddin.farlep.net>, 2004, 2005, 2006, 2007, 2008.
@@ -28,8 +28,7 @@
 #include <argmatch.h>
 #include <argp.h>
 #include <argcv.h>
-#include <getdate.h>
-#include <utimens.h>
+#include <parse-datetime.h>
 #include <inttostr.h>
 #include <fcntl.h>
 #include <sys/stat.h>
@@ -99,6 +98,7 @@ char *buffer;
 /* Number of arguments and argument vector for mode == mode_exec */
 int exec_argc;
 char **exec_argv;
+char *checkpoint_option;
 
 /* Time for --touch option */
 struct timespec touch_time;
@@ -119,6 +119,7 @@ static char doc[] = N_("genfile manipulates data files for GNU paxutils test sui
 #define OPT_DATE       261
 #define OPT_VERBOSE    262
 #define OPT_SEEK       263
+#define OPT_UNLINK     264
 
 static struct argp_option options[] = {
 #define GRP 0
@@ -159,8 +160,8 @@ static struct argp_option options[] = {
   {NULL, 0, NULL, 0,
    N_("Synchronous execution options:"), GRP},
 
-  {"run", 'r', N_("COMMAND"), 0,
-   N_("Execute given COMMAND. Useful with --checkpoint and one of --cut, --append, --touch"),
+  {"run", 'r', N_("OPTION"), OPTION_ARG_OPTIONAL,
+   N_("Execute ARGS. Useful with --checkpoint and one of --cut, --append, --touch, --unlink"),
    GRP+1 },
   {"checkpoint", OPT_CHECKPOINT, N_("NUMBER"), 0,
    N_("Perform given action (see below) upon reaching checkpoint NUMBER"),
@@ -189,6 +190,9 @@ static struct argp_option options[] = {
   {"exec", OPT_EXEC, N_("COMMAND"), 0,
    N_("Execute COMMAND"),
    GRP+1 },
+  {"unlink", OPT_UNLINK, N_("FILE"), 0,
+   N_("Unlink FILE"),
+   GRP+1 },
 #undef GRP
   { NULL, }
 };
@@ -333,7 +337,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
     case 'r':
       mode = mode_exec;
-      argcv_get (arg, "", NULL, &exec_argc, &exec_argv);
+      if (arg)
+       {
+         argcv_get (arg, "", NULL, &exec_argc, &exec_argv);
+         checkpoint_option = "--checkpoint";
+       }
       break;
 
     case 'T':
@@ -355,7 +363,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
 
     case OPT_DATE:
-      if (!get_date (&touch_time, arg, NULL))
+      if (! parse_datetime (&touch_time, arg, NULL))
        argp_error (state, _("Unknown date format"));
       break;
 
@@ -363,6 +371,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case OPT_TRUNCATE:
     case OPT_TOUCH:
     case OPT_EXEC:
+    case OPT_UNLINK:
       reg_action (key, arg);
       break;
 
@@ -572,13 +581,13 @@ print_stat (const char *name)
        printf ("%lu", (unsigned long) st.st_ino);
       else if (strncmp (p, "mode", 4) == 0)
        {
-         mode_t mask = ~0;
+         unsigned val = st.st_mode;
 
-         if (ispunct (p[4]))
+         if (ispunct ((unsigned char) p[4]))
            {
              char *q;
 
-             mask = strtoul (p + 5, &q, 8);
+             val &= strtoul (p + 5, &q, 8);
              if (*q)
                {
                  printf ("\n");
@@ -590,7 +599,7 @@ print_stat (const char *name)
              printf ("\n");
              error (EXIT_FAILURE, 0, _("Unknown field `%s'"), p);
            }
-         printf ("%0o", st.st_mode & mask);
+         printf ("%0o", val);
        }
       else if (strcmp (p, "nlink") == 0)
        printf ("%lu", (unsigned long) st.st_nlink);
@@ -646,7 +655,7 @@ exec_checkpoint (struct action *p)
        struct timespec ts[2];
 
        ts[0] = ts[1] = p->ts;
-       if (utimens (p->name, ts) != 0)
+       if (utimensat (AT_FDCWD, p->name, ts, 0) != 0)
          {
            error (0, errno, _("cannot set time on `%s'"), p->name);
            break;
@@ -685,6 +694,11 @@ exec_checkpoint (struct action *p)
       system (p->name);
       break;
 
+    case OPT_UNLINK:
+      if (unlink (p->name))
+       error (0, errno, _("cannot unlink `%s'"), p->name);
+      break;
+
     default:
       abort ();
     }
@@ -730,11 +744,17 @@ exec_command (void)
 
   /* Insert --checkpoint option.
      FIXME: This assumes that exec_argv does not use traditional tar options
-     (without dash) */
-  exec_argc++;
-  exec_argv = xrealloc (exec_argv, (exec_argc + 1) * sizeof (*exec_argv));
-  memmove (exec_argv+2, exec_argv+1, (exec_argc - 1) * sizeof (*exec_argv));
-  exec_argv[1] = "--checkpoint";
+     (without dash).
+     FIXME: There is no way to set checkpoint argument (granularity).
+  */
+  if (checkpoint_option)
+    {
+      exec_argc++;
+      exec_argv = xrealloc (exec_argv, (exec_argc + 1) * sizeof (*exec_argv));
+      memmove (exec_argv+2, exec_argv+1,
+              (exec_argc - 1) * sizeof (*exec_argv));
+      exec_argv[1] = checkpoint_option;
+    }
 
 #ifdef SIGCHLD
   /* System V fork+wait does not work if SIGCHLD is ignored.  */
@@ -760,7 +780,7 @@ exec_command (void)
       setenv ("LC_ALL", "POSIX", 1);
 
       execvp (exec_argv[0], exec_argv);
-      error (EXIT_FAILURE, errno, "execvp");
+      error (EXIT_FAILURE, errno, "execvp %s", exec_argv[0]);
     }
 
   /* Master */
@@ -771,12 +791,12 @@ exec_command (void)
 
   while ((p = fgets (buf, sizeof buf, fp)))
     {
-      while (*p && !isspace (*p) && *p != ':')
+      while (*p && !isspace ((unsigned char) *p) && *p != ':')
        p++;
 
       if (*p == ':')
        {
-         for (p++; *p && isspace (*p); p++)
+         for (p++; *p && isspace ((unsigned char) *p); p++)
            ;
 
          if (*p
@@ -784,7 +804,7 @@ exec_command (void)
            {
              char *end;
              size_t n = strtoul (p + sizeof CHECKPOINT_TEXT - 1, &end, 10);
-             if (!(*end && !isspace (*end)))
+             if (!(*end && !isspace ((unsigned char) *end)))
                {
                  process_checkpoint (n);
                  continue;
@@ -834,7 +854,7 @@ main (int argc, char **argv)
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
 
-  get_date (&touch_time, "now", NULL);
+  parse_datetime (&touch_time, "now", NULL);
 
   /* Decode command options.  */
 
@@ -872,6 +892,13 @@ main (int argc, char **argv)
       break;
 
     case mode_exec:
+      if (!checkpoint_option)
+       {
+         exec_argc = argc;
+         exec_argv = argv;
+       }
+      else if (argc)
+       error (EXIT_FAILURE, 0, _("too many arguments"));
       exec_command ();
       break;