diff options
author | Jim Meyering <jim@meyering.net> | 1998-06-27 20:44:23 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 1998-06-27 20:44:23 +0000 |
commit | 9d9fef5595fe51e5364d28a7d5259dc28c4bcc1a (patch) | |
tree | 06de37171ac2ecc4840505e0dd74ff29551845df /src/copy.c | |
parent | 6fd3c331ba720d6b91d570267c80bed260e6b393 (diff) | |
download | coreutils-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.c | 67 |
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)) |