]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
On systems that use SysV-style SGID handling for directories,
authorTim Kientzle <kientzle@gmail.com>
Fri, 27 Jun 2008 00:08:58 +0000 (20:08 -0400)
committerTim Kientzle <kientzle@gmail.com>
Fri, 27 Jun 2008 00:08:58 +0000 (20:08 -0400)
the SGID bit can be set intrinsically by the system.
When handling EXTRACT_PERM (tar -p) on such systems, we need
to do an additional chmod() on directories, even if the
dir creation used the correct full mode.

SVN-Revision: 144

libarchive/archive_write_disk.c

index ef6644b1d5e4b05780873e994ff6ec36bd9b6353..238173c42a218afa46b0fa025c56b0a655db645e 100644 (file)
@@ -610,8 +610,8 @@ _archive_write_finish_entry(struct archive *_a)
        /* Restore metadata. */
 
        /*
-        * Look up the "real" UID only if we're going to need it.  We
-        * need this for TODO_SGID because chown() requires both.
+        * Look up the "real" UID only if we're going to need it.
+        * TODO: the TODO_SGID condition can be dropped here, can't it?
         */
        if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) {
                a->uid = a->lookup_uid(a->lookup_uid_data,
@@ -619,6 +619,7 @@ _archive_write_finish_entry(struct archive *_a)
                    archive_entry_uid(a->entry));
        }
        /* Look up the "real" GID only if we're going to need it. */
+       /* TODO: the TODO_SUID condition can be dropped here, can't it? */
        if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) {
                a->gid = a->lookup_gid(a->lookup_gid_data,
                    archive_entry_gname(a->entry),
@@ -1020,7 +1021,10 @@ create_filesystem_object(struct archive_write_disk *a)
                        a->deferred |= (a->todo & TODO_TIMES);
                        a->todo &= ~TODO_TIMES;
                        /* Never use an immediate chmod(). */
-                       if (mode != final_mode)
+                       /* We can't avoid the chmod() entirely if EXTRACT_PERM
+                        * because of SysV SGID inheritance. */
+                       if ((mode != final_mode)
+                           || (a->flags & ARCHIVE_EXTRACT_PERM))
                                a->deferred |= (a->todo & TODO_MODE);
                        a->todo &= ~TODO_MODE;
                }
@@ -1562,8 +1566,8 @@ create_dir(struct archive_write_disk *a, char *path)
 /*
  * Note: Although we can skip setting the user id if the desired user
  * id matches the current user, we cannot skip setting the group, as
- * many systems set the gid bit based on the containing directory.  So
- * we have to perform a chown syscall if we want to restore the SGID
+ * many systems set the gid based on the containing directory.  So
+ * we have to perform a chown syscall if we want to set the SGID
  * bit.  (The alternative is to stat() and then possibly chown(); it's
  * more efficient to skip the stat() and just always chown().)  Note
  * that a successful chown() here clears the TODO_SGID_CHECK bit, which