summaryrefslogtreecommitdiff
path: root/tar
diff options
context:
space:
mode:
authorzoulasc <christos@zoulas.com>2020-01-20 13:20:42 +0100
committerMartin Matuska <martin@matuska.org>2020-01-20 15:31:07 +0100
commitb51d6b621533b6ea7a0a9c4770cc23c2d62a88cf (patch)
tree204b5972b4a5201ae678a38fd25b670c1f48a14c /tar
parent06721c2ad050be144e4cc1719f197fbcfba438eb (diff)
downloadlibarchive-b51d6b621533b6ea7a0a9c4770cc23c2d62a88cf.tar.gz
Introduce archive_write_disk(3) flag ARCHIVE_EXTRACT_SAFE_WRITES
This flag changes the way that regular files are extracted: Instead of removing existing files first and re-creating them in order to replace their contents, a temporary file is created and when writing to the temporary file is completed, the file is rename(2)d to the final destination name. This has the effect of presenting a consistent view of the file to the system (either the file with the new contents or the file with the old contents). Removing and overwriting the file has the undesired side effect that the the system can either not see the file at all (from the time it is being removed till the time it is being re-created), or worse it can see partial file contents. This is problematic when extracting system files (for example shared libraries). If the existing file that is going to be overwritten is a hard link, for now we unlink it before calling rename(2). This can be done correctly by creating a hardlink to a tmpnam(3) generated file and then use rename(2), but that is fairly intrusive and requires refactoring. Fixes #1289
Diffstat (limited to 'tar')
-rw-r--r--tar/bsdtar.127
-rw-r--r--tar/bsdtar.c6
-rw-r--r--tar/bsdtar.h2
-rw-r--r--tar/cmdline.c2
4 files changed, 37 insertions, 0 deletions
diff --git a/tar/bsdtar.1 b/tar/bsdtar.1
index 04b56553..723ea38f 100644
--- a/tar/bsdtar.1
+++ b/tar/bsdtar.1
@@ -469,6 +469,13 @@ This is the reverse of
and the default behavior if
.Nm
is run as non-root in x mode.
+.It Fl Fl no-safe-writes
+(x mode only)
+Do not create temporary files and use
+.Xr rename 2
+to replace the original ones.
+This is the reverse of
+.Fl Fl safe-writes .
.It Fl Fl no-same-owner
(x mode only)
Do not extract owner and group IDs.
@@ -756,6 +763,26 @@ The default is
.Ar hrs
which applies substitutions to all names.
In particular, it is never necessary to specify h, r, or s.
+.It Fl Fl safe-writes
+(x mode only)
+Extract files atomically.
+By default
+.Nm
+unlinks the original file with the same name as the extracted file (if it
+exists), and then creates it immediately under the same name and writes to
+it.
+For a short period of time, applications trying to access the file might
+not find it, or see incomplete results.
+If
+.Fl Fl safe-writes
+is enabled,
+.Nm
+first creates a unique temporary file, then writes the new contents to
+the temporary file, and finally renames the temporary file to its final
+name atomically using
+.Xr rename 2 .
+This guarantees that an application accessing the file, will either see
+the old contents or the new contents at all times.
.It Fl Fl same-owner
(x mode only)
Extract owner and group IDs.
diff --git a/tar/bsdtar.c b/tar/bsdtar.c
index b59963d0..af41be5e 100644
--- a/tar/bsdtar.c
+++ b/tar/bsdtar.c
@@ -542,6 +542,9 @@ main(int argc, char **argv)
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA;
bsdtar->flags |= OPTFLAG_NO_MAC_METADATA;
break;
+ case OPTION_NO_SAFE_WRITES:
+ bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_SAFE_WRITES;
+ break;
case OPTION_NO_SAME_OWNER: /* GNU tar */
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
break;
@@ -658,6 +661,9 @@ main(int argc, char **argv)
usage();
#endif
break;
+ case OPTION_SAFE_WRITES:
+ bsdtar->extract_flags |= ARCHIVE_EXTRACT_SAFE_WRITES;
+ break;
case OPTION_SAME_OWNER: /* GNU tar */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER;
break;
diff --git a/tar/bsdtar.h b/tar/bsdtar.h
index c9206dfd..89aa3aa9 100644
--- a/tar/bsdtar.h
+++ b/tar/bsdtar.h
@@ -164,6 +164,7 @@ enum {
OPTION_NO_ACLS,
OPTION_NO_FFLAGS,
OPTION_NO_MAC_METADATA,
+ OPTION_NO_SAFE_WRITES,
OPTION_NO_SAME_OWNER,
OPTION_NO_SAME_PERMISSIONS,
OPTION_NO_XATTRS,
@@ -177,6 +178,7 @@ enum {
OPTION_OPTIONS,
OPTION_PASSPHRASE,
OPTION_POSIX,
+ OPTION_SAFE_WRITES,
OPTION_SAME_OWNER,
OPTION_STRIP_COMPONENTS,
OPTION_TOTALS,
diff --git a/tar/cmdline.c b/tar/cmdline.c
index 21558e12..b80937ff 100644
--- a/tar/cmdline.c
+++ b/tar/cmdline.c
@@ -123,6 +123,7 @@ static const struct bsdtar_option {
{ "no-fflags", 0, OPTION_NO_FFLAGS },
{ "no-mac-metadata", 0, OPTION_NO_MAC_METADATA },
{ "no-recursion", 0, 'n' },
+ { "no-safe-writes", 0, OPTION_NO_SAFE_WRITES },
{ "no-same-owner", 0, OPTION_NO_SAME_OWNER },
{ "no-same-permissions", 0, OPTION_NO_SAME_PERMISSIONS },
{ "no-xattr", 0, OPTION_NO_XATTRS },
@@ -144,6 +145,7 @@ static const struct bsdtar_option {
{ "posix", 0, OPTION_POSIX },
{ "preserve-permissions", 0, 'p' },
{ "read-full-blocks", 0, 'B' },
+ { "safe-writes", 0, OPTION_SAFE_WRITES },
{ "same-owner", 0, OPTION_SAME_OWNER },
{ "same-permissions", 0, 'p' },
{ "strip-components", 1, OPTION_STRIP_COMPONENTS },