X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Ftar;a=blobdiff_plain;f=src%2Fextract.c;h=2cc1f7b383a121fb5a6d864e96bf54f8af4a9d95;hp=dbcb4dc40515e54d439d0330e2e4795f55cc99cb;hb=45ccda119355a1087450039a250359c1d0de0d08;hpb=085cace1805308589c6211429068f68047be0b0e
diff --git a/src/extract.c b/src/extract.c
index dbcb4dc..2cc1f7b 100644
--- a/src/extract.c
+++ b/src/extract.c
@@ -1,24 +1,24 @@
/* 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 .
+
+ Written by John Gilmore, on 1985-11-19. */
#include
#include
@@ -191,6 +191,19 @@ extr_init (void)
umask (newdir_umask); /* restore the kernel umask */
current_umask = newdir_umask;
}
+
+ /* If the user wants to guarantee that everything is under one directory,
+ determine its name now and let it be created later. */
+ if (one_top_level_option && !one_top_level_dir)
+ {
+ char *base = base_name (archive_name_array[0]);
+
+ one_top_level_dir = strip_compression_suffix (base);
+ free (base);
+
+ if (!one_top_level_dir)
+ USAGE_ERROR ((0, 0, _("Cannot deduce top-level directory name; please set it explicitly with --one-top-level=DIR")));
+ }
}
/* Use fchmod if possible, fchmodat otherwise. */
@@ -297,7 +310,7 @@ set_mode (char const *file_name,
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)));
@@ -855,7 +868,21 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
}
-
+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;
+}
+
/* Extractor functions for various member types */
static int
@@ -911,10 +938,15 @@ extract_dir (char *file_name, int typeflag)
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;
@@ -1341,7 +1373,7 @@ extract_symlink (char *file_name, int typeflag)
if (!warned_once)
{
warned_once = 1;
- WARNOPT (WARN_SYMBOLIC_CAST,
+ WARNOPT (WARN_SYMLINK_CAST,
(0, 0,
_("Attempting extraction of symbolic links as hard links")));
}
@@ -1421,6 +1453,13 @@ extract_failure (char *file_name, int typeflag)
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);
@@ -1501,7 +1540,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
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: