diff -urNp patch-2.7.5/lib/backupfile.c patch-2.7-5/lib/backupfile.c --- patch-2.7.5/lib/backupfile.c 2015-01-30 04:19:27 +1000 +++ patch-2.7-5/lib/backupfile.c 2015-07-10 16:17:15 +1000 @@ -39,7 +39,8 @@ #ifndef _D_EXACT_NAMLEN # define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name) #endif -#if D_INO_IN_DIRENT +#if D_INO_IN_DIRENT \ + && ((! defined _WIN32 && ! defined __WIN32__) || defined __CYGWIN__) # define REAL_DIR_ENTRY(dp) ((dp)->d_ino != 0) #else # define REAL_DIR_ENTRY(dp) 1 diff -urNp patch-2.7.5/lib/euidaccess.c patch-2.7-5/lib/euidaccess.c --- patch-2.7.5/lib/euidaccess.c 2015-01-30 04:19:27 +1000 +++ patch-2.7-5/lib/euidaccess.c 2015-07-10 17:23:46 +1000 @@ -84,7 +84,9 @@ euidaccess (const char *file, int mode) return accessx (file, mode, ACC_SELF); #elif HAVE_EACCESS /* FreeBSD */ return eaccess (file, mode); -#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, mingw, BeOS */ +#elif defined __MINGW32__ + return access (file, mode); +#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, BeOS */ uid_t uid = getuid (); gid_t gid = getgid (); diff -urNp patch-2.7.5/lib/fstat.c patch-2.7-5/lib/fstat.c --- patch-2.7.5/lib/fstat.c 2015-01-30 04:19:27 +1000 +++ patch-2.7-5/lib/fstat.c 2015-07-10 22:03:54 +1000 @@ -30,11 +30,29 @@ # define fstat _fstati64 #endif #undef __need_system_sys_stat_h +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# 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); + } + } +#endif + return result; } /* Specification. */ diff -urNp patch-2.7.5/lib/rename.c patch-2.7-5/lib/rename.c --- patch-2.7.5/lib/rename.c 2015-01-30 04:19:27 +1000 +++ patch-2.7-5/lib/rename.c 2015-07-10 16:17:15 +1000 @@ -183,6 +183,9 @@ rpl_rename (char const *src, char const error = GetLastError (); if (error == ERROR_FILE_EXISTS || error == ERROR_ALREADY_EXISTS) { + /* Remove a possible read-only attribute. */ + SetFileAttributes (dst, FILE_ATTRIBUTE_NORMAL); + if (MoveFileEx (src, dst, MOVEFILE_REPLACE_EXISTING)) return 0; diff -urNp patch-2.7.5/lib/stat.c patch-2.7-5/lib/stat.c --- patch-2.7.5/lib/stat.c 2015-01-30 04:19:27 +1000 +++ patch-2.7-5/lib/stat.c 2015-07-10 21:41:48 +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,32 @@ rpl_stat (char const *name, struct stat } } #endif /* REPLACE_FUNC_STAT_DIR */ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + 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); + } + CloseHandle (h); + } + } +#endif return result; } diff -urNp patch-2.7.5/patch.man patch-2.7-5/patch.man --- patch-2.7.5/patch.man 2014-11-26 23:17:55 +1000 +++ patch-2.7-5/patch.man 2015-07-10 16:17:15 +1000 @@ -552,7 +552,7 @@ You can specify the default value of the option with the environment variable .BR QUOTING_STYLE . If that environment variable is not set, the default value is -.BR shell . +.BR literal . .RE .TP \fB\-r\fP \fIrejectfile\fP or \fB\*=reject\-file=\fP\fIrejectfile\fP diff -urNp patch-2.7.5/src/common.h patch-2.7-5/src/common.h --- patch-2.7.5/src/common.h 2015-03-01 02:02:30 +1000 +++ patch-2.7-5/src/common.h 2015-07-10 16:17:15 +1000 @@ -183,14 +183,24 @@ extern int errno; /* Disable the CR stripping heuristic? */ XTERN bool no_strip_trailing_cr; +XTERN bool patch_is_crlf; +XTERN int input_is_lf; /* O_BINARY if so */ #ifndef NULL_DEVICE +#ifdef HAVE_SETMODE_DOS +#define NULL_DEVICE "nul" +#else #define NULL_DEVICE "/dev/null" #endif +#endif #ifndef TTY_DEVICE +#ifdef HAVE_SETMODE_DOS +#define TTY_DEVICE "con" +#else #define TTY_DEVICE "/dev/tty" #endif +#endif /* Output stream state. */ struct outstate diff -urNp patch-2.7.5/src/inp.c patch-2.7-5/src/inp.c --- patch-2.7.5/src/inp.c 2015-03-07 10:34:20 +1000 +++ patch-2.7-5/src/inp.c 2015-07-10 16:21:33 +1000 @@ -81,6 +81,7 @@ re_input (void) void scan_input (char *filename, mode_t file_type) { + input_is_lf = O_BINARY; using_plan_a = ! (debug & 16) && plan_a (filename); if (!using_plan_a) { @@ -91,6 +92,8 @@ scan_input (char *filename, mode_t file_ } plan_b(filename); } + if (instat.st_size == 0 && patch_is_crlf) + input_is_lf = 0; } /* Report whether a desired revision was found. */ @@ -219,7 +222,7 @@ get_input_file (char const *filename, ch static bool plan_a (char const *filename) { - char const *s; + char *s; char const *lim; char const **ptr; char *buffer; @@ -238,7 +241,7 @@ plan_a (char const *filename) { if (S_ISREG (instat.st_mode)) { - int ifd = safe_open (filename, O_RDONLY|binary_transput, 0); + int ifd = safe_open (filename, O_RDONLY|O_BINARY, 0); size_t buffered = 0, n; if (ifd < 0) pfatal ("can't open file %s", quotearg (filename)); @@ -300,8 +303,14 @@ plan_a (char const *filename) ptr[++iline] = s; if (! (s = (char *) memchr (s, '\n', lim - s))) break; + if (! binary_transput && s != buffer && s[-1] == '\r') + { + s[-1] = '\n'; + *s = '\r'; + input_is_lf = 0; + } } - if (size && lim[-1] != '\n') + if (size && lim[-1] != '\n' && (input_is_lf || lim[-1] != '\r')) ptr[++iline] = lim; input_lines = iline - 1; @@ -342,7 +351,7 @@ plan_b (char const *filename) { int ifd; FILE *ifp; - int c; + int c, cp; size_t len; size_t maxlen; bool found_revision; @@ -353,8 +362,8 @@ plan_b (char const *filename) if (instat.st_size == 0) filename = NULL_DEVICE; - if ((ifd = safe_open (filename, O_RDONLY | binary_transput, 0)) < 0 - || ! (ifp = fdopen (ifd, binary_transput ? "rb" : "r"))) + if ((ifd = safe_open (filename, O_RDONLY | O_BINARY, 0)) < 0 + || ! (ifp = fdopen (ifd, "rb"))) pfatal ("Can't open file %s", quotearg (filename)); if (TMPINNAME_needs_removal) { @@ -375,6 +384,7 @@ plan_b (char const *filename) rev = revision; found_revision = !rev; revlen = rev ? strlen (rev) : 0; + cp = EOF; while ((c = getc (ifp)) != EOF) { @@ -388,7 +398,10 @@ plan_b (char const *filename) if (maxlen < len) maxlen = len; len = 0; + if (! binary_transput && cp == '\r') + input_is_lf = 0; } + cp = c; if (!found_revision) { @@ -468,7 +481,8 @@ ifetch (lin line, bool whichbuf, size_t if (using_plan_a) { p = i_ptr[line]; *psize = i_ptr[line + 1] - p; - return p; + if (! input_is_lf && *psize >= 2 && p[*psize - 1] == '\r') + --*psize; } else { lin offline = line % lines_per_buf; lin baseline = line - offline; @@ -492,6 +506,8 @@ ifetch (lin line, bool whichbuf, size_t /* do nothing */ ; *psize = q - p; } - return p; + if (! input_is_lf && *psize >= 2 && p[*psize - 2] == '\r') + ((char *)p)[--*psize - 1] = '\n'; } + return p; } diff -urNp patch-2.7.5/src/Makefile.in patch-2.7-5/src/Makefile.in --- patch-2.7.5/src/Makefile.in 2015-03-07 10:34:34 +1000 +++ patch-2.7-5/src/Makefile.in 2015-07-10 16:24:19 +1000 @@ -189,11 +189,11 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) -am__patch_SOURCES_DIST = bestmatch.h common.h inp.c inp.h patch.c \ +am__patch_SOURCES_DIST = bestmatch.h common.h inp.c inp.h patch.c patchres.rc \ pch.c pch.h safe.c safe.h util.c util.h version.c version.h \ list.h merge.c @ENABLE_MERGE_TRUE@am__objects_1 = merge.$(OBJEXT) -am_patch_OBJECTS = inp.$(OBJEXT) patch.$(OBJEXT) pch.$(OBJEXT) \ +am_patch_OBJECTS = inp.$(OBJEXT) patch.$(OBJEXT) patchres.$(OBJEXT) pch.$(OBJEXT) \ safe.$(OBJEXT) util.$(OBJEXT) version.$(OBJEXT) \ $(am__objects_1) patch_OBJECTS = $(am_patch_OBJECTS) @@ -1062,7 +1062,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS) -patch_SOURCES = bestmatch.h common.h inp.c inp.h patch.c pch.c pch.h \ +patch_SOURCES = bestmatch.h common.h inp.c inp.h patch.c patch.rc pch.c pch.h \ safe.c safe.h util.c util.h version.c version.h list.h \ $(am__append_1) AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib \ @@ -1073,7 +1073,7 @@ patch_LDADD = $(LDADD) $(top_builddir)/l all: all-am .SUFFIXES: -.SUFFIXES: .c .o .obj +.SUFFIXES: .c .rc .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -1179,6 +1179,10 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +comma = , +.rc.o: + windres -I$(top_builddir) -DPVERB=$(subst .,$(comma),$(PACKAGE_VERSION)),0 $< $@ + ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am diff -urNp patch-2.7.5/src/patch.c patch-2.7-5/src/patch.c --- patch-2.7.5/src/patch.c 2015-03-07 10:34:20 +1000 +++ patch-2.7-5/src/patch.c 2015-07-10 17:58:51 +1000 @@ -136,7 +136,10 @@ main (int argc, char **argv) { int i = val ? argmatch (val, quoting_style_args, 0, 0) : -1; set_quoting_style ((struct quoting_options *) 0, - i < 0 ? shell_quoting_style : (enum quoting_style) i); + i < 0 + ? (O_BINARY + ? literal_quoting_style : shell_quoting_style) + : (enum quoting_style) i); } posixly_correct = getenv ("POSIXLY_CORRECT") != 0; @@ -362,6 +365,9 @@ main (int argc, char **argv) /* find out where all the lines are */ if (!skip_rest_of_patch) { scan_input (inname, file_type); +#if HAVE_SETMODE_DOS + setmode (fileno (outstate.ofp), input_is_lf); +#endif if (verbosity != SILENT) { @@ -1600,12 +1606,13 @@ static void init_reject (char const *outname) { int fd; - fd = make_tempfile (&TMPREJNAME, 'r', outname, O_WRONLY | binary_transput, + fd = make_tempfile (&TMPREJNAME, 'r', outname, + O_WRONLY | binary_transput | input_is_lf, 0666); if (fd == -1) pfatal ("Can't create temporary file %s", TMPREJNAME); TMPREJNAME_needs_removal = true; - rejfp = fdopen (fd, binary_transput ? "wb" : "w"); + rejfp = fdopen (fd, binary_transput || input_is_lf ? "wb" : "w"); if (! rejfp) pfatal ("Can't open stream for file %s", quotearg (TMPREJNAME)); } diff -urNp patch-2.7.5/src/patchres.rc patch-2.7-5/src/patchres.rc --- patch-2.7.5/src/patchres.rc 1970-01-01 10:00:00 +1000 +++ patch-2.7-5/src/patchres.rc 2015-07-10 16:17:15 +1000 @@ -0,0 +1,44 @@ +#include +#include + +VS_VERSION_INFO VERSIONINFO +FILEVERSION PVERB +PRODUCTVERSION PVERB +FILEOS VOS_NT +FILETYPE VFT_APP +{ + BLOCK "StringFileInfo" + { + BLOCK "040904B0" + { + VALUE "Comments", "http://patch.adoxa.vze.com/" + VALUE "CompanyName", "Jason Hood" + VALUE "FileDescription", PACKAGE_NAME + VALUE "FileVersion", PACKAGE_VERSION + VALUE "InternalName", PACKAGE + VALUE "LegalCopyright", "GPL" + VALUE "OriginalFilename", PACKAGE ".exe" + VALUE "ProductName", PACKAGE_NAME + VALUE "ProductVersion", PACKAGE_VERSION + } + } + + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x0409, 0x04B0 + } +} + +1 24 +{ +"\ +\ +\ + \ + \ + \ + \ + \ +\ +" +} diff -urNp patch-2.7.5/src/pch.c patch-2.7-5/src/pch.c --- patch-2.7.5/src/pch.c 2015-03-07 10:34:20 +1000 +++ patch-2.7-5/src/pch.c 2015-07-10 16:17:15 +1000 @@ -116,21 +116,18 @@ open_patch_file (char const *filename) struct stat st; if (!filename || !*filename || strEQ (filename, "-")) - pfp = stdin; + { + pfp = stdin; +#if HAVE_SETMODE_DOS + setmode (fileno (pfp), O_BINARY); +#endif + } else { - pfp = fopen (filename, binary_transput ? "rb" : "r"); + pfp = fopen (filename, "rb"); if (!pfp) pfatal ("Can't open patch file %s", quotearg (filename)); } -#if HAVE_SETMODE_DOS - if (binary_transput) - { - if (isatty (fileno (pfp))) - fatal ("cannot read binary data from tty on this platform"); - setmode (fileno (pfp), O_BINARY); - } -#endif if (fstat (fileno (pfp), &st) != 0) pfatal ("fstat"); if (S_ISREG (st.st_mode) && (pos = file_tell (pfp)) != -1) @@ -269,7 +266,7 @@ there_is_another_patch (bool need_header if (p_indent) say ("(Patch is indented %lu space%s.)\n", (unsigned long int) p_indent, p_indent==1?"":"s"); - if (p_strip_trailing_cr) + if (p_strip_trailing_cr && verbosity == VERBOSE) say ("(Stripping trailing CRs from patch; use --binary to disable.)\n"); if (! inname) { @@ -514,7 +511,8 @@ intuit_diff_type (bool need_header, mode return NO_DIFF; } } - strip_trailing_cr = 2 <= chars_read && buf[chars_read - 2] == '\r'; + strip_trailing_cr = ! binary_transput; + patch_is_crlf = 2 <= chars_read && buf[chars_read - 2] == '\r'; for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) { if (*s == '\t') indent = (indent + 8) & ~7; diff -urNp patch-2.7.5/src/safe.c patch-2.7-5/src/safe.c --- patch-2.7.5/src/safe.c 2015-03-07 10:34:20 +1000 +++ patch-2.7-5/src/safe.c 2015-07-10 17:10:14 +1000 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -92,11 +91,7 @@ static void free_cached_dirfd (struct ca static void init_dirfd_cache (void) { - struct rlimit nofile; - - max_cached_fds = 8; - if (getrlimit (RLIMIT_NOFILE, &nofile) == 0) - max_cached_fds = MAX (nofile.rlim_cur / 4, max_cached_fds); + max_cached_fds = MAX (getdtablesize () / 4, 8); cached_dirfds = hash_initialize (max_cached_fds, NULL, diff -urNp patch-2.7.5/src/util.c patch-2.7-5/src/util.c --- patch-2.7.5/src/util.c 2015-03-07 10:34:20 +1000 +++ patch-2.7-5/src/util.c 2015-07-10 22:05:05 +1000 @@ -254,6 +254,7 @@ set_file_attributes (char const *to, enu S_ISLNK (mode) ? "symbolic link" : "file", quotearg (to)); } +#if ! (defined _WIN32 || defined __WIN32__) || defined __CYGWIN__ if (attr & FA_IDS) { static uid_t euid = -1; @@ -282,6 +283,7 @@ set_file_attributes (char const *to, enu S_ISLNK (mode) ? "symbolic link" : "file", quotearg (to)); } +#endif if (attr & FA_XATTRS) if (copy_attr (from, to) != 0 && errno != ENOSYS && errno != ENOTSUP && errno != EPERM) diff -urNp patch-2.7.5/tests/bad-filenames patch-2.7-5/tests/bad-filenames --- patch-2.7.5/tests/bad-filenames 2014-11-26 23:17:55 +1000 +++ patch-2.7-5/tests/bad-filenames 2015-07-10 16:17:15 +1000 @@ -49,7 +49,7 @@ for dir in "$TMPDIR" "$TMP" "$TEMP" "/tm fi done -check 'emit_patch $filename | (cd / && patch -f -p0 --dry-run) || echo status: $?' < ab.diff < b diff a b | lf2crlf > ab.diff echo 1 > c check 'patch c < ab.diff' < ab.diff echo 1 > c check 'patch c < ab.diff' < ab.diff echo 1 > c check 'patch c < ab.diff' < ab.diff cp a c check 'patch c < ab.diff' < ab.diff cp a c check 'patch c < ab.diff' < f.diff < f echo old > g chmod 644 f g -check 'patch -p1 < f.diff' < g.diff < | cat > d.diff < " "' +ncheck 'echo one > " !"' ncheck 'patch -s -p0 < d.diff' -check 'cat " "' <&1 |sed 's/\(.*\): \*.*/\1/'` eval 'patch() { if test -n "$GDB" ; then