From unknown Sun Jun 22 17:11:58 2025 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Mailer: MIME-tools 5.509 (Entity 5.509) Content-Type: text/plain; charset=utf-8 From: bug#31364 <31364@debbugs.gnu.org> To: bug#31364 <31364@debbugs.gnu.org> Subject: Status: cp -rfs: Fails to overwrite a symlink when it is on a different device Reply-To: bug#31364 <31364@debbugs.gnu.org> Date: Mon, 23 Jun 2025 00:11:58 +0000 retitle 31364 cp -rfs: Fails to overwrite a symlink when it is on a differe= nt device reassign 31364 coreutils submitter 31364 Illia Bobyr severity 31364 normal thanks From debbugs-submit-bounces@debbugs.gnu.org Fri May 04 19:48:00 2018 Received: (at submit) by debbugs.gnu.org; 4 May 2018 23:48:00 +0000 Received: from localhost ([127.0.0.1]:50057 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fEkQh-0001Nd-R9 for submit@debbugs.gnu.org; Fri, 04 May 2018 19:48:00 -0400 Received: from eggs.gnu.org ([208.118.235.92]:60684) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fEkHL-0001AP-OE for submit@debbugs.gnu.org; Fri, 04 May 2018 19:38:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fEkHE-0000Q7-PJ for submit@debbugs.gnu.org; Fri, 04 May 2018 19:38:14 -0400 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,HTML_MESSAGE, T_DKIM_INVALID autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:38390) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fEkHE-0000Pv-Ha for submit@debbugs.gnu.org; Fri, 04 May 2018 19:38:12 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51644) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fEkHC-0006Qz-J1 for bug-coreutils@gnu.org; Fri, 04 May 2018 19:38:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fEkHB-0000Nz-18 for bug-coreutils@gnu.org; Fri, 04 May 2018 19:38:10 -0400 Received: from mail-io0-x22b.google.com ([2607:f8b0:4001:c06::22b]:39582) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fEkHA-0000Mf-Ar for bug-coreutils@gnu.org; Fri, 04 May 2018 19:38:08 -0400 Received: by mail-io0-x22b.google.com with SMTP id r9-v6so27507816iod.6 for ; Fri, 04 May 2018 16:38:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:from:date:message-id:subject:to:cc; bh=tUE0t/m/rpTa/cexq+0rvnizWNCDZeEEpl1jExrb5U4=; b=U5wkz6TxpCREkc6Rx18pV+1qp4+UCsRcMu0+L9iFzqmqzjotpJpSSL6HJUh0rq+7Uc fmRXV9CA1zfukHBNMfk2NtrjihktbH2kOiGDdWkgfYqyR6d8udjEPmGUgSzBr67GJDMK zJFGRTyP0cM9foTXSkfC8vK2xTeQHSqkPGuWcaj5AsMRzs4kzidR17BZGvKo4pMLTeLb ih3uDgMSCHENPe2wU/Y1wVqpPTV433e4TLDj0xLldbo+1csLwAxFPJGoJ0Ts4oZE6HrW lbpcv03m0ya0apmEFBPWM9D+ArXs1uJY9MVq5bHhV1KePdBor7xeVlu/VRsZ8wgk8jJF 2X1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to:cc; bh=tUE0t/m/rpTa/cexq+0rvnizWNCDZeEEpl1jExrb5U4=; b=LAeQO4Rl2sZwYrorwVJElgZIwJ0IWkiOxEgYEz34MOA9SdQLqivTikg1XabCaNj3U6 Kqm0vLIqoAQPBf7UH0rFFUToPIHDke1nsM7nFOCUU8zMGgKK6rKUAFOrPkLgTkKC55Em RjDG3fVoCI5lNdIvqV7/h0CoiqYKHehtmGkx42ey+kw1RolyruEDzOLSJMZFLY3b/2ie oQMpqlX2VSDo/RaoLeEKLZJCkbvt+MhwuuzStDtzOKgZcPSOK4Il5ZnpA1I81eqtU4AR laj3aPS70TvKAqHdqrObhFlz9Z2i8fNlEun9rhMhx+1+prDSF/SNH7ecd4HalXw0Noum oe+w== X-Gm-Message-State: ALQs6tC3LAaNJm/cYGW7vtPYhNAxOzrdVWV/IwsXCwYMJa1ID8mTcQ2B BNuwThj+upMnvTNnwFoVxO46NH9BShpDSlwMerWlR6Ln X-Google-Smtp-Source: AB8JxZprAJ0quD/9LvFF6vyG5zVYnxE29SxFR5pdJCfq50EcENQzHpgekBKHnVzhjuy3cB2oe+q7xK743DmNOSeQxm0= X-Received: by 2002:a6b:4c1:: with SMTP id 184-v6mr30792445ioe.162.1525477086544; Fri, 04 May 2018 16:38:06 -0700 (PDT) MIME-Version: 1.0 From: Illia Bobyr Date: Fri, 04 May 2018 23:37:55 +0000 Message-ID: Subject: cp -rfs: Fails to overwrite a symlink when it is on a different device To: bug-coreutils@gnu.org Content-Type: multipart/mixed; boundary="000000000000dc01a9056b69cff5" X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -4.0 (----) X-Debbugs-Envelope-To: submit X-Mailman-Approved-At: Fri, 04 May 2018 19:47:58 -0400 Cc: Jason Smith X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -5.0 (-----) --000000000000dc01a9056b69cff5 Content-Type: multipart/alternative; boundary="000000000000dc01a6056b69cff3" --000000000000dc01a6056b69cff3 Content-Type: text/plain; charset="UTF-8" Hello, I have found a bug in "cp -rfs". Steps to reproduce: 1. Given "path1" and "path2" are on different devices. 2. $ touch "path1/file" 3. $ cd path2/; ln -s path1/file 4. $ cp --symbolic-link --force --recursive path1/file . Expected: The link is overwritten with an exact copy. Actual result: cp shows an error: cp: 'path1/file' and './file' are the same file This bug was introduced in http://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=376967889ed7ed561e46ff6d88a66779db62737a Specifically this hunk: diff --git a/src/copy.c b/src/copy.c index e3832c2..9dbd536 100644 --- a/src/copy.c +++ b/src/copy.c @@ -46,6 +46,7 @@ #include "file-set.h" #include "filemode.h" #include "filenamecat.h" +#include "force-link.h" #include "full-write.h" #include "hash.h" #include "hash-triple.h" @@ -1623,11 +1624,13 @@ same_file_ok (char const *src_name, struct stat const *src_sb, } } - /* It's ok to remove a destination symlink. But that works only when we - unlink before opening the destination and when the source and destination - files are on the same partition. */ - if (x->unlink_dest_before_opening - && S_ISLNK (dst_sb_link->st_mode)) + /* It's ok to remove a destination symlink. But that works only + when creating symbolic links, or when the source and destination + are on the same file system and when creating hard links or when + unlinking before opening the destination. */ + if (x->symbolic_link + || ((x->hard_link || x->unlink_dest_before_opening) + && S_ISLNK (dst_sb_link->st_mode))) return dst_sb_link->st_dev == src_sb_link->st_dev; if (x->dereference == DEREF_NEVER) Two patches that fix the issue are attached. They are against the current master in https://github.com/coreutils/coreutils The changes are also here: https://github.com/coreutils/coreutils/compare/master...ilya-bobyr:master Thank you, Illia Bobyr --000000000000dc01a6056b69cff3 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hello,

I have found a bug in= "cp -rfs".

Steps to reproduce:

1. Given "path1" and "path2" are on di= fferent devices.
2. $ touch "path1/file"
3. $= cd path2/; ln -s path1/file
4. $ cp=C2=A0--sy= mbolic-link --force=C2=A0--recursive path1/file .

Expected:
<= div>The link is overwritten with an exact copy.

Actual= result:
cp shows an error:
=C2=A0 =C2=A0 cp: 'path1/file' and './file' are the s= ame file=C2=A0

This bug was introduced in


Specifically t= his hunk:

diff --git a/src/copy.c b/src/copy.= c
index e3832c2..9dbd536 100644
--- a/= src/copy.c
+++ b/src/copy.c
=
@@ -46,6= +46,7 @@
#include "file-set.h"
#include "filemode.h"
=
#includ= e "filenamecat.h"
+#include "force-link.h"
#include "full-write= .h"
#include "hash.h"
#include "hash-triple.h"
@@ -1623,1= 1 +1624,13 @@ same_file_ok (char const *src_name, struct stat const *src_sb= ,
= }
}
= - /* It's ok to remove a destination symlink. But that works only whe= n we
- un= link before opening the destination and when the source and destination
- files are = on the same partition. */
- if (x->unlink_dest_before_opening
- && S_ISLNK (dst_sb_= link->st_mode))
+ /* It's ok to remove a destination symlink. But that works = only
+ = when creating symbolic links, or when the source and destination
+ are on the sam= e file system and when creating hard links or when
+ unlinking before opening the = destination. */
+ if (x->symbolic_link
+ || ((x->hard_link || x->unlink_dest_befo= re_opening)
+ && S_ISLNK (dst_sb_link->st_mode)))
return dst_sb= _link->st_dev =3D=3D src_sb_link->st_dev;
if (x->dereference =3D=3D= DEREF_NEVER)

