summaryrefslogtreecommitdiff
path: root/src/copy.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1998-06-27 20:44:23 +0000
committerJim Meyering <jim@meyering.net>1998-06-27 20:44:23 +0000
commit9d9fef5595fe51e5364d28a7d5259dc28c4bcc1a (patch)
tree06de37171ac2ecc4840505e0dd74ff29551845df /src/copy.c
parent6fd3c331ba720d6b91d570267c80bed260e6b393 (diff)
downloadcoreutils-9d9fef5595fe51e5364d28a7d5259dc28c4bcc1a.tar.xz
(copy_reg): Detect identical source and dest here.
(copy_internal): Make the test symmetric.
Diffstat (limited to 'src/copy.c')
-rw-r--r--src/copy.c67
1 files changed, 43 insertions, 24 deletions
diff --git a/src/copy.c b/src/copy.c
index d43d686dc..356da5e04 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -185,7 +185,16 @@ copy_reg (const char *src_path, const char *dst_path,
source_desc = open (src_path, O_RDONLY);
if (source_desc < 0)
{
- error (0, errno, "%s", src_path);
+ /* If SRC_PATH doesn't exist, then chances are good that the
+ user did something like this `cp --backup foo foo': and foo
+ existed to start with, but copy_internal renamed DST_PATH
+ with the backup suffix, thus also renaming SRC_PATH. */
+ if (errno == ENOENT)
+ error (0, 0, _("`%s' and `%s' are the same file"),
+ src_path, dst_path);
+ else
+ error (0, errno, "%s", src_path);
+
return -1;
}
@@ -415,39 +424,49 @@ copy_internal (const char *src_path, const char *dst_path,
return 1;
}
else
- new_dst = 1;
+ {
+ new_dst = 1;
+ }
}
else
{
- int same;
-
/* The destination file exists already. */
- same = (src_sb.st_ino == dst_sb.st_ino
- && src_sb.st_dev == dst_sb.st_dev);
+ if (x->backup_type == none)
+ {
+ int same;
+
+ same = (src_sb.st_ino == dst_sb.st_ino
+ && src_sb.st_dev == dst_sb.st_dev);
#ifdef S_ISLNK
- /* If we're preserving symlinks (--no-dereference) and the
- destination file is a symlink, use stat (not xstat) to
- see if it points back to the source. */
- if (!same && !x->dereference && S_ISLNK (dst_sb.st_mode))
- {
- struct stat dst2_sb;
- if (stat (dst_path, &dst2_sb) == 0
- && (src_sb.st_ino == dst2_sb.st_ino &&
- src_sb.st_dev == dst2_sb.st_dev))
- same = 1;
- }
+ /* If we're preserving symlinks (--no-dereference) and either
+ file is a symlink, use stat (not xstat) to see if they refer
+ to the same file. */
+ if (!same && !x->dereference
+ && (S_ISLNK (dst_sb.st_mode) || S_ISLNK (src_sb.st_mode)))
+ {
+ struct stat dst2_sb;
+ struct stat src2_sb;
+ if (stat (dst_path, &dst2_sb) == 0
+ && stat (src_path, &src2_sb) == 0
+ && src2_sb.st_ino == dst2_sb.st_ino
+ && src2_sb.st_dev == dst2_sb.st_dev)
+ {
+ same = 1;
+ }
+ }
#endif
- if (same)
- {
- if (x->hard_link)
- return 0;
+ if (same)
+ {
+ if (x->hard_link)
+ return 0;
- error (0, 0, _("`%s' and `%s' are the same file"),
- src_path, dst_path);
- return 1;
+ error (0, 0, _("`%s' and `%s' are the same file"),
+ src_path, dst_path);
+ return 1;
+ }
}
if (!S_ISDIR (src_type))