mirror of
https://https.git.savannah.gnu.org/git/diffutils.git
synced 2026-01-27 01:44:20 +00:00
diff: output symlink contents when they differ
* bootstrap.conf (gnulib_modules): Add quote. * src/diff.c: Include quote.h. (compare_files): Print contents of symlinks that differ, and quote their names and contents. * src/system.h (symlink_size_ok): Remove. (stat_size): Don’t worry about symlink sizes. * tests/no-dereference: Adjust tests to match new behavior.
This commit is contained in:
parent
6f357cfa9f
commit
b684567824
5
NEWS
5
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.
|
||||
|
||||
@ -86,6 +86,7 @@ perl
|
||||
popen
|
||||
progname
|
||||
propername-lite
|
||||
quote
|
||||
raise
|
||||
rawmemchr
|
||||
readdir
|
||||
|
||||
61
src/diff.c
61
src/diff.c
@ -34,6 +34,7 @@
|
||||
#include <getopt.h>
|
||||
#include <hard-locale.h>
|
||||
#include <progname.h>
|
||||
#include <quote.h>
|
||||
#include <sh-quote.h>
|
||||
#include <stat-time.h>
|
||||
#include <version-etc.h>
|
||||
@ -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
|
||||
|
||||
@ -114,7 +114,7 @@
|
||||
SYSTEM_EXTERN dev_t proc_dev;
|
||||
#endif
|
||||
|
||||
#if defined __linux__ || defined __ANDROID__
|
||||
#if false && (defined __linux__ || defined __ANDROID__)
|
||||
# include <sys/utsname.h>
|
||||
/* 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)
|
||||
|
||||
@ -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 <<EOF > 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 <<EOF > 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 <<EOF > 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 <<EOF > 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
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user