From: Paul Eggert Date: Sat, 3 Aug 2024 16:35:46 +0000 (-0700) Subject: Support >INT_MAX -C dirs X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=cc691f82727f0e0f274cb4e9490bb02c14dc8931;p=thirdparty%2Ftar.git Support >INT_MAX -C dirs * 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. --- diff --git a/src/common.h b/src/common.h index 8a22c2ba..e81a4631 100644 --- a/src/common.h +++ b/src/common.h @@ -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); diff --git a/src/create.c b/src/create.c index e6cf465f..452a38bd 100644 --- a/src/create.c +++ b/src/create.c @@ -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); } diff --git a/src/extract.c b/src/extract.c index 3a5ecdf9..bf504f18 100644 --- a/src/extract.c +++ b/src/extract.c @@ -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); } diff --git a/src/misc.c b/src/misc.c index e2483cd7..dffd531f 100644 --- a/src/misc.c +++ b/src/misc.c @@ -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) diff --git a/src/names.c b/src/names.c index 792b9d38..77b285c6 100644 --- a/src/names.c +++ b/src/names.c @@ -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])) diff --git a/src/unlink.c b/src/unlink.c index 4619a949..f90608bc 100644 --- a/src/unlink.c +++ b/src/unlink.c @@ -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;