diff options
author | kientzle <kientzle@FreeBSD.org> | 2007-03-24 05:02:16 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2007-03-24 05:02:16 +0000 |
commit | c9ae05df5cc0ead4790c6bc5a640a5de0f89dfed (patch) | |
tree | 13afc0b23299a785f50351dc36070c9d6f0d46ad /lib/libarchive/archive_write_disk.c | |
parent | 758c270b77e6b393d16186449a41e772d3d21c70 (diff) | |
download | FreeBSD-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.c | 25 |
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); |