/* 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
# 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);
+
\f
/* Handling strings. */
/* 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. */
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]));
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,
(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;
{
/* 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. */
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)
{
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++;
}
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)
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)
return buf->buffer;
}
-void
+static void
namebuf_add_dir (namebuf_t buf, const char *name)
{
static char dirsep[] = { DIRECTORY_SEPARATOR, 0 };
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);
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)