Import of patch-2.4.tar.gz

This commit is contained in:
Andreas Gruenbacher 2009-03-12 15:15:17 +01:00
parent 1adb4535a3
commit 6263c220df
21 changed files with 1475 additions and 773 deletions

263
ChangeLog
View File

@ -1,3 +1,222 @@
1997-06-19 Paul Eggert <eggert@pogo.gnu.ai.mit.edu>
* configure.in (VERSION): Version 2.4 released.
* NEWS: Patch is now verbose when patches do not match exactly.
1997-06-17 Paul Eggert <eggert@twinsun.com>
* pc/djgpp/configure.sed (config.h): Remove redundant $(srcdir).
* configure.in (VERSION): Bump to 2.3.9.
* patch.c (main): By default, warn about hunks that succeed
with nonzero offset.
* patch.man: Add LC_ALL=C advice for making patches.
* pc/djgpp/configure.sed (config.h): Fix paths to dependent files.
1997-06-17 Paul Eggert <eggert@twinsun.com>
* configure.in (VERSION): Bump to 2.3.8.
* pch.c (open_patch_file): Test stdin for fseekability.
(intuit_diff_type): Missing context diff headers are now warnings,
not errors; some people use patches with them (e.g. when retrying
rejects).
* patch.c (struct outstate):
New type, collecting together some output state vars.
(apply_hunk, copy_till, spew_output, init_output): Use it.
Keep track of whether some output has been generated.
(backup_if_mismatch): New var.
(ofp): Remove, in favor of local struct outstate vars.
(main): Use struct outstate. Initialize backup_if_mismatch to
be the inverse of posixly_correct. Keep track of whether mismatches
occur, and use this to implement backup_if_mismatch.
Report files that are not empty after patching, but should be.
(longopts, option_help, get_some_switches): New options
--backup-if-mismatch, --no-backup-if-mismatch.
(get_some_switches): -B, -Y, -z no longer set backup_type.
* backupfile.c (find_backup_file_name):
Treat backup_type == none like simple.
* Makefile.in (CONFIG_HDRS):
Remove var; no longer needed by djgpp port.
(DISTFILES_PC_DJGPP): Rename pc/djgpp/config.sed to
pc/djgpp/configure.sed; remove pc/djgpp/config.h in favor of
new file that edits it, called pc/djgpp/config.sed.
* pc/djgpp/configure.bat: Rename config.sed to configure.sed.
* pc/djgpp/configure.sed (CONFIG_HDRS): Remove.
(config.h): Add rule to build this from config.hin and
pc/djgpp/config.sed.
* pc/djgpp/config.sed:
Convert from .h file to .sed script that generates .h file.
* NEWS: Describe --backup-if-mismatch, --no-backup-if-mismatch.
* patch.man:
Describe new options --backup-if-mismatch, --no-backup-if-mismatch
and their ramifications. Use unreadable backup to represent
nonexistent file.
1997-06-12 Paul Eggert <eggert@twinsun.com>
* configure.in (VERSION): Bump to 2.3.7.
(AC_CHECK_FUNCS): Add `raise'.
* Makefile.in (inp.o): No longer depends on quotearg.h.
* common.h (outfile): New decl (was private var named `output').
(invc): New decl.
(GENERIC_OBJECT): Renamed from VOID.
(NULL_DEVICE, TTY_DEVICE): New macros.
* patch.c (output): Remove; renamed to `outfile' and moved to common.h.
(main): `failed' is count, not boolean.
Say "Skipping patch." when deciding to skip patch.
(get_some_switches): Set invc when setting inname.
* inp.c: Do not include <quotearg.h>.
(SCCSPREFIX, GET, GET_LOCKED, SCCSDIFF1, SCCSDIFF2, SCCSDIFF3,
RCSSUFFIX, CHECKOUT, CHECKOUT_LOCKED, RCSDIFF1, RCSDIFF2):
Move to util.c.
(get_input_file): Invoke new functions version_controller and
version_get to simplify this code.
(plan_b): "/dev/tty" -> NULL_DEVICE
* pch.h (pch_timestamp): New decl.
* pch.c (p_timestamp): New var; takes over from global timestamp array.
(pch_timestamp): New function to export p_timestamp.
(there_is_another_patch): Use blander wording when you can't intuit
the file name.
Say "Skipping patch." when deciding to skip patch.
(intuit_diff_type): Look for version-controlled but nonexistent files
when intuiting file names; set invc accordingly.
Ignore Index: line if either old or new line is present, and if
POSIXLY_CORRECT is not set.
(do_ed_script): Flush stdout before invoking popen, since it may
send output to stdout.
* util.h (version_controller, version_get): New decls.
* util.c: Include <quotearg.h> earlier.
(raise): New macro, if ! HAVE_RAISE.
(move_file): Create empty unreadable file when backing up a nonexistent
file.
(DEV_NULL): New constant.
(SCCSPREFIX, GET. GET_LOCKED, SCCSDIFF1, SCCSDIFF2,
RCSSUFFIX, CHECKOUT, CHECKOUT_LOCKED, RCSDIFF1): Moved here from inp.c.
(version_controller, version_get): New functions.
(ask): Look only at /dev/tty for answers; and when standard output is
not a terminal and ! posixly_correct, don't even look there.
Remove unnecessary fflushes of stdout.
(ok_to_reverse): Say "Skipping patch." when deciding to skip patch..
(sigs): SIGPIPE might not be defined.
(exit_with_signal): Use `raise' instead of `kill'.
(systemic): fflush stdout before invoking subsidiary command.
* patch.man: Document recent changes.
Add "COMPATIBILITY ISSUES" section.
* NEWS: New COMPATIBILITY ISSUES for man page.
Changed verbosity when fuzz is found.
File name intuition is changed, again.
Backups are made unreadable when the file did not exist.
* pc/djgpp/config.h (HAVE_STRUCT_UTIMBUF): Define.
(HAVE_RAISE): New macro.
(HAVE_UTIME_H): Define.
(TZ_is_unset): Do not define; it's not a serious problem with `patch'
to have TZ be unset in DOS.
1997-06-08 Paul Eggert <eggert@twinsun.com>
* configure.in (VERSION): Bump to 2.3.6.
(AC_CHECK_HEADERS): Add utime.h.
* acconfig.h, configure.in, pc/djgpp/config.h (HAVE_STRUCT_UTIMBUF):
New macro.
* pc/djgpp/config.h (HAVE_UTIME_H, TZ_is_unset): New macros.
* NEWS, patch.man: Describe new -Z, -T options, new numeric
option for -G, retired -G, and more verbose default behavior
with fuzz.
* pch.c (intuit_diff_type): Record times reported for files in headers.
Remove head_says_nonexistent[x], since it's now equivalent to
!timestamp[x].
* util.h (fetchname): Change argument head_says_nonexistent to
timestamp.
* util.c: #include <partime.h> for TM_LOCAL_ZONE.
Don't include <time.h> since common.h now includes it.
(ok_to_reverse): noreverse and batch cases now output regardless of
verbosity.
(fetchname): Change argument head_says_nonexistent to pstamp, and
store header timestamp into *pstamp.
If -T or -Z option is given, match time stamps more precisely.
(ask): Remove unnecessary close of ttyfd.
When there is no terminal at all, output a newline to make the
output look nicer. After reporting EOF, flush stdout;
when an input error, report the error type.
* inp.c (get_input_file):
Ask user whether to get file if patch_get is negative.
* Makefile.in (clean): Don't clean */*.o; clean core* and *core.
1997-06-04 Paul Eggert <eggert@twinsun.com>
* configure.in (VERSION): Bump to 2.3.5.
* util.c (ok_to_reverse):
Be less chatty if verbosity is SILENT and we don't
have to ask the user. If force is nonzero, apply the patch anyway.
* pch.c (there_is_another_patch):
Before skipping rest of patch, skip to
the patch start, so that another_hunk can skip it properly.
(intuit_diff_type): Slight wording change for missing headers, to
regularize with other diagnostics. Fix off-by-one error when setting
p_input_line when scanning the first hunk to check for deleted files.
1997-06-03 Paul Eggert <eggert@twinsun.com>
* configure.in (VERSION): Bump to 2.3.4.
* NEWS: Now matches more generously against nonexistent or empty files.
* pch.c (there_is_another_patch): Move warning about not being
able to intuit file names here from skip_to.
(intuit_diff_type): Fatal error if we find a headless unified
or context diff.
* util.c (ask): Null-terminate buffer properly even if it grew.
(fetchname): No need to test for null first argument.
1997-06-02 Paul Eggert <eggert@twinsun.com>
* configure.in (VERSION): Bump to 2.3.3.
* pch.c (p_says_nonexistent, pch_says_nonexistent): Is now 1 for empty,
2 for nonexistent.
(intuit_diff_type): Set p_says_nonexistent according to new meaning.
Treat empty files like nonexistent files when reversing.
(skip_to): Output better diagnostic when we can't intuit a file name.
* patch.c (main):
Count bytes, not lines, when testing whether a file is empty,
since it may contain only non-newline chars.
pch_says_nonexistent now returns 2 for nonexistent files.
1997-06-01 Paul Eggert <eggert@twinsun.com>
* configure.in (VERSION): Bump to 2.3.2.
* pch.c (open_patch_file):
Fix bug when computing size of patch read from a pipe.
1997-05-30 Paul Eggert <eggert@twinsun.com>
* configure.in (VERSION): Bump to 2.3.1.
* Makefile.in (transform, patch_name): New vars,
for proper implementation of AC_ARG_PROGRAM.
(install, uninstall): Use them.
(install-strip): New rule.
* pc/djgpp/config.sed (program_transform_name): Set to empty.
1997-05-30 Paul Eggert <eggert@twinsun.com>
* configure.in (VERSION), NEWS: Version 2.3 released.
@ -88,50 +307,6 @@
* Makefile.in (DISTFILES_PC): Remove pc/quotearg.c.
* pc/djgpp/config.sed: Remove unnecessary hooks for quotearg and SHELL.
1997-05-18 Paul Eggert <eggert@pogo.gnu.ai.mit.edu>
* configure.in (VERSION): Increase to 2.2.9.
(AC_TYPE_MODE_T): Add.
* pch.c (hunkmax): Now of type LINENUM.
(malformed): Add decl.
(there_is_another_patch): Skip inname-detection if skip_rest_of_patch.
(intuit_diff_type): To determine whether file appears to have been
deleted, look at replacement, not pattern.
If there is a mismatch between existence of file and whether the
patch claims to change whether the file exists, ask whether to
reverse the patch.
(another_hunk): New parameter REV specifying whether to reverse the
hunk. All callers changed.
(do_ed_script): Add assertion to ensure input file exists.
* common.h (noreverse): New decl.
(ok_to_reverse): Remove decl.
* patch.c (noreverse): Now extern.
(main): New environment var PATCH_VERSION_CONTROL overrides VERSION_CONTROL.
Don't assert(hunk) if we're skipping the patch; we may not have any hunks.
When removing a file, back it up if backups are desired.
Don't chmod output file if input file did not exist.
chmod rej file to input file's mode minus executable bits.
(locate_hunk): Go back to old way of a single fuzz parameter, but
handle it more precisely: context diffs with partial contexts
can only match file ends, since the partial context can occur
only at the start or end of file.
All callers changed.
(create_output_file): Use create_file to create files.
(ok_to_reverse): Move to util.c.
* inp.c (scan_input, get_input_file): Quote file names in diagnostics.
(get_input_file): Set inerrno if it's not already set.
Don't create file; it's now the caller's responsibility.
(plan_b): Use /dev/null if input size is zero, since it might not exist.
Use create_file to create temporary file.
* NEWS: Add PATCH_VERSION_CONTROL; DOS port is untested.
* patch.man: PATCH_VERSION_CONTROL overrides VERSION_CONTROL.
1997-05-18 Paul Eggert <eggert@twinsun.com>
* configure.in (VERSION): Increase to 2.2.9.

View File

