]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
disk read: improve path handling for acls, xattrs and mac_metadata
authorMartin Matuska <martin@matuska.org>
Sat, 18 Feb 2017 21:38:38 +0000 (22:38 +0100)
committerMartin Matuska <martin@matuska.org>
Sat, 18 Feb 2017 21:38:38 +0000 (22:38 +0100)
- 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.

libarchive/archive_read_disk_entry_from_file.c

index e81c28e57323fd5b0aa295ba814ad50f3f26f6d2..ff3cd27afe9eff2fed6b0ee3fa66445d7be93c41 100644 (file)
@@ -450,23 +450,33 @@ setup_acls(struct archive_read_disk *a,
 #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 @@ setup_acls(struct archive_read_disk *a,
                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 @@ setup_acls(struct archive_read_disk *a,
                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 @@ setup_acls(struct archive_read_disk *a,
                        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 @@ setup_acls(struct archive_read_disk *a,
 
 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 @@ setup_xattrs(struct archive_read_disk *a,
        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 @@ setup_xattrs(struct archive_read_disk *a,
                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 @@ setup_xattrs(struct archive_read_disk *a,
  */
 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 @@ setup_xattrs(struct archive_read_disk *a,
        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 @@ setup_xattrs(struct archive_read_disk *a,
                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;
        }