]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
archive_write_disk_posix: open a fd when processing fixup entries
authorMartin Matuska <martin@matuska.org>
Sat, 25 May 2019 21:46:59 +0000 (23:46 +0200)
committerMartin Matuska <martin@matuska.org>
Sat, 25 May 2019 21:46:59 +0000 (23:46 +0200)
libarchive/archive_write_disk_posix.c

index 70b27b50360fd11b539bb7b5991a9c23acf75a8f..0583fbd138d3f5306e63439b9a583ca1aecfc9f3 100644 (file)
@@ -182,6 +182,7 @@ struct fixup_entry {
        void                    *mac_metadata;
        int                      fixup; /* bitmask of what needs fixing */
        char                    *name;
+       int                      fd;
 };
 
 /*
@@ -2354,20 +2355,31 @@ _archive_write_disk_close(struct archive *_a)
 
        while (p != NULL) {
                a->pst = NULL; /* Mark stat cache as out-of-date. */
+               if (p->fd < 0 && p->fixup &
+                   (TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) {
+                       p->fd = open(p->name,
+                           O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC);
+               }
                if (p->fixup & TODO_TIMES) {
-                       set_times(a, -1, p->mode, p->name,
+                       set_times(a, p->fd, p->mode, p->name,
                            p->atime, p->atime_nanos,
                            p->birthtime, p->birthtime_nanos,
                            p->mtime, p->mtime_nanos,
                            p->ctime, p->ctime_nanos);
                }
-               if (p->fixup & TODO_MODE_BASE)
+               if (p->fixup & TODO_MODE_BASE) {
+#ifdef HAVE_FCHMOD
+                       if (p->fd >= 0)
+                               fchmod(p->fd, p->mode);
+                       else
+#endif
                        chmod(p->name, p->mode);
+               }
                if (p->fixup & TODO_ACLS)
-                       archive_write_disk_set_acls(&a->archive, -1, p->name,
-                           &p->acl, p->mode);
+                       archive_write_disk_set_acls(&a->archive, p->fd,
+                           p->name, &p->acl, p->mode);
                if (p->fixup & TODO_FFLAGS)
-                       set_fflags_platform(a, -1, p->name,
+                       set_fflags_platform(a, p->fd, p->name,
                            p->mode, p->fflags_set, 0);
                if (p->fixup & TODO_MAC_METADATA)
                        set_mac_metadata(a, p->name, p->mac_metadata,
@@ -2376,6 +2388,8 @@ _archive_write_disk_close(struct archive *_a)
                archive_acl_clear(&p->acl);
                free(p->mac_metadata);
                free(p->name);
+               if (p->fd >= 0)
+                       close(p->fd);   
                free(p);
                p = next;
        }
@@ -2510,6 +2524,7 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
        a->fixup_list = fe;
        fe->fixup = 0;
        fe->name = strdup(pathname);
+       fe->fd = -1;
        return (fe);
 }