X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fextract.c;h=9b6b7f97487e39d6a297e99c797f9ae37e882cc3;hb=e3d28d84bda24a45c239b398e7b42ccd9be2d0c2;hp=2d8e175985e2cb0d9b2719f305628884e81b47fd;hpb=696338043e52f440853e1143c52b81b41cd59723;p=chaz%2Ftar
diff --git a/src/extract.c b/src/extract.c
index 2d8e175..9b6b7f9 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
+ Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2013
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
@@ -100,6 +100,11 @@ struct delayed_set_stat
int change_dir;
/* extended attributes*/
+ char *cntx_name;
+ char *acls_a_ptr;
+ size_t acls_a_len;
+ char *acls_d_ptr;
+ size_t acls_d_len;
size_t xattr_map_size;
struct xattr_array *xattr_map;
/* Length and contents of name. */
@@ -142,6 +147,15 @@ struct delayed_link
hard-linked together. */
struct string_list *sources;
+ /* SELinux context */
+ char *cntx_name;
+
+ /* ACLs */
+ char *acls_a_ptr;
+ size_t acls_a_len;
+ char *acls_d_ptr;
+ size_t acls_d_len;
+
size_t xattr_map_size;
struct xattr_array *xattr_map;
@@ -283,7 +297,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)));
@@ -375,6 +389,8 @@ set_stat (char const *file_name,
/* these three calls must be done *after* fd_chown() call because fd_chown
causes that linux capabilities becomes cleared. */
xattrs_xattrs_set (st, file_name, typeflag, 1);
+ xattrs_acls_set (st, file_name, typeflag);
+ xattrs_selinux_set (st, file_name, typeflag);
}
/* For each entry H in the leading prefix of entries in HEAD that do
@@ -446,6 +462,29 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
data->atflag = atflag;
data->after_links = 0;
data->change_dir = chdir_current;
+ data->cntx_name = NULL;
+ if (st)
+ assign_string (&data->cntx_name, st->cntx_name);
+ if (st && st->acls_a_ptr)
+ {
+ data->acls_a_ptr = xmemdup (st->acls_a_ptr, st->acls_a_len + 1);
+ data->acls_a_len = st->acls_a_len;
+ }
+ else
+ {
+ data->acls_a_ptr = NULL;
+ data->acls_a_len = 0;
+ }
+ if (st && st->acls_d_ptr)
+ {
+ data->acls_d_ptr = xmemdup (st->acls_d_ptr, st->acls_d_len + 1);
+ data->acls_d_len = st->acls_d_len;
+ }
+ else
+ {
+ data->acls_d_ptr = NULL;
+ data->acls_d_len = 0;
+ }
if (st)
xheader_xattr_copy (st, &data->xattr_map, &data->xattr_map_size);
else
@@ -794,6 +833,11 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
sb.stat.st_gid = data->gid;
sb.atime = data->atime;
sb.mtime = data->mtime;
+ sb.cntx_name = data->cntx_name;
+ sb.acls_a_ptr = data->acls_a_ptr;
+ sb.acls_a_len = data->acls_a_len;
+ sb.acls_d_ptr = data->acls_d_ptr;
+ sb.acls_d_len = data->acls_d_len;
sb.xattr_map = data->xattr_map;
sb.xattr_map_size = data->xattr_map_size;
set_stat (data->file_name, &sb,
@@ -803,12 +847,29 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
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);
}
}
-
+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
@@ -864,10 +925,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;
@@ -1173,6 +1239,12 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
+ strlen (file_name) + 1);
p->sources->next = 0;
strcpy (p->sources->string, file_name);
+ p->cntx_name = NULL;
+ assign_string (&p->cntx_name, current_stat_info.cntx_name);
+ p->acls_a_ptr = NULL;
+ p->acls_a_len = 0;
+ p->acls_d_ptr = NULL;
+ p->acls_d_len = 0;
xheader_xattr_copy (¤t_stat_info, &p->xattr_map, &p->xattr_map_size);
strcpy (p->target, current_stat_info.link_name);
@@ -1288,7 +1360,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")));
}
@@ -1368,6 +1440,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);
@@ -1448,7 +1527,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:
@@ -1609,6 +1688,11 @@ apply_delayed_links (void)
st1.stat.st_gid = ds->gid;
st1.atime = ds->atime;
st1.mtime = ds->mtime;
+ st1.cntx_name = ds->cntx_name;
+ st1.acls_a_ptr = ds->acls_a_ptr;
+ st1.acls_a_len = ds->acls_a_len;
+ st1.acls_d_ptr = ds->acls_d_ptr;
+ st1.acls_d_len = ds->acls_d_len;
st1.xattr_map = ds->xattr_map;
st1.xattr_map_size = ds->xattr_map_size;
set_stat (source, &st1, -1, 0, 0, SYMTYPE,
@@ -1626,6 +1710,7 @@ apply_delayed_links (void)
}
xheader_xattr_free (ds->xattr_map, ds->xattr_map_size);
+ free (ds->cntx_name);
{
struct delayed_link *next = ds->next;