disk read: improve path handling for acls, xattrs and mac_metadata
- Do not execute pathname code at all if we have a fd. The only exception
is setup_acls() for directory entries where default ACLs can be
retrieved only with acl_get_file() - e.g. on Linux.
- Do not fail if tree_enter_working_dir() fails. Fallback to
archive_entry_pathname() instead and try with path-based functions.
- Do not fail if open_on_current_dir() fails. Try with path-based
functions.
- Pass pathname to setup_xattr() to avoid execution of duplicate code.
diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c
index e81c28e..ff3cd27 100644
--- a/libarchive/archive_read_disk_entry_from_file.c
+++ b/libarchive/archive_read_disk_entry_from_file.c
@@ -450,23 +450,33 @@
#endif
int r;
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
- else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Can't change dir to read ACLs");
- return (ARCHIVE_WARN);
- }
- if (*fd < 0 && a->tree != NULL && (a->follow_symlinks ||
- archive_entry_filetype(entry) != AE_IFLNK)) {
- *fd = a->open_on_current_dir(a->tree,
- accpath, O_RDONLY | O_NONBLOCK);
- }
- if (*fd < 0 && accpath == NULL) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Can't open file to read ACLs");
- return (ARCHIVE_WARN);
+ accpath = NULL;
+
+#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP
+ if (*fd < 0)
+#else
+ /* For default ACLs on Linux we need reachable accpath */
+ if (*fd < 0 || S_ISDIR(archive_entry_mode(entry)))
+#endif
+ {
+ accpath = archive_entry_sourcepath(entry);
+ if (accpath == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ accpath = archive_entry_pathname(entry);
+ if (accpath == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read ACLs");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL &&
+#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP
+ *fd < 0 &&
+#endif
+ (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
+ *fd = a->open_on_current_dir(a->tree,
+ accpath, O_RDONLY | O_NONBLOCK);
+ }
}
archive_entry_acl_clear(entry);
@@ -528,11 +538,11 @@
acl_free(acl);
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
-#if HAVE_SUN_ACL
- "Couldn't translate ACLs: %s", accpath);
-#else
- "Couldn't translate NFSv4 ACLs: %s", accpath);
+ "Couldn't translate "
+#if !HAVE_SUN_ACL
+ "NFSv4 "
#endif
+ "ACLs");
}
#if HAVE_DARWIN_ACL
/*
@@ -584,7 +594,7 @@
acl = NULL;
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
- "Couldn't translate access ACLs: %s", accpath);
+ "Couldn't translate access ACLs");
return (r);
}
}
@@ -603,8 +613,7 @@
acl_free(acl);
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
- "Couldn't translate default ACLs: %s",
- accpath);
+ "Couldn't translate default ACLs");
return (r);
}
}
@@ -1409,15 +1418,10 @@
static int
setup_xattr(struct archive_read_disk *a,
- struct archive_entry *entry, const char *name, int fd)
+ struct archive_entry *entry, const char *name, int fd, const char *accpath)
{
ssize_t size;
void *value = NULL;
- const char *accpath;
-
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
#if HAVE_FGETXATTR
if (fd >= 0)
@@ -1482,23 +1486,24 @@
const char *path;
ssize_t list_size;
- path = archive_entry_sourcepath(entry);
- if (path == NULL)
- path = archive_entry_pathname(entry);
- else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Can't change dir to read extended attributes");
- return (ARCHIVE_WARN);
- }
- if (*fd < 0 && a->tree != NULL && (a->follow_symlinks ||
- archive_entry_filetype(entry) != AE_IFLNK)) {
- *fd = a->open_on_current_dir(a->tree, path,
- O_RDONLY | O_NONBLOCK);
- }
- if (*fd < 0 && path == NULL) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Can't open file to read extended attributes");
- return (ARCHIVE_WARN);
+ path = NULL;
+
+ if (*fd < 0) {
+ path = archive_entry_sourcepath(entry);
+ if (path == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ path = archive_entry_pathname(entry);
+ if (path == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read "
+ "extended attributes");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL && (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
+ *fd = a->open_on_current_dir(a->tree,
+ path, O_RDONLY | O_NONBLOCK);
+ }
}
#if HAVE_FLISTXATTR
@@ -1560,7 +1565,7 @@
if (strncmp(p, "system.", 7) == 0 ||
strncmp(p, "xfsroot.", 8) == 0)
continue;
- setup_xattr(a, entry, p, *fd);
+ setup_xattr(a, entry, p, *fd, path);
}
free(list);
@@ -1581,19 +1586,16 @@
*/
static int
setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
- int namespace, const char *name, const char *fullname, int fd);
+ int namespace, const char *name, const char *fullname, int fd,
+ const char *path);
static int
setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
- int namespace, const char *name, const char *fullname, int fd)
+ int namespace, const char *name, const char *fullname, int fd,
+ const char *accpath)
{
ssize_t size;
void *value = NULL;
- const char *accpath;
-
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
if (fd >= 0)
size = extattr_get_fd(fd, namespace, name, NULL, 0);
@@ -1643,23 +1645,24 @@
const char *path;
int namespace = EXTATTR_NAMESPACE_USER;
- path = archive_entry_sourcepath(entry);
- if (path == NULL)
- path = archive_entry_pathname(entry);
- else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Can't change dir to read extended attributes");
- return (ARCHIVE_WARN);
- }
- if (*fd < 0 && a->tree != NULL && (a->follow_symlinks ||
- archive_entry_filetype(entry) != AE_IFLNK)) {
- *fd = a->open_on_current_dir(a->tree, path,
- O_RDONLY | O_NONBLOCK);
- }
- if (*fd < 0 && path == NULL) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Can't open file to read extended attributes");
- return (ARCHIVE_WARN);
+ path = NULL;
+
+ if (*fd < 0) {
+ path = archive_entry_sourcepath(entry);
+ if (path == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ path = archive_entry_pathname(entry);
+ if (path == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read "
+ "extended attributes");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL && (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
+ *fd = a->open_on_current_dir(a->tree,
+ path, O_RDONLY | O_NONBLOCK);
+ }
}
if (*fd >= 0)
@@ -1708,7 +1711,7 @@
name = buff + strlen(buff);
memcpy(name, p + 1, len);
name[len] = '\0';
- setup_xattr(a, entry, namespace, name, buff, *fd);
+ setup_xattr(a, entry, namespace, name, buff, *fd, path);
p += 1 + len;
}