[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: 'cp: .snapshot/xxx and xxx are identical'
From: |
Jim Meyering |
Subject: |
Re: 'cp: .snapshot/xxx and xxx are identical' |
Date: |
Mon, 07 Mar 2005 16:45:05 +0100 |
Jim Meyering <address@hidden> wrote:
...
> That said, it might be worthwhile to change the SAME_INODE checks
> in copy.c to also check same_file_attributes, where that macro
> is defined like this (from diffutils/src/system.c):
Can someone make sure this patch works and let me know?
Just apply it, build cp, and then run a command like
./cp .snapshot/F F
for some file F, on a NetApp-backed file system.
The above command should succeed, while using an
unpatched `cp' should fail.
2005-03-07 Jim Meyering <address@hidden>
Work around POSIX non-compliance of certain file systems so that
using e.g., an Network Appliance server via NFS, cp .snapshot/F F
no longer fails with a diagnostic that the files are the same,
even though the device and inode numbers of .snapshot/F and F are
identical.
* src/copy.c (same_file_ok): Use a stricter test for whether
two stat buffers correspond to the same file system object.
* src/system.h (SAME_FILE_ATTRIBUTES): New macro, from diffutils.
(SAME_INODE_AND_ATTRS): New macro.
Index: src/system.h
===================================================================
RCS file: /fetish/cu/src/system.h,v
retrieving revision 1.100
diff -u -p -r1.100 system.h
--- src/system.h 3 Feb 2005 21:34:34 -0000 1.100
+++ src/system.h 7 Mar 2005 13:44:41 -0000
@@ -566,6 +566,45 @@ uid_t getuid ();
((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \
&& (Stat_buf_1).st_dev == (Stat_buf_2).st_dev)
+/* Do struct stat *S, *T have the same file attributes?
+
+ POSIX says that two files are identical if st_ino and st_dev are
+ the same, but many filesystems incorrectly assign the same (device,
+ inode) pair to two distinct files, including:
+
+ - GNU/Linux NFS servers that export all local filesystems as a
+ single NFS filesystem, if a local device number (st_dev) exceeds
+ 255, or if a local inode number (st_ino) exceeds 16777215.
+
+ - Network Appliance NFS servers in snapshot directories; see
+ Network Appliance bug #195.
+
+ - ClearCase MVFS; see bug id ATRia04618.
+
+ Check whether two files that purport to be the same have the same
+ attributes, to work around instances of this common bug. Do not
+ inspect all attributes, only attributes useful in checking for this
+ bug.
+
+ It's possible for two distinct files on a buggy filesystem to have
+ the same attributes, but it's not worth slowing down all
+ implementations (or complicating the configuration) to cater to
+ these rare cases in buggy implementations. */
+
+#ifndef SAME_FILE_ATTRIBUTES
+# define SAME_FILE_ATTRIBUTES(s, t) \
+ ((s)->st_mode == (t)->st_mode \
+ && (s)->st_nlink == (t)->st_nlink \
+ && (s)->st_uid == (t)->st_uid \
+ && (s)->st_gid == (t)->st_gid \
+ && (s)->st_size == (t)->st_size \
+ && (s)->st_mtime == (t)->st_mtime \
+ && (s)->st_ctime == (t)->st_ctime)
+#endif
+
+#define SAME_INODE_AND_ATTRS(SB1, SB2) \
+ (SAME_INODE (SB1, SB2) && SAME_FILE_ATTRIBUTES (&(SB1), &(SB2)))
+
#define DOT_OR_DOTDOT(Basename) \
(Basename[0] == '.' && (Basename[1] == '\0' \
|| (Basename[1] == '.' && Basename[2] == '\0')))
Index: src/copy.c
===================================================================
RCS file: /fetish/cu/src/copy.c,v
retrieving revision 1.175
diff -u -p -r1.175 copy.c
--- src/copy.c 1 Mar 2005 12:27:47 -0000 1.175
+++ src/copy.c 7 Mar 2005 13:42:50 -0000
@@ -449,7 +449,7 @@ same_file_ok (const char *src_path, cons
struct stat tmp_src_sb;
bool same_link;
- bool same = SAME_INODE (*src_sb, *dst_sb);
+ bool same = SAME_INODE_AND_ATTRS (*src_sb, *dst_sb);
*return_now = false;
*unlink_src = false;
@@ -490,7 +490,7 @@ same_file_ok (const char *src_path, cons
src_sb_link = &tmp_src_sb;
dst_sb_link = &tmp_dst_sb;
- same_link = SAME_INODE (*src_sb_link, *dst_sb_link);
+ same_link = SAME_INODE_AND_ATTRS (*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
@@ -583,7 +583,7 @@ same_file_ok (const char *src_path, cons
hard links to the same file. */
if (!S_ISLNK (src_sb_link->st_mode) && !S_ISLNK (dst_sb_link->st_mode))
{
- if (!SAME_INODE (*src_sb_link, *dst_sb_link))
+ if (!SAME_INODE_AND_ATTRS (*src_sb_link, *dst_sb_link))
return true;
/* If they are the same file, it's ok if we're making hard links. */
@@ -613,7 +613,7 @@ same_file_ok (const char *src_path, cons
else if (stat (dst_path, &tmp_dst_sb))
return true;
- if ( ! SAME_INODE (tmp_src_sb, tmp_dst_sb))
+ if ( ! SAME_INODE_AND_ATTRS (tmp_src_sb, tmp_dst_sb))
return true;
/* FIXME: shouldn't this be testing whether we're making symlinks? */