diff -ru patch-2.5.9-109-g70df4e4/src/pch.c patch-2.5.9-109-g70df4e4-new/src/pch.c --- patch-2.5.9-109-g70df4e4/src/pch.c 2009-05-17 05:54:10 +0000 +++ patch-2.5.9-109-g70df4e4-new/src/pch.c 2009-05-17 06:00:00 +0000 @@ -103,11 +103,13 @@ void open_patch_file (char const *filename) { - file_offset file_pos = 0; + file_offset file_pos; struct stat st; + FILE *fp; + + /* Decide whether or not the patch file is stdin. */ if (!filename || !*filename || strEQ (filename, "-")) { - file_offset stdin_pos; #if HAVE_SETMODE_DOS if (binary_transput) { @@ -116,45 +118,53 @@ setmode (STDIN_FILENO, O_BINARY); } #endif - if (fstat (STDIN_FILENO, &st) != 0) - pfatal ("fstat"); - if (S_ISREG (st.st_mode) && (stdin_pos = file_tell (stdin)) != -1) - { - pfp = stdin; - file_pos = stdin_pos; - } - else - { - size_t charsread; - int exclusive = TMPPATNAME_needs_removal ? 0 : O_EXCL; - TMPPATNAME_needs_removal = 1; - pfp = fdopen (create_file (TMPPATNAME, - O_RDWR | O_BINARY | exclusive, - (mode_t) 0, true), - "w+b"); - if (!pfp) - pfatal ("Can't open stream for file %s", quotearg (TMPPATNAME)); - for (st.st_size = 0; - (charsread = fread (buf, 1, bufsize, stdin)) != 0; - st.st_size += charsread) - if (fwrite (buf, 1, charsread, pfp) != charsread) - write_fatal (); - if (ferror (stdin) || fclose (stdin) != 0) - read_fatal (); - if (fflush (pfp) != 0 - || file_seek (pfp, (file_offset) 0, SEEK_SET) != 0) - write_fatal (); - } + fp = stdin; } else { - pfp = fopen (filename, binary_transput ? "rb" : "r"); - if (!pfp) + fp = fopen (filename, binary_transput ? "rb" : "r"); + if (!fp) pfatal ("Can't open patch file %s", quotearg (filename)); - if (fstat (fileno (pfp), &st) != 0) - pfatal ("fstat"); } - p_filesize = st.st_size; + + /* Make sure that "pfp" seekable. Copy the patch to a regular file if + necessary. Also set "file_pos" and "p_filesize". */ + if (fstat (fileno (fp), &st) != 0) + pfatal ("fstat"); + if ( +#if HAVE_SETMODE_DOS + /* On Windows, seeking doesn't work nicely in text mode when the file is + not a valid (CR-LF) text file. */ + binary_transput && +#endif + S_ISREG (st.st_mode) && (file_pos = file_tell (fp)) != -1) + { + pfp = fp; + p_filesize = st.st_size; + } + else + { + size_t charsread; + int exclusive = TMPPATNAME_needs_removal ? 0 : O_EXCL; + TMPPATNAME_needs_removal = 1; + pfp = fdopen (create_file (TMPPATNAME, + O_RDWR | O_BINARY | exclusive, + (mode_t) 0, true), + "w+b"); + if (!pfp) + pfatal ("Can't open stream for file %s", quotearg (TMPPATNAME)); + for (p_filesize = 0; + (charsread = fread (buf, 1, bufsize, fp)) != 0; + p_filesize += charsread) + if (fwrite (buf, 1, charsread, pfp) != charsread) + write_fatal (); + if (ferror (fp) || fclose (fp) != 0) + read_fatal (); + file_pos = 0; + if (fflush (pfp) != 0 || file_seek (pfp, file_pos, SEEK_SET) != 0) + write_fatal (); + } + if (p_filesize != (file_offset) p_filesize) fatal ("patch file is too long"); next_intuit_at (file_pos, (LINENUM) 1);