]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
Support >INT_MAX -C dirs
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 3 Aug 2024 16:35:46 +0000 (09:35 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 4 Aug 2024 08:41:43 +0000 (01:41 -0700)
* src/extract.c (struct delayed_set_stat, struct delayed_link):
* src/misc.c (normalize_filename, wd_count, chdir_count)
(chdir_arg, tar_getcdpath):
* src/names.c (name_gather, addname, add_hierarchy_to_namelist):
* src/unlink.c (struct deferred_unlink, flush_deferred_unlinks):
Use idx_t, not int, for directory indexes, so as to not
limit their number to INT_MAX; this is theoretically possible
if -T is used.
* src/names.c (name_next_elt, name_next):
Use bool for boolean.

src/common.h
src/create.c
src/extract.c
src/misc.c
src/names.c
src/unlink.c

index 8a22c2ba716c75c9097cc3c8f5c1b2fd918fd876..e81a46319de50b4607711c373b8dd3d5b9d83ea3 100644 (file)
@@ -367,7 +367,7 @@ struct name
     bool cmdline;               /* true if this name was given in the
                                   command line */
 
-    int change_dir;            /* Number of the directory to change to.
+    idx_t change_dir;          /* Number of the directory to change to.
                                   Set with the -C option. */
     uintmax_t found_count;     /* number of times a matching file has
                                   been found */
@@ -650,7 +650,7 @@ void assign_string_n (char **string, const char *value, size_t n);
 #define ASSIGN_STRING_N(s,v) assign_string_n (s, v, sizeof (v))
 int unquote_string (char *str);
 char *zap_slashes (char *name);
-char *normalize_filename (int cdidx, const char *name);
+char *normalize_filename (idx_t, char const *);
 void normalize_filename_x (char *name);
 void replace_prefix (char **pname, const char *samp, size_t slen,
                     const char *repl, size_t rlen);
@@ -744,11 +744,11 @@ int deref_stat (char const *name, struct stat *buf);
 size_t blocking_read (int fd, void *buf, size_t count);
 size_t blocking_write (int fd, void const *buf, size_t count);
 
-extern int chdir_current;
+extern idx_t chdir_current;
 extern int chdir_fd;
-int chdir_arg (char const *dir);
-void chdir_do (int dir);
-int chdir_count (void);
+idx_t chdir_arg (char const *dir);
+void chdir_do (idx_t dir);
+idx_t chdir_count (void);
 
 void close_diag (char const *name);
 void open_diag (char const *name);
@@ -794,10 +794,9 @@ int uname_to_uid (char const *uname, uid_t *puid);
 void name_init (void);
 void name_add_name (const char *name);
 void name_term (void);
-const char *name_next (int change_dirs);
+char const *name_next (bool);
 void name_gather (void);
-struct name *addname (char const *string, int change_dir,
-                     bool cmdline, struct name *parent);
+struct name *addname (char const *, idx_t, bool, struct name *);
 void add_starting_file (char const *file_name);
 void remname (struct name *name);
 bool name_match (const char *name);
index e6cf465f7cbc411609e1e79a51d945b1c19f7dd7..452a38bddf1adecbf96bc90c33855038062c4cfa 100644 (file)
@@ -1395,7 +1395,7 @@ create_archive (void)
   else
     {
       const char *name;
-      while ((name = name_next (1)) != NULL)
+      while ((name = name_next (true)))
        if (!excluded_name (name, NULL))
          dump_file (0, name, name);
     }
index 3a5ecdf94ea791be3d0fcdebdde2cf134cdd5abc..bf504f18753b9b4771d1abe9583bfd311b2e9c5a 100644 (file)
@@ -115,7 +115,7 @@ struct delayed_set_stat
     bool after_links;
 
     /* Directory that the name is relative to.  */
-    int change_dir;
+    idx_t change_dir;
 
     /* extended attributes*/
     char *cntx_name;
@@ -165,7 +165,7 @@ struct delayed_link
     struct timespec mtime;
 
     /* The directory that the sources and target are relative to.  */
-    int change_dir;
+    idx_t change_dir;
 
     /* A list of sources for this link.  The sources are all to be
        hard-linked together.  */
@@ -1850,7 +1850,7 @@ extract_archive (void)
      (see NOTICE in the comment to delay_set_stat above) */
   if (!delay_directory_restore_option)
     {
-      int dir = chdir_current;
+      idx_t dir = chdir_current;
       apply_nonancestor_delayed_set_stat (current_stat_info.file_name, false);
       chdir_do (dir);
     }
index e2483cd70b92d3a920f2411cc12edbecbb42339c..dffd531f49af594205cf8405ba504f4de6227478 100644 (file)
@@ -31,7 +31,7 @@
 
 static void namebuf_add_dir (namebuf_t, char const *);
 static char *namebuf_finish (namebuf_t);
-static const char *tar_getcdpath (int);
+static const char *tar_getcdpath (idx_t);
 
 char const *
 quote_n_colon (int n, char const *arg)
@@ -315,7 +315,7 @@ normalize_filename_x (char *file_name)
    Return a normalized newly-allocated copy.  */
 
 char *
-normalize_filename (int cdidx, const char *name)
+normalize_filename (idx_t cdidx, const char *name)
 {
   char *copy = NULL;
 
@@ -903,7 +903,7 @@ struct wd
 static struct wd *wd;
 
 /* The number of working directories in the vector.  */
-static size_t wd_count;
+static idx_t wd_count;
 
 /* The allocated size of the vector.  */
 static size_t wd_alloc;
@@ -921,17 +921,15 @@ static int wdcache[CHDIR_CACHE_SIZE];
 /* Number of nonzero entries in WDCACHE.  */
 static size_t wdcache_count;
 
-int
+idx_t
 chdir_count (void)
 {
-  if (wd_count == 0)
-    return wd_count;
-  return wd_count - 1;
+  return wd_count - !!wd_count;
 }
 
 /* DIR is the operand of a -C option; add it to vector of chdir targets,
    and return the index of its location.  */
-int
+idx_t
 chdir_arg (char const *dir)
 {
   if (wd_count == wd_alloc)
@@ -967,7 +965,7 @@ chdir_arg (char const *dir)
 }
 
 /* Index of current directory.  */
-int chdir_current;
+idx_t chdir_current;
 
 /* Value suitable for use as the first argument to openat, and in
    similar locations for fstatat, etc.  This is an open file
@@ -981,7 +979,7 @@ int chdir_fd = AT_FDCWD;
    working directory; otherwise, I must be a value returned by
    chdir_arg.  */
 void
-chdir_do (int i)
+chdir_do (idx_t i)
 {
   if (chdir_current != i)
     {
@@ -1049,7 +1047,7 @@ tar_dirname (void)
    process's actual cwd.  (Note that in this case IDX is ignored,
    since it should always be 0.) */
 static const char *
-tar_getcdpath (int idx)
+tar_getcdpath (idx_t idx)
 {
   if (!wd)
     {
@@ -1065,14 +1063,11 @@ tar_getcdpath (int idx)
 
   if (!wd[idx].abspath)
     {
-      int i;
-      int save_cwdi = chdir_current;
-
-      for (i = idx; i >= 0; i--)
-       if (wd[i].abspath)
-         break;
+      idx_t save_cwdi = chdir_current, i = idx;
+      while (0 < i && !wd[i - 1].abspath)
+       i--;
 
-      while (++i <= idx)
+      for (; i <= idx; i++)
        {
          chdir_do (i);
          if (i == 0)
index 792b9d381ba9ae76cfe4d99bab99743e114e2530..77b285c6b92694920b220da171a55d330c063108 100644 (file)
@@ -1100,7 +1100,7 @@ copy_name (struct name_elt *ep)
 
 */
 static struct name_elt *
-name_next_elt (int change_dirs)
+name_next_elt (bool change_dirs)
 {
   static struct name_elt entry;
   struct name_elt *ep;
@@ -1148,7 +1148,7 @@ name_next_elt (int change_dirs)
 }
 
 const char *
-name_next (int change_dirs)
+name_next (bool change_dirs)
 {
   struct name_elt *nelt = name_next_elt (change_dirs);
   return nelt ? nelt->v.name : NULL;
@@ -1181,9 +1181,9 @@ name_gather (void)
 
   if (same_order_option)
     {
-      static int change_dir;
+      static idx_t change_dir;
 
-      while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
+      while ((ep = name_next_elt (false)) && ep->type == NELT_CHDIR)
        change_dir = chdir_arg (xstrdup (ep->v.name));
 
       if (ep)
@@ -1207,12 +1207,12 @@ name_gather (void)
   else
     {
       /* Non sorted names -- read them all in.  */
-      int change_dir = 0;
+      idx_t change_dir = 0;
 
       for (;;)
        {
-         int change_dir0 = change_dir;
-         while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
+         idx_t change_dir0 = change_dir;
+         while ((ep = name_next_elt (false)) && ep->type == NELT_CHDIR)
            change_dir = chdir_arg (xstrdup (ep->v.name));
 
          if (ep)
@@ -1229,7 +1229,8 @@ name_gather (void)
 
 /*  Add a name to the namelist.  */
 struct name *
-addname (char const *string, int change_dir, bool cmdline, struct name *parent)
+addname (char const *string, idx_t change_dir, bool cmdline,
+        struct name *parent)
 {
   struct name *name = make_name (string);
 
@@ -1443,7 +1444,7 @@ names_notfound (void)
     {
       const char *name;
 
-      while ((name = name_next (1)) != NULL)
+      while ((name = name_next (true)))
        {
          regex_usage_warning (name);
          ERROR ((0, 0, _("%s: Not found in archive"),
@@ -1482,7 +1483,7 @@ label_notfound (void)
     {
       const char *name;
 
-      while ((name = name_next (1)) != NULL
+      while ((name = name_next (true))
             && regex_usage_warning (name) == 0)
        ;
     }
@@ -1620,7 +1621,7 @@ add_hierarchy_to_namelist (struct tar_stat_info *st, struct name *name)
       char *namebuf = xmalloc (allocated_length);
       const char *string;
       size_t string_length;
-      int change_dir = name->change_dir;
+      idx_t change_dir = name->change_dir;
 
       strcpy (namebuf, name->name);
       if (! ISSLASH (namebuf[name_length - 1]))
index 4619a9498ee4d11ae3cdb3243c3be4419838b64b..f90608bc2085500772f5e4960d39872ec7535fe1 100644 (file)
@@ -24,7 +24,7 @@
 struct deferred_unlink
   {
     struct deferred_unlink *next;   /* Next unlink in the queue */
-    int dir_idx;                    /* Directory index in wd */
+    idx_t dir_idx;                 /* Directory index in wd */
     char *file_name;                /* Name of the file to unlink, relative
                                       to dir_idx */
     bool is_dir;                    /* True if file_name is a directory */
@@ -72,7 +72,7 @@ dunlink_insert (struct deferred_unlink *anchor, struct deferred_unlink *p)
       p->next = anchor->next;
       anchor->next = p;
     }
-  else 
+  else
     {
       p->next = dunlink_head;
       dunlink_head = p;
@@ -94,8 +94,8 @@ static void
 flush_deferred_unlinks (bool force)
 {
   struct deferred_unlink *p, *prev = NULL;
-  int saved_chdir = chdir_current;
-  
+  idx_t saved_chdir = chdir_current;
+
   for (p = dunlink_head; p; )
     {
       struct deferred_unlink *next = p->next;
@@ -188,8 +188,8 @@ flush_deferred_unlinks (bool force)
          p = next;
        }
       dunlink_head = dunlink_tail = NULL;
-    }    
-           
+    }
+
   chdir_do (saved_chdir);
 }
 
@@ -197,7 +197,7 @@ void
 finish_deferred_unlinks (void)
 {
   flush_deferred_unlinks (true);
-  
+
   while (dunlink_avail)
     {
       struct deferred_unlink *next = dunlink_avail->next;