Fixed the bug with checking physically the same file; for example:
'mount --bind parent parent/child' command makes 'parent' mount point which
physically is 'parent/child';
If we are trying to 'diff parent parent/child' we must get '0' because
files (dirs) are physically the same;
That means we need to check stats of files and return '0' in this case.

There is the comment in diff-utils: src/system.h which is describing
why isn't comparing only st_dev and st_ino sufficient:
/* 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 file systems incorrectly assign the same (device,
inode) pair to two distinct files, including:

GNU/Linux NFS servers that export all local file systems as a
single NFS file system, if a local device number (st_dev) exceeds
255, or if a local inode number (st_ino) exceeds 16777215.

...

It's ppossible for two distinct files on a buggy file system 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.  */

Signed-off-by: Roman Borisov <[email protected]>
---
 editors/diff.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/editors/diff.c b/editors/diff.c
index ca4a4ea..ba8cd64 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -952,6 +952,21 @@ int diff_main(int argc UNUSED_PARAM, char **argv)
        if (gotstdin && (S_ISDIR(stb[0].st_mode) || S_ISDIR(stb[1].st_mode)))
                bb_error_msg_and_die("can't compare stdin to a directory");
 
+       /* Compare stats to check if the files are the same physically;
+          See diffutils: src/system.h for full description */
+       if (stb[0].st_ino == stb[1].st_ino && 
+               stb[0].st_dev == stb[1].st_dev &&
+               stb[0].st_mode == stb[1].st_mode &&
+               stb[0].st_nlink == stb[1].st_nlink &&
+               stb[0].st_uid == stb[1].st_uid &&
+               stb[0].st_gid == stb[1].st_gid &&
+               stb[0].st_size == stb[1].st_size &&
+               stb[0].st_mtime == stb[1].st_mtime &&
+               stb[0].st_ctime == stb[1].st_ctime) {
+               /* files are physically the same; no need to compare them */
+               return STATUS_SAME;
+       }
+
        if (S_ISDIR(stb[0].st_mode) && S_ISDIR(stb[1].st_mode)) {
 #if ENABLE_FEATURE_DIFF_DIR
                diffdir(file, s_start);
-- 
1.7.0.4

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to