Two patches that fix the issue are attached.
They are against t= he current master in https://github.com/coreutils/coreut= ils
The changes are also here:


Thank you, Illia Bobyr

--000000000000dc01a6056b69cff3-- --000000000000dc01a9056b69cff5 Content-Type: text/x-patch; charset="US-ASCII"; name="0002-cp-Overwrite-symlinks-on-another-device.patch" Content-Disposition: attachment; filename="0002-cp-Overwrite-symlinks-on-another-device.patch" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_jgslnjw41 RnJvbSA1MWQ0MjI0NTY3NGRjODY0YWMwZGJiMmYxNjBhNTVjZDM4ZmMyNDU4IE1vbiBTZXAgMTcg MDA6MDA6MDAgMjAwMQpGcm9tOiBJbGxpYSBCb2J5ciA8aWJvYnlyQGdvb2dsZS5jb20+CkRhdGU6 IEZyaSwgNCBNYXkgMjAxOCAwOTo0MToyNyAtMDcwMApTdWJqZWN0OiBbUEFUQ0ggMi8yXSBjcDog T3ZlcndyaXRlIHN5bWxpbmtzIG9uIGFub3RoZXIgZGV2aWNlCgpXaGVuIHRhcmdldCBvZiBhIGNv cHkgb3BlcmF0aW9uIGlzIGEgc3ltbGluaywgaXQgaXMgbm90IHRoZSBzYW1lIGZpbGUgYXMKdGhl IHNvdXJjZSwgc28gaXQgaXMgc2FmZSB0byBvdmVyd3JpdGUgaXQsIHJlZ2FyZGxlc3Mgb2YgaWYg aXQgaXMgdGhlCnNhbWUgZGV2aWNlIGFzIHRoZSBzb3VyY2Ugb3IgYSBkaWZmZXJlbnQgZGV2aWNl LgoKUHJldmlvdXMgY2hlY2sgb25seSBhbGxvd2VkIG92ZXJ3cml0ZSBvbiB0aGUgc2FtZSBkZXZp Y2UgYW5kIHByb2R1Y2VkIGFuCmVycm9yIHdoZW4gcnVuIGFjcm9zcyBkaWZmZXJlbnQgZmlsZSBz eXN0ZW1zLgotLS0KIHNyYy9jb3B5LmMgfCAxNSArKysrKysrKysrLS0tLS0KIDEgZmlsZSBjaGFu Z2VkLCAxMCBpbnNlcnRpb25zKCspLCA1IGRlbGV0aW9ucygtKQoKZGlmZiAtLWdpdCBhL3NyYy9j b3B5LmMgYi9zcmMvY29weS5jCmluZGV4IGRiZmFiZjIxNS4uYjM1Zjk1NjhiIDEwMDY0NAotLS0g YS9zcmMvY29weS5jCisrKyBiL3NyYy9jb3B5LmMKQEAgLTE2MjcsMTEgKzE2MjcsMTYgQEAgc2Ft ZV9maWxlX29rIChjaGFyIGNvbnN0ICpzcmNfbmFtZSwgc3RydWN0IHN0YXQgY29uc3QgKnNyY19z YiwKICAgICAgICAgfQogICAgIH0KIAotICAvKiBJdCdzIG9rIHRvIHJlbW92ZSBhIGRlc3RpbmF0 aW9uIHN5bWxpbmsuICBCdXQgdGhhdCB3b3JrcyBvbmx5Ci0gICAgIHdoZW4gY3JlYXRpbmcgc3lt Ym9saWMgbGlua3MsIG9yIHdoZW4gdGhlIHNvdXJjZSBhbmQgZGVzdGluYXRpb24KLSAgICAgYXJl IG9uIHRoZSBzYW1lIGZpbGUgc3lzdGVtIGFuZCBjcmVhdGluZyBoYXJkIGxpbmtzLiAgKi8KLSAg aWYgKHgtPnN5bWJvbGljX2xpbmsKLSAgICAgIHx8ICh4LT5oYXJkX2xpbmsgJiYgU19JU0xOSyAo ZHN0X3NiX2xpbmstPnN0X21vZGUpKSkKKyAgLyogSXQncyBvayB0byByZW1vdmUgYSBkZXN0aW5h dGlvbiBzeW1saW5rIC0gZG9lcyBub3QgYWZmZWN0IHRoZSBzb3VyY2UuICovCisgIGlmICh4LT5z eW1ib2xpY19saW5rKQorICAgIHJldHVybiB0cnVlOworCisgIC8qIFdoZW4gY3JlYXRpbmcgaGFy ZCBsaW5rcyBpdCBPSyB3aGVuIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGFyZSBvbiB0aGUK KyAgICAgc2FtZSBmaWxlIHN5c3RlbS4gIFRPRE86IFRoZSBTX0lTTE5LKCkgY2hlY2sgaXMgcHJv YmFibHkgcmVkdW5kYW50LCBhcyB3ZQorICAgICBzaG91bGQgbm90IGJlIGhlcmUgaWYgdGhlIHNv dXJjZSBhbmQgdGhlIGRlc3RpbmF0aW9uIGFyZSB0aGUgc2FtZSBmaWxlIGFuZAorICAgICB0aGUg ZGVzdGluYXRpb24gaXMgbm90IGEgc3ltYm9saWMgbGluay4gIFRoZSBjYXNlIHdoZW4gdGhlIHNv dXJjZSBhbmQgdGhlCisgICAgIGRlc3RpbmF0aW9uIGFyZSB0aGUgc2FtZSBkdWUgdG8gYmVpbmcg aGFyZCBsaW5rcyBpcyBjaGVja2VkIGFib3ZlLiAgKi8KKyAgaWYgKHgtPmhhcmRfbGluayAmJiBT X0lTTE5LIChkc3Rfc2JfbGluay0+c3RfbW9kZSkpCiAgICAgcmV0dXJuIGRzdF9zYl9saW5rLT5z dF9kZXYgPT0gc3JjX3NiX2xpbmstPnN0X2RldjsKIAogICBpZiAoeC0+ZGVyZWZlcmVuY2UgPT0g REVSRUZfTkVWRVIpCi0tIAoyLjE3LjAuNDQxLmdiNDZmZTYwZTFkLWdvb2cKCg== --000000000000dc01a9056b69cff5 Content-Type: text/x-patch; charset="US-ASCII"; name="0001-cp-No-dup-check-for-unlink_dest_after_failed_open.patch" Content-Disposition: attachment; filename="0001-cp-No-dup-check-for-unlink_dest_after_failed_open.patch" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_jgslnjvs0 RnJvbSBhMmIyMWYyOWVkYWEyYzM0NDhkNjU0Mjg3MDI3OWQ2MjE3YzQzNTA4IE1vbiBTZXAgMTcg MDA6MDA6MDAgMjAwMQpGcm9tOiBJbGxpYSBCb2J5ciA8aWJvYnlyQGdvb2dsZS5jb20+CkRhdGU6 IFRodSwgMyBNYXkgMjAxOCAxNjozODo0MCAtMDcwMApTdWJqZWN0OiBbUEFUQ0ggMS8yXSBjcDog Tm8gZHVwIGNoZWNrIGZvciB1bmxpbmtfZGVzdF9hZnRlcl9mYWlsZWRfb3BlbgoKQSBjYXNlIHdo ZW4gdW5saW5rX2Rlc3RfYWZ0ZXJfZmFpbGVkX29wZW4gaXMgc2V0IGFuZCB0aGUgZGVzdGluYXRp b24gaXMKYSBzeW1ib2xpYyBsaW5rIGlzIGNoZWNrZWQgaW4gc2FtZV9maWxlX29rKCkgaW4gbGlu ZXMgMTU2NS0xNTcyLiAgSXQKZG9lcyBub3QgbWFrZSBzZW5zZSB0byBjaGVjayBhZ2Fpbi4KLS0t CiBzcmMvY29weS5jIHwgNiArKy0tLS0KIDEgZmlsZSBjaGFuZ2VkLCAyIGluc2VydGlvbnMoKyks IDQgZGVsZXRpb25zKC0pCgpkaWZmIC0tZ2l0IGEvc3JjL2NvcHkuYyBiL3NyYy9jb3B5LmMKaW5k ZXggNDk5OGM4M2U2Li5kYmZhYmYyMTUgMTAwNjQ0Ci0tLSBhL3NyYy9jb3B5LmMKKysrIGIvc3Jj L2NvcHkuYwpAQCAtMTYyOSwxMSArMTYyOSw5IEBAIHNhbWVfZmlsZV9vayAoY2hhciBjb25zdCAq c3JjX25hbWUsIHN0cnVjdCBzdGF0IGNvbnN0ICpzcmNfc2IsCiAKICAgLyogSXQncyBvayB0byBy ZW1vdmUgYSBkZXN0aW5hdGlvbiBzeW1saW5rLiAgQnV0IHRoYXQgd29ya3Mgb25seQogICAgICB3 aGVuIGNyZWF0aW5nIHN5bWJvbGljIGxpbmtzLCBvciB3aGVuIHRoZSBzb3VyY2UgYW5kIGRlc3Rp bmF0aW9uCi0gICAgIGFyZSBvbiB0aGUgc2FtZSBmaWxlIHN5c3RlbSBhbmQgd2hlbiBjcmVhdGlu ZyBoYXJkIGxpbmtzIG9yIHdoZW4KLSAgICAgdW5saW5raW5nIGJlZm9yZSBvcGVuaW5nIHRoZSBk ZXN0aW5hdGlvbi4gICovCisgICAgIGFyZSBvbiB0aGUgc2FtZSBmaWxlIHN5c3RlbSBhbmQgY3Jl YXRpbmcgaGFyZCBsaW5rcy4gICovCiAgIGlmICh4LT5zeW1ib2xpY19saW5rCi0gICAgICB8fCAo KHgtPmhhcmRfbGluayB8fCB4LT51bmxpbmtfZGVzdF9iZWZvcmVfb3BlbmluZykKLSAgICAgICAg ICAmJiBTX0lTTE5LIChkc3Rfc2JfbGluay0+c3RfbW9kZSkpKQorICAgICAgfHwgKHgtPmhhcmRf bGluayAmJiBTX0lTTE5LIChkc3Rfc2JfbGluay0+c3RfbW9kZSkpKQogICAgIHJldHVybiBkc3Rf c2JfbGluay0+c3RfZGV2ID09IHNyY19zYl9saW5rLT5zdF9kZXY7CiAKICAgaWYgKHgtPmRlcmVm ZXJlbmNlID09IERFUkVGX05FVkVSKQotLSAKMi4xNy4wLjQ0MS5nYjQ2ZmU2MGUxZC1nb29nCgo= --000000000000dc01a9056b69cff5-- From debbugs-submit-bounces@debbugs.gnu.org Sat May 05 23:18:40 2018 Received: (at 31364) by debbugs.gnu.org; 6 May 2018 03:18:40 +0000 Received: from localhost ([127.0.0.1]:50930 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fFAC7-0003Eb-PI for submit@debbugs.gnu.org; Sat, 05 May 2018 23:18:40 -0400 Received: from mail.magicbluesmoke.com ([82.195.144.49]:49114) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fFAC4-0003ES-Uj for 31364@debbugs.gnu.org; Sat, 05 May 2018 23:18:37 -0400 Received: from localhost.localdomain (unknown [76.21.115.186]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.magicbluesmoke.com (Postfix) with ESMTPSA id AF9A29B0C; Sun, 6 May 2018 04:18:34 +0100 (IST) Subject: Re: bug#31364: cp -rfs: Fails to overwrite a symlink when it is on a different device To: Illia Bobyr , 31364@debbugs.gnu.org References: From: =?UTF-8?Q?P=c3=a1draig_Brady?= Message-ID: Date: Sat, 5 May 2018 20:18:32 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 31364 Cc: Jason Smith X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On 04/05/18 16:37, Illia Bobyr wrote: > Hello, > > I have found a bug in "cp -rfs". > > Steps to reproduce: > > 1. Given "path1" and "path2" are on different devices. > 2. $ touch "path1/file" > 3. $ cd path2/; ln -s path1/file > 4. $ cp --symbolic-link --force --recursive path1/file . > > Expected: > The link is overwritten with an exact copy. > > Actual result: > cp shows an error: > cp: 'path1/file' and './file' are the same file > > This bug was introduced in > > http://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=376967889ed7ed561e46ff6d88a66779db62737a > > Specifically this hunk: > > diff --git a/src/copy.c b/src/copy.c > index e3832c2..9dbd536 100644 > --- a/src/copy.c > > +++ b/src/copy.c > > @@ -46,6 +46,7 @@ > #include "file-set.h" > #include "filemode.h" > #include "filenamecat.h" > +#include "force-link.h" > #include "full-write.h" > #include "hash.h" > #include "hash-triple.h" > @@ -1623,11 +1624,13 @@ same_file_ok (char const *src_name, struct stat > const *src_sb, > } > } > - /* It's ok to remove a destination symlink. But that works only when we > - unlink before opening the destination and when the source and destination > - files are on the same partition. */ > - if (x->unlink_dest_before_opening > - && S_ISLNK (dst_sb_link->st_mode)) > + /* It's ok to remove a destination symlink. But that works only > + when creating symbolic links, or when the source and destination > + are on the same file system and when creating hard links or when > + unlinking before opening the destination. */ > + if (x->symbolic_link > + || ((x->hard_link || x->unlink_dest_before_opening) > + && S_ISLNK (dst_sb_link->st_mode))) > return dst_sb_link->st_dev == src_sb_link->st_dev; > if (x->dereference == DEREF_NEVER) > > Two patches that fix the issue are attached. > They are against the current master in > https://github.com/coreutils/coreutils > The changes are also here: > > https://github.com/coreutils/coreutils/compare/master...ilya-bobyr:master > > Thank you, Illia Bobyr > Thanks for the careful analysis of this hairy code. Your use case works with --remove, which is similar to the very recent https://bugs.gnu.org/31335 which also requests --force to replace symlinks. Your case is slightly different and a change from previous behavior. Note the specific reason for the change is not the hunk you mentioned, but this hunk in cp.c which used to make --force --symlink also imply --remove. /* If --force (-f) was specified and we're in link-creation mode, first remove any existing destination file. */ if (x.unlink_dest_after_failed_open && (x.hard_link || x.symbolic_link)) x.unlink_dest_before_opening = true; That was also changed in the commit you referenced, as we no longer unconditionally unlink() for atomicity reasons. I.E. we now create a temp symlink and rename it over the existing destination. If you don't require these new guarantees then --remove will work for your use case. So back to the hunk you mentioned. I think the logic in the hunk you referenced was suspect before commit 3769678 and only became significant as now hit due to --remove no longer being set unconditionally for -sf. Your analysis wrt x->symbolic_link being independent of the src and dst devices is sound. Though things aren't quite right as one can now nuke a file like: $ touch file $ ln -s file l1 $ cp -s -f l1 file That would be a regression in commit 3769678 not in your change. What I've currently have to address both these cases is: diff --git a/src/copy.c b/src/copy.c index 4998c83..806323e 100644 --- a/src/copy.c +++ b/src/copy.c @@ -1627,14 +1627,17 @@ same_file_ok (char const *src_name, struct stat const *src_sb, } } - /* It's ok to remove a destination symlink. But that works only - when creating symbolic links, or when the source and destination - are on the same file system and when creating hard links or when - unlinking before opening the destination. */ - if (x->symbolic_link - || ((x->hard_link || x->unlink_dest_before_opening) - && S_ISLNK (dst_sb_link->st_mode))) - return dst_sb_link->st_dev == src_sb_link->st_dev; + if (S_ISLNK (dst_sb_link->st_mode)) + { + /* It's ok to replace a destination symlink. */ + if (x->symbolic_link) + return true; + + /* Or when hard links are possible. + TODO: Analyze this case further. */ + if (x->hard_link) + return dst_sb_link->st_dev == src_sb_link->st_dev; + } if (x->dereference == DEREF_NEVER) { I'll test a few more cases, and add tests and NEWS. Thanks again for pinpointing these issues! Pįdraig From debbugs-submit-bounces@debbugs.gnu.org Sun May 06 22:04:49 2018 Received: (at 31364) by debbugs.gnu.org; 7 May 2018 02:04:49 +0000 Received: from localhost ([127.0.0.1]:51838 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fFVWC-0006kJ-LX for submit@debbugs.gnu.org; Sun, 06 May 2018 22:04:49 -0400 Received: from mail-vk0-f42.google.com ([209.85.213.42]:43569) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fFVQX-0006au-7f for 31364@debbugs.gnu.org; Sun, 06 May 2018 21:58:58 -0400 Received: by mail-vk0-f42.google.com with SMTP id x191-v6so3990219vke.10 for <31364@debbugs.gnu.org>; Sun, 06 May 2018 18:58:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=WdzLv9IbOwoxpoh2gUacHHPm6L5Ekzv5PB0eF7QK1qc=; b=DPhAwSdPuHXK7flO0Grd7Fz4OVsFaiDbGACdKqgql6BgO787JB141bFm+aVJZCzUWb xBG64baNaRU2wAk+wmHj3uP78u4iVkuEq+Dbd2Zv7TkShbqWygpkC1Q7/uRvsRdgocGL n9dCuiOrkocwrLwDujOZ055T1USLo8vy8UtglPpUG/uq11weM6L57UjbZmFTZgLgvl3R ZCC4ySRgazrRJK90b15vQBvJt5uPolNIJimUVWVkxMI+BgvvlUhSsnp/g/y8M4yIYVdE VG3D0MS5NayGYn6Hgfl6fOdrYcEjtKvXnfkzT18ma1f/bKiWQ+HfyJ/niVD6VxxIWXpW Gs7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=WdzLv9IbOwoxpoh2gUacHHPm6L5Ekzv5PB0eF7QK1qc=; b=TsccfwhzRLWWxvq5l9TLBxIKZj4oBz7PA02V5KekM56bFaQhVgpv/k5a3yF4DK+ell 0N0zloxXLprtzvaCXHPTSxRjkHmOlhrPBziYSn9LK1DhT6ZJpJfO4769VNA/17zUT405 iRYNQPlXLzx8SiSvaF4csln2ocwri5exhm8NLHPXjmhLmBG5VpYA1UVjXAaN9CTXyWDw CecD+QMzsxeQ6vDzOjv/KCu6LEA05gy6uspm7o6t/zweSBRlMVsWJy1nnJ9DKFLRZLq5 JuxcaDjVoT0Rw+SLXbTvGpbevx/ojMeOWk0MB04R3cIPpIkn+Nt9kioRe/WcaWF04Swh Ciqw== X-Gm-Message-State: ALQs6tDMi49F8PaAvj8bmqcklU4LePO6uQwlShXhhoLcvXkXCHb63IUT I2fSA+otkYRQS6pIvfsbhWN/cFnojLGJ7pJlTaIkRQ== X-Google-Smtp-Source: AB8JxZq7YRvtBvvoXk2BwdTRDMSvlFpV7tgQKMGSrqq0Jo8m+v3CwFNPHr0EO8hunb7owWBd1pNDNlmw6HlXVU7pPEE= X-Received: by 2002:a1f:8b8c:: with SMTP id n134-v6mr27691216vkd.150.1525658331146; Sun, 06 May 2018 18:58:51 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Jason Smith Date: Mon, 07 May 2018 01:58:38 +0000 Message-ID: Subject: Re: bug#31364: cp -rfs: Fails to overwrite a symlink when it is on a different device To: P@draigbrady.com Content-Type: multipart/alternative; boundary="000000000000e1329a056b9402c5" X-Spam-Score: -8.0 (--------) X-Debbugs-Envelope-To: 31364 X-Mailman-Approved-At: Sun, 06 May 2018 22:04:46 -0400 Cc: Illia Bobyr , 31364@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -9.0 (---------) --000000000000e1329a056b9402c5 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hello, P=C3=A1draig, I was actually the one to identify the bug and analyze the code underlying it (Illia, my colleague, was kind enough to volunteer to file the bug report and attempt a patch), and so I may be in the better position to follow up on this. I appreciate your addressing the matter so promptly. We are indeed provisionally using --remove-destination; however, we would prefer to use --force instead for the atomicity it affords. Regarding the proposed solution, I think that it well addresses the present issue. But there are related issues that I should raise while we are discussing it and that may influence its resolution. To begin, it seems problematic to make the return value in the case of hard-link creation dependent on whether the source and the destination are associated with the same device ID, as the purpose of the same_file_ok function seems to be to indicate whether it matters that the files may somehow be the same. If their file systems are different, that is not a problem with the files' being the same; it is a problem with their being on different file systems. The resulting error message (that the operation cannot be performed because the files are the same) is therefore incorrect and misleading. Perhaps, as it seems to me, this check should rather be performed outside this function and associated with its own error message. In fact, even if the source and destination are completely unrelated, this function may still return false and cause the same-file error message to be displayed. For example, let [source] be a regular file or directory on one file system, and let [destination] be a symbolic link on another. Then the following command will result in a same-file error, even if [destination] does not refer to [source]: cp --recursive --link --no-dereference [source] [destination] Moreover, the name and description of the function seem misleading. One would think from reading these that the source and destination files passed to it have already been determined to be equivalent in some way, and that the function is meant to determine whether it is all right in that case to overwrite the destination; however, it appears that the function is called whenever the destination already exists, regardless of its relation to the source. This discrepancy can lead to misunderstandings and problems such as the kind last described. Ideally, the function's name and description would be made more accurate and precise, and the function used strictly accordingly. Assuming we were to move the file-system check outside the same_file_ok function, we would be left with the following code within the function: /* It's ok to remove a destination symbolic link when creating a symbolic link or hard link. */ if (S_ISLNK (dst_sb_link->st_mode) && (x->symbolic_link || x->hard_link)) return true; But as we earlier in the function handle the cases when both the source and the destination are symbolic links, and there does not seem to be a reason to constrain overwriting of symbolic links otherwise (at least within this function), we can perhaps simplify this even further to the following: /* At this point, it's ok to remove a destination symbolic link. */ if (S_ISLNK (dst_sb_link->st_mode)) return true; But I have not analyzed all the relevant code to determine the full impact of this change. Finally, it would seem to make sense for the same_file_ok function to return true immediately if the source and destination files passed to it have different inode numbers or are on different file systems (and are thus not the same file). In fact, this is done in lines 1488-89 if DEREF_NEVER is not set; however, it is not done if DEREF_NEVER is set. For reference, those lines read as follows: if (!same) return true; Cursory analysis suggests that if these lines were unconditionally executed near the top of the function, certain problems might be avoided. Cheers, Jason On Sat, May 5, 2018 at 8:18 PM P=C3=A1draig Brady wrote: > On 04/05/18 16:37, Illia Bobyr wrote: > > Hello, > > > > I have found a bug in "cp -rfs". > > > > Steps to reproduce: > > > > 1. Given "path1" and "path2" are on different devices. > > 2. $ touch "path1/file" > > 3. $ cd path2/; ln -s path1/file > > 4. $ cp --symbolic-link --force --recursive path1/file . > > > > Expected: > > The link is overwritten with an exact copy. > > > > Actual result: > > cp shows an error: > > cp: 'path1/file' and './file' are the same file > > > > This bug was introduced in > > > > > http://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=3D376967889ed7e= d561e46ff6d88a66779db62737a > > > > Specifically this hunk: > > > > diff --git a/src/copy.c b/src/copy.c > > index e3832c2..9dbd536 100644 > > --- a/src/copy.c > > < > http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/copy.c?id=3D2f69d= ba5df8caaf9eda658c1808b1379e9949f22 > > > > +++ b/src/copy.c > > < > http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/copy.c?id=3D37696= 7889ed7ed561e46ff6d88a66779db62737a > > > > @@ -46,6 +46,7 @@ > > #include "file-set.h" > > #include "filemode.h" > > #include "filenamecat.h" > > +#include "force-link.h" > > #include "full-write.h" > > #include "hash.h" > > #include "hash-triple.h" > > @@ -1623,11 +1624,13 @@ same_file_ok (char const *src_name, struct stat > > const *src_sb, > > } > > } > > - /* It's ok to remove a destination symlink. But that works only when = we > > - unlink before opening the destination and when the source and > destination > > - files are on the same partition. */ > > - if (x->unlink_dest_before_opening > > - && S_ISLNK (dst_sb_link->st_mode)) > > + /* It's ok to remove a destination symlink. But that works only > > + when creating symbolic links, or when the source and destination > > + are on the same file system and when creating hard links or when > > + unlinking before opening the destination. */ > > + if (x->symbolic_link > > + || ((x->hard_link || x->unlink_dest_before_opening) > > + && S_ISLNK (dst_sb_link->st_mode))) > > return dst_sb_link->st_dev =3D=3D src_sb_link->st_dev; > > if (x->dereference =3D=3D DEREF_NEVER) > > > > Two patches that fix the issue are attached. > > They are against the current master in > > https://github.com/coreutils/coreutils > > The changes are also here: > > > > > https://github.com/coreutils/coreutils/compare/master...ilya-bobyr:master > > > > Thank you, Illia Bobyr > > > Thanks for the careful analysis of this hairy code. > > Your use case works with --remove, which is similar > to the very recent https://bugs.gnu.org/31335 > which also requests --force to replace symlinks. > Your case is slightly different and a change from previous behavior. > > Note the specific reason for the change is not the > hunk you mentioned, but this hunk in cp.c which used to > make --force --symlink also imply --remove. > > /* If --force (-f) was specified and we're in link-creation mode, > first remove any existing destination file. */ > if (x.unlink_dest_after_failed_open && (x.hard_link || x.symbolic_link)= ) > x.unlink_dest_before_opening =3D true; > > That was also changed in the commit you referenced, > as we no longer unconditionally unlink() for atomicity reasons. > I.E. we now create a temp symlink and rename it over > the existing destination. If you don't require these new > guarantees then --remove will work for your use case. > > So back to the hunk you mentioned. > I think the logic in the hunk you referenced was suspect > before commit 3769678 and only became significant as now > hit due to --remove no longer being set unconditionally for -sf. > Your analysis wrt x->symbolic_link being independent > of the src and dst devices is sound. > > Though things aren't quite right as one can now nuke a file like: > > $ touch file > $ ln -s file l1 > $ cp -s -f l1 file > > That would be a regression in commit 3769678 not in your change. > > What I've currently have to address both these cases is: > > diff --git a/src/copy.c b/src/copy.c > index 4998c83..806323e 100644 > --- a/src/copy.c > +++ b/src/copy.c > @@ -1627,14 +1627,17 @@ same_file_ok (char const *src_name, struct stat > const *src_sb, > } > } > > - /* It's ok to remove a destination symlink. But that works only > - when creating symbolic links, or when the source and destination > - are on the same file system and when creating hard links or when > - unlinking before opening the destination. */ > - if (x->symbolic_link > - || ((x->hard_link || x->unlink_dest_before_opening) > - && S_ISLNK (dst_sb_link->st_mode))) > - return dst_sb_link->st_dev =3D=3D src_sb_link->st_dev; > + if (S_ISLNK (dst_sb_link->st_mode)) > + { > + /* It's ok to replace a destination symlink. */ > + if (x->symbolic_link) > + return true; > + > + /* Or when hard links are possible. > + TODO: Analyze this case further. */ > + if (x->hard_link) > + return dst_sb_link->st_dev =3D=3D src_sb_link->st_dev; > + } > > if (x->dereference =3D=3D DEREF_NEVER) > { > > I'll test a few more cases, and add tests and NEWS. > > Thanks again for pinpointing these issues! > > P=C3=A1draig > --000000000000e1329a056b9402c5 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hello, P=C3=A1draig,

I was actually the= one to identify the bug and analyze the code underlying it (Illia, my coll= eague, was kind enough to volunteer to file the bug report and attempt a pa= tch), and so I may be in the better position to follow up on this. I apprec= iate your addressing the matter so promptly.

We ar= e indeed provisionally using --remove-destination; however, we would prefer= to use --force instead for the atomicity it affords.

<= div>Regarding the proposed solution, I think that it well addresses the pre= sent issue. But there are related issues that I should raise while we are d= iscussing it and that may influence its resolution.

To begin, it seems problematic to make the return value in the case of ha= rd-link creation dependent on whether the source and the destination are as= sociated with the same device ID, as the purpose of the same_file_ok functi= on seems to be to indicate whether it matters that the files may somehow be= the same. If their file systems are different, that is not a problem with = the files' being the same; it is a problem with their being on differen= t file systems. The resulting error message (that the operation cannot be p= erformed because the files are the same) is therefore incorrect and mislead= ing. Perhaps, as it seems to me, this check should rather be performed outs= ide this function and associated with its own error message.

=
In fact, even if the source and destination are completely unrel= ated, this function may still return false and cause the same-file error me= ssage to be displayed. For example, let=C2=A0[source] be= a regular file or directory on one file system, and let=C2=A0[desti= nation] be a symbolic link on another. Then the following command will resu= lt in a same-file error, even if [destination] does not refer to [source]:<= /div>

cp --recursive --link --no-dereference [source] [d= estination]

Moreover, the name and description of = the function seem misleading. One would think from reading these that the s= ource and destination files passed to it have already been determined to be= equivalent in some way, and that the function is meant to determine whethe= r it is all right in that case to overwrite the destination; however, it ap= pears that the function is called whenever the destination already exists, = regardless of its relation to the source. This discrepancy can lead to misu= nderstandings and problems such as the kind last described. Ideally, the fu= nction's name and description would be made more accurate and precise, = and the function used strictly accordingly.

Assumi= ng we were to move the file-system check outside the same_file_ok function,= we would be left with the following code within the function:
/* It's ok to remove a destination symbolic link when crea= ting a symbolic link or hard link. */
if (S_ISLNK (dst_sb_link-&g= t;st_mode) && (x->symbolic_link ||=C2=A0x->hard_link))
=C2=A0 return true;

But as we earlie= r in the function handle the cases when both the source and the destination= are symbolic links, and there does not seem to be a reason to constrain ov= erwriting of symbolic links otherwise (at least within this function), we c= an perhaps simplify this even further to the following:

/* At this point, it's ok to rem= ove a destination symbolic link. */
i= f (S_ISLNK (dst_sb_link->st_mode))=
=C2=A0 return true;

But I have not analyzed all the relevant code to determine the full= impact of this change.

Finally, it would seem to make sense for the same_fi= le_ok function to return true immediately if the source and destination fil= es passed to it have different inode numbers or are on different file syste= ms (and are thus not the same file). In fact, this is done in lines 1488-89= if=C2=A0DEREF_NEVER is not set; however, it is not done if=C2=A0DEREF_NEVE= R is set. For reference, those lines read as follows:

if (!same)=
=C2=A0 return true;

Cursory analysis su= ggests that if these lines were unconditionally executed near the top of th= e function, certain problems might be avoided.

Che= ers,
Jason

On Sat, May 5, 2018 at 8:18 PM P=C3=A1draig Brady <P@draigbrady.com> wrote:
On 04/05/18 16:37, Illia Bobyr wrote: > Hello,
>
> I have found a bug in "cp -rfs".
>
> Steps to reproduce:
>
> 1. Given "path1" and "path2" are on different devi= ces.
> 2. $ touch "path1/file"
> 3. $ cd path2/; ln -s path1/file
> 4. $ cp --symbolic-link --force --recursive path1/file .
>
> Expected:
> The link is overwritten with an exact copy.
>
> Actual result:
> cp shows an error:
>=C2=A0 =C2=A0 =C2=A0cp: 'path1/file' and './file' are t= he same file
>
> This bug was introduced in
>
> http://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=3D37696788= 9ed7ed561e46ff6d88a66779db62737a
>
> Specifically this hunk:
>
> diff --git a/src/copy.c b/src/copy.c
> index e3832c2..9dbd536 100644
> --- a/src/copy.c
> <http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/co= py.c?id=3D2f69dba5df8caaf9eda658c1808b1379e9949f22>
> +++ b/src/copy.c
> <http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/co= py.c?id=3D376967889ed7ed561e46ff6d88a66779db62737a>
> @@ -46,6 +46,7 @@
> #include "file-set.h"
> #include "filemode.h"
> #include "filenamecat.h"
> +#include "force-link.h"
> #include "full-write.h"
> #include "hash.h"
> #include "hash-triple.h"
> @@ -1623,11 +1624,13 @@ same_file_ok (char const *src_name, struct sta= t
> const *src_sb,
> }
> }
> - /* It's ok to remove a destination symlink. But that works only = when we
> - unlink before opening the destination and when the source and destin= ation
> - files are on the same partition. */
> - if (x->unlink_dest_before_opening
> - && S_ISLNK (dst_sb_link->st_mode))
> + /* It's ok to remove a destination symlink. But that works only<= br> > + when creating symbolic links, or when the source and destination
> + are on the same file system and when creating hard links or when
> + unlinking before opening the destination. */
> + if (x->symbolic_link
> + || ((x->hard_link || x->unlink_dest_before_opening)
> + && S_ISLNK (dst_sb_link->st_mode)))
> return dst_sb_link->st_dev =3D=3D src_sb_link->st_dev;
> if (x->dereference =3D=3D DEREF_NEVER)
>
> Two patches that fix the issue are attached.
> They are against the current master in
> https://github.com/coreutils/coreutils
> The changes are also here:
>
> https://github.com/cor= eutils/coreutils/compare/master...ilya-bobyr:master
>
> Thank you, Illia Bobyr
>
Thanks for the careful analysis of this hairy code.

Your use case works with --remove, which is similar
to the very recent https://bugs.gnu.org/31335
which also requests --force to replace symlinks.
Your case is slightly different and a change from previous behavior.

Note the specific reason for the change is not the
hunk you mentioned, but this hunk in cp.c which used to
make --force --symlink also imply --remove.

=C2=A0 /* If --force (-f) was specified and we're in link-creation mode= ,
=C2=A0 =C2=A0 =C2=A0first remove any existing destination file.=C2=A0 */ =C2=A0 if (x.unlink_dest_after_failed_open && (x.hard_link || x.sym= bolic_link))
=C2=A0 =C2=A0 x.unlink_dest_before_opening =3D true;

That was also changed in the commit you referenced,
as we no longer unconditionally unlink() for atomicity reasons.
I.E. we now create a temp symlink and rename it over
the existing destination.=C2=A0 If you don't require these new
guarantees then --remove will work for your use case.

So back to the hunk you mentioned.
I think the logic in the hunk you referenced was suspect
before commit 3769678 and only became significant as now
hit due to --remove no longer being set unconditionally for -sf.
Your analysis wrt x->symbolic_link being independent
of the src and dst devices is sound.

Though things aren't quite right as one can now nuke a file like:

=C2=A0 $ touch file
=C2=A0 $ ln -s file l1
=C2=A0 $ cp -s -f l1 file

That would be a regression in commit 3769678 not in your change.

What I've currently have to address both these cases is:

diff --git a/src/copy.c b/src/copy.c
index 4998c83..806323e 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -1627,14 +1627,17 @@ same_file_ok (char const *src_name, struct stat con= st *src_sb,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
=C2=A0 =C2=A0 =C2=A0}

-=C2=A0 /* It's ok to remove a destination symlink.=C2=A0 But that work= s only
-=C2=A0 =C2=A0 =C2=A0when creating symbolic links, or when the source and d= estination
-=C2=A0 =C2=A0 =C2=A0are on the same file system and when creating hard lin= ks or when
-=C2=A0 =C2=A0 =C2=A0unlinking before opening the destination.=C2=A0 */
-=C2=A0 if (x->symbolic_link
-=C2=A0 =C2=A0 =C2=A0 || ((x->hard_link || x->unlink_dest_before_open= ing)
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 && S_ISLNK (dst_sb_link->st_= mode)))
-=C2=A0 =C2=A0 return dst_sb_link->st_dev =3D=3D src_sb_link->st_dev;=
+=C2=A0 if (S_ISLNK (dst_sb_link->st_mode))
+=C2=A0 =C2=A0 {
+=C2=A0 =C2=A0 =C2=A0 /* It's ok to replace a destination symlink. */ +=C2=A0 =C2=A0 =C2=A0 if (x->symbolic_link)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return true;
+
+=C2=A0 =C2=A0 =C2=A0 /* Or when hard links are possible.
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0TODO: Analyze this case further.=C2=A0 *= /
+=C2=A0 =C2=A0 =C2=A0 if (x->hard_link)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return dst_sb_link->st_dev =3D=3D src_sb_li= nk->st_dev;
+=C2=A0 =C2=A0 }

=C2=A0 =C2=A0if (x->dereference =3D=3D DEREF_NEVER)
=C2=A0 =C2=A0 =C2=A0{

I'll test a few more cases, and add tests and NEWS.

Thanks again for pinpointing these issues!

P=C3=A1draig
--000000000000e1329a056b9402c5-- From debbugs-submit-bounces@debbugs.gnu.org Mon May 14 06:10:55 2018 Received: (at 31364) by debbugs.gnu.org; 14 May 2018 10:10:55 +0000 Received: from localhost ([127.0.0.1]:33328 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fIARJ-0003bN-GZ for submit@debbugs.gnu.org; Mon, 14 May 2018 06:10:55 -0400 Received: from mail.magicbluesmoke.com ([82.195.144.49]:59220) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fIARE-0003bB-1y for 31364@debbugs.gnu.org; Mon, 14 May 2018 06:10:43 -0400 Received: from localhost.localdomain (unknown [76.21.115.186]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.magicbluesmoke.com (Postfix) with ESMTPSA id 3863FCA; Mon, 14 May 2018 11:10:38 +0100 (IST) Subject: Re: bug#31364: cp -rfs: Fails to overwrite a symlink when it is on a different device To: Jason Smith References: From: =?UTF-8?Q?P=c3=a1draig_Brady?= Message-ID: Date: Mon, 14 May 2018 03:10:36 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/mixed; boundary="------------ED423307E7D81906A0D32527" X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 31364 Cc: Illia Bobyr , 31364@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) This is a multi-part message in MIME format. --------------ED423307E7D81906A0D32527 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit On 06/05/18 18:58, Jason Smith wrote: > Hello, PƔdraig, > > I was actually the one to identify the bug and analyze the code underlying it (Illia, my colleague, was kind enough to volunteer to file the bug report and attempt a patch), and so I may be in the better position to follow up on this. I appreciate your addressing the matter so promptly. > > We are indeed provisionally using --remove-destination; however, we would prefer to use --force instead for the atomicity it affords. > > Regarding the proposed solution, I think that it well addresses the present issue. But there are related issues that I should raise while we are discussing it and that may influence its resolution. > > To begin, it seems problematic to make the return value in the case of hard-link creation dependent on whether the source and the destination are associated with the same device ID, as the purpose of the same_file_ok function seems to be to indicate whether it matters that the files may somehow be the same. If their file systems are different, that is not a problem with the files' being the same; it is a problem with their being on different file systems. The resulting error message (that the operation cannot be performed because the files are the same) is therefore incorrect and misleading. Perhaps, as it seems to me, this check should rather be performed outside this function and associated with its own error message. > > In fact, even if the source and destination are completely unrelated, this function may still return false and cause the same-file error message to be displayed. For example, let [source] be a regular file or directory on one file system, and let [destination] be a symbolic link on another. Then the following command will result in a same-file error, even if [destination] does not refer to [source]: > > cp --recursive --link --no-dereference [source] [destination] > > Moreover, the name and description of the function seem misleading. One would think from reading these that the source and destination files passed to it have already been determined to be equivalent in some way, and that the function is meant to determine whether it is all right in that case to overwrite the destination; however, it appears that the function is called whenever the destination already exists, regardless of its relation to the source. This discrepancy can lead to misunderstandings and problems such as the kind last described. Ideally, the function's name and description would be made more accurate and precise, and the function used strictly accordingly. > > Assuming we were to move the file-system check outside the same_file_ok function, we would be left with the following code within the function: > > /* It's ok to remove a destination symbolic link when creating a symbolic link or hard link. */ > if (S_ISLNK (dst_sb_link->st_mode) && (x->symbolic_link || x->hard_link)) > return true; > > But as we earlier in the function handle the cases when both the source and the destination are symbolic links, and there does not seem to be a reason to constrain overwriting of symbolic links otherwise (at least within this function), we can perhaps simplify this even further to the following: > > /* At this point, it's ok to remove a destination symbolic link. */ > if (S_ISLNK (dst_sb_link->st_mode)) > return true; > > But I have not analyzed all the relevant code to determine the full impact of this change. > > Finally, it would seem to make sense for the same_file_ok function to return true immediately if the source and destination files passed to it have different inode numbers or are on different file systems (and are thus not the same file). In fact, this is done in lines 1488-89 if DEREF_NEVER is not set; however, it is not done if DEREF_NEVER is set. For reference, those lines read as follows: > > if (!same) > return true; > > Cursory analysis suggests that if these lines were unconditionally executed near the top of the function, certain problems might be avoided. > > Cheers, > Jason same_file_ok() has accreted awkward complexity, having started out with a series of FIXMEs. It gained support for `mv hardlink1 hardlink2` in fc6073d6 and then having that removed in 222d7ac0. As part of the change in fc6073d6 (2003), it actually made the problematic clause we've been analyzing in same_file_ok() a noop. Thus that clause stagnated for 14 years and so when being converted as part of the recent 37696788 change it no longer became a noop. So while I agree this whole area definitely needs a refactor, let's address the specific issues for now, so that distributors can fix the issue with minimal risk. Since this clause was a noop for 14 years, we should discount it. However the recent change also tries to handle this case: touch foo ln -s foo symlink cp -dl foo symlink Up until the recent 37696788, cp did nothing but after it errors out saying 'symlink' exists. This could be seen as correct as -f is not specified. Now it could also be argued that a noop is ok as the symlink points to the right place, and on some systems we simulate hardlinks to symlinks with symlinks. But on the otherhand `ln foo symlink` does give EEXIST, so for consistency it would be good to keep this behavior of 37696788. The attached patch hopefully handles everything, and adds tests for the two problematic cases. thanks again, PƔdraig. --------------ED423307E7D81906A0D32527 Content-Type: text/x-patch; name="cp-s-fixes.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="cp-s-fixes.patch" =46rom df3e53f003533feb9a4ae1daa01ad1a7cd9e0c96 Mon Sep 17 00:00:00 2001 From: =3D?UTF-8?q?P=3DC3=3DA1draig=3D20Brady?=3D Date: Mon, 14 May 2018 02:26:05 -0700 Subject: [PATCH] cp: fix symlink checks when overwriting files Ensure this _does_ recreate the symlink Given "path1" and "path2" are on different devices. $ touch "path1/file" $ cd path2/; ln -s path1/file $ cp -sf path1/file . Ensure this does _not_ overwrite file $ touch file $ ln -s file l1 $ cp -sf l1 file * src/copy.c (same_file_ok): Remove device ids from consideration, instead deferring to future EXDEV with --link or allowing the first case above to work. Also ensure that we do not exist this function too early, when the destination file is not a symlink, which protects against the second case. * tests/cp/cross-dev-symlink.sh: Add a test for the first case. * tests/cp/same-file.sh: Add a test for the second case above. * NEWS: Mention the bug fixes. * THANKS.in: Mention the reporters who also analyzed the code. Fixes https://bugs.gnu.org/31364 --- NEWS | 7 +++++++ THANKS.in | 2 ++ src/copy.c | 18 ++++++++---------- tests/cp/cross-dev-symlink.sh | 38 +++++++++++++++++++++++++++++++++++++= + tests/cp/same-file.sh | 15 ++++++++++++++- tests/local.mk | 1 + 6 files changed, 70 insertions(+), 11 deletions(-) create mode 100755 tests/cp/cross-dev-symlink.sh diff --git a/NEWS b/NEWS index de02814..7aa2925 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,13 @@ GNU coreutils NEWS -*= - outline -*- =20 ** Bug fixes =20 + 'cp --symlink SRC DST' will again correctly validate DST. + If DST is a regular file and SRC is a symlink to DST, + then cp will no longer allow that operation to clobber DST. + Also if DST is a symlink, then it can always be replaced, + even if it points to SRC on a separate device. + [bug introduced with coreutils-8.27] + 'ls -aA' is now equivalent to 'ls -A', since -A now overrides -a. [bug introduced in coreutils-5.3.0] =20 diff --git a/THANKS.in b/THANKS.in index c63cc9b..3951b66 100644 --- a/THANKS.in +++ b/THANKS.in @@ -261,6 +261,7 @@ Ian Kent ikent@redhat.com Ian Lance Taylor ian@cygnus.com Ian Turner vectro@pipeline.com Iida Yosiaki iida@gnu.org +Illia Bobyr ibobyr@google.com Ilya N. Golubev gin@mo.msk.ru Ingo Saitz ingo@debian.org Ivan Labath labath3@st.fmph.uniba.sk @@ -285,6 +286,7 @@ Jan-Pawel Wrozstinski jpwroz@gmail.com Jari Aalto jari.aalto@cante.net Jarkko Hietaniemi jhi@epsilon.hut.fi Jarod Wilson jwilson@redhat.com +Jason Smith jasonmsmith@google.com Jean Charles Delepine delepine@u-picardie.fr Jean-Pierre Tosoni jpt.7196@gmail.com Jeff Moore jbm@mordor.com diff --git a/src/copy.c b/src/copy.c index 4998c83..0407c56 100644 --- a/src/copy.c +++ b/src/copy.c @@ -1627,14 +1627,9 @@ same_file_ok (char const *src_name, struct stat co= nst *src_sb, } } =20 - /* It's ok to remove a destination symlink. But that works only - when creating symbolic links, or when the source and destination - are on the same file system and when creating hard links or when - unlinking before opening the destination. */ - if (x->symbolic_link - || ((x->hard_link || x->unlink_dest_before_opening) - && S_ISLNK (dst_sb_link->st_mode))) - return dst_sb_link->st_dev =3D=3D src_sb_link->st_dev; + /* It's ok to recreate a destination symlink. */ + if (x->symbolic_link && S_ISLNK (dst_sb_link->st_mode)) + return true; =20 if (x->dereference =3D=3D DEREF_NEVER) { @@ -1651,10 +1646,13 @@ same_file_ok (char const *src_name, struct stat c= onst *src_sb, if ( ! SAME_INODE (tmp_src_sb, tmp_dst_sb)) return true; - /* FIXME: shouldn't this be testing whether we're making symlinks?= */ if (x->hard_link) { - *return_now =3D true; + /* It's ok to attempt to hardlink the same file, + and return early if not replacing a symlink. + Note we need to return early to avoid a later + unlink() of DST (when SRC is a symlink). */ + *return_now =3D ! S_ISLNK (dst_sb_link->st_mode); return true; } } diff --git a/tests/cp/cross-dev-symlink.sh b/tests/cp/cross-dev-symlink.s= h new file mode 100755 index 0000000..e945b40 --- /dev/null +++ b/tests/cp/cross-dev-symlink.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# Ensure symlinks can be replaced across devices + +# Copyright (C) 2018 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see .= + +. "${srcdir=3D.}/tests/init.sh"; path_prepend_ ./src +print_ver_ cp +require_root_ + +cwd=3D$(pwd) +cleanup_() { cd /; umount "$cwd/mnt"; } + +truncate -s100M fs.img || framework_failure_ +mkfs -t ext4 fs.img || skip_ 'failed to create ext4 file system' +mkdir mnt || framework_failure_ +mount fs.img mnt || skip_ 'failed to mount ext4 file system' + +mkdir mnt/path1 || framework_failure_ +touch mnt/path1/file || framework_failure_ +mkdir path2 || framework_failure_ +cd path2 && ln -s ../mnt/path1/file || framework_failure_ + +cp -sf ../mnt/path1/file . 2>err || fail=3D1 + +Exit $fail diff --git a/tests/cp/same-file.sh b/tests/cp/same-file.sh index 01bdb98..e50a991 100755 --- a/tests/cp/same-file.sh +++ b/tests/cp/same-file.sh @@ -47,7 +47,7 @@ contents=3DXYZ for args in 'foo symlink' 'symlink foo' 'foo foo' 'sl1 sl2' \ 'foo hardlink' 'hlsl sl2'; do for options in '' -d -f -df --rem -b -bd -bf -bdf \ - -l -dl -fl -dfl -bl -bdl -bfl -bdfl; do + -l -dl -fl -dfl -bl -bdl -bfl -bdfl -s -sf; do case $args$options in # These tests are not portable. # They all involve making a hard link to a symbolic link. @@ -100,6 +100,7 @@ for args in 'foo symlink' 'symlink foo' 'foo foo' 'sl= 1 sl2' \ # and put brackets around the output. if test -s _err; then sed ' + s/symbolic link/symlink/ s/^[^:]*:\([^:]*\).*/cp:\1/ 1s/^/[/ $s/$/]/ @@ -149,6 +150,8 @@ cat <<\EOF | sed "$remove_these_sed" > expected 0 -bdl (foo symlink symlink.~1~ -> foo) 0 -bfl (foo symlink symlink.~1~ -> foo) 0 -bdfl (foo symlink symlink.~1~ -> foo) +1 -s [cp: cannot create symlink 'symlink' to 'foo'] (foo symlink -> foo)= +0 -sf (foo symlink -> foo) =20 1 [cp: 'symlink' and 'foo' are the same file] (foo symlink -> foo) 1 -d [cp: 'symlink' and 'foo' are the same file] (foo symlink -> foo) @@ -164,6 +167,8 @@ cat <<\EOF | sed "$remove_these_sed" > expected 0 -fl (foo symlink -> foo) 0 -bl (foo symlink -> foo) 0 -bfl (foo symlink -> foo) +1 -s [cp: 'symlink' and 'foo' are the same file] (foo symlink -> foo) +1 -sf [cp: 'symlink' and 'foo' are the same file] (foo symlink -> foo) =20 1 [cp: 'foo' and 'foo' are the same file] (foo) 1 -d [cp: 'foo' and 'foo' are the same file] (foo) @@ -182,6 +187,8 @@ cat <<\EOF | sed "$remove_these_sed" > expected 0 -bdl (foo) 0 -bfl (foo foo.~1~) 0 -bdfl (foo foo.~1~) +1 -s [cp: 'foo' and 'foo' are the same file] (foo) +1 -sf [cp: 'foo' and 'foo' are the same file] (foo) =20 1 [cp: 'sl1' and 'sl2' are the same file] (foo sl1 -> foo sl2 -> foo) 0 -d (foo sl1 -> foo sl2 -> foo) @@ -196,6 +203,8 @@ cat <<\EOF | sed "$remove_these_sed" > expected 0 -fl (foo sl1 -> foo sl2) 0 -bl (foo sl1 -> foo sl2 sl2.~1~ -> foo) 0 -bfl (foo sl1 -> foo sl2 sl2.~1~ -> foo) +1 -s [cp: cannot create symlink 'sl2' to 'sl1'] (foo sl1 -> foo sl2 -> f= oo) +0 -sf (foo sl1 -> foo sl2 -> sl1) =20 1 [cp: 'foo' and 'hardlink' are the same file] (foo hardlink) 1 -d [cp: 'foo' and 'hardlink' are the same file] (foo hardlink) @@ -214,6 +223,8 @@ cat <<\EOF | sed "$remove_these_sed" > expected 0 -bdl (foo hardlink) 0 -bfl (foo hardlink) 0 -bdfl (foo hardlink) +1 -s [cp: 'foo' and 'hardlink' are the same file] (foo hardlink) +1 -sf [cp: 'foo' and 'hardlink' are the same file] (foo hardlink) =20 1 [cp: 'hlsl' and 'sl2' are the same file] (foo hlsl -> foo sl2 -> foo) 0 -d (foo hlsl -> foo sl2 -> foo) @@ -232,6 +243,8 @@ cat <<\EOF | sed "$remove_these_sed" > expected 0 -bdl (foo hlsl -> foo sl2 -> foo) 0 -bfl (foo hlsl -> foo sl2 sl2.~1~ -> foo) 0 -bdfl (foo hlsl -> foo sl2 -> foo) +1 -s [cp: cannot create symlink 'sl2' to 'hlsl'] (foo hlsl -> foo sl2 ->= foo) +0 -sf (foo hlsl -> foo sl2 -> hlsl) =20 EOF =20 diff --git a/tests/local.mk b/tests/local.mk index e60ea1d..1f8b189 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -113,6 +113,7 @@ all_root_tests =3D \ tests/cp/cp-mv-enotsup-xattr.sh \ tests/cp/capability.sh \ tests/cp/sparse-fiemap.sh \ + tests/cp/cross-dev-symlink.sh \ tests/dd/skip-seek-past-dev.sh \ tests/df/problematic-chars.sh \ tests/df/over-mount-device.sh \ --=20 2.9.3 --------------ED423307E7D81906A0D32527-- From debbugs-submit-bounces@debbugs.gnu.org Tue May 15 13:01:28 2018 Received: (at 31364-done) by debbugs.gnu.org; 15 May 2018 17:01:28 +0000 Received: from localhost ([127.0.0.1]:35921 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fIdKK-0006md-G6 for submit@debbugs.gnu.org; Tue, 15 May 2018 13:01:28 -0400 Received: from mail.magicbluesmoke.com ([82.195.144.49]:41998) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fIdKG-0006mS-Um for 31364-done@debbugs.gnu.org; Tue, 15 May 2018 13:01:25 -0400 Received: from localhost.localdomain (unknown [76.21.115.186]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.magicbluesmoke.com (Postfix) with ESMTPSA id 158144B10; Tue, 15 May 2018 18:01:22 +0100 (IST) Subject: Re: bug#31364: cp -rfs: Fails to overwrite a symlink when it is on a different device To: Jason Smith References: From: =?UTF-8?Q?P=c3=a1draig_Brady?= Message-ID: Date: Tue, 15 May 2018 10:01:20 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 31364-done Cc: Illia Bobyr , 31364-done@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Pushed at https://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v8.29-36-gd3daa95 marking this as done cheers, PƔdraig. From debbugs-submit-bounces@debbugs.gnu.org Tue May 15 13:52:50 2018 Received: (at 31364-done) by debbugs.gnu.org; 15 May 2018 17:52:50 +0000 Received: from localhost ([127.0.0.1]:35973 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fIe82-00080f-JY for submit@debbugs.gnu.org; Tue, 15 May 2018 13:52:50 -0400 Received: from mail-ua0-f171.google.com ([209.85.217.171]:36135) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fIe81-00080T-18 for 31364-done@debbugs.gnu.org; Tue, 15 May 2018 13:52:49 -0400 Received: by mail-ua0-f171.google.com with SMTP id b25-v6so740405uak.3 for <31364-done@debbugs.gnu.org>; Tue, 15 May 2018 10:52:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=Z55WiobTOKj2ZXiyP4nXkXseSJ6TdYQ3Azd33RsB3PU=; b=XFzn/7w/eAxaUinPciyYL13hEOZRhkoMG+3m51RCeyB6JH+iRooUJ+ax2imjuRAo5v fcnqnCysW5lnBlrgeA84V+CXjtTdeAj60i+sTzZsHTlUbT7p1n30FuHewr4zqyyA2vFq 7xQR6tcIItmOzVHQ58Z7WxY8kuu+X1c/krtALUA/zF8DCJAU1XJZl0xnl3HGoYUZm7Gm QZJBzA94oLBlutwlnIX3eOEIOUH6zKpEVLVYL6dO1gHBCHWJY4kKhBqtMoM5rhCP+Ufm e/iMHCf6RiOj0JdEhY2lUi+LEIszzoN0JQDcG01n3DBOqg5w7QowFDYJ9cApEgEtzSHy XTYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=Z55WiobTOKj2ZXiyP4nXkXseSJ6TdYQ3Azd33RsB3PU=; b=EBzlhN30HNIN/JKV6fle8PBYcas2zkPNw4cW5aMBN318gNXccodFrPmJxus+Y5cyny LQxjXTzZpT0w4TXlNvXs05da7J0q5vPuI2Tpl5QXN1rJZ59tdEUdwCF+etHIvmNrlHNI eubT66RWJonwYuYznVyPzbuoLB0O1s91CzJEWpcn40fHy9Yi+YiF248JaEfa2ZTOF/dS hdnKusv+mFVk99WJLupSHZYScoO99VUBMFQp9pzEqKlyvZDAQknjJoxwFneGWGICJaFB dObQrGdewlL8DsrWFsGVj/1G3nr/OIkE8LjE61116eaCgvHoM/X49LPjDd9ili08oWy+ oGCg== X-Gm-Message-State: ALKqPwfcFsgIFN6mUV/fUGaBwLTKvZmcr6WsIk/EmmWUftLktqEK2106 nRWCLnuVfEKMfkRohGKv5wztGfQxYFi/s+O3YJH5xQ== X-Google-Smtp-Source: AB8JxZo6UXL6WuipyCFHUrJTC043h2ujJxty3+ctFc03idSWxmjPHDc7f5ygPabRYP9XFKCkx3CTIxtn3RGgljkXcVk= X-Received: by 2002:ab0:6aa:: with SMTP id g39-v6mr17114743uag.82.1526406762931; Tue, 15 May 2018 10:52:42 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Jason Smith Date: Tue, 15 May 2018 10:52:31 -0700 Message-ID: Subject: Re: bug#31364: cp -rfs: Fails to overwrite a symlink when it is on a different device To: =?UTF-8?Q?P=C3=A1draig_Brady?= Content-Type: multipart/alternative; boundary="000000000000e42e94056c424417" X-Spam-Score: -8.6 (--------) X-Debbugs-Envelope-To: 31364-done Cc: Illia Bobyr , 31364-done@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -9.6 (---------) --000000000000e42e94056c424417 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Many thanks, P=C3=A1draig. =E2=80=93Jason On Tue, May 15, 2018 at 10:01 AM P=C3=A1draig Brady wrot= e: > Pushed at > https://git.sv.gnu.org/gitweb/?p=3Dcoreutils.git;a=3Dcommitdiff;h=3Dv8.29= -36-gd3daa95 > > marking this as done > > cheers, > P=C3=A1draig. > > --000000000000e42e94056c424417 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Many thanks, P=C3=A1draig. =E2=80=93Jason

<= div class=3D"gmail_quote">
On Tue, May 15, 2018 at 10:01 AM P=C3=A1drai= g Brady <P@draigbrady.com> wr= ote:
Pushed at https://git.sv.gnu.org/gitweb/?p=3D= coreutils.git;a=3Dcommitdiff;h=3Dv8.29-36-gd3daa95

marking this as done

cheers,
P=C3=A1draig.

--000000000000e42e94056c424417-- From unknown Sun Jun 22 17:11:58 2025 Received: (at fakecontrol) by fakecontrolmessage; To: internal_control@debbugs.gnu.org From: Debbugs Internal Request Subject: Internal Control Message-Id: bug archived. Date: Wed, 13 Jun 2018 11:24:06 +0000 User-Agent: Fakemail v42.6.9 # This is a fake control message. # # The action: # bug archived. thanks # This fakemail brought to you by your local debbugs # administrator