X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fmisc.c;h=071cf2a105240f1dba3ff665bdc0ac3180c27edc;hb=HEAD;hp=0424ea7cc2f9a582805a99e6463ce042cf68d626;hpb=e4faf46844fa3162def723f12a09791e350caabb;p=debian%2Ftar diff --git a/src/misc.c b/src/misc.c index 0424ea7c..071cf2a1 100644 --- a/src/misc.c +++ b/src/misc.c @@ -1,7 +1,7 @@ /* Miscellaneous functions, not really specific to GNU tar. Copyright 1988, 1992, 1994-1997, 1999-2001, 2003-2007, 2009-2010, - 2012-2013 Free Software Foundation, Inc. + 2012-2014, 2016 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -29,6 +29,10 @@ # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 #endif +static void namebuf_add_dir (namebuf_t, char const *); +static char *namebuf_finish (namebuf_t); +static const char *tar_getcdpath (int); + /* Handling strings. */ @@ -230,7 +234,7 @@ zap_slashes (char *name) /* Normalize FILE_NAME by removing redundant slashes and "." components, including redundant trailing slashes. - Leave ".." alone, as it may be significant in the presence + Leave ".." alone, as it may be significant in the presence of symlinks and on platforms where "/.." != "/". Destructive version: modifies its argument. */ @@ -286,11 +290,14 @@ normalize_filename (int cdidx, const char *name) this following approach may lead to situations where the same file or directory is processed twice under different absolute paths without that duplication being detected. Perhaps we - should use dev+ino pairs instead of names? */ + should use dev+ino pairs instead of names? (See listed03.at for + a related test case.) */ const char *cdpath = tar_getcdpath (cdidx); size_t copylen; bool need_separator; - + + if (!cdpath) + call_arg_fatal ("getcwd", "."); copylen = strlen (cdpath); need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT && copylen == 2 && ISSLASH (cdpath[1])); @@ -581,7 +588,12 @@ safer_rmdir (const char *file_name) return -1; } - return unlinkat (chdir_fd, file_name, AT_REMOVEDIR); + if (unlinkat (chdir_fd, file_name, AT_REMOVEDIR) == 0) + { + remove_delayed_set_stat (file_name); + return 0; + } + return -1; } /* Remove FILE_NAME, returning 1 on success. If FILE_NAME is a directory, @@ -645,7 +657,7 @@ remove_any_file (const char *file_name, enum remove_option option) (entrylen = strlen (entry)) != 0; entry += entrylen + 1) { - char *file_name_buffer = new_name (file_name, entry); + char *file_name_buffer = make_file_name (file_name, entry); int r = remove_any_file (file_name_buffer, RECURSIVE_REMOVE_OPTION); int e = errno; @@ -834,10 +846,11 @@ struct wd { /* The directory's name. */ char const *name; - /* "absolute" path representing this directory; in the contrast to + /* "Absolute" path representing this directory; in the contrast to the real absolute pathname, it can contain /../ components (see - normalize_filename_x for the reason of it). */ - char *abspath; + normalize_filename_x for the reason of it). It is NULL if the + absolute path could not be determined. */ + char *abspath; /* If nonzero, the file descriptor of the directory, or AT_FDCWD if the working directory. If zero, the directory needs to be opened to be used. */ @@ -879,15 +892,13 @@ chdir_count (void) int chdir_arg (char const *dir) { + char *absdir; + if (wd_count == wd_alloc) { if (wd_alloc == 0) - { - wd_alloc = 2; - wd = xmalloc (sizeof *wd * wd_alloc); - } - else - wd = x2nrealloc (wd, &wd_alloc, sizeof *wd); + wd_alloc = 2; + wd = x2nrealloc (wd, &wd_alloc, sizeof *wd); if (! wd_count) { @@ -909,18 +920,22 @@ chdir_arg (char const *dir) return wd_count - 1; } - wd[wd_count].name = dir; - /* if the given name is an absolute path, then use that path - to represent this working directory; otherwise, construct - a path based on the previous -C option's absolute path */ - if (IS_ABSOLUTE_FILE_NAME (wd[wd_count].name)) - wd[wd_count].abspath = xstrdup (wd[wd_count].name); - else + + /* If the given name is absolute, use it to represent this directory; + otherwise, construct a name based on the previous -C option. */ + if (IS_ABSOLUTE_FILE_NAME (dir)) + absdir = xstrdup (dir); + else if (wd[wd_count - 1].abspath) { namebuf_t nbuf = namebuf_create (wd[wd_count - 1].abspath); - namebuf_add_dir (nbuf, wd[wd_count].name); - wd[wd_count].abspath = namebuf_finish (nbuf); + namebuf_add_dir (nbuf, dir); + absdir = namebuf_finish (nbuf); } + else + absdir = 0; + + wd[wd_count].name = dir; + wd[wd_count].abspath = absdir; wd[wd_count].fd = 0; return wd_count++; } @@ -1007,7 +1022,7 @@ tar_dirname (void) chdir_args() has never been called, so we simply return the process's actual cwd. (Note that in this case IDX is ignored, since it should always be 0.) */ -const char * +static const char * tar_getcdpath (int idx) { if (!wd) @@ -1098,13 +1113,6 @@ file_removed_diag (const char *name, bool top_level, diagfn (name); } -void -write_fatal_details (char const *name, ssize_t status, size_t size) -{ - write_error_details (name, status, size); - fatal_exit (); -} - /* Fork, aborting if unsuccessful. */ pid_t xfork (void) @@ -1189,7 +1197,7 @@ namebuf_name (namebuf_t buf, const char *name) return buf->buffer; } -void +static void namebuf_add_dir (namebuf_t buf, const char *name) { static char dirsep[] = { DIRECTORY_SEPARATOR, 0 }; @@ -1202,11 +1210,11 @@ namebuf_add_dir (namebuf_t buf, const char *name) buf->dir_length += strlen (name); } -char * +static char * namebuf_finish (namebuf_t buf) { char *res = buf->buffer; - + if (ISSLASH (buf->buffer[buf->dir_length - 1])) buf->buffer[buf->dir_length] = 0; free (buf); @@ -1232,7 +1240,7 @@ tar_savedir (const char *name, int must_exist) open_error (name); } else if (! ((dir = fdopendir (fd)) - && (ret = streamsavedir (dir)))) + && (ret = streamsavedir (dir, savedir_sort_order)))) savedir_error (name); if (dir ? closedir (dir) != 0 : 0 <= fd && close (fd) != 0)