]> 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,
    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.
 
    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 <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>
 #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;
 /* 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;
 
 /* 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_DATE       261
 #define OPT_VERBOSE    262
 #define OPT_SEEK       263
+#define OPT_UNLINK     264
 
 static struct argp_option options[] = {
 #define GRP 0
 
 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},
 
   {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"),
    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 },
   {"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, }
 };
 #undef GRP
   { NULL, }
 };
@@ -333,7 +337,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
     case 'r':
       mode = mode_exec;
 
     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':
       break;
 
     case 'T':
@@ -355,7 +363,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
 
     case OPT_DATE:
       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;
 
        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_TRUNCATE:
     case OPT_TOUCH:
     case OPT_EXEC:
+    case OPT_UNLINK:
       reg_action (key, arg);
       break;
 
       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)
        {
        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;
 
            {
              char *q;
 
-             mask = strtoul (p + 5, &q, 8);
+             val &= strtoul (p + 5, &q, 8);
              if (*q)
                {
                  printf ("\n");
              if (*q)
                {
                  printf ("\n");
@@ -590,7 +599,7 @@ print_stat (const char *name)
              printf ("\n");
              error (EXIT_FAILURE, 0, _("Unknown field `%s'"), p);
            }
              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);
        }
       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;
        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;
          {
            error (0, errno, _("cannot set time on `%s'"), p->name);
            break;
@@ -685,6 +694,11 @@ exec_checkpoint (struct action *p)
       system (p->name);
       break;
 
       system (p->name);
       break;
 
+    case OPT_UNLINK:
+      if (unlink (p->name))
+       error (0, errno, _("cannot unlink `%s'"), p->name);
+      break;
+
     default:
       abort ();
     }
     default:
       abort ();
     }
@@ -730,11 +744,17 @@ exec_command (void)
 
   /* Insert --checkpoint option.
      FIXME: This assumes that exec_argv does not use traditional tar options
 
   /* 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.  */
 
 #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);
       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 */
     }
 
   /* Master */
@@ -771,12 +791,12 @@ exec_command (void)
 
   while ((p = fgets (buf, sizeof buf, fp)))
     {
 
   while ((p = fgets (buf, sizeof buf, fp)))
     {
-      while (*p && !isspace (*p) && *p != ':')
+      while (*p && !isspace ((unsigned char) *p) && *p != ':')
        p++;
 
       if (*p == ':')
        {
        p++;
 
       if (*p == ':')
        {
-         for (p++; *p && isspace (*p); p++)
+         for (p++; *p && isspace ((unsigned char) *p); p++)
            ;
 
          if (*p
            ;
 
          if (*p
@@ -784,7 +804,7 @@ exec_command (void)
            {
              char *end;
              size_t n = strtoul (p + sizeof CHECKPOINT_TEXT - 1, &end, 10);
            {
              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;
                {
                  process_checkpoint (n);
                  continue;
@@ -834,7 +854,7 @@ main (int argc, char **argv)
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
 
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
 
-  get_date (&touch_time, "now", NULL);
+  parse_datetime (&touch_time, "now", NULL);
 
   /* Decode command options.  */
 
 
   /* Decode command options.  */
 
@@ -872,6 +892,13 @@ main (int argc, char **argv)
       break;
 
     case mode_exec:
       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;
 
       exec_command ();
       break;