]> Dogcows Code - chaz/tar/blobdiff - src/tar.c
(confirm): Rewritten using rpmatch.
[chaz/tar] / src / tar.c
index eacdaaf31436fbc192a60f7a0a7352281f69026d..8fd0548e0d8641547b506eb7b10a4d64346a74db 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -42,6 +42,7 @@
 #include <prepargs.h>
 #include <quotearg.h>
 #include <xstrtol.h>
+#include <stdopen.h>
 
 /* Local declarations.  */
 
@@ -74,12 +75,15 @@ request_stdin (const char *option)
   stdin_used_by = option;
 }
 
-/* Returns true if and only if the user typed 'y' or 'Y'.  */
+extern int rpmatch (char const *response);
+
+/* Returns true if and only if the user typed an affirmative response.  */
 int
 confirm (const char *message_action, const char *message_name)
 {
   static FILE *confirm_file;
   static int confirm_file_EOF;
+  bool status = false;
 
   if (!confirm_file)
     {
@@ -99,22 +103,24 @@ confirm (const char *message_action, const char *message_name)
   fprintf (stdlis, "%s %s?", message_action, quote (message_name));
   fflush (stdlis);
 
-  {
-    int reply = confirm_file_EOF ? EOF : getc (confirm_file);
-    int character;
+  if (!confirm_file_EOF)
+    {
+      char *response = NULL;
+      size_t response_size = 0;
+      if (getline (&response, &response_size, confirm_file) < 0)
+       confirm_file_EOF = 1;
+      else
+       status = rpmatch (response) > 0;
+      free (response);
+    }
+  
+  if (confirm_file_EOF)
+    {
+      fputc ('\n', stdlis);
+      fflush (stdlis);
+    }
 
-    for (character = reply;
-        character != '\n';
-        character = getc (confirm_file))
-      if (character == EOF)
-       {
-         confirm_file_EOF = 1;
-         fputc ('\n', stdlis);
-         fflush (stdlis);
-         break;
-       }
-    return reply == 'y' || reply == 'Y';
-  }
+  return status;
 }
 
 static struct fmttab {
@@ -130,7 +136,7 @@ static struct fmttab {
 #endif
   { "gnu",     GNU_FORMAT },
   { "pax",     POSIX_FORMAT }, /* An alias for posix */
-  { NULL,       0 }
+  { NULL,      0 }
 };
 
 static void
@@ -162,7 +168,7 @@ archive_format_string (enum archive_format fmt)
 static void
 assert_format(unsigned fmt_mask)
 {
-  if ((FORMAT_MASK(archive_format) & fmt_mask) == 0)
+  if ((FORMAT_MASK (archive_format) & fmt_mask) == 0)
     USAGE_ERROR ((0, 0,
                  _("GNU features wanted on incompatible archive format")));
 }
@@ -171,13 +177,6 @@ assert_format(unsigned fmt_mask)
 \f
 /* Options.  */
 
-/* For long options that unconditionally set a single flag, we have getopt
-   do it.  For the others, we share the code for the equivalent short
-   named option, the name of which is stored in the otherwise-unused `val'
-   field of the `struct option'; for long options that have no equivalent
-   short option, we use non-characters as pseudo short options,
-   starting at CHAR_MAX + 1 and going upwards.  */
-
 enum
 {
   ANCHORED_OPTION = CHAR_MAX + 1,
@@ -265,9 +264,10 @@ The version control may be set with --backup or VERSION_CONTROL, values are:\n\n
    Available option letters are DEIJQY and aeqy. Consider the following
    assignments:
 
-   [For Solaris tar compatibility]
+   [For Solaris tar compatibility =/= Is it important at all?]
    e  exit immediately with a nonzero exit status if unexpected errors occur
    E  use extended headers (--format=posix)
+   
    [q  alias for --occurrence=1 =/= this would better be used for quiet?]
    [I  same as T =/= will harm star compatibility]
 
@@ -314,7 +314,7 @@ static struct argp_option options[] = {
   {"occurrence", OCCURRENCE_OPTION, N_("NUMBER"), OPTION_ARG_OPTIONAL,
    N_("process only the NUMBERth occurrence of each file in the archive. This option is valid only in conjunction with one of the subcommands --delete, --diff, --extract or --list and when a list of files is given either on the command line or via -T option. NUMBER defaults to 1."), 21 },
   {"seek", 'n', NULL, 0,
-   N_("archive is seekable"), 21 },    
+   N_("archive is seekable"), 21 },
 
   {NULL, 0, NULL, 0,
    N_("Overwrite control:"), 30},
@@ -557,7 +557,7 @@ static struct argp_option options[] = {
   {"show-stored-names", SHOW_STORED_NAMES_OPTION, 0, 0,
    N_("When creating archive in verbose mode, list member names as stored in the archive"),
    102 },
-    
+
   {NULL, 0, NULL, 0,
    N_("Compatibility options:"), 110 },
 
@@ -1047,7 +1047,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       set_subcommand_option (LIST_SUBCOMMAND);
       test_label_option = true;
       break;
-      
+
     case 'T':
       update_argv (arg, state);
       /* Indicate we've been given -T option. This is for backward
@@ -1323,7 +1323,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case SHOW_STORED_NAMES_OPTION:
       show_stored_names_option = true;
       break;
-      
+
     case SUFFIX_OPTION:
       backup_option = true;
       args->backup_suffix_string = arg;
@@ -1667,15 +1667,10 @@ decode_options (int argc, char **argv)
        archive_format = DEFAULT_ARCHIVE_FORMAT;
     }
 
-  if (volume_label_option && subcommand_option == CREATE_SUBCOMMAND)
-    assert_format (FORMAT_MASK (OLDGNU_FORMAT)
-                  | FORMAT_MASK (GNU_FORMAT));
-
-
-  if (incremental_option || multi_volume_option)
-    assert_format (FORMAT_MASK (OLDGNU_FORMAT) | FORMAT_MASK (GNU_FORMAT));
-
-  if (sparse_option)
+  if ((volume_label_option && subcommand_option == CREATE_SUBCOMMAND)
+      || incremental_option
+      || multi_volume_option
+      || sparse_option)
     assert_format (FORMAT_MASK (OLDGNU_FORMAT)
                   | FORMAT_MASK (GNU_FORMAT)
                   | FORMAT_MASK (POSIX_FORMAT));
@@ -1729,22 +1724,27 @@ decode_options (int argc, char **argv)
 
   if (volume_label_option)
     {
-      size_t volume_label_max_len =
-       (sizeof current_header->header.name
-        - 1 /* for trailing '\0' */
-        - (multi_volume_option
-           ? (sizeof " Volume "
-              - 1 /* for null at end of " Volume " */
-              + INT_STRLEN_BOUND (int) /* for volume number */
-              - 1 /* for sign, as 0 <= volno */)
-           : 0));
-      if (volume_label_max_len < strlen (volume_label_option))
-       USAGE_ERROR ((0, 0,
-                     ngettext ("%s: Volume label is too long (limit is %lu byte)",
-                               "%s: Volume label is too long (limit is %lu bytes)",
-                               volume_label_max_len),
-                     quotearg_colon (volume_label_option),
-                     (unsigned long) volume_label_max_len));
+      if (archive_format == GNU_FORMAT || archive_format == OLDGNU_FORMAT)
+       {
+         size_t volume_label_max_len =
+           (sizeof current_header->header.name
+            - 1 /* for trailing '\0' */
+            - (multi_volume_option
+               ? (sizeof " Volume "
+                  - 1 /* for null at end of " Volume " */
+                  + INT_STRLEN_BOUND (int) /* for volume number */
+                  - 1 /* for sign, as 0 <= volno */)
+               : 0));
+         if (volume_label_max_len < strlen (volume_label_option))
+           USAGE_ERROR ((0, 0,
+                         ngettext ("%s: Volume label is too long (limit is %lu byte)",
+                                   "%s: Volume label is too long (limit is %lu bytes)",
+                                   volume_label_max_len),
+                         quotearg_colon (volume_label_option),
+                         (unsigned long) volume_label_max_len));
+       }
+      /* else FIXME
+        Label length in PAX format is limited by the volume size. */
     }
 
   if (verify_option)
@@ -1759,8 +1759,11 @@ decode_options (int argc, char **argv)
     {
       if (multi_volume_option)
        USAGE_ERROR ((0, 0, _("Cannot use multi-volume compressed archives")));
-      if (subcommand_option == UPDATE_SUBCOMMAND)
+      if (subcommand_option == UPDATE_SUBCOMMAND
+         || subcommand_option == APPEND_SUBCOMMAND)
        USAGE_ERROR ((0, 0, _("Cannot update compressed archives")));
+      if (subcommand_option == CAT_SUBCOMMAND)
+       USAGE_ERROR ((0, 0, _("Cannot concatenate compressed archives")));
     }
 
   /* It is no harm to use --pax-option on non-pax archives in archive
@@ -1867,6 +1870,9 @@ main (int argc, char **argv)
   filename_terminator = '\n';
   set_quoting_style (0, escape_quoting_style);
 
+  /* Make sure we have first three descriptors available */
+  stdopen ();
+    
   /* Pre-allocate a few structures.  */
 
   allocated_archive_names = 10;
@@ -1970,5 +1976,20 @@ tar_stat_destroy (struct tar_stat_info *st)
   free (st->uname);
   free (st->gname);
   free (st->sparse_map);
+  free (st->dumpdir);
   memset (st, 0, sizeof (*st));
 }
+
+/* Format mask for all available formats that support nanosecond
+   timestamp resolution. */
+#define NS_PRECISION_FORMAT_MASK FORMAT_MASK (POSIX_FORMAT)
+
+/* Same as timespec_cmp, but ignore nanoseconds if current archive
+   format does not provide sufficient resolution.  */
+int
+tar_timespec_cmp (struct timespec a, struct timespec b)
+{
+  if (!(FORMAT_MASK (current_format) & NS_PRECISION_FORMAT_MASK))
+    a.tv_nsec = b.tv_nsec = 0;
+  return timespec_cmp (a, b);
+}
This page took 0.028519 seconds and 4 git commands to generate.