diff -urp diffutils-3.5/lib/fnmatch.c diffutils-3-5/lib/fnmatch.c --- diffutils-3.5/lib/fnmatch.c 2016-08-05 09:38:16 +1000 +++ diffutils-3-5/lib/fnmatch.c 2017-01-07 16:14:02 +1000 @@ -30,12 +30,10 @@ #include #include -#include #include #include #include #include -#include #define WIDE_CHAR_SUPPORT \ (HAVE_WCTYPE_H && HAVE_BTOWC && HAVE_ISWCTYPE \ @@ -48,6 +46,9 @@ # include #endif +#include +#include + /* We need some of the locale data (the collation sequence information) but there is no interface to get this information in general. Therefore we support a correct implementation only in glibc. */ diff -urp diffutils-3.5/lib/fstat.c diffutils-3-5/lib/fstat.c --- diffutils-3.5/lib/fstat.c 2016-08-05 09:37:51 +1000 +++ diffutils-3-5/lib/fstat.c 2017-01-06 12:43:00 +1000 @@ -30,11 +30,38 @@ # define fstat _fstati64 #endif #undef __need_system_sys_stat_h +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +# include +# include +#endif static int orig_fstat (int fd, struct stat *buf) { - return fstat (fd, buf); + int result = fstat (fd, buf); +#ifdef WIN32_LEAN_AND_MEAN + if (result == 0) + { + BY_HANDLE_FILE_INFORMATION fi; + if (GetFileInformationByHandle ((HANDLE) _get_osfhandle (fd), &fi)) + { + buf->st_ino = LOWORD (fi.dwVolumeSerialNumber); + buf->st_dev = (HIWORD (fi.nFileIndexHigh) << 24) + | (fi.nFileIndexLow & 0xFFFFFF); + } + else if (fd == STDOUT_FILENO && S_ISCHR (buf->st_mode)) + { + /* Use GetConsoleMode to distinguish between console and device (and + assume NUL if it is a device). */ + DWORD mode; + if (!GetConsoleMode (GetStdHandle (STD_OUTPUT_HANDLE), &mode)) + buf->st_dev = 0x4E554C4C/*'NULL'*/; + } + } +#endif + return result; } /* Specification. */ diff -urp diffutils-3.5/lib/regex_internal.h diffutils-3-5/lib/regex_internal.h --- diffutils-3.5/lib/regex_internal.h 2016-08-05 09:38:16 +1000 +++ diffutils-3-5/lib/regex_internal.h 2017-01-09 12:51:02 +1000 @@ -21,7 +21,6 @@ #define _REGEX_INTERNAL_H 1 #include -#include #include #include #include @@ -30,6 +29,7 @@ #include #include #include +#include #include #include diff -urp diffutils-3.5/lib/stat.c diffutils-3-5/lib/stat.c --- diffutils-3.5/lib/stat.c 2016-08-05 09:37:51 +1000 +++ diffutils-3-5/lib/stat.c 2017-01-06 12:43:00 +1000 @@ -28,6 +28,8 @@ #undef __need_system_sys_stat_h #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include # if _GL_WINDOWS_64_BIT_ST_SIZE # undef stat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */ # define stat _stati64 @@ -134,5 +136,36 @@ rpl_stat (char const *name, struct stat } } #endif /* REPLACE_FUNC_STAT_DIR */ +#ifdef WIN32_LEAN_AND_MEAN + if (result == 0) + { + /* Under Windows, st_dev (32 bits) is the drive number & st_ino (16 bits) + is always 0. The handle file information contains a 32-bit volume + serial number (i.e. a device id) with a 64-bit file index (unique file + id). Since the two st values are always tested together, put the + lower 16 bits of the serial into st_ino and combine the index values + into st_dev (brief testing shows the low word of the high index and + the high three digits of the low index are likely 0). */ + BY_HANDLE_FILE_INFORMATION fi; + HANDLE h = CreateFile (name, 0, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if (h != INVALID_HANDLE_VALUE) + { + if (GetFileInformationByHandle (h, &fi)) + { + st->st_ino = LOWORD (fi.dwVolumeSerialNumber); + st->st_dev = (HIWORD (fi.nFileIndexHigh) << 24) + | (fi.nFileIndexLow & 0xFFFFFF); + } + else if (strcmp (name, "nul"/*NULL_DEVICE*/) == 0) + /* Special case for NUL, + so the comparison with stdout in cmp works. */ + st->st_dev = 0x4E554C4C/*'NULL'*/; + CloseHandle (h); + } + } +#endif return result; } diff -urp diffutils-3.5/lib/strftime.c diffutils-3-5/lib/strftime.c --- diffutils-3.5/lib/strftime.c 2016-08-05 09:37:51 +1000 +++ diffutils-3-5/lib/strftime.c 2017-01-08 16:53:01 +1000 @@ -1357,7 +1357,14 @@ strftime_case_ (bool upcase, STREAM_OR_C diff = tp->tm_gmtoff; #else if (!tz) - diff = 0; + { +#ifdef _WIN32 + tzset(); + diff = - _timezone; +#else + diff = 0; +#endif + } else { struct tm gtm; diff -urp diffutils-3.5/lib/time.in.h diffutils-3-5/lib/time.in.h --- diffutils-3.5/lib/time.in.h 2016-08-05 09:38:16 +1000 +++ diffutils-3-5/lib/time.in.h 2017-01-08 18:22:09 +1000 @@ -37,6 +37,10 @@ # define _@GUARD_PREFIX@_TIME_H +# ifdef __MINGW32__ +# include +# endif + # @INCLUDE_NEXT@ @NEXT_TIME_H@ /* NetBSD 5.0 mis-defines NULL. */ diff -urp diffutils-3.5/lib/wchar.in.h diffutils-3-5/lib/wchar.in.h --- diffutils-3.5/lib/wchar.in.h 2016-08-05 09:38:16 +1000 +++ diffutils-3-5/lib/wchar.in.h 2017-01-09 12:50:29 +1000 @@ -80,7 +80,13 @@ Some builds of uClibc lack it. */ /* The include_next requires a split double-inclusion guard. */ #if @HAVE_WCHAR_H@ +# ifdef __STRING_H_SOURCED__ +# undef __STRING_H_SOURCED__ +# include_next +# define __STRING_H_SOURCED__ +# else # @INCLUDE_NEXT@ @NEXT_WCHAR_H@ +# endif #endif #undef _GL_ALREADY_INCLUDING_WCHAR_H diff -urp diffutils-3.5/lib/wctype.in.h diffutils-3-5/lib/wctype.in.h --- diffutils-3.5/lib/wctype.in.h 2016-08-05 09:38:16 +1000 +++ diffutils-3-5/lib/wctype.in.h 2017-01-08 18:35:29 +1000 @@ -41,8 +41,10 @@ # include # include # include +#ifndef __MINGW32__ # include #endif +#endif /* mingw has declarations of towupper and towlower in as well . Include in advance to avoid rpl_ prefix diff -urp diffutils-3.5/man/diff.1 diffutils-3-5/man/diff.1 --- diffutils-3.5/man/diff.1 2016-08-21 15:22:04 +1000 +++ diffutils-3-5/man/diff.1 2017-01-08 18:52:50 +1000 @@ -130,6 +130,9 @@ treat all files as text \fB\-\-strip\-trailing\-cr\fR strip trailing carriage return on input .TP +\fB\-\-binary\fR +read and write data in binary mode +.TP \fB\-D\fR, \fB\-\-ifdef\fR=\fINAME\fR output merged file with '#ifdef NAME' diffs .TP diff -urp diffutils-3.5/man/help2man diffutils-3-5/man/help2man --- diffutils-3.5/man/help2man 2016-08-05 09:37:45 +1000 +++ diffutils-3-5/man/help2man 2017-01-08 18:10:00 +1000 @@ -634,7 +634,7 @@ exit; sub get_option_value { my ($prog, $opt) = @_; - my $stderr = $discard_stderr ? '/dev/null' : '&1'; + my $stderr = $discard_stderr ? 'nul' : '&1'; my $value = join '', map { s/ +$//; expand $_ } map { dec $_ } diff -urp diffutils-3.5/src/diff.c diffutils-3-5/src/diff.c --- diffutils-3.5/src/diff.c 2016-08-09 11:50:37 +1000 +++ diffutils-3-5/src/diff.c 2017-01-09 11:40:45 +1000 @@ -89,6 +89,14 @@ static struct regexp_list ignore_regexp_ /* Use binary I/O when reading and writing data (--binary). On POSIX hosts, this has no effect. */ static bool binary; +# define BS_TO_SLASH(s) \ + do \ + { \ + char *p = (char *) s; \ + while ((p = strchr (p, '\\'))) \ + *p = '/'; \ + } \ + while (0) #else enum { binary = true }; #endif @@ -296,6 +304,10 @@ main (int argc, char **argv) re_set_syntax (RE_SYNTAX_GREP | RE_NO_POSIX_BACKTRACKING); excluded = new_exclude (); +#if O_BINARY + ignore_file_name_case = true; +#endif + /* Decode the options. */ while ((c = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1) @@ -764,6 +776,15 @@ main (int argc, char **argv) switch_string = option_list (argv + 1, optind - 1); +#if O_BINARY + if (from_file) + BS_TO_SLASH (from_file); + if (to_file) + BS_TO_SLASH (to_file); + for (i = optind; i < argc; i++) + BS_TO_SLASH (argv[i]); +#endif + if (from_file) { if (to_file) diff -urp diffutils-3.5/src/io.c diffutils-3-5/src/io.c --- diffutils-3.5/src/io.c 2016-08-05 09:37:45 +1000 +++ diffutils-3-5/src/io.c 2017-01-06 12:43:00 +1000 @@ -121,6 +121,31 @@ sip (struct file_data *current, bool ski int prev_mode = set_binary_mode (current->desc, O_BINARY); off_t buffered; +#if defined _WIN32 || defined __WIN32__ + /* Can't seek the console or a pipe, so read up to the first CR. */ + if (prev_mode != O_BINARY && ! S_ISREG (current->stat.st_mode)) + { + char *b = FILE_BUFFER (current); + current->buffered = 0; + current->eof = false; + for (buffered = current->bufsize; buffered != 0; --buffered) + { + if (read (current->desc, b + current->buffered, 1) != 1) + { + current->eof = true; + break; + } + if (b[current->buffered++] == '\r') + break; + } + set_binary_mode (current->desc, prev_mode); + if (binary_file_p (current->buffer, current->buffered)) + return true; + if (b[current->buffered - 1] == '\r') + --current->buffered; + return false; + } +#endif file_block_read (current, current->bufsize); buffered = current->buffered; diff -urp diffutils-3.5/src/sdiff.c diffutils-3-5/src/sdiff.c --- diffutils-3.5/src/sdiff.c 2016-08-05 09:37:45 +1000 +++ diffutils-3-5/src/sdiff.c 2017-01-07 17:34:25 +1000 @@ -577,7 +577,16 @@ main (int argc, char *argv[]) diffarg (argv[optind]); diffarg (argv[optind + 1]); diffarg (0); +#ifdef __MINGW32__ + { + char *command = system_quote_argv (SCI_SYSTEM, (char **) diffargv); + int rc = system (command); + if (rc >= 0) + exit (rc); + } +#else execvp (diffargv[0], (char **) diffargv); +#endif perror_fatal (diffargv[0]); } else @@ -805,7 +814,11 @@ checksigs (void) /* Yield an exit status indicating that a signal was received. */ untrapsig (s); +#if HAVE_RAISE + raise (s); +#else kill (getpid (), s); +#endif /* That didn't work, so exit with error status. */ exit (EXIT_TROUBLE); @@ -1152,7 +1165,11 @@ diraccess (char const *dir) # define P_tmpdir "/tmp" #endif #ifndef TMPDIR_ENV -# define TMPDIR_ENV "TMPDIR" +# ifdef _WIN32 +# define TMPDIR_ENV "TMP" +# else +# define TMPDIR_ENV "TMPDIR" +# endif #endif /* Open a temporary file and return its file descriptor. Put into diff -urp diffutils-3.5/src/system.h diffutils-3-5/src/system.h --- diffutils-3.5/src/system.h 2016-08-05 09:37:45 +1000 +++ diffutils-3-5/src/system.h 2017-01-06 12:43:00 +1000 @@ -145,7 +145,11 @@ verify (sizeof (lin) <= sizeof (long int that are meant to be overridden by hand in config.h as needed. */ #ifndef file_name_cmp -# define file_name_cmp strcmp +# if O_BINARY +# define file_name_cmp _stricmp +# else +# define file_name_cmp strcmp +# endif #endif #ifndef initialize_main @@ -153,7 +157,11 @@ verify (sizeof (lin) <= sizeof (long int #endif #ifndef NULL_DEVICE -# define NULL_DEVICE "/dev/null" +# if O_BINARY +# define NULL_DEVICE "nul" +#else +# define NULL_DEVICE "/dev/null" +# endif #endif /* Do struct stat *S, *T describe the same special file? */ diff -urp diffutils-3.5/src/util.c diffutils-3-5/src/util.c --- diffutils-3.5/src/util.c 2016-08-18 06:37:55 +1000 +++ diffutils-3-5/src/util.c 2017-01-09 12:05:39 +1000 @@ -224,7 +224,9 @@ process_signals (void) if (stops) { stop_signal_count = stops - 1; +#ifdef SIGSTOP sig = SIGSTOP; +#endif } else signal (sig, SIG_DFL); @@ -245,10 +247,24 @@ install_signal_handlers (void) static int const sig[] = { /* This one is handled specially. */ +#ifdef SIGTSTP SIGTSTP, +#endif /* The usual suspects. */ - SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT, SIGTERM, + SIGINT, SIGTERM, +#ifdef SIGALRM + SIGALRM, +#endif +#ifdef SIGHUP + SIGHUP, +#endif +#ifdef SIGPIPE + SIGPIPE, +#endif +#ifdef SIGQUIT + SIGQUIT, +#endif #ifdef SIGPOLL SIGPOLL, #endif @@ -298,7 +314,11 @@ install_signal_handlers (void) caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN); if (caught_sig[j]) { +#ifdef SIGTSTP signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler); +#else + signal (sig[j], sighandler); +#endif siginterrupt (sig[j], 0); } } @@ -310,6 +330,11 @@ static char const *current_name0; static char const *current_name1; static bool currently_recursive; static bool colors_enabled; +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +static HANDLE hOut; +#endif static struct color_ext_type *color_ext_list = NULL; @@ -317,6 +342,9 @@ struct bin_str { size_t len; /* Number of bytes */ const char *string; /* Pointer to the same */ +#ifdef _WIN32 + WORD attr; /* Console text attribute */ +#endif }; struct color_ext_type @@ -702,6 +730,115 @@ parse_diff_color (void) } } +#ifdef _WIN32 +static const int bgr_to_rgb[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + +static void +ansi_to_attr (struct bin_str *ind) +{ + int len = ind->len; + const char *s = ind->string; + WORD attr = color_indicator[3].attr; /* C_RESET */ + int num = 0; + bool reverse = false; + + while (len--) + { + if (*s >= '0' && *s <= '9') + num = num * 10 + *s - '0'; + if (*s == ';' || len == 0) + { + switch (num) + { + case 0: + attr = color_indicator[3].attr; + if (len != 0) + attr &= ~0x8808; /* turn off bright & underline */ + break; + case 1: + attr |= 0x08; /* bold = bright fg */ + break; + case 4: + attr |= 0x8000; /* underline (Win10 or DBCS) */ + break; + case 5: + attr |= 0x80; /* blink = bright bg */ + break; + case 7: + reverse = true; + break; + case 22: + attr &= ~0x08; + break; + case 24: + attr &= ~0x8000; + break; + case 25: + attr &= ~0x80; + break; + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + attr = (attr & ~0x07) | bgr_to_rgb[num - 30]; + break; + case 39: + attr = (attr & ~0x07) | (color_indicator[3].attr & 0x07); + break; + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + attr = (attr & ~0x70) | (bgr_to_rgb[num - 40] << 4); + break; + case 49: + attr = (attr & ~0x70) | (color_indicator[3].attr & 0x70); + break; + case 90: + case 91: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + attr = (attr & ~0x0F) | bgr_to_rgb[num - 90] | 8; + break; + case 99: + attr = (attr & ~0x0F) | (color_indicator[3].attr & 0x07) | 8; + break; + case 100: + case 101: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + attr = (attr & ~0xF0) | (bgr_to_rgb[num - 100] << 4) | 0x80; + break; + case 109: + attr = (attr & ~0xF0) | (color_indicator[3].attr & 0x70) | 0x80; + break; + } + num = 0; + } + s++; + } + if (reverse) + attr = (attr & ~0xFF) | ((attr & 0x0F) << 4) | ((attr & 0xF0) >> 4); + ind->attr = attr; +} +#endif + static void check_color_output (bool is_pipe) { @@ -718,6 +855,38 @@ check_color_output (bool is_pipe) if (colors_enabled) parse_diff_color (); +#ifdef _WIN32 + if (colors_enabled && output_is_tty) + { + CONSOLE_SCREEN_BUFFER_INFO csbi; + csbi.wAttributes = 0; + hOut = (HANDLE) _get_osfhandle (fileno (outfile)); + if (!GetConsoleScreenBufferInfo (hOut, &csbi)) + { + HANDLE hCon = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, + NULL); + GetConsoleScreenBufferInfo (hCon, &csbi); + CloseHandle (hCon); + } + if (csbi.wAttributes == 0) + { + if (colors_style == ALWAYS) + hOut = NULL; + else + colors_enabled = false; + } + else + { + int ind_no; + color_indicator[3].attr = csbi.wAttributes; /* C_RESET */ + /* C_HEADER, C_ADD, C_DELETE, C_LINE */ + for (ind_no = 4; indicator_name[ind_no] != NULL; ++ind_no) + ansi_to_attr (&color_indicator[ind_no]); + } + } +#endif + if (output_is_tty) install_signal_handlers (); } @@ -1341,6 +1510,14 @@ enum indicator_no static void put_indicator (const struct bin_str *ind) { +#ifdef _WIN32 + if (hOut != NULL) + { + if (ind != &color_indicator[C_LEFT] && ind != &color_indicator[C_RIGHT]) + SetConsoleTextAttribute (hOut, ind->attr); + } + else +#endif fwrite (ind->string, ind->len, 1, outfile); } diff -urp diffutils-3.5/tests/binary diffutils-3-5/tests/binary --- diffutils-3.5/tests/binary 2014-09-04 14:29:30 +1000 +++ diffutils-3-5/tests/binary 2017-01-06 12:43:00 +1000 @@ -3,7 +3,7 @@ . "${srcdir=.}/init.sh"; path_prepend_ ../src -printf 'Binary files - and /dev/null differ\n' > out-exp || fail_ setup +printf 'Binary files - and nul differ\n' > out-exp || fail_ setup fail=0 diff -urp diffutils-3.5/tests/colors diffutils-3-5/tests/colors --- diffutils-3.5/tests/colors 2016-08-09 11:49:40 +1000 +++ diffutils-3-5/tests/colors 2017-01-08 15:43:29 +1000 @@ -77,6 +77,12 @@ $ad> b$rs " } +strip_date_time() +{ + sed -e 's/^\(\(\[[0-9;]*m\)\?[-+*][-+*][-+*] [^ ]*\) .*/\1/' exp > k; mv k exp + sed -e 's/^\(\(\[[0-9;]*m\)\?[-+*][-+*][-+*] [^ ]*\) .*/\1/' out > k; mv k out +} + # Compare with some known outputs rs=0 hd=1 ad=32 de=31 ln=36 @@ -109,26 +115,30 @@ compare exp out || fail=1 diff -u --color=always a b > out test $? = 1 || fail=1 gen_exp_u > exp || framework_failure_ +strip_date_time compare exp out || fail=1 diff -c --color=always a b > out test $? = 1 || fail=1 gen_exp_c > exp || framework_failure_ +strip_date_time compare exp out || fail=1 rs=0 hd=33 ad=34 de=35 ln=36 diff -u --color=always --palette="rs=0:hd=33:ad=34:de=35:ln=36" a b > out test $? = 1 || fail=1 gen_exp_u > exp || framework_failure_ +strip_date_time compare exp out || fail=1 # Before the fix in http://debbugs.gnu.org/22067, # this test would trigger an infinite loop bug. -mkfifo fifo +mkfifo fifo && ( printf '%*s-a' 1000000 > a printf '%*s-b' 1000000 > b head -c 10 < fifo > /dev/null & diff --color=always ---presume-output-tty a b > fifo test $? = 141 || fail=1 +) Exit $fail diff -urp diffutils-3.5/tests/filename-quoting diffutils-3-5/tests/filename-quoting --- diffutils-3.5/tests/filename-quoting 2014-09-04 14:29:30 +1000 +++ diffutils-3-5/tests/filename-quoting 2017-01-06 12:43:00 +1000 @@ -6,23 +6,23 @@ fail=0 cat < exp- || fail=1 -diff -N -r "a/ " "b/ " +diff -N -r "a/ !" "b/ !" 0a1 > space EOF cat < exp--u || fail=1 -diff -N -r -u "a/ " "b/ " ---- "a/ " -+++ "b/ " +diff -N -r -u "a/ !" "b/ !" +--- "a/ !" ++++ "b/ !" @@ -0,0 +1 @@ +space EOF cat < exp--c || fail=1 -diff -N -r -c "a/ " "b/ " -*** "a/ " ---- "b/ " +diff -N -r -c "a/ !" "b/ !" +*** "a/ !" +--- "b/ !" *************** *** 0 **** --- 1 ---- @@ -30,7 +30,7 @@ diff -N -r -c "a/ " "b/ " EOF mkdir a b -echo space > "b/ " || fail=1 +echo space > "b/ !" || fail=1 for opt in '' -u -c; do diff -N -r $opt a b > out 2> err; test $? = 1 || fail=1 # Remove date and time. @@ -38,18 +38,18 @@ for opt in '' -u -c; do compare exp-$(echo $opt|tr ' ' _) out || fail=1 done -rm -f "b/ " +rm -f "b/ !" cat < exp || fail=1 ---- "a/\t" -+++ "b/\001" +--- "a/\377" ++++ "b/\200" @@ -1 +1 @@ -tab +one EOF -tab=$(printf '\t') -x01=$(printf '\001') +tab=$(printf '\377') +x01=$(printf '\200') echo tab > "a/$tab" || fail=1 echo one > "b/$x01" || fail=1 diff -urp diffutils-3.5/tests/Makefile.am diffutils-3-5/tests/Makefile.am --- diffutils-3.5/tests/Makefile.am 2016-08-15 10:09:36 +1000 +++ diffutils-3-5/tests/Makefile.am 2017-01-06 12:43:00 +1000 @@ -20,6 +20,9 @@ TESTS = \ filename-quoting \ colors +XFAIL_TESTS = \ + no-dereference + EXTRA_DIST = \ $(TESTS) init.sh t-local.sh envvar-check diff -urp diffutils-3.5/tests/Makefile.in diffutils-3-5/tests/Makefile.in --- diffutils-3.5/tests/Makefile.in 2016-08-21 15:18:38 +1000 +++ diffutils-3-5/tests/Makefile.in 2017-01-06 12:43:00 +1000 @@ -1371,6 +1371,9 @@ TESTS = \ filename-quoting \ colors +XFAIL_TESTS = \ + no-dereference + EXTRA_DIST = \ $(TESTS) init.sh t-local.sh envvar-check