@ -28,6 +28,7 @@ ed_PROGRAM = @ed_PROGRAM@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
transform = @program_transform_name@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
@ -45,11 +46,10 @@ bindir = $(exec_prefix)/bin
# Where to put the manual pages.
man1dir = $(prefix)/man/man1
# Extension (not including `.') for the manual page filenames.
# Extension (including `.') for the manual page filenames.
man1ext = .1
# Hooks for nonstandard builds.
CONFIG_HDRS = config.h
# Hook for nonstandard builds.
CONFIG_STATUS = config.status
#### End of system configuration section. ####
@ -68,8 +68,10 @@ MISC = COPYING ChangeLog INSTALL Makefile.in NEWS README \
install-sh mkinstalldirs patch.man
DISTFILES = $(MISC) $(SRCS) $(HDRS)
DISTFILES_PC = pc/chdirsaf.c
DISTFILES_PC_DJGPP = pc/djgpp/README pc/djgpp/config.h \
pc/djgpp/config.sed pc/djgpp/configure.bat
DISTFILES_PC_DJGPP = pc/djgpp/README pc/djgpp/config.sed \
pc/djgpp/configure.bat pc/djgpp/configure.sed
patch_name = `echo patch | sed '$(transform)'`
all:: patch
@ -87,15 +89,17 @@ patch: $(OBJS)
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS)
install:: all installdirs
$(INSTALL_PROGRAM) patch $(bindir)/`echo patch | sed '$(transform)'`
-$(INSTALL_DATA) $(srcdir)/patch.man \
$(man1dir)/`echo patch | sed '$(transform)'`$(man1ext)
$(INSTALL_PROGRAM) patch $(bindir)/$(patch_name)
-$(INSTALL_DATA) $(srcdir)/patch.man $(man1dir)/$(patch_name)$(man1ext)
installdirs::
$(SHELL) $(srcdir)/mkinstalldirs $(bindir) $(man1dir)
install-strip::
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
uninstall::
rm -f $(bindir)/patch $(man1dir)/patch$(man1ext)
rm -f $(bindir)/$(patch_name) $(man1dir)/$(patch_name)$(man1ext)
Makefile: Makefile.in $(CONFIG_STATUS)
$(SHELL) $(CONFIG_STATUS)
@ -113,7 +117,7 @@ TAGS: $(HDRS) patchlevel.h $(SRCS)
etags $(HDRS) patchlevel.h $(SRCS)
clean::
rm -f patch *.o */*.o core
rm -f patch core* *core *.o
mostlyclean:: clean
@ -138,17 +142,17 @@ dist:: $(DISTFILES) $(DISTFILES_PC) $(DISTFILES_PC_DJGPP)
tar -chf - $(PV) | gzip -9 >$(PV).tar.gz
rm -rf $(PV)
$(OBJS): $(CONFIG_HDRS)
$(OBJS): config.h
addext.o: backupfile.h
argmatch.o: argmatch.h
backupfile.o: argmatch.h backupfile.h
basename.o: backupfile.h
getopt.o getopt1.o: getopt.h
maketime.o: maketime.h partime.h
inp.o: backupfile.h common.h inp.h pch.h quotearg.h util.h
inp.o: backupfile.h common.h inp.h pch.h util.h
partime.o: partime.h
patch.o: argmatch.h backupfile.h common.h getopt.h inp.h pch.h util.h version.h
pch.o: common.h inp.h pch.h util.h
quotearg.o: quotearg.h
util.o: backupfile.h common.h maketime.h quotearg.h util.h version.h
util.o: backupfile.h common.h maketime.h partime.h quotearg.h util.h version.h
version.o: common.h patchlevel.h util.h version.h

72
NEWS
View File

@ -3,6 +3,46 @@ Known problems:
* The diffutils 2.7 documentation for `patch' is obsolete; this should be
fixed in diffutils 2.8. Until then, see `patch --help' or `man patch'.
Change in version 2.4:
* New options:
-Z or --set-utc sets times of patched files, assuming diff uses UTC (GMT).
-T or --set-time is similar, assuming local time (not recommended).
--backup-if-mismatch makes a backup if the patch does not match exactly
--no-backup-if-mismatch makes a backup only if otherwise requested
* The default is now --backup-if-mismatch unless POSIXLY_CORRECT is set.
* The -B or --prefix, -Y or --basename-prefix, and -z or --suffix options
no longer affect whether backups are made (as they did in patch 2.2 and 2.3);
they now merely specify the file names used when simple backups are made.
* When patching a nonexistent file and making backups, an empty backup file
is now made (just as with traditional patch); but the backup file is
unreadable, as a way of indicating that it represents a nonexistent file.
* `patch' now matches against empty and nonexistent files more generously.
A patch against an empty file applies to a nonexistent file, and vice versa.
* -g or --get and PATCH_GET now have a numeric value that specifies
whether `patch' is getting files.
If the value is positive, working files are gotten from RCS or SCCS files;
if zero, `patch' ignores RCS and SCCS and working files are not gotten;
and if negative, `patch' asks the user whether to get each file.
The default is normally negative, but it is zero if POSIXLY_CORRECT is set.
* The -G or --no-get option introduced in GNU patch 2.3 has been removed;
use -g0 instead.
* The method used to intuit names of files to be patched is changed again:
`Index:' lines are normally ignored for context diffs,
and RCS and SCCS files are normally looked for when files do not exist.
The complete new method is described in the man page.
* By default, `patch' is now more verbose when patches do not match exactly.
* The manual page has a new COMPATIBILITY ISSUES section.
Changes in version 2.3:
* Unless the POSIXLY_CORRECT environment variable is set:
@ -11,35 +51,19 @@ Changes in version 2.3:
nonexistent files if the input is a context diff.
A file is assumed to not exist if its context diff header
suggests that it is empty, and if the header timestamp
is within 24 hours of 1970-01-01 00:00:00 UTC.
looks like it might be equivalent to 1970-01-01 00:00:00 UTC.
- Files that ``become nonexistent'' after patching are now removed.
When a file is removed, any empty ancestor directories are also removed.
* Files are now automatically gotten from RCS and SCCS
if the -g or --get option is specified,
or if the PATCH_GET environment variable is set
and the -G or --no-get option is not specified.
if the -g or --get option is specified.
(The -G or --no-get option, also introduced in 2.3, was withdrawn in 2.4.)
* If the PATCH_VERSION_CONTROL environment variable is set,
it overrides the VERSION_CONTROL environment variable.
* The method used to intuit names of files to be patched is now as follows:
- Take the old and new names from the context header if present,
and take the index name from the `Index:' line if present.
Consider the file names to be in the order (old, new, index).
- If some named files exist, use the first one if POSIXLY_CORRECT is set,
the best one otherwise.
- If no named files exist, some names are given, POSIXLY_CORRECT is not set,
and the patch appears to create a file, then use the best name
requiring the creation of the fewest directories.
- Otherwise, ask the user for a file name.
The ``best'' of a nonempty list of file names is defined as follows:
- Take the names with the fewest path name components;
of those, take the names with the shortest basename;
of those, take the shortest names;
of those, take the first name.
* The method used to intuit names of files to be patched is changed.
(It was further revised in 2.4; see above.)
* The new --binary option makes `patch' read and write files in binary mode.
This option has no effect on POSIX-compliant hosts;
@ -73,8 +97,8 @@ Changes in version 2.2:
* Patch now complies better with POSIX.2 if your host complies with POSIX.1.
Therefore:
- By default, no backups are made. Set the VERSION_CONTROL environment
variable to "existing" if you prefer patch's traditional behavior.
- By default, no backups are made.
(But this was changed again in patch 2.4; see above.)
- The simple backup file name for F defaults to F.orig
regardless of whether the file system supports long file names,
and F~ is used only if F.orig is too long for that particular file.
@ -89,6 +113,7 @@ Changes in version 2.2:
consulted if none of the above files exist. However, if the patch
appears to create a file, the file does not have to exist: instead,
the first name with the longest existing directory prefix is taken.
(These rules were changed again in patch 2.3 and 2.4; see above.)
- Exit status 0 means success, 1 means hunks were rejected, 2 means trouble.
- `-l' ignores changes only in spaces and tabs, not in other white space.
- If no `-p' option is given, `-pINFINITY' is assumed, instead of trying
@ -107,6 +132,7 @@ Changes in version 2.2:
* RCS is used only if the version control method is `existing'
and there is already an RCS file. Similarly for SCCS.
(But this was changed again in patch 2.3 and 2.4; see above.)
* Copyright notices have been clarified. Every file in this version of `patch'
can be distributed under the GNU General Public License. See README for

View File

@ -9,3 +9,6 @@
/* Define if memchr works. */
#undef HAVE_MEMCHR
/* Define if `struct utimbuf' is declared -- usually in <utime.h>. */
#undef HAVE_STRUCT_UTIMBUF

View File

