summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2000-09-04 14:42:32 +0000
committerJim Meyering <jim@meyering.net>2000-09-04 14:42:32 +0000
commit65a185d75496e4c428b16e2aef85af184ecf2c85 (patch)
treee10118574f6040cd93edca07198a73524d056b2d /src
parent5dcb9b11aaf18d99340e6a78b9d407782ceb47fc (diff)
downloadcoreutils-65a185d75496e4c428b16e2aef85af184ecf2c85.tar.xz
(same_file_ok): factor some more. improve -- now passes all tests.
checkpoint
Diffstat (limited to 'src')
-rw-r--r--src/copy.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/src/copy.c b/src/copy.c
index de7dfd87a..611583bea 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -393,6 +393,7 @@ same_file_ok (const char *src_path, const struct stat *src_sb,
const struct stat *src_sb_no_link;
const struct stat *dst_sb_no_link;
+ int same_link;
int same = (SAME_INODE (*src_sb, *dst_sb));
*return_now = 0;
@@ -410,6 +411,7 @@ same_file_ok (const char *src_path, const struct stat *src_sb,
if (x->xstat == lstat)
{
+ same_link = same;
/* The backup code ensures there's a copy, so it's ok to remove
any destination file. But there's one exception: when both
@@ -418,19 +420,12 @@ same_file_ok (const char *src_path, const struct stat *src_sb,
would also rename the source file and result in an error. */
if (x->backup_type != none)
{
- if (!same)
+ if (!same_link)
return 1;
return ! same_name (src_path, dst_path);
}
- /* They may refer to the same file if we're in move mode and the
- target is a symlink. That is ok, since we remove any existing
- destination file before opening it -- via `rename' if they're on
- the same file system, via `unlink (DST_PATH)' otherwise. */
- if (x->move_mode && S_ISLNK (dst_sb->st_mode))
- return 1;
-
/* If both the source and destination files are symlinks (and we'll
know this here IFF preserving symlinks (aka xstat == lstat),
then it's ok. */
@@ -454,6 +449,8 @@ same_file_ok (const char *src_path, const struct stat *src_sb,
src_sb_link = &tmp_src_sb;
dst_sb_link = &tmp_dst_sb;
+ same_link = SAME_INODE (*src_sb_link, *dst_sb_link);
+
/* If both are symlinks, then it's ok, but only if the destination
will be unlinked before being opened. This is like the test
above, but with the addition of the unlink_dest_before_opening
@@ -471,7 +468,7 @@ same_file_ok (const char *src_path, const struct stat *src_sb,
would also rename the source file and result in an error. */
if (x->backup_type != none)
{
- if (!SAME_INODE (*src_sb_link, *dst_sb_link))
+ if (!same_link)
return 1;
return ! same_name (src_path, dst_path);
@@ -479,6 +476,7 @@ same_file_ok (const char *src_path, const struct stat *src_sb,
}
#if 0
+ /* FIXME: remove or use */
/* If we're making a backup, we'll detect the problem case in
copy_reg because SRC_PATH will no longer exist. Allowing
the test to be deferred lets cp do some useful things.
@@ -494,6 +492,16 @@ same_file_ok (const char *src_path, const struct stat *src_sb,
return 1;
#endif
+ /* They may refer to the same file if we're in move mode and the
+ target is a symlink. That is ok, since we remove any existing
+ destination file before opening it -- via `rename' if they're on
+ the same file system, via `unlink (DST_PATH)' otherwise.
+ It's also ok if they're distinct hard links to the same file. */
+ if ((x->move_mode || x->unlink_dest_before_opening)
+ && (S_ISLNK (dst_sb_link->st_mode)
+ || (same_link && !same_name (src_path, dst_path))))
+ return 1;
+
/* If neither is a symlink, then it's ok as long as they aren't
links to the same file. */
if (!S_ISLNK (src_sb_link->st_mode) && !S_ISLNK (dst_sb_link->st_mode))
@@ -533,17 +541,14 @@ same_file_ok (const char *src_path, const struct stat *src_sb,
dst_sb_no_link = dst_sb;
}
+ /* FIXME: hoist this to precede if/else? */
/* It's ok to remove a destination symlink. But that works only when we
unlink before opening the destination and when they're on the same
partition. */
if (x->unlink_dest_before_opening
- && S_ISLNK (dst_sb_no_link->st_mode))
+ && S_ISLNK (dst_sb_link->st_mode))
return src_sb_link->st_dev == src_sb_link->st_dev;
- /* FIXME: explain this!! */
- if (x->unlink_dest_before_opening && ! same_name (src_path, dst_path))
- return 1;
-
return 0;
}