diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2015-11-02 15:19:10 +0200 |
---|---|---|
committer | Lasse Collin <lasse.collin@tukaani.org> | 2015-11-02 15:19:10 +0200 |
commit | e18adc56f2262aa9394d46681e9e4b9981ed5e97 (patch) | |
tree | 71bedec9ab990f466b75cddf7df2a784756dc162 /src/xz | |
parent | Update THANKS. (diff) | |
download | xz-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.
Diffstat (limited to 'src/xz')
-rw-r--r-- | src/xz/file_io.c | 25 |
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; |