@ -109,8 +109,7 @@ static int version_number __BACKUPFILE_P ((const char *, const char *, size_t));
/* Return the name of the new backup file for file FILE,
allocated with malloc. Return 0 if out of memory.
FILE must not end with a '/' unless it is the root directory.
Do not call this function if backup_type == none. */
FILE must not end with a '/' unless it is the root directory. */
char *
find_backup_file_name (file)
@ -133,7 +132,7 @@ find_backup_file_name (file)
strcpy (s, file);
#if HAVE_DIR
if (backup_type != simple)
if (backup_type != simple && backup_type != none)
{
int highest_backup;
size_t dir_len = base_name (s) - s;

View File

@ -1,6 +1,6 @@
/* common definitions for `patch' */
/* $Id: common.h,v 1.16 1997/05/26 05:34:43 eggert Exp $ */
/* $Id: common.h,v 1.18 1997/06/13 06:28:37 eggert Exp $ */
/*
Copyright 1986, 1988 Larry Wall
@ -44,6 +44,7 @@ If not, write to the Free Software Foundation,
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <sys/stat.h>
#if ! defined S_ISDIR && defined S_IFDIR
@ -148,7 +149,9 @@ XTERN size_t bufsize; /* allocated size of buf */
XTERN bool using_plan_a; /* try to keep everything in memory */
XTERN char *inname;
XTERN char *outfile;
XTERN int inerrno;
XTERN int invc;
XTERN struct stat instat;
XTERN bool dry_run;
XTERN bool posixly_correct;
@ -174,6 +177,8 @@ XTERN bool skip_rest_of_patch;
XTERN int strippath;
XTERN bool canonicalize;
XTERN int patch_get;
XTERN int set_time;
XTERN int set_utc;
enum diff
{
@ -190,9 +195,9 @@ XTERN enum diff diff_type;
XTERN char *revision; /* prerequisite revision, if any */
#ifdef __STDC__
# define VOID void
# define GENERIC_OBJECT void
#else
# define VOID char
# define GENERIC_OBJECT char
#endif
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) || __STRICT_ANSI__
@ -207,7 +212,7 @@ XTERN char *revision; /* prerequisite revision, if any */
# endif
#endif
VOID *xmalloc PARAMS ((size_t));
GENERIC_OBJECT *xmalloc PARAMS ((size_t));
void fatal_exit PARAMS ((int)) __attribute__ ((noreturn));
#include <errno.h>
@ -221,7 +226,7 @@ extern int errno;
# if !HAVE_MEMCHR
# define memcmp(s1, s2, n) bcmp (s1, s2, n)
# define memcpy(d, s, n) bcopy (s, d, n)
VOID *memchr ();
GENERIC_OBJECT *memchr ();
# endif
#endif
@ -230,8 +235,8 @@ VOID *memchr ();
#else
long atol ();
char *getenv ();
VOID *malloc ();
VOID *realloc ();
GENERIC_OBJECT *malloc ();
GENERIC_OBJECT *realloc ();
#endif
#if HAVE_UNISTD_H
@ -292,3 +297,11 @@ off_t lseek ();
#else
# define binary_transput 0
#endif
#ifndef NULL_DEVICE
#define NULL_DEVICE "/dev/null"
#endif
#ifndef TTY_DEVICE
#define TTY_DEVICE "/dev/tty"
#endif

View File

@ -54,6 +54,9 @@
/* Define if memchr works. */
#undef HAVE_MEMCHR
/* Define if `struct utimbuf' is declared -- usually in <utime.h>. */
#undef HAVE_STRUCT_UTIMBUF
/* Define if you have the _doprintf function. */
#undef HAVE__DOPRINTF
@ -75,6 +78,9 @@
/* Define if you have the pathconf function. */
#undef HAVE_PATHCONF
/* Define if you have the raise function. */
#undef HAVE_RAISE
/* Define if you have the rename function. */
#undef HAVE_RENAME
@ -111,5 +117,8 @@
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
/* Define if you have the <varargs.h> header file. */
#undef HAVE_VARARGS_H

92
configure vendored
View File

@ -540,7 +540,7 @@ test "$program_transform_name" = "" && program_transform_name="s,x,x,"
PACKAGE=patch
VERSION=2.3
VERSION=2.4
@ -1349,7 +1349,7 @@ EOF
fi
for ac_hdr in fcntl.h limits.h string.h unistd.h varargs.h
for ac_hdr in fcntl.h limits.h string.h unistd.h utime.h varargs.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
@ -1531,9 +1531,45 @@ EOF
fi
echo $ac_n "checking for struct utimbuf""... $ac_c" 1>&6
echo "configure:1536: checking for struct utimbuf" >&5
if eval "test \"`echo '$''{'patch_cv_sys_struct_utimbuf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1541 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if HAVE_UTIME_H
#include <utime.h>
#endif
int main() {
static struct utimbuf x; x.actime = x.modtime;
; return 0; }
EOF
if { (eval echo configure:1551: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
patch_cv_sys_struct_utimbuf=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
patch_cv_sys_struct_utimbuf=no
fi
rm -f conftest*
fi
echo "$ac_t""$patch_cv_sys_struct_utimbuf" 1>&6
if test $patch_cv_sys_struct_utimbuf = yes; then
cat >> confdefs.h <<\EOF
#define HAVE_STRUCT_UTIMBUF 1
EOF
fi
# Check for NetBSD 1.0 bug, where memchr(..., 0) returns nonzero.
echo $ac_n "checking for working memchr""... $ac_c" 1>&6
echo "configure:1537: checking for working memchr" >&5
echo "configure:1573: checking for working memchr" >&5
if eval "test \"`echo '$''{'ac_cv_func_memchr'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1542,12 +1578,12 @@ else
ac_cv_func_memchr=no
else
cat > conftest.$ac_ext <<EOF
#line 1546 "configure"
#line 1582 "configure"
#include "confdefs.h"
#include <string.h>
main () { exit (memchr ("", 0, 0) != 0 || memchr ("", 1, 0) != 0); }
EOF
if { (eval echo configure:1551: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:1587: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
ac_cv_func_memchr=yes
else
@ -1569,12 +1605,12 @@ EOF
fi
echo $ac_n "checking for getopt_long""... $ac_c" 1>&6
echo "configure:1573: checking for getopt_long" >&5
echo "configure:1609: checking for getopt_long" >&5
if eval "test \"`echo '$''{'ac_cv_func_getopt_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1578 "configure"
#line 1614 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char getopt_long(); below. */
@ -1597,7 +1633,7 @@ getopt_long();
; return 0; }
EOF
if { (eval echo configure:1601: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:1637: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_getopt_long=yes"
else
@ -1618,15 +1654,15 @@ LIBOBJS="$LIBOBJS getopt1.o getopt.o"
fi
for ac_func in _doprintf isascii memcmp mkdir mktemp pathconf sigaction sigprocmask sigsetmask
for ac_func in _doprintf isascii memcmp mkdir mktemp pathconf raise sigaction sigprocmask sigsetmask
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:1625: checking for $ac_func" >&5
echo "configure:1661: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1630 "configure"
#line 1666 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@ -1649,7 +1685,7 @@ $ac_func();
; return 0; }
EOF
if { (eval echo configure:1653: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:1689: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@ -1676,12 +1712,12 @@ done
for ac_func in memchr rename
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:1680: checking for $ac_func" >&5
echo "configure:1716: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1685 "configure"
#line 1721 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@ -1704,7 +1740,7 @@ $ac_func();
; return 0; }
EOF
if { (eval echo configure:1708: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:1744: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@ -1731,7 +1767,7 @@ done
echo $ac_n "checking whether closedir returns void""... $ac_c" 1>&6
echo "configure:1735: checking whether closedir returns void" >&5
echo "configure:1771: checking whether closedir returns void" >&5
if eval "test \"`echo '$''{'ac_cv_func_closedir_void'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1739,13 +1775,13 @@ else
ac_cv_func_closedir_void=yes
else
cat > conftest.$ac_ext <<EOF
#line 1743 "configure"
#line 1779 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_header_dirent>
int closedir(); main() { exit(closedir(opendir(".")) != 0); }
EOF
if { (eval echo configure:1749: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:1785: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
ac_cv_func_closedir_void=no
else
@ -1768,12 +1804,12 @@ EOF
fi
echo $ac_n "checking for vprintf""... $ac_c" 1>&6
echo "configure:1772: checking for vprintf" >&5
echo "configure:1808: checking for vprintf" >&5
if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1777 "configure"
#line 1813 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char vprintf(); below. */
@ -1796,7 +1832,7 @@ vprintf();
; return 0; }
EOF
if { (eval echo configure:1800: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:1836: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_vprintf=yes"
else
@ -1820,12 +1856,12 @@ fi
if test "$ac_cv_func_vprintf" != yes; then
echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
echo "configure:1824: checking for _doprnt" >&5
echo "configure:1860: checking for _doprnt" >&5
if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1829 "configure"
#line 1865 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char _doprnt(); below. */
@ -1848,7 +1884,7 @@ _doprnt();
; return 0; }
EOF
if { (eval echo configure:1852: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:1888: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func__doprnt=yes"
else
@ -1874,7 +1910,7 @@ fi
echo $ac_n "checking for long file names""... $ac_c" 1>&6
echo "configure:1878: checking for long file names" >&5
echo "configure:1914: checking for long file names" >&5
if eval "test \"`echo '$''{'ac_cv_sys_long_file_names'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1919,12 +1955,12 @@ fi
echo $ac_n "checking for d_ino member in directory struct""... $ac_c" 1>&6
echo "configure:1923: checking for d_ino member in directory struct" >&5
echo "configure:1959: checking for d_ino member in directory struct" >&5
if eval "test \"`echo '$''{'patch_cv_sys_d_ino_in_dirent'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1928 "configure"
#line 1964 "configure"
#include "confdefs.h"
#include <sys/types.h>
@ -1947,7 +1983,7 @@ int main() {
struct dirent dp; dp.d_ino = 0;
; return 0; }
EOF
if { (eval echo configure:1951: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:1987: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
patch_cv_sys_d_ino_in_dirent=yes
else

View File

@ -8,7 +8,7 @@ AC_CONFIG_HEADER(config.h:config.hin)
AC_ARG_PROGRAM
PACKAGE=patch
VERSION=2.3
VERSION=2.4
AC_SUBST(PACKAGE)
AC_SUBST(VERSION)
@ -60,13 +60,27 @@ AC_C_CONST
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h limits.h string.h unistd.h varargs.h)
AC_CHECK_HEADERS(fcntl.h limits.h string.h unistd.h utime.h varargs.h)
AC_TYPE_MODE_T
AC_TYPE_OFF_T
AC_TYPE_SIGNAL
AC_TYPE_SIZE_T
dnl Some systems have utime.h but don't declare the struct anywhere.
AC_MSG_CHECKING(for struct utimbuf)
AC_CACHE_VAL(patch_cv_sys_struct_utimbuf,
[AC_TRY_COMPILE([#include <sys/types.h>
#if HAVE_UTIME_H
#include <utime.h>
#endif], [static struct utimbuf x; x.actime = x.modtime;],
patch_cv_sys_struct_utimbuf=yes,
patch_cv_sys_struct_utimbuf=no)])
AC_MSG_RESULT($patch_cv_sys_struct_utimbuf)
if test $patch_cv_sys_struct_utimbuf = yes; then
AC_DEFINE(HAVE_STRUCT_UTIMBUF)
fi
# Check for NetBSD 1.0 bug, where memchr(..., 0) returns nonzero.
AC_MSG_CHECKING(for working memchr)
AC_CACHE_VAL(ac_cv_func_memchr,
@ -83,7 +97,7 @@ fi
AC_CHECK_FUNC(getopt_long, , [LIBOBJS="$LIBOBJS getopt1.o getopt.o"])
AC_SUBST(LIBOBJS)
AC_CHECK_FUNCS(_doprintf isascii memcmp mkdir mktemp pathconf sigaction sigprocmask sigsetmask)
AC_CHECK_FUNCS(_doprintf isascii memcmp mkdir mktemp pathconf raise sigaction sigprocmask sigsetmask)
AC_REPLACE_FUNCS(memchr rename)
AC_FUNC_CLOSEDIR_VOID
AC_FUNC_VPRINTF

134
inp.c
View File

@ -1,6 +1,6 @@
/* inputting files to be patched */
/* $Id: inp.c,v 1.14 1997/05/26 05:34:43 eggert Exp $ */
/* $Id: inp.c,v 1.16 1997/06/13 06:28:37 eggert Exp $ */
/*
Copyright 1986, 1988 Larry Wall
@ -26,25 +26,11 @@ If not, write to the Free Software Foundation,
#include <common.h>
#include <backupfile.h>
#include <pch.h>
#include <quotearg.h>
#include <util.h>
#undef XTERN
#define XTERN
#include <inp.h>
static char const SCCSPREFIX[] = "s.";
static char const GET[] = "get ";
static char const GET_LOCKED[] = "get -e ";
static char const SCCSDIFF1[] = "get -p ";
static char const SCCSDIFF2[] = "|diff - %s";
static char const SCCSDIFF3[] = ">/dev/null";
static char const RCSSUFFIX[] = ",v";
static char const CHECKOUT[] = "co %s";
static char const CHECKOUT_LOCKED[] = "co -l %s";
static char const RCSDIFF1[] = "rcsdiff %s";
#define RCSDIFF2 SCCSDIFF3
/* Input-file-with-indexable-lines abstract type */
static char const **i_ptr; /* pointers to lines in plan A buffer */
@ -148,92 +134,28 @@ get_input_file (filename, outname)
char const *outname;
{
int elsewhere = strcmp (filename, outname);
char const *cs;
char *diffbuf;
char *getbuf;
if (inerrno == -1)
inerrno = stat (inname, &instat) == 0 ? 0 : errno;
/* Perhaps look for RCS or SCCS versions. */
if (patch_get
&& invc != 0
&& (inerrno
|| (! elsewhere
&& (/* No one can write to it. */
(instat.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0
/* Only the owner (who's not me) can write to it. */
|| ((instat.st_mode & (S_IWGRP|S_IWOTH)) == 0
&& instat.st_uid != geteuid ()))))) {
struct stat cstat;
char const *cs = 0;
char const *filebase = base_name (filename);
char const *dotslash = *filename=='-' ? "./" : "";
size_t dir_len = filebase - filename;
size_t filenamelen = strlen (filename);
size_t maxfixlen = sizeof "SCCS/" - 1 + sizeof SCCSPREFIX - 1;
size_t maxtrysize = filenamelen + maxfixlen + 1;
size_t quotelen = quote_system_arg (0, filename);
size_t maxgetsize = sizeof GET_LOCKED + quotelen + maxfixlen;
size_t maxdiffsize =
(sizeof SCCSDIFF1 + sizeof SCCSDIFF2 + sizeof SCCSDIFF3 - 2
+ 2 * quotelen + maxfixlen);
char *trybuf = xmalloc (maxtrysize + maxgetsize + maxdiffsize);
char *getbuf = trybuf + maxtrysize;
char *diffbuf = getbuf + maxgetsize;
&& instat.st_uid != geteuid ()))))
&& (invc = !! (cs = (version_controller
(filename, elsewhere,
inerrno ? (struct stat *) 0 : &instat,
&getbuf, &diffbuf))))) {
strcpy (trybuf, filename);
#define try1(f,a1) (sprintf (trybuf + dir_len, f, a1), stat (trybuf, &cstat) == 0)
#define try2(f,a1,a2) (sprintf (trybuf + dir_len, f, a1,a2), stat (trybuf, &cstat) == 0)
if (( try2 ("RCS/%s%s", filebase, RCSSUFFIX)
|| try1 ("RCS/%s" , filebase)
|| try2 ( "%s%s", filebase, RCSSUFFIX))
&&
/* Check that RCS file is not working file.
Some hosts don't report file name length errors. */
(inerrno
|| instat.st_dev != cstat.st_dev
|| instat.st_ino != cstat.st_ino)) {
char *p = getbuf;
sprintf (p, elsewhere ? CHECKOUT : CHECKOUT_LOCKED, dotslash);
p += strlen (p);
p += quote_system_arg (p, filename);
*p = '\0';
p = diffbuf;
sprintf (p, RCSDIFF1, dotslash);
p += strlen (p);
p += quote_system_arg (p, filename);
strcpy (p, RCSDIFF2);
cs = "RCS";
} else if ( try2 ("SCCS/%s%s", SCCSPREFIX, filebase)
|| try2 ( "%s%s", SCCSPREFIX, filebase)) {
char *p = getbuf;
sprintf (p, elsewhere ? GET : GET_LOCKED);
p += strlen (p);
p += quote_system_arg (p, trybuf);
*p = '\0';
p = diffbuf;
strcpy (p, SCCSDIFF1);
p += sizeof SCCSDIFF1 - 1;
p += quote_system_arg (p, trybuf);
sprintf (p, SCCSDIFF2, dotslash);
p += strlen (p);
p += quote_system_arg (p, filename);
strcpy (p, SCCSDIFF3);
cs = "SCCS";
} else if (inerrno && !pch_says_nonexistent (reverse))
{
errno = inerrno;
pfatal ("can't find file `%s'", filename);
}
/* else we can't write to it but it's not under a version
control system, so just proceed. */
if (cs) {
if (!inerrno) {
if (!elsewhere
&& (instat.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) != 0)
@ -252,27 +174,19 @@ get_input_file (filename, outname)
cs = 0;
}
}
if (cs)
{
if (dry_run)
{
if (inerrno)
fatal ("can't do dry run on nonexistent version-controlled file `%s'; invoke `%s' and try again",
filename, buf);
}
else
{
if (verbosity == VERBOSE)
say ("Getting file `%s' from %s...\n", filename, cs);
if (systemic (getbuf) != 0
|| stat (filename, &instat) != 0)
fatal ("can't get file `%s' from %s", filename, cs);
inerrno = 0;
}
}
}
free (trybuf);
}
if (cs && version_get (filename, cs, ! inerrno, elsewhere, getbuf,
&instat))
inerrno = 0;
free (getbuf);
free (diffbuf);
} else if (inerrno && !pch_says_nonexistent (reverse))
{
errno = inerrno;
pfatal ("can't find file `%s'", filename);
}
if (inerrno)
{
@ -397,7 +311,7 @@ plan_b(filename)
register LINENUM line;
if (instat.st_size == 0)
filename = "/dev/null";
filename = NULL_DEVICE;
if (! (ifp = fopen (filename, binary_transput ? "rb" : "r")))
pfatal ("can't open file `%s'", filename);
tifd = create_file (TMPINNAME, O_RDWR | O_BINARY, (mode_t) 0);

View File

@ -36,6 +36,8 @@
# define const
# endif
# endif
/* MIPS RISCOS4.52 defines time_t in <sys/types.h> not <time.h>. */
# include <sys/types.h>
# if HAVE_LIMITS_H
# include <limits.h>
# endif
@ -57,7 +59,7 @@
#include <maketime.h>
char const maketId[] =
"$Id: maketime.c,v 5.13 1997/05/15 17:33:14 eggert Exp $";
"$Id: maketime.c,v 5.15 1997/06/17 16:54:36 eggert Exp $";
static int isleap P ((int));
static int month_days P ((struct tm const *));
@ -101,10 +103,10 @@ time2tm (unixtime, localzone)
int localzone;
{
struct tm *tm;
#if TZ_must_be_set
#ifdef TZ_is_unset
static char const *TZ;
if (!TZ && !(TZ = getenv ("TZ")))
faterror ("The TZ environment variable is not set; please set it to your timezone");
TZ_is_unset ("The TZ environment variable is not set; please set it to your timezone");
#endif
if (localzone || !(tm = gmtime (&unixtime)))
tm = localtime (&unixtime);
@ -114,7 +116,8 @@ time2tm (unixtime, localzone)
/* Yield A - B, measured in seconds. */
time_t
difftm (a, b)
struct tm const *a, *b;
struct tm const *a;
struct tm const *b;
{
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);

330
patch.c
View File

@ -1,6 +1,6 @@
/* patch - a program to apply diffs to original files */
/* $Id: patch.c,v 1.17 1997/05/26 05:34:43 eggert Exp $ */
/* $Id: patch.c,v 1.22 1997/06/17 22:32:49 eggert Exp $ */
/*
Copyright 1984, 1985, 1986, 1987, 1988 Larry Wall
@ -34,25 +34,46 @@ If not, write to the Free Software Foundation,
#include <util.h>
#include <version.h>
#if HAVE_UTIME_H
# include <utime.h>
#endif
/* Some nonstandard hosts don't declare this structure even in <utime.h>. */
#if ! HAVE_STRUCT_UTIMBUF
struct utimbuf
{
time_t actime;
time_t modtime;
};
#endif
/* Output stream state. */
struct outstate
{
FILE *ofp;
int after_newline;
int zero_output;
};
/* procedures */
static FILE *create_output_file PARAMS ((char const *));
static LINENUM locate_hunk PARAMS ((LINENUM));
static bool apply_hunk PARAMS ((bool *, LINENUM));
static bool copy_till PARAMS ((bool *, LINENUM));
static bool apply_hunk PARAMS ((struct outstate *, LINENUM));
static bool copy_till PARAMS ((struct outstate *, LINENUM));
static bool patch_match PARAMS ((LINENUM, LINENUM, LINENUM, LINENUM));
static bool similar PARAMS ((char const *, size_t, char const *, size_t));
static bool spew_output PARAMS ((bool *));
static bool spew_output PARAMS ((struct outstate *));
static char const *make_temp PARAMS ((int));
static int numeric_optarg PARAMS ((char const *));
static int numeric_string PARAMS ((char const *, int, char const *));
static void abort_hunk PARAMS ((void));
static void cleanup PARAMS ((void));
static void get_some_switches PARAMS ((void));
static void init_output PARAMS ((char const *));
static void init_output PARAMS ((char const *, struct outstate *));
static void init_reject PARAMS ((char const *));
static void reinitialize_almost_everything PARAMS ((void));
static void usage PARAMS ((FILE *, int)) __attribute__((noreturn));
static int backup_if_mismatch;
static int remove_empty_files;
/* TRUE if -R was specified on command line. */
@ -70,10 +91,8 @@ static char const end_defined[] = "\n#endif /* %s */\n";
static int Argc;
static char * const *Argv;
static FILE *ofp; /* output file pointer */
static FILE *rejfp; /* reject file pointer */
static char *output;
static char const *patchname;
static char *rejname;
static char const * volatile TMPREJNAME;
@ -94,7 +113,9 @@ main(argc,argv)
int argc;
char **argv;
{
char const *val;
bool somefailed = FALSE;
struct outstate outstate;
init_time ();
@ -105,8 +126,11 @@ char **argv;
strippath = INT_MAX;
patch_get = getenv ("PATCH_GET") != 0;
posixly_correct = getenv ("POSIXLY_CORRECT") != 0;
backup_if_mismatch = ! posixly_correct;
patch_get = ((val = getenv ("PATCH_GET"))
? numeric_string (val, 1, "PATCH_GET value")
: posixly_correct - 1);
{
char const *v;
@ -134,8 +158,7 @@ char **argv;
Argv = argv;
get_some_switches();
if (output)
init_output (output);
init_output (outfile, &outstate);
/* Make sure we clean up in case of disaster. */
set_signals(0);
@ -147,22 +170,32 @@ char **argv;
) { /* for each patch in patch file */
int hunk = 0;
int failed = 0;
char *outname = output ? output : inname;
int mismatch = 0;
char *outname = outfile ? outfile : inname;
if (!skip_rest_of_patch)
get_input_file (inname, outname);
if (diff_type == ED_DIFF) {
outstate.zero_output = 0;
if (! dry_run)
do_ed_script (ofp);
{
do_ed_script (outstate.ofp);
if (! outfile)
{
struct stat statbuf;
if (stat (TMPOUTNAME, &statbuf) != 0)
pfatal ("%s", TMPOUTNAME);
outstate.zero_output = statbuf.st_size == 0;
}
}
} else {
int got_hunk;
int apply_anyway = 0;
bool after_newline = TRUE;
/* initialize the patched file */
if (!skip_rest_of_patch && !output)
init_output(TMPOUTNAME);
if (! skip_rest_of_patch && ! outfile)
init_output (TMPOUTNAME, &outstate);
/* initialize reject file */
init_reject(TMPREJNAME);
@ -188,7 +221,10 @@ char **argv;
if (!skip_rest_of_patch) {
do {
where = locate_hunk(fuzz);
if (hunk == 1 && !where && !(force|apply_anyway)) {
if (! where || fuzz || last_offset)
mismatch = 1;
if (hunk == 1 && ! where && ! (force | apply_anyway)
&& reverse == reverse_flag_specified) {
/* dwim for reversed patch? */
if (!pch_swap()) {
say (
@ -221,10 +257,10 @@ char **argv;
&& ++fuzz <= mymaxfuzz);
if (skip_rest_of_patch) { /* just got decided */
if (ofp && !output)
if (outstate.ofp && ! outfile)
{
fclose (ofp);
ofp = 0;
fclose (outstate.ofp);
outstate.ofp = 0;
}
}
}
@ -233,26 +269,27 @@ char **argv;
if (skip_rest_of_patch) {
abort_hunk();
failed++;
if (verbosity != SILENT)
if (verbosity == VERBOSE)
say ("Hunk #%d ignored at %ld.\n", hunk, newwhere);
}
else if (!where
|| (where == 1 && pch_says_nonexistent (reverse)
&& input_lines)) {
&& instat.st_size)) {
if (where)
say ("\nPatch attempted to create file `%s', which already exists.\n", inname);
say ("Patch attempted to create file `%s', which already exists.\n", inname);
abort_hunk();
failed++;
if (verbosity != SILENT)
say ("Hunk #%d FAILED at %ld.\n", hunk, newwhere);
}
else {
if (! apply_hunk (&after_newline, where)) {
abort_hunk ();
failed++;
if (verbosity != SILENT)
say ("Hunk #%d FAILED at %ld.\n", hunk, newwhere);
} else if (verbosity == VERBOSE) {
else if (! apply_hunk (&outstate, where)) {
abort_hunk ();
failed++;
if (verbosity != SILENT)
say ("Hunk #%d FAILED at %ld.\n", hunk, newwhere);
} else {
if (verbosity == VERBOSE
|| (verbosity != SILENT && (fuzz || last_offset))) {
say ("Hunk #%d succeeded at %ld", hunk, newwhere);
if (fuzz)
say (" with fuzz %ld", fuzz);
@ -265,13 +302,13 @@ char **argv;
}
if (got_hunk < 0 && using_plan_a) {
if (output)
if (outfile)
fatal ("out of memory using Plan A");
say ("\n\nRan out of memory using Plan A -- trying again...\n\n");
if (ofp)
if (outstate.ofp)
{
fclose (ofp);
ofp = 0;
fclose (outstate.ofp);
outstate.ofp = 0;
}
fclose (rejfp);
continue;
@ -281,19 +318,21 @@ char **argv;
if (!skip_rest_of_patch)
{
assert (hunk);
skip_rest_of_patch = ! spew_output (&after_newline);
if (! spew_output (&outstate))
{
say ("Skipping patch.\n");
skip_rest_of_patch = TRUE;
}
}
}
/* and put the output where desired */
ignore_signals ();
if (!skip_rest_of_patch && !output) {
struct stat statbuf;
if ((remove_empty_files
|| (pch_says_nonexistent (reverse ^ 1) && !posixly_correct))
&& stat (TMPOUTNAME, &statbuf) == 0
&& statbuf.st_size == 0)
if (! skip_rest_of_patch && ! outfile) {
if (outstate.zero_output
&& (remove_empty_files
|| (pch_says_nonexistent (reverse ^ 1) == 2
&& ! posixly_correct)))
{
if (verbosity == VERBOSE)
say ("Removing file `%s'%s.\n", outname,
@ -301,16 +340,49 @@ char **argv;
if (! dry_run)
{
move_file ((char *) 0, outname, (mode_t) 0,
backup_type != none);
(backup_type != none
|| (backup_if_mismatch && (mismatch | failed))));
removedirs (outname);
}
}
else
{
if (! outstate.zero_output
&& pch_says_nonexistent (reverse ^ 1))
{
mismatch = 1;
if (verbosity != SILENT)
say ("File `%s' is not empty after patch, as expected.\n",
outname);
}
if (! dry_run)
{
time_t t;
move_file (TMPOUTNAME, outname, instat.st_mode,
backup_type != none);
(backup_type != none
|| (backup_if_mismatch && (mismatch | failed))));
if ((set_time | set_utc)
&& (t = pch_timestamp (reverse ^ 1)) != (time_t) -1)
{
struct utimbuf utimbuf;
utimbuf.actime = utimbuf.modtime = t;
if (! force && ! inerrno
&& ! pch_says_nonexistent (reverse)
&& (t = pch_timestamp (reverse)) != (time_t) -1
&& t != instat.st_mtime)
say ("not setting time of file `%s' (time mismatch)\n",
outname);
else if (! force && (mismatch | failed))
say ("not setting time of file `%s' (contents mismatch)\n",
outname);
else if (utime (outname, &utimbuf) != 0)
pfatal ("can't set timestamp on file `%s'", outname);
}
if (! inerrno && chmod (outname, instat.st_mode) != 0)
pfatal ("can't set permissions on file `%s'", outname);
}
@ -348,7 +420,7 @@ char **argv;
}
set_signals (1);
}
if (ofp && (ferror (ofp) || fclose (ofp) != 0))
if (outstate.ofp && (ferror (outstate.ofp) || fclose (outstate.ofp) != 0))
write_fatal ();
cleanup ();
if (somefailed)
@ -385,7 +457,7 @@ reinitialize_almost_everything()
skip_rest_of_patch = FALSE;
}
static char const shortopts[] = "bB:cd:D:eEfF:gGi:lnNo:p:r:RstuvV:x:Y:z:";
static char const shortopts[] = "bB:cd:D:eEfF:g:i:lnNo:p:r:RstTuvV:x:Y:z:Z";
static struct option const longopts[] =
{
{"backup", no_argument, NULL, 'b'},
@ -398,7 +470,6 @@ static struct option const longopts[] =
{"force", no_argument, NULL, 'f'},
{"fuzz", required_argument, NULL, 'F'},
{"get", no_argument, NULL, 'g'},
{"no-get", no_argument, NULL, 'G'},
{"input", required_argument, NULL, 'i'},
{"ignore-whitespace", no_argument, NULL, 'l'},
{"normal", no_argument, NULL, 'n'},
@ -410,16 +481,20 @@ static struct option const longopts[] =
{"quiet", no_argument, NULL, 's'},
{"silent", no_argument, NULL, 's'},
{"batch", no_argument, NULL, 't'},
{"set-time", no_argument, NULL, 'T'},
{"unified", no_argument, NULL, 'u'},
{"version", no_argument, NULL, 'v'},
{"version-control", required_argument, NULL, 'V'},
{"debug", required_argument, NULL, 'x'},
{"basename-prefix", required_argument, NULL, 'Y'},
{"suffix", required_argument, NULL, 'z'},
{"set-utc", no_argument, NULL, 'Z'},
{"dry-run", no_argument, NULL, 129},
{"verbose", no_argument, NULL, 130},
{"binary", no_argument, NULL, 131},
{"help", no_argument, NULL, 132},
{"backup-if-mismatch", no_argument, NULL, 133},
{"no-backup-if-mismatch", no_argument, NULL, 134},
{NULL, no_argument, NULL, 0}
};
@ -449,18 +524,22 @@ static char const *const option_help[] =
" -D NAME --ifdef=NAME Make merged if-then-else output using NAME.",
" -E --remove-empty-files Remove output files that are empty after patching.",
"",
" -Z --set-utc Set times of patched files, assuming diff uses UTC (GMT).",
" -T --set-time Likewise, assuming local time.",
"",
"Backup and version control options:",
"",
" -V STYLE --version-control=STYLE Use STYLE version control.",
" STYLE is either 'simple', 'numbered', or 'existing'.",
"",
" -b --backup Save the original contents of each file F into F.orig.",
" -b --backup Back up the original contents of each file.",
" --backup-if-mismatch Back up if the patch does not match exactly.",
" --no-backup-if-mismatch Back up mismatches only if otherwise requested.",
" -B PREFIX --prefix=PREFIX Prepend PREFIX to backup file names.",
" -Y PREFIX --basename-prefix=PREFIX Prepend PREFIX to backup file basenames.",
" -z SUFFIX --suffix=SUFFIX Append SUFFIX to backup file names.",
"",
" -g --get Get files from RCS or SCCS.",
" -G --no-get Do not get files.",
" -g NUM --get=NUM Get files from RCS or SCCS if positive; ask if negative.",
"",
"Miscellaneous options:",
"",
@ -544,7 +623,6 @@ get_some_switches()
if (!*optarg)
fatal ("backup prefix is empty");
origprae = savestr (optarg);
backup_type = simple;
break;
case 'c':
diff_type = CONTEXT_DIFF;
@ -566,13 +644,10 @@ get_some_switches()
force = TRUE;
break;
case 'F':
maxfuzz = numeric_optarg ("fuzz factor");
maxfuzz = numeric_string (optarg, 0, "fuzz factor");
break;
case 'g':
patch_get = 1;
break;
case 'G':
patch_get = 0;
patch_get = numeric_string (optarg, 1, "get option value");
break;
case 'i':
patchname = savestr (optarg);
@ -589,10 +664,10 @@ get_some_switches()
case 'o':
if (strcmp (optarg, "-") == 0)
fatal ("can't output patches to standard output");
output = savestr (optarg);
outfile = savestr (optarg);
break;
case 'p':
strippath = numeric_optarg ("strip count");
strippath = numeric_string (optarg, 0, "strip count");
break;
case 'r':
rejname = savestr (optarg);
@ -607,6 +682,9 @@ get_some_switches()
case 't':
batch = TRUE;
break;
case 'T':
set_time = 1;
break;
case 'u':
diff_type = UNI_DIFF;
break;
@ -619,21 +697,22 @@ get_some_switches()
break;
#if DEBUGGING
case 'x':
debug = numeric_optarg ("debugging option");
debug = numeric_string (optarg, 1, "debugging option");
break;
#endif
case 'Y':
if (!*optarg)
fatal ("backup basename prefix is empty");
origbase = savestr (optarg);
backup_type = simple;
break;
case 'z':
case_z:
if (!*optarg)
fatal ("backup suffix is empty");
simple_backup_suffix = savestr (optarg);
backup_type = simple;
break;
case 'Z':
set_utc = 1;
break;
case 129:
dry_run = TRUE;
@ -648,6 +727,12 @@ get_some_switches()
break;
case 132:
usage (stdout, 0);
case 133:
backup_if_mismatch = 1;
break;
case 134:
backup_if_mismatch = 0;
break;
default:
usage (stderr, 2);
}
@ -657,6 +742,7 @@ get_some_switches()
if (optind < Argc)
{
inname = savestr (Argv[optind++]);
invc = -1;
if (optind < Argc)
{
patchname = savestr (Argv[optind++]);
@ -670,30 +756,41 @@ get_some_switches()
}
}
/* Handle a numeric option of type ARGTYPE_MSGID by converting
optarg to a nonnegative integer, returning the result. */
/* Handle STRING (possibly negative if NEGATIVE_ALLOWED is nonzero)
of type ARGTYPE_MSGID by converting it to an integer,
returning the result. */
static int
numeric_optarg (argtype_msgid)
numeric_string (string, negative_allowed, argtype_msgid)
char const *string;
int negative_allowed;
char const *argtype_msgid;
{
int value = 0;
char const *p = optarg;
char const *p = string;
int sign = *p == '-' ? -1 : 1;
p += *p == '-' || *p == '+';
do
{
int v10 = value * 10;
int digit = *p - '0';
int signed_digit = sign * digit;
int next_value = v10 + signed_digit;
if (9 < (unsigned) digit)
fatal ("%s `%s' is not a number", argtype_msgid, optarg);
fatal ("%s `%s' is not a number", argtype_msgid, string);
if (v10 / 10 != value || v10 + digit < v10)
fatal ("%s `%s' is too large", argtype_msgid, optarg);
if (v10 / 10 != value || (next_value < v10) != (signed_digit < 0))
fatal ("%s `%s' is too large", argtype_msgid, string);
value = v10 + digit;
value = next_value;
}
while (*++p);
if (value < 0 && ! negative_allowed)
fatal ("%s `%s' is negative", argtype_msgid, string);
return value;
}
@ -825,9 +922,9 @@ abort_hunk()
/* We found where to apply it (we hope), so do it. */
static bool
apply_hunk (after_newline, where)
bool *after_newline;
LINENUM where;
apply_hunk (outstate, where)
struct outstate *outstate;
LINENUM where;
{
register LINENUM old = 1;
register LINENUM lastline = pch_ptrn_lines ();
@ -835,7 +932,7 @@ LINENUM where;
register enum {OUTSIDE, IN_IFNDEF, IN_IFDEF, IN_ELSE} def_state = OUTSIDE;
register char const *R_do_defines = do_defines;
register LINENUM pat_end = pch_end ();
register FILE *fp = ofp;
register FILE *fp = outstate->ofp;
where--;
while (pch_char(new) == '=' || pch_char(new) == '\n')
@ -843,21 +940,23 @@ LINENUM where;
while (old <= lastline) {
if (pch_char(old) == '-') {
assert (*after_newline);
if (! copy_till (after_newline, where + old - 1))
assert (outstate->after_newline);
if (! copy_till (outstate, where + old - 1))
return FALSE;
if (R_do_defines) {
if (def_state == OUTSIDE) {
fprintf (fp, *after_newline + if_defined, R_do_defines);
fprintf (fp, outstate->after_newline + if_defined,
R_do_defines);
def_state = IN_IFNDEF;
}
else if (def_state == IN_IFDEF) {
fprintf (fp, *after_newline + else_defined);
fprintf (fp, outstate->after_newline + else_defined);
def_state = IN_ELSE;
}
if (ferror (fp))
write_fatal ();
*after_newline = pch_write_line (old, fp);
outstate->after_newline = pch_write_line (old, fp);
outstate->zero_output = 0;
}
last_frozen_line++;
old++;
@ -866,21 +965,23 @@ LINENUM where;
break;
}
else if (pch_char(new) == '+') {
if (! copy_till (after_newline, where + old - 1))
if (! copy_till (outstate, where + old - 1))
return FALSE;
if (R_do_defines) {
if (def_state == IN_IFNDEF) {
fprintf (fp, *after_newline + else_defined);
fprintf (fp, outstate->after_newline + else_defined);
def_state = IN_ELSE;
}
else if (def_state == OUTSIDE) {
fprintf (fp, *after_newline + if_defined, R_do_defines);
fprintf (fp, outstate->after_newline + if_defined,
R_do_defines);
def_state = IN_IFDEF;
}
if (ferror (fp))
write_fatal ();
}
*after_newline = pch_write_line (new, fp);
outstate->after_newline = pch_write_line (new, fp);
outstate->zero_output = 0;
new++;
}
else if (pch_char(new) != pch_char(old)) {
@ -892,10 +993,10 @@ LINENUM where;
pch_hunk_beg() + new);
}
else if (pch_char(new) == '!') {
assert (*after_newline);
if (! copy_till (after_newline, where + old - 1))
assert (outstate->after_newline);
if (! copy_till (outstate, where + old - 1))
return FALSE;
assert (*after_newline);
assert (outstate->after_newline);
if (R_do_defines) {
fprintf (fp, not_defined, R_do_defines);
if (ferror (fp))
@ -906,7 +1007,7 @@ LINENUM where;
do
{
if (R_do_defines) {
*after_newline = pch_write_line (old, fp);
outstate->after_newline = pch_write_line (old, fp);
}
last_frozen_line++;
old++;
@ -914,7 +1015,7 @@ LINENUM where;
while (pch_char (old) == '!');
if (R_do_defines) {
fprintf (fp, *after_newline + else_defined);
fprintf (fp, outstate->after_newline + else_defined);
if (ferror (fp))
write_fatal ();
def_state = IN_ELSE;
@ -922,54 +1023,59 @@ LINENUM where;
do
{
*after_newline = pch_write_line (new, fp);
outstate->after_newline = pch_write_line (new, fp);
new++;
}
while (pch_char (new) == '!');
outstate->zero_output = 0;
}
else {
assert(pch_char(new) == ' ');
old++;
new++;
if (R_do_defines && def_state != OUTSIDE) {
fprintf (fp, *after_newline + end_defined, R_do_defines);
fprintf (fp, outstate->after_newline + end_defined,
R_do_defines);
if (ferror (fp))
write_fatal ();
*after_newline = TRUE;
outstate->after_newline = 1;
def_state = OUTSIDE;
}
}
}
if (new <= pat_end && pch_char(new) == '+') {
if (! copy_till (after_newline, where + old - 1))
if (! copy_till (outstate, where + old - 1))
return FALSE;
if (R_do_defines) {
if (def_state == OUTSIDE) {
fprintf (fp, *after_newline + if_defined, R_do_defines);
fprintf (fp, outstate->after_newline + if_defined,
R_do_defines);
def_state = IN_IFDEF;
}
else if (def_state == IN_IFNDEF) {
fprintf (fp, *after_newline + else_defined);
fprintf (fp, outstate->after_newline + else_defined);
def_state = IN_ELSE;
}
if (ferror (fp))
write_fatal ();
outstate->zero_output = 0;
}
do
{
if (!*after_newline && putc ('\n', fp) == EOF)
if (! outstate->after_newline && putc ('\n', fp) == EOF)
write_fatal ();
*after_newline = pch_write_line (new, fp);
outstate->after_newline = pch_write_line (new, fp);
outstate->zero_output = 0;
new++;
}
while (new <= pat_end && pch_char (new) == '+');
}
if (R_do_defines && def_state != OUTSIDE) {
fprintf (fp, *after_newline + end_defined, R_do_defines);
fprintf (fp, outstate->after_newline + end_defined, R_do_defines);
if (ferror (fp))
write_fatal ();
*after_newline = TRUE;
outstate->after_newline = 1;
}
return TRUE;
}
@ -990,10 +1096,13 @@ create_output_file (name)
/* Open the new file. */
static void
init_output(name)
init_output (name, outstate)
char const *name;
struct outstate *outstate;
{
ofp = create_output_file (name);
outstate->ofp = name ? create_output_file (name) : (FILE *) 0;
outstate->after_newline = 1;
outstate->zero_output = 1;
}
/* Open a file to put hunks we can't locate. */
@ -1008,12 +1117,12 @@ init_reject(name)
/* Copy input file to output, up to wherever hunk is to be applied. */
static bool
copy_till (after_newline, lastline)
register bool *after_newline;
copy_till (outstate, lastline)
register struct outstate *outstate;
register LINENUM lastline;
{
register LINENUM R_last_frozen_line = last_frozen_line;
register FILE *fp = ofp;
register FILE *fp = outstate->ofp;
register char const *s;
size_t size;
@ -1027,10 +1136,11 @@ copy_till (after_newline, lastline)
s = ifetch (++R_last_frozen_line, 0, &size);
if (size)
{
if ((!*after_newline && putc ('\n', fp) == EOF)
if ((! outstate->after_newline && putc ('\n', fp) == EOF)
|| ! fwrite (s, sizeof *s, size, fp))
write_fatal ();
*after_newline = s[size - 1] == '\n';
outstate->after_newline = s[size - 1] == '\n';
outstate->zero_output = 0;
}
}
last_frozen_line = R_last_frozen_line;
@ -1040,21 +1150,21 @@ copy_till (after_newline, lastline)
/* Finish copying the input file to the output file. */
static bool
spew_output (after_newline)
bool *after_newline;
spew_output (outstate)
struct outstate *outstate;
{
if (debug & 256)
say ("il=%ld lfl=%ld\n", input_lines, last_frozen_line);
if (last_frozen_line < input_lines)
if (! copy_till (after_newline, input_lines))
if (! copy_till (outstate, input_lines))
return FALSE;
if (ofp && !output)
if (outstate->ofp && ! outfile)
{
if (fclose (ofp) != 0)
if (fclose (outstate->ofp) != 0)
write_fatal ();
ofp = 0;
outstate->ofp = 0;
}
return TRUE;

507
patch.man
View File

@ -2,7 +2,7 @@
.de Id
.ds Dt \\$4
..
.Id $Id: patch.man,v 1.16 1997/05/30 08:03:48 eggert Exp $
.Id $Id: patch.man,v 1.20 1997/06/17 22:32:49 eggert Exp $
.ds = \-\^\-
.de Sp
.if t .sp .3
@ -20,7 +20,7 @@ patch \- apply a diff file to an original
.Sp
but usually just
.Sp
.BI "patch \-p" "number"
.BI "patch \-p" "num"
.BI < patchfile
.SH DESCRIPTION
.B patch
@ -115,9 +115,6 @@ As each hunk is completed, you are told if the hunk
failed, and if so which line (in the new file)
.B patch
thought the hunk should go on.
If the
.B \*=verbose
option is given, you are also told about hunks that succeeded.
If the hunk is installed at a different line
from the line number specified in the diff you
are told the offset.
@ -127,38 +124,76 @@ indicate that a hunk was installed in the
wrong place.
You are also told if a fuzz factor was used to make the match, in which
case you should also be slightly suspicious.
If the
.B \*=verbose
option is given, you are also told about hunks that match exactly.
.PP
If no original file
.I origfile
is specified on the command line,
.B patch
tries to figure out from the leading garbage what the name of the file
to edit is.
to edit is, using the following rules.
.TP 3
.B " \(bu"
If the header is that of a context diff,
.B patch
takes the old and new file names in the header,
and if there is an
.B Index:\&
line in the leading garbage,
.B patch
obtains the name in that line; any
takes the old and new file names in the header.
Any
.B /dev/null
names are ignored.
These names are considered to be in the order (old, new, index),
.TP
.B " \(bu"
If there is an
.B Index:\&
line in the leading garbage
and if either the old and new names are both absent or the
.B POSIXLY_CORRECT
environment variable is set,
.B patch
takes the name in the
.B Index:\&
line.
.TP
.B " \(bu"
For the purpose of the following rules,
the names are considered to be in the order (old, new, index),
regardless of the order that they appear in the header.
.TP
.B " \(bu"
If some of the named files exist,
.B patch
uses the first name if the
.B POSIXLY_CORRECT
environment variable is set, and the best name otherwise.
If no named files exist, some names are given,
.TP
.B " \(bu"
If
.B patch
is not ignoring \s-1RCS\s0 and \s-1SCCS\s0 (see the
.BI "\-g " num
or
.BI \*=get= num
option), and no named files exist
but an \s-1RCS\s0 or \s-1SCCS\s0 master is found,
.B patch
uses the first named file with an \s-1RCS\s0 or \s-1SCCS\s0 master.
.TP
.B " \(bu"
If no named files exist, no \s-1RCS\s0 or \s-1SCCS\s0 master was found,
some names are given,
.B POSIXLY_CORRECT
is not set, and the patch appears to create a file,
.B patch
uses the best name requiring the creation of the fewest directories.
.TP
.B " \(bu"
If no file name results from the above heuristics, you are asked
for the name of the file to patch.
To determine the best of a nonempty list of file names,
.LP
To determine the
.I best
of a nonempty list of file names,
.B patch
first takes all the names with the fewest path name components;
of those, it then takes all the names with the shortest basename;
@ -175,22 +210,6 @@ If not,
.B patch
asks for confirmation before proceeding.
.PP
If an
\s-1RCS\s0 file is handy,
and the original file cannot be found
or is read-only and matches the default version,
and if version control
(see the
.B \-V
or
.B \*=version\-control
option)
is set to
.BR existing ,
.B patch
attempts to get and lock the file.
\s-1SCCS\s0 is treated in a similar way.
.PP
The upshot of all this is that you should be able to say, while in a news
interface, something like the following:
.Sp
@ -213,20 +232,38 @@ mentioned previously.
.TP 3
\fB\-b\fP or \fB\*=backup\fP
Make backup files.
That is, when patching a file,
rename or copy the original instead of removing it.
When backing up a file that does not exist,
an empty, unreadable backup file is created
as a placeholder to represent the nonexistent file.
.Sp
This option is equivalent to
.BR \*=version\-control=simple ;
see the
.B \-V
or
.B \*=version\-control
option for details.
In older versions of
.BR patch ,
this option had an argument specifying the simple backup suffix;
this argument has been moved to the
.B \-z
option.
.TP
.B \*=backup\-if\-mismatch
Back up a file if the patch does not match the file exactly
and if backups are not otherwise requested.
The backup file name is calculated as usual,
except that if the version control method is
.BR none ,
a simple backup name is used.
This is the default unless the
.B POSIXLY_CORRECT
environment variable is set.
.TP
.B \*=no\-backup\-if\-mismatch
Do not back up a file if the patch does not match the file exactly
and if backups are not otherwise requested.
This is the default if the
.B POSIXLY_CORRECT
environment variable is set.
.TP
\fB\-B\fP \fIpref\fP or \fB\*=prefix=\fP\fIpref\fP
Prefix simple backup file names with
.IR pref .
@ -249,20 +286,17 @@ the patch should be generated by
\fB\-c\fP or \fB\*=context\fP
Interpret the patch file as a ordinary context diff.
.TP
\fB\*=verbose\fP
Output extra information about the work being done.
.TP
\fB\-d\fP \fIdir\fP or \fB\*=directory=\fP\fIdir\fP
Change to the directory
.I dir
immediately, before doing
anything else.
.TP
\fB\-D\fP \fIsym\fP or \fB\*=ifdef=\fP\fIsym\fP
\fB\-D\fP \fIdefine\fP or \fB\*=ifdef=\fP\fIdefine\fP
Use the
.BR #ifdef " .\|.\|. " #endif
construct to mark changes, with
.I sym
.I define
as the differentiating symbol.
.TP
.B "\*=dry\-run"
@ -277,7 +311,7 @@ script.
Remove output files that are empty after the patches have been applied.
Normally this option is unnecessary, since
.B patch
can examine the timestamps on the header to determine whether a file
can examine the time stamps on the header to determine whether a file
should exist after patching.
However, if the input is not a context diff or if the
.B POSIXLY_CORRECT
@ -300,7 +334,7 @@ This option does not suppress commentary; use
.B \-s
for that.
.TP
\fB\-F\fP \fInumber\fP or \fB\*=fuzz=\fP\fInumber\fP
\fB\-F\fP \fInum\fP or \fB\*=fuzz=\fP\fInum\fP
Set the maximum fuzz factor.
This option only applies to diffs that have context, and causes
.B patch
@ -309,19 +343,25 @@ Note that a larger fuzz factor increases the odds of a faulty patch.
The default fuzz factor is 2, and it may not be set to more than
the number of lines of context in the context diff, ordinarily 3.
.TP
\fB\-g\fP or \fB\*=get\fP
If a file does not exist or is read-only and matches the default version,
get it from \s-1RCS\s0 if it is under \s-2RCS\s0 control;
similarly for \s-1SCCS\s0.
If the
\fB\-g\fP \fInum\fP or \fB\*=get=\fP\fInum\fP
This option controls
.BR patch 's
actions when a file is under \s-1RCS\s0 or \s-1SCCS\s0 control,
and does not exist or is read-only and matches the default version.
If
.I num
is positive,
.B patch
gets (or checks out) the file from the revision control system; if zero,
.B patch
ignores \s-1RCS\s0 and \s-1SCCS\s0 and does not get the file; and if negative,
.B patch
asks the user whether to get the file.
The default value of this option is given by the value of the
.B PATCH_GET
environment variable is set, this is the default.
.TP
\fB\-G\fP or \fB\*=no\-get\fP
Do not get files from \s-1RCS\s0 or \s-2SCCS\s0.
This is the default unless the
.B PATCH_GET
environment variable is set.
environment variable if it is set; if not, the default value is zero if
.B POSIXLY_CORRECT
is set, negative otherwise.
.TP
.B "\*=help"
Print a summary of options and exit.
@ -351,14 +391,14 @@ Ignore patches that seem to be reversed or already applied.
See also
.BR \-R .
.TP
\fB\-o\fP \fIfile\fP or \fB\*=output=\fP\fIfile\fP
\fB\-o\fP \fIoutfile\fP or \fB\*=output=\fP\fIoutfile\fP
Send output to
.I file
.I outfile
instead of patching files in place.
.TP
\fB\-p\fP\fInumber\fP or \fB\*=strip\fP\fB=\fP\fInumber\fP
\fB\-p\fP\fInum\fP or \fB\*=strip\fP\fB=\fP\fInum\fP
Strip the smallest prefix containing
.I number
.I num
leading slashes from each file name found in the patch file.
A sequence of one or more adjacent slashes is counted as a single slash.
This controls how file names found in the patch file are treated, in case
@ -389,19 +429,10 @@ Whatever you end up with is looked for either in the current directory,
or the directory specified by the
.B \-d
option.
With \s-1GNU\s0
.BR patch ,
the two-argument
.BI "\-p " N
form of this option is equivalent to one-argument
.BI \-p N
form, but this is not true of traditional
.BR patch ,
so the one-argument form is recommended for portability.
.TP
\fB\-r\fP \fIfile\fP or \fB\*=reject\-file=\fP\fIfile\fP
\fB\-r\fP \fIrejectfile\fP or \fB\*=reject\-file=\fP\fIrejectfile\fP
Put rejects into
.I file
.I rejectfile
instead of the default
.B \&.rej
file.
@ -449,6 +480,19 @@ line
in the patch; and assume that patches are reversed if they look like
they are.
.TP
\fB\-T\fP or \fB\*=set\-time\fP
Set the modification and access times of patched files from time stamps
given in context diff headers, assuming that the context diff headers
use local time. This option is not recommended, because patches using
local time cannot easily be used by people in other time zones, and
because local time stamps are ambiguous when local clocks move backwards
during daylight-saving time adjustments. Instead of using this option,
generate patches with \s-1UTC\s0 and use the
.B \-Z
or
.B \*=set\-utc
option instead.
.TP
\fB\-u\fP or \fB\*=unified\fP
Interpret the patch file as a unified context diff.
.TP
@ -460,8 +504,8 @@ revision header and patch level, and exit.
\fB\-V\fP \fImethod\fP or \fB\*=version\-control=\fP\fImethod\fP
Use
.I method
when creating
backup file names. The type of backups made can also be given in the
to determine
backup file names. The method can also be given by the
.B PATCH_VERSION_CONTROL
(or, if that's not set, the
.BR VERSION_CONTROL )
@ -484,7 +528,8 @@ Make numbered backups of files that already have them,
otherwise simple backups.
.TP
\fBnone\fP
Do not make backups.
Do not make backups, unless backup-if-mismatch is in effect
and patches do not match files.
This is the default.
.TP
\fBnumbered\fP or \fBt\fP
@ -497,9 +542,7 @@ where
is the version number.
.TP
\fBsimple\fP or \fBnever\fP
Make simple backups. That is, when patching a file
.IR F ,
rename or copy the original instead of removing it.
Make simple backups.
The
.B \-B
or
@ -529,7 +572,10 @@ would make the name too long, then
replaces the last character of the file name.
.RE
.TP
\fB\-x\fP \fInumber\fP or \fB\*=debug=\fP\fInumber\fP
\fB\*=verbose\fP
Output extra information about the work being done.
.TP
\fB\-x\fP \fInum\fP or \fB\*=debug=\fP\fInum\fP
Set internal debugging flags of interest only to
.B patch
patchers.
@ -544,23 +590,72 @@ the backup file name for
is
.BR src/patch/.del/util.c .
.TP
\fB\-z\fP \fIsuff\fP or \fB\*=suffix=\fP\fIsuff\fP
\fB\-z\fP \fIsuffix\fP or \fB\*=suffix=\fP\fIsuffix\fP
Use
.I suff
.I suffix
as the simple backup suffix.
The backup extension may also be specified by the
.B SIMPLE_BACKUP_SUFFIX
environment variable, which is overridden by this option.
.TP
\fB\-Z\fP or \fB\*=set\-utc\fP
Set the modification and access times of patched files from time stamps
given in context diff headers, assuming that the context diff headers
use Coordinated Universal Time (\s-1UTC\s0, often known as \s-1GMT\s0).
Also see the
.B \-T
or
.B \*=set\-time
option.
.Sp
The
.B \-Z
or
.B \*=set\-utc
and
.B \-T
or
.B \*=set\-time
options normally refrain from setting a file's time if the file's original time
does not match the time given in the patch header, or if its
contents do not match the patch exactly. However, if the
.B \-f
or
.B \*=force
option is given, the file time is set regardless.
.Sp
Due to the limitations of
.B diff
output format, these options cannot update the times of files whose
contents have not changed. Also, if you use these options, you should remove
(e.g. with
.BR "make\ clean" )
all files that depend on the patched files, so that later invocations of
.B make
do not get confused by the patched files' times.
.SH ENVIRONMENT
.TP 3
\fBPATCH_GET\fP
This specifies whether
.B patch
gets missing or read-only files from \s-1RCS\s0 or \s-1SCCS\s0
by default; see the
.B \-g
or
.B \*=get
option.
.TP
.B POSIXLY_CORRECT
If set,
.B patch
conforms more strictly to the \s-1POSIX\s0 standard:
it takes the first existing file when intuiting file names from diff headers,
it takes the first existing file from the list (old, new, index)
when intuiting file names from diff headers,
it does not remove files that are empty after patching,
and it requires that all options precede the
files in the command line.
it does not ask whether to get files from \s-1RCS\s0 or \s-1SCCS\s0,
it requires that all options precede the
files in the command line,
and by default it does not make backup files.
.TP
.B SIMPLE_BACKUP_SUFFIX
Extension to use for simple backup file names instead of
@ -575,33 +670,19 @@ it is normally
.B /tmp
on Unix hosts.
.TP
\fBPATCH_VERSION_CONTROL\fP or \fBVERSION_CONTROL\fP
\fBVERSION_CONTROL\fP or \fBPATCH_VERSION_CONTROL\fP
Selects version control style; see the
.B \-v
or
.B \*=version\-control
option.
.TP
\fBPATCH_GET\fP
If set,
.B patch
gets missing or read-only files from \s-1RCS\s0 or \s-1SCCS\s0
by default; see the
.B \-g
or
.B \*= get
and the
.B \-G
or
.B \*= no\-get
options.
.SH FILES
.TP 3
.IB $TMPDIR "/p\(**"
temporary files
.TP
.B /dev/tty
console; used to get answers to questions asked of the user
controlling terminal; used to get answers to questions asked of the user
.SH "SEE ALSO"
.BR diff (1),
.BR ed (1)
@ -622,9 +703,18 @@ The names
and
.I new
should not contain any slashes.
Here is an example:
The
.B diff
command's headers should have dates
and times in Universal Time using traditional Unix format,
so that patch recipients can use the
.B \-Z
or
.B \*=set\-utc
option.
Here is an example command, using Bourne shell syntax:
.Sp
\fBdiff \-Naur version\-2.2 version\-2.3\fP
\fBLC_ALL=C TZ=UTC0 diff \-Naur gcc\-2.7 gcc\-2.8\fP
.PP
Tell your recipients how to apply the patch
by telling them which directory to
@ -646,19 +736,14 @@ If you put a
line in with the patch, it won't let them apply
patches out of order without some warning.
.PP
Make sure you've specified the file names right, either in a
context diff header, or with an
.B Index:\&
line.
.PP
You can create a file by sending out a diff that compares an
empty file (such as
.BR /dev/null )
You can create a file by sending out a diff that compares
.B /dev/null
or an empty file dated the Epoch (1970-01-01 00:00:00 \s-1UTC\s0)
to the file you want to create.
This only works if the file you want to create doesn't exist already in
the target directory.
Conversely, you can remove a file by sending out a diff that compares the
file to be deleted with an empty file.
Conversely, you can remove a file by sending out a context diff that compares
the file to be deleted with an empty file dated the Epoch.
The file will be removed unless the
.B POSIXLY_CORRECT
environment variable is set and the
@ -669,6 +754,8 @@ option is not given.
An easy way to generate patches that create and remove files
is to use \s-1GNU\s0
.BR diff 's
.B \-N
or
.B \*=new\-file
option.
.PP
@ -723,49 +810,14 @@ where there is a line
in your makefile), since the recipient should be
able to regenerate the derived files anyway.
If you must send diffs of derived files,
ensure that the diffs for each derived file
follow the diffs for the files that it depends on,
so that the dependencies will be preserved as
.B patch
updates the files one by one.
Here is a sample shell script that output patches in an order that
should preserve dependencies:
.nf
.Sp
.ft B
.in +3n
#! /bin/sh
.Sp
.ne 2
old=${1?}
new=${2?}
.Sp
.ne 10
fs=
for f in `
diff \-Nqr $old $new |
sed \-e "s,.\(** $new/,," \-e 's, differ$,,'`
do
if [ \-f $new/$f ]
then fs="$fs $f"
else diff \-au $old/$f /dev/null
fi
done
.Sp
.ne 10
case $fs in
?\(**)
for f in `cd $new; ls \-rt $fs`
do
if [ \-f $old/$f ]
then diff \-au $old/$f $new/$f
else diff \-au /dev/null $new/$f
fi
done
esac
.in
.ft
.fi
generate the diffs using \s-1UTC\s0,
have the recipients apply the patch with the
.B \-Z
or
.B \*=set\-utc
option, and have them remove any unpatched files that depend on patched files
(e.g. with
.BR "make\ clean" ).
.PP
While you may be able to get away with putting 582 diff listings into
one file, it may be wiser to group related patches into separate files in
@ -817,6 +869,150 @@ guessing.
However, the results are guaranteed to be correct only when the patch is
applied to exactly the same version of the file that the patch was
generated from.
.SH "COMPATIBILITY ISSUES"
The \s-1POSIX\s0 standard specifies behavior that differs from
.BR patch 's
traditional behavior.
You should be aware of these differences if you must interoperate with
.B patch
versions 2.1 and earlier, which are not \s-1POSIX\s0-compliant.
.TP 3
.B " \(bu"
In traditional
.BR patch ,
the
.B \-p
option's operand was optional, and a bare
.B \-p
was equivalent to
.BR \-p0.
The
.B \-p
option now requires an operand, and
.B "\-p\ 0"
is now equivalent to
.BR \-p0 .
For maximum compatibility, use options like
.B \-p0
and
.BR \-p1 .
.Sp
Also,
traditional
.B patch
simply counted slashes when stripping path prefixes;
.B patch
now counts pathname components.
That is, a sequence of one or more adjacent slashes
now counts as a single slash.
For maximum portability, avoid sending patches containing
.B //
in file names.
.TP
.B " \(bu"
In traditional
.BR patch ,
simple backups were enabled by default.
This behavior is now enabled with the
.B \-b
or
.B \*=backup
option, or by setting the
.B VERSION_CONTROL
environment variable to
.BR simple .
.Sp
Conversely, in \s-1POSIX\s0
.BR patch ,
backups are never made, even when there is a mismatch.
In \s-1GNU\s0
.BR patch ,
this behavior is enabled with the
.B \*=no\-backup\-if\-mismatch
option or by setting the
.B POSIXLY_CORRECT
environment variable.
.Sp
The
.BI \-b " suffix"
option
of traditional
.B patch
is equivalent to the
.BI "\-b \-z" " suffix"
options of \s-1GNU\s0
.BR patch .
.TP
.B " \(bu"
Traditional
.B patch
used a complicated (and incompletely documented) method
to intuit the name of the file to be patched from the patch header.
This method was not \s-1POSIX\s0-compliant, and had a few gotchas.
Now
.B patch
uses a different, equally complicated (but better documented) method
that is optionally \s-1POSIX\s0-compliant; we hope it has
fewer gotchas. The two methods are compatible if the
file names in the context diff header and the
.B Index:\&
line are all identical after prefix-stripping.
Your patch is normally compatible if each header's file names
all contain the same number of slashes.
.TP
.B " \(bu"
When traditional
.B patch
asked the user a question, it sent the question to standard error
and looked for an answer from
the first file in the following list that was a terminal:
standard error, standard output,
.BR /dev/tty ,
and standard input.
Now
.B patch
sends questions to standard output and gets answers from
.BR /dev/tty .
Defaults for some answers have been changed so that
.B patch
never goes into an infinite loop when using default answers.
.TP
.B " \(bu"
Traditional
.B patch
exited with a status value that counted the number of bad hunks,
or with status 1 if there was real trouble.
Now
.B patch
exits with status 1 if some hunks failed,
or with 2 if there was real trouble.
.TP
.B " \(bu"
Limit yourself to the following options when sending instructions
meant to be executed by anyone running \s-1GNU\s0
.BR patch ,
traditional
.BR patch ,
or a \s-1POSIX\s0-compliant
.BR patch .
Spaces are significant in the following list, and operands are required.
.Sp
.nf
.in +3
.ne 11
.B \-c
.BI \-d " dir"
.BI \-D " define"
.B \-e
.B \-l
.B \-n
.B \-N
.BI \-o " outfile"
.BI \-p num
.B \-R
.BI \-r " rejectfile"
.in
.fi
.SH BUGS
.B patch
could be smarter about partial matches, excessively deviant offsets and
@ -860,7 +1056,8 @@ Larry Wall wrote the original version of
.BR patch .
Paul Eggert removed
.BR patch 's
arbitrary limits, added support for binary files,
arbitrary limits; added support for binary files,
setting file times, and deleting files;
and made it conform better to \s-1POSIX\s0.
Other contributors include Wayne Davison, who added unidiff support,
and David MacKenzie, who added configuration and backup support.

View File

@ -1,139 +0,0 @@
/* config.h for compiling `patch' with DJGPP for MS-DOS and MS-Windows.
Please keep this file as similar as possible to ../../config.h
to simplify maintenance later. */
/* This does most of the work; the rest of this file defines only those
symbols that <sys/config.h> doesn't define correctly. */
#include <sys/config.h>
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
/* #undef _ALL_SOURCE */
#endif
/* Define if the closedir function returns void instead of int. */
/* #undef CLOSEDIR_VOID */
/* Define to empty if the keyword does not work. */
/* #undef const */
/* Define if you don't have vprintf but do have _doprnt. */
/* #undef HAVE_DOPRNT */
/* Define if you support file names longer than 14 characters. */
#define HAVE_LONG_FILE_NAMES 1
/* Define if you have the vprintf function. */
#define HAVE_VPRINTF 1
/* Define if on MINIX. */
/* #undef _MINIX */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef mode_t */
/* Define to `long' if <sys/types.h> doesn't define. */
/* #undef off_t */
/* Define if the system does not provide POSIX.1 features except
with this defined. */
/* #undef _POSIX_1_SOURCE */
/* Define if you need to in order for stat and other things to work. */
/* #undef _POSIX_SOURCE */
/* Define as the return type of signal handlers (int or void). */
/* #undef RETSIGTYPE */
/* Define to `unsigned' if <sys/types.h> doesn't define. */
/* #undef size_t */
/* Define if you have the ANSI C header files. */
/* #undef STDC_HEADERS */
/* Define if there is a member named d_ino in the struct describing
directory headers. */
/* #undef D_INO_IN_DIRENT */
/* Define if memchr works. */
/* #undef HAVE_MEMCHR */
/* Define if you have the _doprintf function. */
/* #undef HAVE__DOPRINTF */
/* Define if you have the isascii function. */
/* #undef HAVE_ISASCII */
/* Define if you have the memchr function. */
/* #undef HAVE_MEMCHR 1 */
/* Define if you have the memcmp function. */
#define HAVE_MEMCMP 1
/* Define if you have the mkdir function. */
/* #undef HAVE_MKDIR */
/* Define if you have the mktemp function. */
#define HAVE_MKTEMP 1
/* Define if you have the pathconf function. */
#define HAVE_PATHCONF 1
/* Define if you have the rename function. */
/* #undef HAVE_RENAME */
/* Define if you have the sigaction function. */
/* #undef HAVE_SIGACTION */
/* Define if you have the sigprocmask function. */
#define HAVE_SIGPROCMASK 1
/* Define if you have the sigsetmask function. */
/* #undef HAVE_SIGSETMASK */
/* Define if you have the <dirent.h> header file. */
/* #undef HAVE_DIRENT_H */
/* Define if you have the <fcntl.h> header file. */
/* #undef HAVE_FCNTL_H */
/* Define if you have the <limits.h> header file. */
/* #undef HAVE_LIMITS_H */
/* Define if you have the <ndir.h> header file. */
/* #undef HAVE_NDIR_H */
/* Define if you have the <string.h> header file. */
/* #undef HAVE_STRING_H */
/* Define if you have the <sys/dir.h> header file. */
/* #undef HAVE_SYS_DIR_H */
/* Define if you have the <sys/ndir.h> header file. */
/* #undef HAVE_SYS_NDIR_H */
/* Define if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */
/* Define if you have the <varargs.h> header file. */
/* #undef HAVE_VARARGS_H */
/* PC-specific definitions */
#define chdir chdir_safer
int chdir_safer (char const *);
#define FILESYSTEM_PREFIX_LEN(f) ((f)[0] && (f)[1] == ':' ? 2 : 0)
#define ISSLASH(c) ((c) == '/' || (c) == '\\')
#define HAVE_DOS_FILE_NAMES 1
#define HAVE_SETMODE 1
#ifdef WIN32
# define setmode _setmode
#endif
#define TMPDIR "c:"

View File

@ -1,35 +1,38 @@
# Edit Makefile.in to produce Makefile for DJGPP v2
# $Id: config.sed,v 1.4 1997/05/26 17:52:29 eggert Exp $
1c\
/* config.h for compiling `patch' with DJGPP for MS-DOS and MS-Windows.\
Please keep this file as similar as possible to ../../config.h\
to simplify maintenance later. */\
\
/* This does most of the work; the rest of this file defines only those\
symbols that <sys/config.h> doesn't define correctly. */\
#include <sys/config.h>
1i\
# Makefile generated by "configure.bat" for DJGPP v2\
s/#undef HAVE_LONG_FILE_NAMES/#define HAVE_LONG_FILE_NAMES 1/
s/#undef HAVE_MEMCMP/#define HAVE_MEMCMP 1/
s/#undef HAVE_MKTEMP/#define HAVE_MKTEMP 1/
s/#undef HAVE_PATHCONF/#define HAVE_PATHCONF 1/
s/#undef HAVE_RAISE/#define HAVE_RAISE 1/
s/#undef HAVE_SIGPROCMASK/#define HAVE_SIGPROCMASK 1/
s/#undef HAVE_UTIME_H/#define HAVE_UTIME_H 1/
s/#undef HAVE_STRUCT_UTIMBUF/#define HAVE_STRUCT_UTIMBUF 1/
s/#undef HAVE_VPRINTF/#define HAVE_VPRINTF 1/
/@SET_MAKE@/d
s|@CC@|gcc|g
s|@ed_PROGRAM@|ed|g
s|@INSTALL@|${DJDIR}/bin/ginstall -c|g
s|@INSTALL_PROGRAM@|${INSTALL}|g
s|@INSTALL_DATA@|${INSTALL} -m 644|g
s|@CFLAGS@|-g -O2|g
s|@CPPFLAGS@|-I$(srcdir)/pc/djgpp|g
s|@DEFS@|-DHAVE_CONFIG_H|g
s|@LDFLAGS@||g
s|@LIBOBJS@|getopt1.o getopt.o chdirsaf.o|g
s|@LIBS@||g
s|@PACKAGE@|patch|g
/@VERSION@/d
s|@prefix@|${DJDIR}|g
s|@exec_prefix@|${prefix}|g
/^CONFIG_HDRS *=/s|=.*|= pc/djgpp/config.h|
/^CONFIG_STATUS *=/s|=.*|= $(srcdir)/pc/djgpp/configure.bat|
/^ \$(SHELL) \$(CONFIG_STATUS) *$/s// $(CONFIG_STATUS) $(srcdir)/
s,#undef.*,/* & */,
$a\
chdirsaf.o: chdirsaf.c\
# Use sed instead of cp, since cp might not be installed.\
chdirsaf.c: pc/chdirsaf.c; sed -e '' $? > $@\
distclean::; rm -f chdirsaf.c
/* DGJPP-specific definitions */\
\
#define chdir chdir_safer\
int chdir_safer (char const *);\
\
#define FILESYSTEM_PREFIX_LEN(f) ((f)[0] && (f)[1] == ':' ? 2 : 0)\
#define ISSLASH(c) ((c) == '/' || (c) == '\\\\')\
\
#define HAVE_DOS_FILE_NAMES 1\
\
#define HAVE_SETMODE 1\
#ifdef WIN32\
# define setmode _setmode\
#endif\
\
#define TMPDIR "c:"

View File

@ -1,6 +1,6 @@
@echo off
Rem Configure patch for DJGPP v2.
Rem $Id: configure.bat,v 1.3 1997/05/26 17:52:29 eggert Exp $
Rem $Id: configure.bat,v 1.4 1997/06/17 06:52:12 eggert Exp $
Rem The DOS shell has fixed-size environment storage.
Rem When the environment is full, the shell prints
@ -15,7 +15,7 @@ if not "%1" == "" set srcdir=%1
if not "%1" == "" if not "%srcdir%" == "%1" goto SmallEnv
Rem Create Makefile
sed -f %srcdir%/pc/djgpp/config.sed -e "s,@srcdir@,%srcdir%,g" %srcdir%/Makefile.in >Makefile
sed -f %srcdir%/pc/djgpp/configure.sed -e "s,@srcdir@,%srcdir%,g" %srcdir%/Makefile.in >Makefile
sed -n -e "/^VERSION/p" %srcdir%/configure.in >>Makefile
goto Exit

36
pc/djgpp/configure.sed Normal file
View File

@ -0,0 +1,36 @@
# Edit Makefile.in to produce Makefile for DJGPP v2
# $Id: configure.sed,v 1.8 1997/06/18 06:26:43 eggert Exp $
1i\
# Makefile generated by "configure.bat" for DJGPP v2\
/@SET_MAKE@/d
s|@CC@|gcc|g
s|@ed_PROGRAM@|ed|g
s|@INSTALL@|${DJDIR}/bin/ginstall -c|g
s|@INSTALL_PROGRAM@|${INSTALL}|g
s|@INSTALL_DATA@|${INSTALL} -m 644|g
s|@program_transform_name@||g
s|@CFLAGS@|-g -O2|g
s|@CPPFLAGS@|-I$(srcdir)/pc/djgpp|g
s|@DEFS@|-DHAVE_CONFIG_H|g
s|@LDFLAGS@||g
s|@LIBOBJS@|getopt1.o getopt.o chdirsaf.o|g
s|@LIBS@||g
s|@PACKAGE@|patch|g
/@VERSION@/d
s|@prefix@|${DJDIR}|g
s|@exec_prefix@|${prefix}|g
/^CONFIG_STATUS *=/s|=.*|= $(srcdir)/pc/djgpp/configure.bat|
/^ \$(SHELL) \$(CONFIG_STATUS) *$/s// $(CONFIG_STATUS) $(srcdir)/
$a\
config.h: config.hin pc/djgpp/config.sed; sed -f $(srcdir)/pc/djgpp/config.sed $(srcdir)/config.hin >$@\
chdirsaf.o: chdirsaf.c\
# Use sed instead of cp, since cp might not be installed.\
chdirsaf.c: pc/chdirsaf.c; sed -e '' $? > $@\
distclean::; rm -f chdirsaf.c

195
pch.c
View File

@ -1,6 +1,6 @@
/* reading patches */
/* $Id: pch.c,v 1.16 1997/05/26 17:52:29 eggert Exp $ */
/* $Id: pch.c,v 1.23 1997/06/17 06:52:12 eggert Exp $ */
/*
Copyright 1986, 1987, 1988 Larry Wall
@ -36,7 +36,9 @@ If not, write to the Free Software Foundation,
/* Patch (diff listing) abstract type. */
static FILE *pfp; /* patch file pointer */
static int p_says_nonexistent[2]; /* [0] for old file, [1] for new */
static int p_says_nonexistent[2]; /* [0] for old file, [1] for new;
value is 0 for nonempty, 1 for empty, 2 for nonexistent */
static time_t p_timestamp[2]; /* timestamps in patch headers */
static off_t p_filesize; /* size of the patch file */
static LINENUM p_first; /* 1st line number */
static LINENUM p_newfirst; /* 1st line number of replacement */
@ -97,6 +99,7 @@ open_patch_file(filename)
struct stat st;
if (!filename || !*filename || strEQ (filename, "-"))
{
file_offset stdin_pos;
#if HAVE_SETMODE
if (binary_transput)
{
@ -107,10 +110,10 @@ open_patch_file(filename)
#endif
if (fstat (STDIN_FILENO, &st) != 0)
pfatal ("fstat");
if (S_ISREG (st.st_mode))
if (S_ISREG (st.st_mode) && (stdin_pos = file_tell (stdin)) != -1)
{
pfp = stdin;
file_pos = file_tell (stdin);
file_pos = stdin_pos;
}
else
{
@ -118,7 +121,9 @@ open_patch_file(filename)
pfp = fopen (TMPPATNAME, "w+b");
if (!pfp)
pfatal ("can't create `%s'", TMPPATNAME);
while ((charsread = fread (buf, 1, bufsize, stdin)) != 0)
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)
@ -195,7 +200,11 @@ there_is_another_patch()
return FALSE;
}
if (skip_rest_of_patch)
{
Fseek (pfp, p_start, SEEK_SET);
p_input_line = p_sline - 1;
return TRUE;
}
if (verbosity == VERBOSE)
say (" %sooks like %s to me...\n",
(p_base == 0 ? "L" : "The next patch l"),
@ -204,21 +213,32 @@ there_is_another_patch()
diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
diff_type == NORMAL_DIFF ? "a normal diff" :
"an ed script" );
if (p_indent && verbosity != SILENT)
say ("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");
if (verbosity != SILENT)
{
if (p_indent)
say ("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");
if (! inname)
say ("can't find file to patch at input line %ld\n",
p_sline);
}
skip_to(p_start,p_sline);
while (!inname) {
if (force || batch) {
say ("No file to patch. Skipping...\n");
say ("No file to patch. Skipping patch.\n");
skip_rest_of_patch = TRUE;
return TRUE;
}
ask ("File to patch: ");
inname = fetchname (buf, 0, (int *) 0);
inname = fetchname (buf, 0, (time_t *) 0);
if (inname)
{
if (stat (inname, &instat) == 0)
inerrno = 0;
{
inerrno = 0;
invc = -1;
}
else
{
perror (inname);
@ -230,7 +250,7 @@ there_is_another_patch()
ask ("Skip this patch? [y] ");
if (*buf != 'n') {
if (verbosity != SILENT)
say ("Skipping patch...\n");
say ("Skipping patch.\n");
skip_rest_of_patch = TRUE;
return TRUE;
}
@ -259,11 +279,14 @@ intuit_diff_type()
char *name[3];
struct stat st[3];
int stat_errno[3];
int version_controlled[3];
register enum diff retval;
int head_says_nonexistent[2];
name[OLD] = name[NEW] = name[INDEX] = 0;
head_says_nonexistent[OLD] = head_says_nonexistent[NEW] = 0;
version_controlled[OLD] = -1;
version_controlled[NEW] = -1;
version_controlled[INDEX] = -1;
p_timestamp[OLD] = p_timestamp[NEW] = (time_t) -1;
p_says_nonexistent[OLD] = p_says_nonexistent[NEW] = 0;
Fseek (pfp, p_base, SEEK_SET);
p_input_line = p_bline - 1;
@ -304,14 +327,14 @@ intuit_diff_type()
p_indent = indent; /* assume this for now */
}
if (!stars_last_line && strnEQ(s, "*** ", 4))
name[OLD] = fetchname (s+4, strippath, &head_says_nonexistent[OLD]);
name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);
else if (strnEQ(s, "--- ", 4))
name[NEW] = fetchname (s+4, strippath, &head_says_nonexistent[NEW]);
name[NEW] = fetchname (s+4, strippath, &p_timestamp[NEW]);
else if (strnEQ(s, "+++ ", 4))
/* Swap with NEW below. */
name[OLD] = fetchname (s+4, strippath, &head_says_nonexistent[OLD]);
name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);
else if (strnEQ(s, "Index:", 6))
name[INDEX] = fetchname (s+6, strippath, (int *) 0);
name[INDEX] = fetchname (s+6, strippath, (time_t *) 0);
else if (strnEQ(s, "Prereq:", 7)) {
for (t = s + 7; ISSPACE ((unsigned char) *t); t++)
continue;
@ -338,24 +361,32 @@ intuit_diff_type()
}
if ((diff_type == NO_DIFF || diff_type == UNI_DIFF)
&& strnEQ(s, "@@ -", 4)) {
s += 4;
/* `name' and `head_says_nonexistent' are backwards.
Swap the former, and interpret the latter backwards. */
/* `name' and `p_timestamp' are backwards; swap them. */
time_t ti = p_timestamp[OLD];
p_timestamp[OLD] = p_timestamp[NEW];
p_timestamp[NEW] = ti;
t = name[OLD];
name[OLD] = name[NEW];
name[NEW] = t;
if (head_says_nonexistent[NEW] && ! atol (s))
p_says_nonexistent[OLD] = 1;
s += 4;
if (! atol (s))
p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD];
while (*s != ' ' && *s != '\n')
s++;
while (*s == ' ')
s++;
if (head_says_nonexistent[OLD] && ! atol (s))
p_says_nonexistent[NEW] = 1;
if (! atol (s))
p_says_nonexistent[NEW] = 1 + ! p_timestamp[NEW];
p_indent = indent;
p_start = this_line;
p_sline = p_input_line;
retval = UNI_DIFF;
if (! ((name[OLD] || ! p_timestamp[OLD])
&& (name[NEW] || ! p_timestamp[NEW])))
say ("missing header for unified diff at line %ld of patch\n",
p_sline);
goto scan_exit;
}
stars_this_line = strnEQ(s, "********", 8);
@ -364,8 +395,8 @@ intuit_diff_type()
|| diff_type == NEW_CONTEXT_DIFF)
&& stars_last_line && strnEQ (s, "*** ", 4)) {
s += 4;
if (head_says_nonexistent[OLD] && ! atol (s))
p_says_nonexistent[OLD] = 1;
if (! atol (s))
p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD];
/* if this is a new context diff the character just before */
/* the newline is a '*'. */
while (*s != '\n')
@ -375,20 +406,23 @@ intuit_diff_type()
p_sline = p_input_line - 1;
retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
if (head_says_nonexistent[NEW])
{
/* Scan the first hunk to see whether the file appears to
have been deleted. */
file_offset saved_p_base = p_base;
LINENUM saved_p_bline = p_bline;
p_input_line = p_sline;
Fseek (pfp, previous_line, SEEK_SET);
if (another_hunk (retval, 0)
&& ! p_repl_lines && p_newfirst == 1)
p_says_nonexistent[NEW] = 1;
next_intuit_at (saved_p_base, saved_p_bline);
}
{
/* Scan the first hunk to see whether the file contents
appear to have been deleted. */
file_offset saved_p_base = p_base;
LINENUM saved_p_bline = p_bline;
Fseek (pfp, previous_line, SEEK_SET);
p_input_line -= 2;
if (another_hunk (retval, 0)
&& ! p_repl_lines && p_newfirst == 1)
p_says_nonexistent[NEW] = 1 + ! p_timestamp[NEW];
next_intuit_at (saved_p_base, saved_p_bline);
}
if (! ((name[OLD] || ! p_timestamp[OLD])
&& (name[NEW] || ! p_timestamp[NEW])))
say ("missing header for context diff at line %ld of patch\n",
p_sline);
goto scan_exit;
}
if ((diff_type == NO_DIFF || diff_type == NORMAL_DIFF) &&
@ -409,12 +443,18 @@ intuit_diff_type()
(with some modifications if posixly_correct is zero):
- Take the old and new names from the context header if present,
and take the index name from the `Index:' line if present.
and take the index name from the `Index:' line if present and
if either the old and new names are both absent
or posixly_correct is nonzero.
Consider the file names to be in the order (old, new, index).
- If some named files exist, use the first one if posixly_correct
is nonzero, the best one otherwise.
- If no named files exist, some names are given, posixly_correct is
zero, and the patch appears to create a file, then use the best name
- If patch_get is nonzero, and no named files exist,
but an RCS or SCCS master file exists,
use the first named file with an RCS or SCCS master.
- If no named files exist, no RCS or SCCS master was found,
some names are given, posixly_correct is zero,
and the patch appears to create a file, then use the best name
requiring the creation of the fewest directories.
- Otherwise, report failure by setting `inname' to 0;
this causes our invoker to ask the user for a file name. */
@ -425,6 +465,12 @@ intuit_diff_type()
{
enum nametype i0 = NONE;
if (! posixly_correct && (name[OLD] || name[NEW]) && name[INDEX])
{
free (name[INDEX]);
name[INDEX] = 0;
}
for (i = OLD; i <= INDEX; i++)
if (name[i])
{
@ -450,15 +496,57 @@ intuit_diff_type()
{
i = best_name (name, stat_errno);
if (p_says_nonexistent[reverse ^ (i == NONE)])
if (i == NONE && patch_get)
{
enum nametype nope = NONE;
for (i = OLD; i <= INDEX; i++)
if (name[i])
{
char const *cs;
char *getbuf;
char *diffbuf;
int readonly = outfile && strcmp (outfile, name[i]) != 0;
if (nope == NONE || strcmp (name[nope], name[i]) != 0)
{
cs = (version_controller
(name[i], readonly, (struct stat *) 0,
&getbuf, &diffbuf));
version_controlled[i] = !! cs;
if (cs)
{
if (version_get (name[i], cs, 0, readonly,
getbuf, &st[i]))
stat_errno[i] = 0;
else
version_controlled[i] = 0;
free (getbuf);
free (diffbuf);
if (! stat_errno[i])
break;
}
}
nope = i;
}
}
if (p_says_nonexistent[reverse ^ (i == NONE || st[i].st_size == 0)])
{
assert (i0 != NONE);
if (ok_to_reverse
("The next patch%s would %s the file `%s',\nwhich %s!",
reverse ? ", when reversed," : "",
i == NONE ? "delete" : "create",
name[i == NONE ? i0 : i],
i == NONE ? "does not exist" : "already exists"))
(i == NONE ? "delete"
: st[i].st_size == 0 ? "empty out"
: "create"),
name[i == NONE || st[i].st_size == 0 ? i0 : i],
(i == NONE ? "does not exist"
: st[i].st_size == 0 ? "is already empty"
: "already exists")))
reverse ^= 1;
}
@ -493,6 +581,7 @@ intuit_diff_type()
inname = name[i];
name[i] = 0;
inerrno = stat_errno[i];
invc = version_controlled[i];
instat = st[i];
}
@ -1533,7 +1622,8 @@ pch_swap()
return TRUE;
}
/* Return whether file WHICH (0 = old, 1 = new) appears to be nonexistent. */
/* Return whether file WHICH (0 = old, 1 = new) appears to nonexistent.
Return 1 for empty, 2 for nonexistent. */
bool
pch_says_nonexistent (which)
@ -1542,6 +1632,16 @@ pch_says_nonexistent (which)
return p_says_nonexistent[which];
}
/* Return timestamp of patch header for file WHICH (0 = old, 1 = new),
or -1 if there was no timestamp or an error in the timestamp. */
time_t
pch_timestamp (which)
int which;
{
return p_timestamp[which];
}
/* Return the specified line position in the old file of the old context. */
LINENUM
@ -1665,6 +1765,7 @@ do_ed_script (ofp)
copy_file (inname, TMPOUTNAME, instat.st_mode);
sprintf (buf, "%s %s%s", ed_program, verbosity == VERBOSE ? "" : "- ",
TMPOUTNAME);
fflush (stdout);
pipefp = popen(buf, binary_transput ? "wb" : "w");
if (!pipefp)
pfatal ("can't open pipe to `%s'", buf);

3
pch.h
View File

@ -1,6 +1,6 @@
/* reading patches */
/* $Id: pch.h,v 1.7 1997/05/19 06:52:03 eggert Exp $ */
/* $Id: pch.h,v 1.8 1997/06/13 06:28:37 eggert Exp $ */
LINENUM pch_end PARAMS ((void));
LINENUM pch_first PARAMS ((void));
@ -18,6 +18,7 @@ char pch_char PARAMS ((LINENUM));
int another_hunk PARAMS ((enum diff, int));
int pch_says_nonexistent PARAMS ((int));
size_t pch_line_len PARAMS ((LINENUM));
time_t pch_timestamp PARAMS ((int));
void do_ed_script PARAMS ((FILE *));
void open_patch_file PARAMS ((char const *));
void re_patch PARAMS ((void));

297
util.c
View File

@ -1,6 +1,6 @@
/* utility functions for `patch' */
/* $Id: util.c,v 1.17 1997/05/30 08:03:48 eggert Exp $ */
/* $Id: util.c,v 1.22 1997/06/13 06:28:37 eggert Exp $ */
/*
Copyright 1986 Larry Wall
@ -25,18 +25,22 @@ If not, write to the Free Software Foundation,
#define XTERN extern
#include <common.h>
#include <backupfile.h>
#include <quotearg.h>
#include <version.h>
#undef XTERN
#define XTERN
#include <util.h>
#include <time.h>
#include <maketime.h>
#include <partime.h>
#include <signal.h>
#if !defined SIGCHLD && defined SIGCLD
#define SIGCHLD SIGCLD
#endif
#if ! HAVE_RAISE
# define raise(sig) kill (getpid (), sig)
#endif
#ifdef __STDC__
# include <stdarg.h>
@ -77,7 +81,7 @@ move_file (from, to, mode, backup)
struct stat to_st;
int to_errno = ! backup ? -1 : stat (to, &to_st) == 0 ? 0 : errno;
if (! to_errno)
if (backup)
{
int try_makedirs_errno = 0;
char *bakname;
@ -110,15 +114,36 @@ move_file (from, to, mode, backup)
memory_fatal ();
}
if (debug & 4)
say ("renaming `%s' to `%s'\n", to, bakname);
while (rename (to, bakname) != 0)
if (to_errno)
{
if (errno != try_makedirs_errno)
pfatal ("can't rename `%s' to `%s'", to, bakname);
makedirs (bakname);
try_makedirs_errno = 0;
int fd;
if (debug & 4)
say ("creating empty unreadable file `%s'\n", bakname);
try_makedirs_errno = ENOENT;
unlink (bakname);
while ((fd = creat (bakname, 0)) < 0)
{
if (errno != try_makedirs_errno)
pfatal ("can't create file `%s'", bakname);
makedirs (bakname);
try_makedirs_errno = 0;
}
if (close (fd) != 0)
pfatal ("can't close `%s'", bakname);
}
else
{
if (debug & 4)
say ("renaming `%s' to `%s'\n", to, bakname);
while (rename (to, bakname) != 0)
{
if (errno != try_makedirs_errno)
pfatal ("can't rename `%s' to `%s'", to, bakname);
makedirs (bakname);
try_makedirs_errno = 0;
}
}
free (bakname);
}
@ -218,6 +243,159 @@ copy_file (from, to, mode)
write_fatal ();
}
static char const DEV_NULL[] = NULL_DEVICE;
static char const SCCSPREFIX[] = "s.";
static char const GET[] = "get ";
static char const GET_LOCKED[] = "get -e ";
static char const SCCSDIFF1[] = "get -p ";
static char const SCCSDIFF2[] = "|diff - %s";
static char const RCSSUFFIX[] = ",v";
static char const CHECKOUT[] = "co %s";
static char const CHECKOUT_LOCKED[] = "co -l %s";
static char const RCSDIFF1[] = "rcsdiff %s";
/* Return "RCS" if FILENAME is controlled by RCS,
"SCCS" if it is controlled by SCCS, and 0 otherwise.
READONLY is nonzero if we desire only readonly access to FILENAME.
FILESTAT describes FILENAME's status or is 0 if FILENAME does not exist.
If successful and if GETBUF is nonzero, set *GETBUF to a command
that gets the file; similarly for DIFFBUF and a command to diff the file.
*GETBUF and *DIFFBUF must be freed by the caller. */
char const *
version_controller (filename, readonly, filestat, getbuf, diffbuf)
char const *filename;
int readonly;
struct stat const *filestat;
char **getbuf;
char **diffbuf;
{
struct stat cstat;
char const *filebase = base_name (filename);
char const *dotslash = *filename == '-' ? "./" : "";
size_t dir_len = filebase - filename;
size_t filenamelen = strlen (filename);
size_t maxfixlen = sizeof "SCCS/" - 1 + sizeof SCCSPREFIX - 1;
size_t maxtrysize = filenamelen + maxfixlen + 1;
size_t quotelen = quote_system_arg (0, filename);
size_t maxgetsize = sizeof GET_LOCKED + quotelen + maxfixlen;
size_t maxdiffsize =
(sizeof SCCSDIFF1 + sizeof SCCSDIFF2 + sizeof DEV_NULL - 1
+ 2 * quotelen + maxfixlen);
char *trybuf = xmalloc (maxtrysize);
char const *r = 0;
strcpy (trybuf, filename);
#define try1(f,a1) (sprintf (trybuf + dir_len, f, a1), stat (trybuf, &cstat) == 0)
#define try2(f,a1,a2) (sprintf (trybuf + dir_len, f, a1,a2), stat (trybuf, &cstat) == 0)
/* Check that RCS file is not working file.
Some hosts don't report file name length errors. */
if ((try2 ("RCS/%s%s", filebase, RCSSUFFIX)
|| try1 ("RCS/%s", filebase)
|| try2 ("%s%s", filebase, RCSSUFFIX))
&& ! (filestat
&& filestat->st_dev == cstat.st_dev
&& filestat->st_ino == cstat.st_ino))
{
if (getbuf)
{
char *p = *getbuf = xmalloc (maxgetsize);
sprintf (p, readonly ? CHECKOUT : CHECKOUT_LOCKED, dotslash);
p += strlen (p);
p += quote_system_arg (p, filename);
*p = '\0';
}
if (diffbuf)
{
char *p = *diffbuf = xmalloc (maxdiffsize);
sprintf (p, RCSDIFF1, dotslash);
p += strlen (p);
p += quote_system_arg (p, filename);
*p++ = '>';
strcpy (p, DEV_NULL);
}
r = "RCS";
}
else if (try2 ("SCCS/%s%s", SCCSPREFIX, filebase)
|| try2 ("%s%s", SCCSPREFIX, filebase))
{
if (getbuf)
{
char *p = *getbuf = xmalloc (maxgetsize);
sprintf (p, readonly ? GET : GET_LOCKED);
p += strlen (p);
p += quote_system_arg (p, trybuf);
*p = '\0';
}
if (diffbuf)
{
char *p = *diffbuf = xmalloc (maxdiffsize);
strcpy (p, SCCSDIFF1);
p += sizeof SCCSDIFF1 - 1;
p += quote_system_arg (p, trybuf);
sprintf (p, SCCSDIFF2, dotslash);
p += strlen (p);
p += quote_system_arg (p, filename);
*p++ = '>';
strcpy (p, DEV_NULL);
}
r = "SCCS";
}
free (trybuf);
return r;
}
/* Get FILENAME from version control system CS. The file already exists if
EXISTS is nonzero. Only readonly access is needed if READONLY is nonzero.
Use the command GETBUF to actually get the named file.
Store the resulting file status into *FILESTAT.
Return nonzero if successful. */
int
version_get (filename, cs, exists, readonly, getbuf, filestat)
char const *filename;
char const *cs;
int exists;
int readonly;
char const *getbuf;
struct stat *filestat;
{
if (patch_get < 0)
{
ask ("Get file `%s' from %s%s? [y] ", filename,
cs, readonly ? "" : " with lock");
if (*buf == 'n')
return 0;
}
if (dry_run)
{
if (! exists)
fatal ("can't do dry run on nonexistent version-controlled file `%s'; invoke `%s' and try again",
filename, getbuf);
}
else
{
if (verbosity == VERBOSE)
say ("Getting file `%s' from %s%s...\n", filename,
cs, readonly ? "" : " with lock");
if (systemic (getbuf) != 0)
fatal ("can't get file `%s' from %s", filename, cs);
if (stat (filename, filestat) != 0)
pfatal ("%s", filename);
}
return 1;
}
/* Allocate a unique area for a string. */
char *
@ -339,7 +517,7 @@ pfatal (format, va_alist)
vararg_start (args, format);
vfprintf (stderr, format, args);
va_end (args);
fflush (stderr);
fflush (stderr); /* perror bypasses stdio on some hosts. */
errno = errnum;
perror (" ");
fflush (stderr);
@ -388,21 +566,22 @@ ask (format, va_alist)
if (ttyfd == -2)
{
ttyfd = open ("/dev/tty", O_RDONLY);
if (ttyfd < 0)
{
close (ttyfd);
for (ttyfd = STDERR_FILENO; 0 <= ttyfd; ttyfd--)
if (isatty (ttyfd))
break;
}
/* If standard output is not a tty, don't bother opening /dev/tty,
since it's unlikely that stdout will be seen by the tty user.
The isatty test also works around a bug in GNU Emacs 19.34 under Linux
which makes a call-process `patch' hang when it reads from /dev/tty.
POSIX.2 requires that we read /dev/tty, though. */
ttyfd = (posixly_correct || isatty (STDOUT_FILENO)
? open (TTY_DEVICE, O_RDONLY)
: -1);
}
if (ttyfd < 0)
{
/* No terminal at all -- default it. */
printf ("\n");
buf[0] = '\n';
r = 1;
buf[1] = '\0';
}
else
{
@ -420,13 +599,14 @@ ask (format, va_alist)
printf ("EOF\n");
else if (r < 0)
{
perror ("tty read");
fflush (stderr);
close (ttyfd);
ttyfd = -1;
r = 0;
}
buf[s + r] = '\0';
}
buf[r] = '\0';
}
/* Return nonzero if it OK to reverse a patch. */
@ -442,7 +622,7 @@ ok_to_reverse (format, va_alist)
{
int r = 0;
if (noreverse || ! batch || verbosity != SILENT)
if (noreverse || ! (force && verbosity == SILENT))
{
va_list args;
vararg_start (args, format);
@ -452,14 +632,19 @@ ok_to_reverse (format, va_alist)
if (noreverse)
{
printf (" Ignoring it.\n");
printf (" Skipping patch.\n");
skip_rest_of_patch = TRUE;
r = 0;
}
else if (force)
{
if (verbosity != SILENT)
printf (" Applying it anyway.\n");
r = 0;
}
else if (batch)
{
if (verbosity != SILENT)
say (reverse ? " Ignoring -R.\n" : " Assuming -R.\n");
say (reverse ? " Ignoring -R.\n" : " Assuming -R.\n");
r = 1;
}
else
@ -470,7 +655,11 @@ ok_to_reverse (format, va_alist)
{
ask ("Apply anyway? [n] ");
if (*buf != 'y')
skip_rest_of_patch = TRUE;
{
if (verbosity != SILENT)
say ("Skipping patch.\n");
skip_rest_of_patch = TRUE;
}
}
}
@ -484,6 +673,9 @@ static int const sigs[] = {
#ifdef SIGHUP
SIGHUP,
#endif
#ifdef SIGPIPE
SIGPIPE,
#endif
#ifdef SIGTERM
SIGTERM,
#endif
@ -493,8 +685,7 @@ static int const sigs[] = {
#ifdef SIGXFSZ
SIGXFSZ,
#endif
SIGINT,
SIGPIPE
SIGINT
};
#if !HAVE_SIGPROCMASK
@ -616,7 +807,7 @@ exit_with_signal (sig)
sigemptyset (&s);
sigaddset (&s, sig);
sigprocmask (SIG_UNBLOCK, &s, (sigset_t *) 0);
kill (getpid (), sig);
raise (sig);
exit (2);
}
@ -626,6 +817,7 @@ systemic (command)
{
if (debug & 8)
say ("+ %s\n", command);
fflush (stdout);
return system (command);
}
@ -633,7 +825,6 @@ systemic (command)
/* These mkdir and rmdir substitutes are good enough for `patch';
they are not general emulators. */
#include <quotearg.h>
static int doprogram PARAMS ((char const *, char const *));
static int mkdir PARAMS ((char const *, mode_t));
static int rmdir PARAMS ((char const *));
@ -793,18 +984,16 @@ init_time ()
/* Make filenames more reasonable. */
char *
fetchname (at, strip_leading, head_says_nonexistent)
fetchname (at, strip_leading, pstamp)
char *at;
int strip_leading;
int *head_says_nonexistent;
time_t *pstamp;
{
char *name;
register char *t;
int sleading = strip_leading;
int says_nonexistent = 0;
time_t stamp = (time_t) -1;
if (!at)
return 0;
while (ISSPACE ((unsigned char) *at))
at++;
if (debug & 128)
@ -823,15 +1012,21 @@ int *head_says_nonexistent;
}
else if (ISSPACE ((unsigned char) *t))
{
/* The head says the file is nonexistent if the timestamp
is the epoch; but the listed time is local time, not UTC,
and POSIX.1 allows local time to be 24 hours away from UTC.
So match any time within 24 hours of the epoch.
Use a default time zone 24 hours behind UTC so that any
non-zoned time within 24 hours of the epoch is valid. */
time_t stamp = str2time (t, initial_time, -24L * 60 * 60);
if (0 <= stamp && stamp <= 2 * 24L * 60 * 60)
says_nonexistent = 1;
if (set_time | set_utc)
stamp = str2time (t, initial_time, set_utc ? 0L : TM_LOCAL_ZONE);
else
{
/* The head says the file is nonexistent if the timestamp
is the epoch; but the listed time is local time, not UTC,
and POSIX.1 allows local time to be 24 hours away from UTC.
So match any time within 24 hours of the epoch.
Use a default time zone 24 hours behind UTC so that any
non-zoned time within 24 hours of the epoch is valid. */
stamp = str2time (t, initial_time, -24L * 60 * 60);
if (0 <= stamp && stamp <= 2 * 24L * 60 * 60)
stamp = 0;
}
*t = '\0';
break;
}
@ -843,22 +1038,22 @@ int *head_says_nonexistent;
/* Allow files to be created by diffing against /dev/null. */
if (strcmp (at, "/dev/null") == 0)
{
if (head_says_nonexistent)
*head_says_nonexistent = 1;
if (pstamp)
*pstamp = 0;
return 0;
}
if (head_says_nonexistent)
*head_says_nonexistent = says_nonexistent;
if (pstamp)
*pstamp = stamp;
return savestr (name);
}
VOID *
GENERIC_OBJECT *
xmalloc (size)
size_t size;
{
register VOID *p = malloc (size);
register GENERIC_OBJECT *p = malloc (size);
if (!p)
memory_fatal ();
return p;

6
util.h
View File

@ -1,6 +1,6 @@
/* utility functions for `patch' */
/* $Id: util.h,v 1.12 1997/05/19 06:52:03 eggert Exp $ */
/* $Id: util.h,v 1.14 1997/06/13 06:28:37 eggert Exp $ */
int ok_to_reverse PARAMS ((char const *, ...)) __attribute__ ((format (printf, 1, 2)));
void ask PARAMS ((char const *, ...)) __attribute__ ((format (printf, 1, 2)));
@ -11,9 +11,11 @@ void fatal PARAMS ((char const *, ...))
void pfatal PARAMS ((char const *, ...))
__attribute__ ((noreturn, format (printf, 1, 2)));
char *fetchname PARAMS ((char *, int, int *));
char *fetchname PARAMS ((char *, int, time_t *));
char *savebuf PARAMS ((char const *, size_t));
char *savestr PARAMS ((char const *));
char const *version_controller PARAMS ((char const *, int, struct stat const *, char **, char **));
int version_get PARAMS ((char const *, char const *, int, int, char const *, struct stat *));
int create_file PARAMS ((char const *, int, mode_t));
int systemic PARAMS ((char const *));
void Fseek PARAMS ((FILE *, file_offset, int));