diff --git a/NEWS b/NEWS index 07cbc88..6fb45bd 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,11 @@ GNU diffutils NEWS -*- outline -*- ** Improvements + diff now outputs more information when symbolic links differ, and + quotes their names to avoid ambiguity. For example, instead of + "Symbolic links d/x do and e/x do differ", diff now outputs + "Symbolic links 'd/x do' -> 'a' and 'e/x do' -> 'b' differ". + diff's --ignore-case (-i) and --ignore-file-name-case options now support multi-byte characters. For example, they treat Greek capital Δ like small δ when input uses UTF-8. diff --git a/bootstrap.conf b/bootstrap.conf index 6f435e5..eba0390 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -86,6 +86,7 @@ perl popen progname propername-lite +quote raise rawmemchr readdir diff --git a/src/diff.c b/src/diff.c index eaf952f..cb5ba33 100644 --- a/src/diff.c +++ b/src/diff.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -1493,45 +1494,39 @@ compare_files (struct comparison const *parent, dassert (no_dereference_symlinks); /* Compare the values of the symbolic links. */ - if (cmp.file[0].stat.st_size != cmp.file[1].stat.st_size - && 0 <= cmp.file[0].stat.st_size - && 0 <= cmp.file[1].stat.st_size) - status = EXIT_FAILURE; - else + char *link_value[2]; link_value[1] = nullptr; + char linkbuf[2][128]; + + for (bool f = false; ; f = true) { - char *link_value[2]; link_value[1] = nullptr; - char linkbuf[2][128]; - - for (bool f = false; ; f = true) + int dirfd = parent->file[f].desc; + char const *name = cmp.file[f].name; + char const *nm = dirfd < 0 ? name : last_component (name); + link_value[f] = careadlinkat (dirfd, nm, + linkbuf[f], sizeof linkbuf[f], + nullptr, readlinkat); + if (!link_value[f]) { - int dirfd = parent->file[f].desc; - char const *name = cmp.file[f].name; - char const *nm = dirfd < 0 ? name : last_component (name); - link_value[f] = careadlinkat (dirfd, nm, - linkbuf[f], sizeof linkbuf[f], - nullptr, readlinkat); - if (!link_value[f]) - { - perror_with_name (cmp.file[f].name); - status = EXIT_TROUBLE; - break; - } - if (f) - { - status = (STREQ (link_value[0], link_value[f]) - ? EXIT_SUCCESS : EXIT_FAILURE); - break; - } + perror_with_name (cmp.file[f].name); + status = EXIT_TROUBLE; + break; + } + if (f) + { + status = (STREQ (link_value[0], link_value[f]) + ? EXIT_SUCCESS : EXIT_FAILURE); + break; } - - for (int f = 0; f < 2; f++) - if (link_value[f] != linkbuf[f]) - free (link_value[f]); } if (status == EXIT_FAILURE) - message ("Symbolic links %s and %s differ\n", - cmp.file[0].name, cmp.file[1].name); + message ("Symbolic links %s -> %s and %s -> %s differ\n", + quote_n (0, cmp.file[0].name), quote_n (1, link_value[0]), + quote_n (2, cmp.file[1].name), quote_n (3, link_value[1])); + + for (int f = 0; f < 2; f++) + if (link_value[f] != linkbuf[f]) + free (link_value[f]); } else if (files_can_be_treated_as_binary && cmp.file[0].detype == DE_REG diff --git a/src/system.h b/src/system.h index 45209fa..b96dd39 100644 --- a/src/system.h +++ b/src/system.h @@ -114,7 +114,7 @@ SYSTEM_EXTERN dev_t proc_dev; #endif -#if defined __linux__ || defined __ANDROID__ +#if false && (defined __linux__ || defined __ANDROID__) # include /* 1 if symlink st_size is OK, -1 if not, 0 if unknown yet. */ SYSTEM_EXTERN signed char symlink_size_ok; @@ -197,9 +197,10 @@ SYSTEM_INLINE off_t stat_size (struct stat *s) return -1; } #endif -#if defined __linux__ || defined __ANDROID__ +#if false && (defined __linux__ || defined __ANDROID__) /* Symlinks have suspect sizes on Linux kernels before 5.15, - due to bugs in fscrypt. */ + due to bugs in fscrypt. However, diffutils never looks + at symlink sizes so this code is not needed. */ if (S_ISLNK (mode)) { if (! symlink_size_ok) diff --git a/tests/no-dereference b/tests/no-dereference index 3f67bd2..f7165c1 100644 --- a/tests/no-dereference +++ b/tests/no-dereference @@ -43,17 +43,17 @@ compare /dev/null out || fail=1 # Test case 7: Compare symbolic links with different value and different target # contents. -returns_ 1 diff --no-dereference symlink1 symlink2 > out || fail=1 +LC_ALL=C returns_ 1 diff --no-dereference symlink1 symlink2 > out || fail=1 cat < expected || framework_failure_ -Symbolic links symlink1 and symlink2 differ +Symbolic links 'symlink1' -> 'regular1' and 'symlink2' -> 'regular2' differ EOF compare expected out || fail=1 # Test case 8: Compare symbolic links with different value and same target # contents. -returns_ 1 diff --no-dereference symlink2 symlink3 > out || fail=1 +LC_ALL=C returns_ 1 diff --no-dereference symlink2 symlink3 > out || fail=1 cat < expected || framework_failure_ -Symbolic links symlink2 and symlink3 differ +Symbolic links 'symlink2' -> 'regular2' and 'symlink3' -> 'regular3' differ EOF compare expected out || fail=1 @@ -134,9 +134,9 @@ mkdir subdir7a mkdir subdir7b ln -s ../regular1 subdir7a/foo ln -s ../regular2 subdir7b/foo -returns_ 1 diff -r --no-dereference subdir7a subdir7b > out || fail=1 +LC_ALL=C returns_ 1 diff -r --no-dereference subdir7a subdir7b > out || fail=1 cat < expected || framework_failure_ -Symbolic links subdir7a/foo and subdir7b/foo differ +Symbolic links 'subdir7a/foo' -> '../regular1' and 'subdir7b/foo' -> '../regular2' differ EOF compare expected out || fail=1 @@ -146,9 +146,9 @@ mkdir subdir8a mkdir subdir8b ln -s ../regular2 subdir8a/foo ln -s ../regular3 subdir8b/foo -returns_ 1 diff -r --no-dereference subdir8a subdir8b > out || fail=1 +LC_ALL=C returns_ 1 diff -r --no-dereference subdir8a subdir8b > out || fail=1 cat < expected || framework_failure_ -Symbolic links subdir8a/foo and subdir8b/foo differ +Symbolic links 'subdir8a/foo' -> '../regular2' and 'subdir8b/foo' -> '../regular3' differ EOF compare expected out || fail=1