]> Dogcows Code - chaz/tar/blobdiff - src/tar.c
gnulib: sync from latest gnulib, notably bootstrap and parse-datetime
[chaz/tar] / src / tar.c
index 5b61144c65c979fcb2c51b3e8918a59629a78fba..928cfddd44a86220ab444844cac61c10da6495aa 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -43,7 +43,7 @@
 #include <closeout.h>
 #include <configmake.h>
 #include <exitfail.h>
-#include <getdate.h>
+#include <parse-datetime.h>
 #include <rmt.h>
 #include <rmt-command.h>
 #include <prepargs.h>
@@ -74,7 +74,7 @@
 static const char *stdin_used_by;
 
 /* Doesn't return if stdin already requested.  */
-void
+static void
 request_stdin (const char *option)
 {
   if (stdin_used_by)
@@ -1014,7 +1014,7 @@ get_date_or_file (struct tar_args *args, const char *option,
       || *str == '.')
     {
       struct stat st;
-      if (deref_stat (dereference_option, str, &st) != 0)
+      if (stat (str, &st) != 0)
        {
          stat_error (str);
          USAGE_ERROR ((0, 0, _("Date sample file not found")));
@@ -1023,7 +1023,7 @@ get_date_or_file (struct tar_args *args, const char *option,
     }
   else
     {
-      if (! get_date (ts, str, NULL))
+      if (! parse_datetime (ts, str, NULL))
        {
          WARN ((0, 0, _("Substituting %s for unknown date format %s"),
                 tartime (*ts, false), quote (str)));
@@ -1364,6 +1364,8 @@ expand_pax_option (struct tar_args *targs, const char *arg)
 }
 
 \f
+#define TAR_SIZE_SUFFIXES "bBcGgkKMmPTtw"
+
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
 {
@@ -1506,10 +1508,15 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case 'L':
       {
        uintmax_t u;
-       if (xstrtoumax (arg, 0, 10, &u, "") != LONGINT_OK)
+       char *p;
+
+       if (xstrtoumax (arg, &p, 10, &u, TAR_SIZE_SUFFIXES) != LONGINT_OK)
          USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
                        _("Invalid tape length")));
-       tape_length_option = 1024 * (tarlong) u;
+       if (p > arg && !strchr (TAR_SIZE_SUFFIXES, p[-1]))
+         tape_length_option = 1024 * (tarlong) u;
+       else
+         tape_length_option = (tarlong) u;
        multi_volume_option = true;
       }
       break;
@@ -1961,7 +1968,8 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case RECORD_SIZE_OPTION:
       {
        uintmax_t u;
-       if (! (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK
+
+       if (! (xstrtoumax (arg, NULL, 10, &u, TAR_SIZE_SUFFIXES) == LONGINT_OK
               && u == (size_t) u))
          USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
                        _("Invalid record size")));
@@ -2457,6 +2465,18 @@ decode_options (int argc, char **argv)
   if (recursive_unlink_option)
     old_files_option = UNLINK_FIRST_OLD_FILES;
 
+  /* Flags for accessing files to be read from or copied into.  POSIX says
+     O_NONBLOCK has unspecified effect on most types of files, but in
+     practice it never harms and sometimes helps.  */
+  {
+    int base_open_flags =
+      (O_BINARY | O_CLOEXEC | O_NOCTTY | O_NONBLOCK
+       | (dereference_option ? 0 : O_NOFOLLOW)
+       | (atime_preserve_option == system_atime_preserve ? O_NOATIME : 0));
+    open_read_flags = O_RDONLY | base_open_flags;
+    open_searchdir_flags = O_SEARCH | O_DIRECTORY | base_open_flags;
+  }
+  fstatat_flags = dereference_option ? 0 : AT_SYMLINK_NOFOLLOW;
 
   if (subcommand_option == TEST_LABEL_SUBCOMMAND)
     {
@@ -2486,8 +2506,8 @@ decode_options (int argc, char **argv)
                      _("Cowardly refusing to create an empty archive")));
       if (args.compress_autodetect && archive_names
          && strcmp (archive_name_array[0], "-"))
-       set_comression_program_by_suffix (archive_name_array[0],
-                                         use_compress_program_option);
+       set_compression_program_by_suffix (archive_name_array[0],
+                                          use_compress_program_option);
       break;
 
     case EXTRACT_SUBCOMMAND:
@@ -2668,9 +2688,31 @@ tar_stat_init (struct tar_stat_info *st)
   memset (st, 0, sizeof (*st));
 }
 
+/* Close the stream or file descriptor associated with ST, and remove
+   all traces of it from ST.  Return true if successful, false (with a
+   diagnostic) otherwise.  */
+bool
+tar_stat_close (struct tar_stat_info *st)
+{
+  int status = (st->dirstream ? closedir (st->dirstream)
+               : 0 < st->fd ? close (st->fd)
+               : 0);
+  st->dirstream = 0;
+  st->fd = 0;
+
+  if (status == 0)
+    return true;
+  else
+    {
+      close_diag (st->orig_file_name);
+      return false;
+    }
+}
+
 void
 tar_stat_destroy (struct tar_stat_info *st)
 {
+  tar_stat_close (st);
   free (st->orig_file_name);
   free (st->file_name);
   free (st->link_name);
This page took 0.02311 seconds and 4 git commands to generate.