bug-coreutils
[Top][All Lists]
Advanced

[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?  */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]