/* Extract files from a tar archive.
- Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
- 2001, 2003, 2004, 2005, 2006, 2007, 2010, 2012
- Free Software Foundation, Inc.
+ Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2014 Free
+ Software Foundation, Inc.
- Written by John Gilmore, on 1985-11-19.
+ This file is part of GNU tar.
- 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
- Free Software Foundation; either version 3, or (at your option) any later
- version.
+ GNU tar is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- Public License for more details.
+ GNU tar is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ Written by John Gilmore, on 1985-11-19. */
#include <system.h>
#include <quotearg.h>
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")));
}
return 1;
}
+static int
+extract_skip (char *file_name, int typeflag)
+{
+ skip_member ();
+ return 0;
+}
+
typedef int (*tar_extractor_t) (char *file_name, int typeflag);
\f
ERROR ((0, 0,
_("%s: Cannot extract -- file is continued from another volume"),
quotearg_colon (current_stat_info.file_name)));
- *fun = extract_failure;
+ *fun = extract_skip;
break;
case GNUTYPE_LONGNAME: