MFV r316454,316455:

Vendor changes (FreeBSD-related):
  Report which extended attributes could not be restored
  Update archive_read_disk.3 and archive_write_disk.3 manual pages
  Plug memory leaks in xattr tests.

MFC after:	1 week
This commit is contained in:
Martin Matuska 2017-04-03 12:26:20 +00:00
commit 43f9e382c0
9 changed files with 231 additions and 112 deletions

View File

@ -24,11 +24,12 @@
.\"
.\" $FreeBSD$
.\"
.Dd December 30, 2016
.Dd April 3, 2017
.Dt ARCHIVE_READ_DISK 3
.Os
.Sh NAME
.Nm archive_read_disk_new ,
.Nm archive_read_disk_set_behavior ,
.Nm archive_read_disk_set_symlink_logical ,
.Nm archive_read_disk_set_symlink_physical ,
.Nm archive_read_disk_set_symlink_hybrid ,
@ -46,6 +47,8 @@ Streaming Archive Library (libarchive, -larchive)
.Ft struct archive *
.Fn archive_read_disk_new "void"
.Ft int
.Fn archive_read_disk_set_behavior "struct archive *" "int"
.Ft int
.Fn archive_read_disk_set_symlink_logical "struct archive *"
.Ft int
.Fn archive_read_disk_set_symlink_physical "struct archive *"
@ -89,6 +92,51 @@ objects.
Allocates and initializes a
.Tn struct archive
object suitable for reading object information from disk.
.It Fn archive_read_disk_set_behavior
Configures various behavior options when reading entries from disk.
The flags field consists of a bitwise OR of one or more of the
following values:
.Bl -tag -compact -width "indent"
.It Cm ARCHIVE_READDISK_HONOR_NODUMP
Skip files and directories with the nodump file attribute (file flag) set.
By default, the nodump file atrribute is ignored.
.It Cm ARCHIVE_READDISK_MAC_COPYFILE
Mac OS X specific. Read metadata (ACLs and extended attributes) with
.Xr copyfile 3 .
By default, metadata is read using
.Xr copyfile 3 .
.It Cm ARCHIVE_READDISK_NO_ACL
Do not read Access Control Lists.
By default, ACLs are read from disk.
.It Cm ARCHIVE_READDISK_NO_FFLAGS
Do not read file attributes (file flags).
By default, file attributes are read from disk.
See
.Xr chattr 1
.Pq Linux
or
.Xr chflags 1
.Pq FreeBSD, Mac OS X
for more information on file attributes.
.It Cm ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS
Do not traverse mount points.
By defaut, moint points are traversed.
.It Cm ARCHIVE_READDISK_NO_XATTR
Do not read extended file attributes (xattrs).
By default, extended file attributes are read from disk.
See
.Xr xattr 7
.Pq Linux ,
.Xr xattr 2
.Pq Mac OS X ,
or
.Xr getextattr 8
.Pq FreeBSD
for more information on extended file attributes.
.It Cm ARCHIVE_READDISK_RESTORE_ATIME
Restore access time of traversed files.
By default, access time of traversed files is not restored.
.El
.It Xo
.Fn archive_read_disk_set_symlink_logical ,
.Fn archive_read_disk_set_symlink_physical ,

View File

@ -613,9 +613,21 @@ setup_xattrs(struct archive_read_disk *a,
}
for (p = list; (p - list) < list_size; p += strlen(p) + 1) {
if (strncmp(p, "system.", 7) == 0 ||
strncmp(p, "xfsroot.", 8) == 0)
#if ARCHIVE_XATTR_LINUX
/* Linux: skip POSIX.1e ACL extended attributes */
if (strncmp(p, "system.", 7) == 0 &&
(strcmp(p + 7, "posix_acl_access") == 0 ||
strcmp(p + 7, "posix_acl_default") == 0))
continue;
if (strncmp(p, "trusted.SGI_", 12) == 0 &&
(strcmp(p + 12, "ACL_DEFAULT") == 0 ||
strcmp(p + 12, "ACL_FILE") == 0))
continue;
/* Linux: xfsroot namespace is obsolete and unsupported */
if (strncmp(p, "xfsroot.", 8) == 0)
continue;
#endif
setup_xattr(a, entry, p, *fd, path);
}

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 28, 2017
.Dd April 3, 2017
.Dt ARCHIVE_WRITE_DISK 3
.Os
.Sh NAME
@ -96,6 +96,33 @@ performance optimization in practice.
The options field consists of a bitwise OR of one or more of the
following values:
.Bl -tag -compact -width "indent"
.It Cm ARCHIVE_EXTRACT_ACL
Attempt to restore Access Control Lists.
By default, extended ACLs are ignored.
.It Cm ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS
Before removing a file system object prior to replacing it, clear
platform-specific file flags which might prevent its removal.
.It Cm ARCHIVE_EXTRACT_FFLAGS
Attempt to restore file attributes (file flags).
By default, file attributes are ignored.
See
.Xr chattr 1
.Pq Linux
or
.Xr chflags 1
.Pq FreeBSD, Mac OS X
for more information on file attributes.
.It Cm ARCHIVE_EXTRACT_MAC_METADATA
Mac OS X specific. Restore metadata using
.Xr copyfile 3 .
By default,
.Xr copyfile 3
metadata is ignored.
.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE
Existing files on disk will not be overwritten.
By default, existing regular files are truncated and overwritten;
existing directories will have their permissions updated;
other pre-existing objects are unlinked and recreated from scratch.
.It Cm ARCHIVE_EXTRACT_OWNER
The user and group IDs should be set on the restored file.
By default, the user and group IDs are not restored.
@ -111,43 +138,9 @@ is not specified, then SUID and SGID bits will only be restored
if the default user and group IDs of newly-created objects on disk
happen to match those specified in the archive entry.
By default, only basic permissions are restored, and umask is obeyed.
.It Cm ARCHIVE_EXTRACT_TIME
The timestamps (mtime, ctime, and atime) should be restored.
By default, they are ignored.
Note that restoring of atime is not currently supported.
.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE
Existing files on disk will not be overwritten.
By default, existing regular files are truncated and overwritten;
existing directories will have their permissions updated;
other pre-existing objects are unlinked and recreated from scratch.
.It Cm ARCHIVE_EXTRACT_UNLINK
Existing files on disk will be unlinked before any attempt to
create them.
In some cases, this can prove to be a significant performance improvement.
By default, existing files are truncated and rewritten, but
the file is not recreated.
In particular, the default behavior does not break existing hard links.
.It Cm ARCHIVE_EXTRACT_ACL
Attempt to restore ACLs.
By default, extended ACLs are ignored.
.It Cm ARCHIVE_EXTRACT_FFLAGS
Attempt to restore extended file flags.
By default, file flags are ignored.
.It Cm ARCHIVE_EXTRACT_XATTR
Attempt to restore POSIX.1e extended attributes.
By default, they are ignored.
.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS
Refuse to extract any object whose final location would be altered
by a symlink on disk.
This is intended to help guard against a variety of mischief
caused by archives that (deliberately or otherwise) extract
files outside of the current directory.
The default is not to perform this check.
If
.Cm ARCHIVE_EXTRACT_UNLINK
is specified together with this option, the library will
remove any intermediate symlinks it finds and return an
error only if such symlink could not be removed.
.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
Refuse to extract an absolute path.
The default is to not refuse such paths.
.It Cm ARCHIVE_EXTRACT_SECURE_NODOTDOT
Refuse to extract a path that contains a
.Pa ..
@ -156,16 +149,45 @@ The default is to not refuse such paths.
Note that paths ending in
.Pa ..
always cause an error, regardless of this flag.
.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
Refuse to extract an absolute path.
The default is to not refuse such paths.
.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS
Refuse to extract any object whose final location would be altered
by a symlink on disk.
This is intended to help guard against a variety of mischief
caused by archives that (deliberately or otherwise) extract
files outside of the current directory.
The default is not to perform this check.
If
.It Cm ARCHIVE_EXTRACT_SPARSE
Scan data for blocks of NUL bytes and try to recreate them with holes.
This results in sparse files, independent of whether the archive format
supports or uses them.
.It Cm ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS
Before removing a file system object prior to replacing it, clear
platform-specific file flags which might prevent its removal.
.Cm ARCHIVE_EXTRACT_UNLINK
is specified together with this option, the library will
remove any intermediate symlinks it finds and return an
error only if such symlink could not be removed.
.It Cm ARCHIVE_EXTRACT_TIME
The timestamps (mtime, ctime, and atime) should be restored.
By default, they are ignored.
Note that restoring of atime is not currently supported.
.It Cm ARCHIVE_EXTRACT_UNLINK
Existing files on disk will be unlinked before any attempt to
create them.
In some cases, this can prove to be a significant performance improvement.
By default, existing files are truncated and rewritten, but
the file is not recreated.
In particular, the default behavior does not break existing hard links.
.It Cm ARCHIVE_EXTRACT_XATTR
Attempt to restore extended file attributes.
By default, they are ignored.
See
.Xr xattr 7
.Pq Linux ,
.Xr xattr 2
.Pq Mac OS X ,
or
.Xr getextattr 8
.Pq FreeBSD
for more information on extended file attributes.
.El
.It Xo
.Fn archive_write_disk_set_group_lookup ,

View File

@ -4092,61 +4092,86 @@ static int
set_xattrs(struct archive_write_disk *a)
{
struct archive_entry *entry = a->entry;
static int warning_done = 0;
struct archive_string errlist;
int ret = ARCHIVE_OK;
int i = archive_entry_xattr_reset(entry);
short fail = 0;
archive_string_init(&errlist);
while (i--) {
const char *name;
const void *value;
size_t size;
int e;
archive_entry_xattr_next(entry, &name, &value, &size);
if (name != NULL &&
strncmp(name, "xfsroot.", 8) != 0 &&
strncmp(name, "system.", 7) != 0) {
int e;
if (a->fd >= 0) {
if (name == NULL)
continue;
#if ARCHIVE_XATTR_LINUX
e = fsetxattr(a->fd, name, value, size, 0);
#elif ARCHIVE_XATTR_DARWIN
e = fsetxattr(a->fd, name, value, size, 0, 0);
#elif ARCHIVE_XATTR_AIX
e = fsetea(a->fd, name, value, size, 0);
/* Linux: quietly skip POSIX.1e ACL extended attributes */
if (strncmp(name, "system.", 7) == 0 &&
(strcmp(name + 7, "posix_acl_access") == 0 ||
strcmp(name + 7, "posix_acl_default") == 0))
continue;
if (strncmp(name, "trusted.SGI_", 12) == 0 &&
(strcmp(name + 12, "ACL_DEFAULT") == 0 ||
strcmp(name + 12, "ACL_FILE") == 0))
continue;
/* Linux: xfsroot namespace is obsolete and unsupported */
if (strncmp(name, "xfsroot.", 8) == 0) {
fail = 1;
archive_strcat(&errlist, name);
archive_strappend_char(&errlist, ' ');
continue;
}
#endif
} else {
if (a->fd >= 0) {
#if ARCHIVE_XATTR_LINUX
e = lsetxattr(archive_entry_pathname(entry),
name, value, size, 0);
e = fsetxattr(a->fd, name, value, size, 0);
#elif ARCHIVE_XATTR_DARWIN
e = setxattr(archive_entry_pathname(entry),
name, value, size, 0, XATTR_NOFOLLOW);
e = fsetxattr(a->fd, name, value, size, 0, 0);
#elif ARCHIVE_XATTR_AIX
e = lsetea(archive_entry_pathname(entry),
name, value, size, 0);
e = fsetea(a->fd, name, value, size, 0);
#endif
}
if (e == -1) {
if (errno == ENOTSUP || errno == ENOSYS) {
if (!warning_done) {
warning_done = 1;
archive_set_error(&a->archive,
errno,
"Cannot restore extended "
"attributes on this file "
"system");
}
} else
archive_set_error(&a->archive, errno,
"Failed to set extended attribute");
ret = ARCHIVE_WARN;
}
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid extended attribute encountered");
#if ARCHIVE_XATTR_LINUX
e = lsetxattr(archive_entry_pathname(entry),
name, value, size, 0);
#elif ARCHIVE_XATTR_DARWIN
e = setxattr(archive_entry_pathname(entry),
name, value, size, 0, XATTR_NOFOLLOW);
#elif ARCHIVE_XATTR_AIX
e = lsetea(archive_entry_pathname(entry),
name, value, size, 0);
#endif
}
if (e == -1) {
ret = ARCHIVE_WARN;
archive_strcat(&errlist, name);
archive_strappend_char(&errlist, ' ');
if (errno != ENOTSUP && errno != ENOSYS)
fail = 1;
}
}
if (ret == ARCHIVE_WARN) {
if (fail && errlist.length > 0) {
errlist.length--;
errlist.s[errlist.length] = '\0';
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore extended attributes: %s",
errlist.s);
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore extended "
"attributes on this file system.");
}
archive_string_free(&errlist);
return (ret);
}
#elif ARCHIVE_XATTR_FREEBSD
@ -4157,9 +4182,12 @@ static int
set_xattrs(struct archive_write_disk *a)
{
struct archive_entry *entry = a->entry;
static int warning_done = 0;
struct archive_string errlist;
int ret = ARCHIVE_OK;
int i = archive_entry_xattr_reset(entry);
short fail = 0;
archive_string_init(&errlist);
while (i--) {
const char *name;
@ -4175,15 +4203,13 @@ set_xattrs(struct archive_write_disk *a)
name += 5;
namespace = EXTATTR_NAMESPACE_USER;
} else {
/* Warn about other extended attributes. */
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't restore extended attribute ``%s''",
name);
/* Other namespaces are unsupported */
archive_strcat(&errlist, name);
archive_strappend_char(&errlist, ' ');
fail = 1;
ret = ARCHIVE_WARN;
continue;
}
errno = 0;
if (a->fd >= 0) {
e = extattr_set_fd(a->fd, namespace, name,
@ -4194,24 +4220,30 @@ set_xattrs(struct archive_write_disk *a)
name, value, size);
}
if (e != (ssize_t)size) {
if (errno == ENOTSUP || errno == ENOSYS) {
if (!warning_done) {
warning_done = 1;
archive_set_error(&a->archive,
errno,
"Cannot restore extended "
"attributes on this file "
"system");
}
} else {
archive_set_error(&a->archive, errno,
"Failed to set extended attribute");
}
archive_strcat(&errlist, name);
archive_strappend_char(&errlist, ' ');
ret = ARCHIVE_WARN;
if (errno != ENOTSUP && errno != ENOSYS)
fail = 1;
}
}
}
if (ret == ARCHIVE_WARN) {
if (fail && errlist.length > 0) {
errlist.length--;
errlist.s[errlist.length] = '\0';
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore extended attributes: %s",
errlist.s);
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore extended "
"attributes on this file system.");
}
archive_string_free(&errlist);
return (ret);
}
#else

