Page MenuHomeFreeBSD

D34203.diff
No OneTemporary

D34203.diff

diff --git a/usr.bin/diff/diff.h b/usr.bin/diff/diff.h
--- a/usr.bin/diff/diff.h
+++ b/usr.bin/diff/diff.h
@@ -101,7 +101,7 @@
};
extern bool lflag, Nflag, Pflag, rflag, sflag, Tflag, cflag;
-extern bool ignore_file_case, suppress_common, color;
+extern bool ignore_file_case, suppress_common, color, noderef;
extern int diff_format, diff_context, status;
extern int tabsize, width;
extern char *start, *ifdefname, *diffargs, *label[2];
diff --git a/usr.bin/diff/diff.c b/usr.bin/diff/diff.c
--- a/usr.bin/diff/diff.c
+++ b/usr.bin/diff/diff.c
@@ -39,7 +39,7 @@
#include "xmalloc.h"
bool lflag, Nflag, Pflag, rflag, sflag, Tflag, cflag;
-bool ignore_file_case, suppress_common, color;
+bool ignore_file_case, suppress_common, color, noderef;
int diff_format, diff_context, status;
int tabsize = 8, width = 130;
static int colorflag = COLORFLAG_NEVER;
@@ -62,6 +62,7 @@
OPT_CHANGED_GROUP_FORMAT,
OPT_SUPPRESS_COMMON,
OPT_COLOR,
+ OPT_NO_DEREFERENCE,
};
static struct option longopts[] = {
@@ -97,6 +98,7 @@
{ "side-by-side", no_argument, NULL, 'y' },
{ "ignore-file-name-case", no_argument, NULL, OPT_IGN_FN_CASE },
{ "horizon-lines", required_argument, NULL, OPT_HORIZON_LINES },
+ { "no-dereference", no_argument, NULL, OPT_NO_DEREFERENCE},
{ "no-ignore-file-name-case", no_argument, NULL, OPT_NO_IGN_FN_CASE },
{ "normal", no_argument, NULL, OPT_NORMAL },
{ "strip-trailing-cr", no_argument, NULL, OPT_STRIPCR },
@@ -328,6 +330,10 @@
errx(2, "unsupported --color value '%s' (must be always, auto, or never)",
optarg);
break;
+ case OPT_NO_DEREFERENCE:
+ rflag = true;
+ noderef = true;
+ break;
default:
usage();
break;
diff --git a/usr.bin/diff/diffdir.c b/usr.bin/diff/diffdir.c
--- a/usr.bin/diff/diffdir.c
+++ b/usr.bin/diff/diffdir.c
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <unistd.h>
#include "diff.h"
@@ -175,28 +176,87 @@
{
flags |= D_HEADER;
strlcpy(path1 + plen1, dp->d_name, PATH_MAX - plen1);
- if (stat(path1, &stb1) != 0) {
- if (!(Nflag || Pflag) || errno != ENOENT) {
- warn("%s", path1);
- return;
+ strlcpy(path2 + plen2, dp->d_name, PATH_MAX - plen2);
+
+ if (noderef) {
+ if (lstat(path1, &stb1) != 0) {
+ if (!(Nflag || Pflag) || errno != ENOENT) {
+ warn("%s", path1);
+ return;
+ }
+ flags |= D_EMPTY1;
+ memset(&stb1, 0, sizeof(stb1));
}
- flags |= D_EMPTY1;
- memset(&stb1, 0, sizeof(stb1));
- }
- strlcpy(path2 + plen2, dp->d_name, PATH_MAX - plen2);
- if (stat(path2, &stb2) != 0) {
- if (!Nflag || errno != ENOENT) {
- warn("%s", path2);
+ if (lstat(path2, &stb2) != 0) {
+ if (!Nflag || errno != ENOENT) {
+ warn("%s", path2);
+ return;
+ }
+ flags |= D_EMPTY2;
+ memset(&stb2, 0, sizeof(stb2));
+ stb2.st_mode = stb1.st_mode;
+ }
+ if (stb1.st_mode == 0)
+ stb1.st_mode = stb2.st_mode;
+ if (S_ISLNK(stb1.st_mode) || S_ISLNK(stb2.st_mode)) {
+ if (S_ISLNK(stb1.st_mode) && S_ISLNK(stb2.st_mode)) {
+ char buf1[PATH_MAX];
+ char buf2[PATH_MAX];
+ ssize_t len1 = 0;
+ ssize_t len2 = 0;
+
+ len1 = readlink(path1, buf1, sizeof(buf1));
+ len2 = readlink(path2, buf2, sizeof(buf2));
+
+ if (len1 < 0 || len2 < 0) {
+ perror("reading links");
+ return;
+ }
+ buf1[len1] = '\0';
+ buf2[len2] = '\0';
+
+ if (len1 != len2 || strncmp(buf1, buf2, len1) != 0) {
+ printf("Symbolic links %s and %s differ\n",
+ path1, path2);
+ status |= 1;
+ }
+
+ return;
+ }
+
+ printf("File %s is a %s while file %s is a %s\n",
+ path1, S_ISLNK(stb1.st_mode) ? "symbolic link" :
+ (S_ISDIR(stb1.st_mode) ? "directory" :
+ (S_ISREG(stb1.st_mode) ? "file" : "error")),
+ path2, S_ISLNK(stb2.st_mode) ? "symbolic link" :
+ (S_ISDIR(stb2.st_mode) ? "directory" :
+ (S_ISREG(stb2.st_mode) ? "file" : "error")));
+ status |= 1;
return;
}
- flags |= D_EMPTY2;
- memset(&stb2, 0, sizeof(stb2));
- stb2.st_mode = stb1.st_mode;
- }
- if (stb1.st_mode == 0)
- stb1.st_mode = stb2.st_mode;
+ } else {
+ if (stat(path1, &stb1) != 0) {
+ if (!(Nflag || Pflag) || errno != ENOENT) {
+ warn("%s", path1);
+ return;
+ }
+ flags |= D_EMPTY1;
+ memset(&stb1, 0, sizeof(stb1));
+ }
+ if (stat(path2, &stb2) != 0) {
+ if (!Nflag || errno != ENOENT) {
+ warn("%s", path2);
+ return;
+ }
+ flags |= D_EMPTY2;
+ memset(&stb2, 0, sizeof(stb2));
+ stb2.st_mode = stb1.st_mode;
+ }
+ if (stb1.st_mode == 0)
+ stb1.st_mode = stb2.st_mode;
+ }
if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) {
if (rflag)
diffdir(path1, path2, flags);
diff --git a/usr.bin/diff/tests/diff_test.sh b/usr.bin/diff/tests/diff_test.sh
--- a/usr.bin/diff/tests/diff_test.sh
+++ b/usr.bin/diff/tests/diff_test.sh
@@ -20,6 +20,7 @@
atf_test_case non_regular_file
atf_test_case binary
atf_test_case functionname
+atf_test_case noderef
simple_body()
{
@@ -296,6 +297,35 @@
"$(atf_get_srcdir)/functionname.in" "$(atf_get_srcdir)/functionname_objcclassm.in"
}
+noderef_body()
+{
+ atf_check mkdir A B
+
+ atf_check -x "echo 1 > A/test-file"
+ atf_check -x "echo 1 > test-file"
+ atf_check -x "echo 1 > test-file2"
+
+ atf_check ln -s $(pwd)/test-file B/test-file
+
+ atf_check -o empty -s exit:0 diff -r A B
+ atf_check -o inline:"File A/test-file is a file while file B/test-file is a symbolic link\n" \
+ -s exit:1 diff -r --no-dereference A B
+
+ # both test files are now the same symbolic link
+ atf_check rm A/test-file
+
+ atf_check ln -s $(pwd)/test-file A/test-file
+ atf_check -o empty -s exit:0 diff -r A B
+ atf_check -o empty -s exit:0 diff -r --no-dereference A B
+
+ # make test files different symbolic links, but same contents
+ atf_check unlink A/test-file
+ atf_check ln -s $(pwd)/test-file2 A/test-file
+
+ atf_check -o empty -s exit:0 diff -r A B
+ atf_check -o inline:"Symbolic links A/test-file and B/test-file differ\n" -s exit:1 diff -r --no-dereference A B
+}
+
atf_init_test_cases()
{
atf_add_test_case simple
@@ -318,4 +348,5 @@
atf_add_test_case non_regular_file
atf_add_test_case binary
atf_add_test_case functionname
+ atf_add_test_case noderef
}

File Metadata

Mime Type
text/plain
Expires
Sun, Aug 16, 1:48 AM (3 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36809554
Default Alt Text
D34203.diff (6 KB)

Event Timeline