/* Extract files from a tar archive.
- Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2013
- Free Software Foundation, Inc.
+ Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2014 Free
+ Software Foundation, Inc.
This file is part of GNU tar.
static void
check_time (char const *file_name, struct timespec t)
{
- if (t.tv_sec <= 0)
+ if (t.tv_sec < 0)
WARNOPT (WARN_TIMESTAMP,
(0, 0, _("%s: implausibly old time stamp %s"),
file_name, tartime (t, true)));
quotearg_colon (dir)));
}
+static void
+free_delayed_set_stat (struct delayed_set_stat *data)
+{
+ xheader_xattr_free (data->xattr_map, data->xattr_map_size);
+ free (data->cntx_name);
+ free (data->acls_a_ptr);
+ free (data->acls_d_ptr);
+ free (data);
+}
+
+void
+remove_delayed_set_stat (const char *fname)
+{
+ struct delayed_set_stat *data, *next, *prev = NULL;
+ for (data = delayed_set_stat_head; data; data = next)
+ {
+ next = data->next;
+ if (chdir_current == data->change_dir
+ && strcmp (data->file_name, fname) == 0)
+ {
+ free_delayed_set_stat (data);
+ if (prev)
+ prev->next = next;
+ else
+ delayed_set_stat_head = next;
+ return;
+ }
+ else
+ prev = data;
+ }
+}
+
/* After a file/link/directory creation has failed, see if
it's because some required directory was not present, and if so,
create all required directories. Return zero if all the required
}
delayed_set_stat_head = data->next;
- xheader_xattr_free (data->xattr_map, data->xattr_map_size);
- free (data->cntx_name);
- free (data->acls_a_ptr);
- free (data->acls_d_ptr);
- free (data);
+ free_delayed_set_stat (data);
}
}
\f
-
+static bool
+is_directory_link (const char *file_name)
+{
+ struct stat st;
+ int e = errno;
+ int res;
+
+ res = (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0 &&
+ S_ISLNK (st.st_mode) &&
+ fstatat (chdir_fd, file_name, &st, 0) == 0 &&
+ S_ISDIR (st.st_mode));
+ errno = e;
+ return res;
+}
+\f
/* Extractor functions for various member types */
static int
if (errno == EEXIST
&& (interdir_made
+ || keep_directory_symlink_option
|| old_files_option == DEFAULT_OLD_FILES
|| old_files_option == OVERWRITE_OLD_FILES))
{
struct stat st;
+
+ if (keep_directory_symlink_option && is_directory_link (file_name))
+ return 0;
+
if (deref_stat (file_name, &st) == 0)
{
current_mode = st.st_mode;
if (!warned_once)
{
warned_once = 1;
- WARNOPT (WARN_SYMBOLIC_CAST,
+ WARNOPT (WARN_SYMLINK_CAST,
(0, 0,
_("Attempting extraction of symbolic links as hard links")));
}