]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Fix a return-value mixup when time restore failed.
authorTim Kientzle <kientzle@gmail.com>
Fri, 14 May 2010 14:23:59 +0000 (10:23 -0400)
committerTim Kientzle <kientzle@gmail.com>
Fri, 14 May 2010 14:23:59 +0000 (10:23 -0400)
Restore ACLs after restoring time.  (NFS4 ACLs
can prohibit the owner from setting time on a file.)

SVN-Revision: 2401

libarchive/archive_write_disk.c

index 047a5184a4ecc24bb80bd0e573e7afb59d86cb41..cdfcef6116979f6ee94d08aafd18d4ea494a25a0 100644 (file)
@@ -255,7 +255,7 @@ static int  set_fflags_platform(struct archive_write_disk *, int fd,
 static int     set_ownership(struct archive_write_disk *);
 static int     set_mode(struct archive_write_disk *, int mode);
 static int     set_time(int, int, const char *, time_t, long, time_t, long);
-static int     set_times(int, int, const char *,
+static int     set_times(struct archive_write_disk *, int, int, const char *,
                    time_t, long, time_t, long, time_t, long);
 static int     set_times_from_entry(struct archive_write_disk *);
 static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
@@ -812,10 +812,6 @@ _archive_write_disk_finish_entry(struct archive *_a)
                int r2 = set_mode(a, a->mode);
                if (r2 < ret) ret = r2;
        }
-       if (a->todo & TODO_ACLS) {
-               int r2 = set_acls(a);
-               if (r2 < ret) ret = r2;
-       }
 
        /*
         * Security-related extended attributes (such as
@@ -844,6 +840,15 @@ _archive_write_disk_finish_entry(struct archive *_a)
                if (r2 < ret) ret = r2;
        }
 
+       /*
+        * ACLs must be restored after timestamps because there are
+        * ACLs that prevent attribute changes (including time).
+        */
+       if (a->todo & TODO_ACLS) {
+               int r2 = set_acls(a);
+               if (r2 < ret) ret = r2;
+       }
+
        /* If there's an fd, we can close it now. */
        if (a->fd >= 0) {
                close(a->fd);
@@ -1322,7 +1327,7 @@ _archive_write_disk_close(struct archive *_a)
        while (p != NULL) {
                a->pst = NULL; /* Mark stat cache as out-of-date. */
                if (p->fixup & TODO_TIMES) {
-                       set_times(-1, p->mode, p->name,
+                       set_times(a, -1, p->mode, p->name,
                            p->atime, p->atime_nanos,
                            p->birthtime, p->birthtime_nanos,
                            p->mtime, p->mtime_nanos);
@@ -1893,7 +1898,9 @@ set_ownership(struct archive_write_disk *a)
        return (ARCHIVE_WARN);
 }
 
-
+/*
+ * Note: Returns 0 on success, non-zero on failure.
+ */
 static int
 set_time(int fd, int mode, const char *name,
     time_t atime, long atime_nsec,
@@ -1973,12 +1980,15 @@ set_time(int fd, int mode, const char *name,
 }
 
 static int
-set_times(int fd, int mode, const char *name,
+set_times(struct archive_write_disk *a,
+    int fd, int mode, const char *name,
     time_t atime, long atime_nanos,
     time_t birthtime, long birthtime_nanos,
     time_t mtime, long mtime_nanos)
 {
-       int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK;
+       /* Note: set_time doesn't use libarchive return conventions!
+        * It uses syscall conventions.  So 0 here instead of ARCHIVE_OK. */
+       int r1 = 0, r2 = 0;
 
 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
        /*
@@ -1998,7 +2008,12 @@ set_times(int fd, int mode, const char *name,
        r2 = set_time(fd, mode, name,
                      atime, atime_nanos,
                      mtime, mtime_nanos);
-       return (r1 < r2) ? r1 : r2;
+       if (r1 != 0 || r2 != 0) {
+               archive_set_error(&a->archive, errno,
+                                 "Can't restore time");
+               return (ARCHIVE_WARN);
+       }
+       return (ARCHIVE_OK);
 }
 
 static int
@@ -2032,7 +2047,7 @@ set_times_from_entry(struct archive_write_disk *a)
                mtime_nsec = archive_entry_mtime_nsec(a->entry);
        }
 
-       return set_times(a->fd, a->mode, a->name,
+       return set_times(a, a->fd, a->mode, a->name,
                         atime, atime_nsec,
                         birthtime, birthtime_nsec,
                         mtime, mtime_nsec);