summaryrefslogtreecommitdiffstats
path: root/lib/libarchive/archive_write_disk.c
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2007-03-24 05:02:16 +0000
committerkientzle <kientzle@FreeBSD.org>2007-03-24 05:02:16 +0000
commitc9ae05df5cc0ead4790c6bc5a640a5de0f89dfed (patch)
tree13afc0b23299a785f50351dc36070c9d6f0d46ad /lib/libarchive/archive_write_disk.c
parent758c270b77e6b393d16186449a41e772d3d21c70 (diff)
downloadFreeBSD-src-c9ae05df5cc0ead4790c6bc5a640a5de0f89dfed.zip
FreeBSD-src-c9ae05df5cc0ead4790c6bc5a640a5de0f89dfed.tar.gz
Notice when mkdir() fails.
Don't change permissions on an existing dir unless _EXTRACT_PERM is requested. In particular, bsdtar -x should not edit mode of existing dirs now; bsdtar -xp will.
Diffstat (limited to 'lib/libarchive/archive_write_disk.c')
-rw-r--r--lib/libarchive/archive_write_disk.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/lib/libarchive/archive_write_disk.c b/lib/libarchive/archive_write_disk.c
index 02fabd6..0f2e173 100644
--- a/lib/libarchive/archive_write_disk.c
+++ b/lib/libarchive/archive_write_disk.c
@@ -111,6 +111,7 @@ struct fixup_entry {
* that verification can occur explicitly through a stat() call or
* implicitly because of a successful chown() call.
*/
+#define TODO_MODE_FORCE 0x40000000
#define TODO_MODE_BASE 0x20000000
#define TODO_SUID 0x10000000
#define TODO_SUID_CHECK 0x08000000
@@ -320,6 +321,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
/* Figure out what we need to do for this entry. */
a->todo = TODO_MODE_BASE;
if (a->flags & ARCHIVE_EXTRACT_PERM) {
+ a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */
/*
* SGID requires an extra "check" step because we
* cannot easily predict the GID that the system will
@@ -732,9 +734,12 @@ restore_entry(struct archive_write_disk *a)
* There's a dir in the way of a dir. Don't
* waste time with rmdir()/mkdir(), just fix
* up the permissions on the existing dir.
+ * Note that we don't change perms on existing
+ * dirs unless _EXTRACT_PERM is specified.
*/
- if (a->mode != a->st.st_mode)
- a->deferred |= TODO_MODE;
+ if ((a->mode != a->st.st_mode)
+ && (a->todo & TODO_MODE_FORCE))
+ a->deferred |= (a->todo & TODO_MODE);
/* Ownership doesn't need deferred fixup. */
en = 0; /* Forget the EEXIST. */
}
@@ -806,13 +811,15 @@ create_filesystem_object(struct archive_write_disk *a)
case S_IFDIR:
mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE;
r = mkdir(a->name, mode);
- /* Defer setting dir times. */
- a->deferred |= (a->todo & TODO_TIMES);
- a->todo &= ~TODO_TIMES;
- /* Never use an immediate chmod(). */
- if (mode != final_mode)
- a->deferred |= (a->todo & TODO_MODE);
- a->todo &= ~TODO_MODE;
+ if (r == 0) {
+ /* Defer setting dir times. */
+ a->deferred |= (a->todo & TODO_TIMES);
+ a->todo &= ~TODO_TIMES;
+ /* Never use an immediate chmod(). */
+ if (mode != final_mode)
+ a->deferred |= (a->todo & TODO_MODE);
+ a->todo &= ~TODO_MODE;
+ }
break;
case S_IFIFO:
r = mkfifo(a->name, mode);
OpenPOWER on IntegriCloud