? o Index: libarchive/archive.h =================================================================== RCS file: /cvsroot/src/external/bsd/libarchive/dist/libarchive/archive.h,v retrieving revision 1.4 diff -u -u -r1.4 archive.h --- libarchive/archive.h 24 Jul 2019 14:03:57 -0000 1.4 +++ libarchive/archive.h 13 Nov 2019 22:06:25 -0000 @@ -693,6 +693,8 @@ #define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000) /* Default: Do not clear no-change flags when unlinking object */ #define ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS (0x20000) +/* Default: Do not extract atomically (using rename) */ +#define ARCHIVE_EXTRACT_ATOMIC (0x40000) __LA_DECL int archive_read_extract(struct archive *, struct archive_entry *, int flags); Index: libarchive/archive_write_disk_posix.c =================================================================== RCS file: /cvsroot/src/external/bsd/libarchive/dist/libarchive/archive_write_disk_posix.c,v retrieving revision 1.1.1.2 diff -u -u -r1.1.1.2 archive_write_disk_posix.c --- libarchive/archive_write_disk_posix.c 24 Jul 2019 13:50:21 -0000 1.1.1.2 +++ libarchive/archive_write_disk_posix.c 13 Nov 2019 22:06:25 -0000 @@ -253,6 +253,8 @@ struct archive_entry *entry; /* Entry being extracted. */ char *name; /* Name of entry, possibly edited. */ struct archive_string _name_data; /* backing store for 'name' */ + char *tmpname; /* Temporary name * */ + struct archive_string _tmpname_data; /* backing store for 'tmpname' */ /* Tasks remaining for this object. */ int todo; /* Tasks deferred until end-of-archive. */ @@ -1826,6 +1828,13 @@ if (a->fd >= 0) { close(a->fd); a->fd = -1; + if (a->tmpname) { + if (rename(a->tmpname, a->name) == -1) { + archive_set_error(&a->archive, errno, + "rename failed"); + ret = ARCHIVE_FATAL; + } + } } /* If there's an entry, we can release it now. */ archive_entry_free(a->entry); @@ -2288,8 +2297,24 @@ /* POSIX requires that we fall through here. */ /* FALLTHROUGH */ case AE_IFREG: - a->fd = open(a->name, - O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, mode); + if (a->flags & ARCHIVE_EXTRACT_ATOMIC) { + archive_string_empty(&a->_tmpname_data); + archive_string_sprintf(&a->_tmpname_data, "%sXXXXXX", + a->name); + a->tmpname = a->_tmpname_data.s; + a->fd = mkostemp(a->tmpname, O_CLOEXEC); + if (a->fd >= 0 && fchmod(a->fd, mode) == -1) { + int oerrno = errno; + close(a->fd); + errno = oerrno; + a->fd = -1; + } + } else { + a->tmpname = NULL; + a->fd = open(a->name, + O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, + mode); + } __archive_ensure_cloexec_flag(a->fd); r = (a->fd < 0); break; @@ -2449,6 +2474,7 @@ archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL); archive_entry_free(a->entry); archive_string_free(&a->_name_data); + archive_string_free(&a->_tmpname_data); archive_string_free(&a->archive.error_string); archive_string_free(&a->path_safe); a->archive.magic = 0; Index: tar/bsdtar.c =================================================================== RCS file: /cvsroot/src/external/bsd/libarchive/dist/tar/bsdtar.c,v retrieving revision 1.1.1.4 diff -u -u -r1.1.1.4 bsdtar.c --- tar/bsdtar.c 24 Jul 2019 13:50:41 -0000 1.1.1.4 +++ tar/bsdtar.c 13 Nov 2019 22:06:25 -0000 @@ -231,6 +231,9 @@ /* Default: Perform basic security checks. */ bsdtar->extract_flags |= SECURITY; + /* Default: Extract atomically if possible */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_ATOMIC; + #ifndef _WIN32 /* On POSIX systems, assume --same-owner and -p when run by * the root user. This doesn't make any sense on Windows. */