mv -n: do not overwrite the destination

This commit is contained in:
Kamil Dudka 2018-01-23 16:42:41 +01:00
parent d51b521e30
commit 79fe59c7fc
2 changed files with 71 additions and 1 deletions

View File

@ -0,0 +1,63 @@
From 76df06ff8fa39ae0cb0d167b7f622139778dc7d7 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Thu, 4 Jan 2018 09:42:10 +0100
Subject: [PATCH] mv -n: do not overwrite the destination
... if it is created by another process after mv has checked its
non-existence.
* src/copy.c (copy_internal): Use renameat2 (..., RENAME_NOREPLACE)
if called by mv -n. If it fails with EEXIST in that case, pretend
successful rename as if the existing destination file was detected
by the preceding lstat call.
Fixes https://bugs.gnu.org/29961
---
src/copy.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/src/copy.c b/src/copy.c
index 2a804945e..be4e357a8 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -53,6 +53,7 @@
#include "ignore-value.h"
#include "ioblksize.h"
#include "quote.h"
+#include "renameat2.h"
#include "root-uid.h"
#include "same.h"
#include "savedir.h"
@@ -2319,7 +2320,12 @@ copy_internal (char const *src_name, char const *dst_name,
if (x->move_mode)
{
- if (rename (src_name, dst_name) == 0)
+ int flags = 0;
+ if (x->interactive == I_ALWAYS_NO)
+ /* do not replace DST_NAME if it was created since our last check */
+ flags = RENAME_NOREPLACE;
+
+ if (renameat2 (AT_FDCWD, src_name, AT_FDCWD, dst_name, flags) == 0)
{
if (x->verbose)
{
@@ -2351,6 +2357,15 @@ copy_internal (char const *src_name, char const *dst_name,
return true;
}
+ if ((flags & RENAME_NOREPLACE) && (errno == EEXIST))
+ {
+ /* Pretend the rename succeeded, so the caller (mv)
+ doesn't end up removing the source file. */
+ if (rename_succeeded)
+ *rename_succeeded = true;
+ return true;
+ }
+
/* FIXME: someday, consider what to do when moving a directory into
itself but when source and destination are on different devices. */
--
2.13.6

View File

@ -1,7 +1,7 @@
Summary: A set of basic GNU tools commonly used in shell scripts
Name: coreutils
Version: 8.29
Release: 1%{?dist}
Release: 2%{?dist}
License: GPLv3+
Group: System Environment/Base
Url: https://www.gnu.org/software/coreutils/
@ -13,6 +13,10 @@ Source106: coreutils-colorls.csh
# do not make coreutils-single depend on /usr/bin/coreutils
%global __requires_exclude ^%{_bindir}/coreutils$
# mv -n: do not overwrite the destination, superseded by
# http://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=v8.29-9-g29baf25aa
Patch1: coreutils-8.29-mv-n-noreplace.patch
# disable the test-lock gnulib test prone to deadlock
Patch100: coreutils-8.26-test-lock.patch
@ -273,6 +277,9 @@ fi
%license COPYING
%changelog
* Tue Jan 23 2018 Kamil Dudka <kdudka@redhat.com> - 8.29-2
- mv -n: do not overwrite the destination
* Tue Jan 02 2018 Kamil Dudka <kdudka@redhat.com> - 8.29-1
- new upstream release 8.29