View File

@ -35,6 +35,7 @@ DEFINE_TEST(test_xattr_platform)
struct archive_entry *ae;
const char *name;
const void *value;
void *rvalue;
size_t size, insize;
int e, r;
const char *attrname = "user.libarchive.test";
@ -95,8 +96,9 @@ DEFINE_TEST(test_xattr_platform)
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
value = getXattr("writetest", attrname, &insize);
rvalue = getXattr("writetest", attrname, &insize);
if (assertEqualInt(insize, strlen(writeval) + 1) != 0)
assertEqualMem(value, writeval, insize);
assertEqualMem(rvalue, writeval, insize);
free(rvalue);
#endif
}

View File

@ -360,8 +360,10 @@ compare_acls(const char *path_a, const char *path_b)
if (richacl_a != NULL) {
richacl_b = richacl_get_file(path_b);
if (richacl_b == NULL &&
(errno == ENODATA || errno == ENOTSUP || errno == ENOSYS))
(errno == ENODATA || errno == ENOTSUP || errno == ENOSYS)) {
richacl_free(richacl_a);
return (0);
}
failure("richacl_get_file() error: %s (%s)", path_b,
strerror(errno));
if (assert(richacl_b != NULL) == 0) {

View File

@ -33,7 +33,7 @@ DEFINE_TEST(test_option_xattrs)
const char *testattr = "user.libarchive.test";
const char *testval = "testval";
const void *readval;
void *readval;
size_t size;
int r;
@ -62,6 +62,7 @@ DEFINE_TEST(test_option_xattrs)
readval = getXattr("xattrs_xattrs/f", testattr, &size);
if(assertEqualInt(size, strlen(testval) + 1) != 0)
assertEqualMem(readval, testval, size);
free(readval);
/* Extract xattrs without xattrs */
assertMakeDir("xattrs_noxattrs", 0755);

View File

@ -348,7 +348,7 @@ int canNodump(void);
int setTestAcl(const char *path);
/* Get extended attribute */
const void *getXattr(const char *, const char *, size_t *);
void *getXattr(const char *, const char *, size_t *);
/* Set extended attribute */
int setXattr(const char *, const char *, const void *, size_t);

View File

@ -2451,8 +2451,8 @@ canNodump(void)
return (0);
}
/* Get extended attribute from a path */
const void *
/* Get extended attribute value from a path */
void *
getXattr(const char *path, const char *name, size_t *sizep)
{
void *value = NULL;