aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2015-11-02 15:19:10 +0200
committerLasse Collin <lasse.collin@tukaani.org>2015-11-02 15:19:10 +0200
commite18adc56f2262aa9394d46681e9e4b9981ed5e97 (patch)
tree71bedec9ab990f466b75cddf7df2a784756dc162
parentUpdate THANKS. (diff)
downloadxz-e18adc56f2262aa9394d46681e9e4b9981ed5e97.tar.xz
xz: Always close the file before trying to delete it.
unlink() can return EBUSY in errno for open files on some operating systems and file systems.
-rw-r--r--src/xz/file_io.c25
1 files changed, 12 insertions, 13 deletions
diff --git a/src/xz/file_io.c b/src/xz/file_io.c
index e5a29925..69cf6326 100644
--- a/src/xz/file_io.c
+++ b/src/xz/file_io.c
@@ -760,23 +760,22 @@ io_close_src(file_pair *pair, bool success)
#endif
if (pair->src_fd != STDIN_FILENO && pair->src_fd != -1) {
-#ifdef TUKLIB_DOSLIKE
+ // Close the file before possibly unlinking it. On DOS-like
+ // systems this is always required since unlinking will fail
+ // if the file is open. On POSIX systems it usually works
+ // to unlink open files, but in some cases it doesn't and
+ // one gets EBUSY in errno.
+ //
+ // xz 5.2.2 and older unlinked the file before closing it
+ // (except on DOS-like systems). The old code didn't handle
+ // EBUSY and could fail e.g. on some CIFS shares. The
+ // advantage of unlinking before closing is negligible
+ // (avoids a race between close() and stat()/lstat() and
+ // unlink()), so let's keep this simple.
(void)close(pair->src_fd);
-#endif
- // If we are going to unlink(), do it before closing the file.
- // This way there's no risk that someone replaces the file and
- // happens to get same inode number, which would make us
- // unlink() wrong file.
- //
- // NOTE: DOS-like systems are an exception to this, because
- // they don't allow unlinking files that are open. *sigh*
if (success && !opt_keep_original)
io_unlink(pair->src_name, &pair->src_st);
-
-#ifndef TUKLIB_DOSLIKE
- (void)close(pair->src_fd);
-#endif
}
return;