mirror of
https://https.git.savannah.gnu.org/git/patch.git
synced 2026-01-27 18:05:02 +00:00
Compare commits
310 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d161c9a9db | ||
|
|
4c302306a8 | ||
|
|
aea66268c9 | ||
|
|
77c27209f6 | ||
|
|
48ceda8200 | ||
|
|
b3d0c93338 | ||
|
|
29fced6251 | ||
|
|
b5d2124e2e | ||
|
|
86ac7e2d7b | ||
|
|
7d876522e9 | ||
|
|
86baf979f4 | ||
|
|
1ba2c1bdf8 | ||
|
|
1da6bf84db | ||
|
|
30ee6103a5 | ||
|
|
6dbc381055 | ||
|
|
05ac924fef | ||
|
|
95e0092f97 | ||
|
|
5bac274507 | ||
|
|
910fecf695 | ||
|
|
be8b3c68b0 | ||
|
|
c61485bd05 | ||
|
|
499916fdd8 | ||
|
|
adb1ebce7f | ||
|
|
6bdae94eb3 | ||
|
|
72a146cfaf | ||
|
|
e2e6820f71 | ||
|
|
606c09176c | ||
|
|
ee3cc4016d | ||
|
|
8cae4fc221 | ||
|
|
164b529f53 | ||
|
|
91c1e4f071 | ||
|
|
a03e1bac4a | ||
|
|
9ba5eb00b3 | ||
|
|
79dd5e762c | ||
|
|
8492a6a212 | ||
|
|
f6f2c6f31a | ||
|
|
0525681eb5 | ||
|
|
301411d927 | ||
|
|
461520693e | ||
|
|
923e0ef280 | ||
|
|
5d17ca0e5f | ||
|
|
5f4edd389e | ||
|
|
802511c09b | ||
|
|
a93b50de71 | ||
|
|
55e224bd73 | ||
|
|
33a7fd89ec | ||
|
|
2313b37f6a | ||
|
|
37fec39c58 | ||
|
|
cc87173e46 | ||
|
|
7887622b77 | ||
|
|
18f4dd67ad | ||
|
|
638675c19a | ||
|
|
53400a17ed | ||
|
|
e8e1bcb7a0 | ||
|
|
b963510dcd | ||
|
|
85949fb4ac | ||
|
|
448ff9bc72 | ||
|
|
b95a603908 | ||
|
|
2663228379 | ||
|
|
fc779640b0 | ||
|
|
470699c8f2 | ||
|
|
f696e4ef12 | ||
|
|
4d3a4ab09a | ||
|
|
b3bb925cee | ||
|
|
070d859e07 | ||
|
|
f46a90f137 | ||
|
|
2e64cfd98c | ||
|
|
45de0d99c8 | ||
|
|
82c4940a2e | ||
|
|
eceea619a6 | ||
|
|
9c55d3f541 | ||
|
|
61c72f07b3 | ||
|
|
705c9bcdc1 | ||
|
|
77f21a6068 | ||
|
|
fe8ffd9ba4 | ||
|
|
5e84bda3ff | ||
|
|
8d4ca493ed | ||
|
|
fe5d4a06f7 | ||
|
|
ca4c431f8a | ||
|
|
0ad4347277 | ||
|
|
c49a16d0ca | ||
|
|
22efdeebaa | ||
|
|
5a70a1b6b9 | ||
|
|
c0d465f21b | ||
|
|
b91aab2c88 | ||
|
|
55c8a5c494 | ||
|
|
e0e121efe5 | ||
|
|
241e57ea5b | ||
|
|
0f8c62835f | ||
|
|
f2c3676393 | ||
|
|
cec6407930 | ||
|
|
6b7b01b89b | ||
|
|
043355371a | ||
|
|
0a66dee829 | ||
|
|
36ff2c9296 | ||
|
|
3951496739 | ||
|
|
6429630c0c | ||
|
|
03cb187db6 | ||
|
|
cc7cde7a2c | ||
|
|
4c6650b507 | ||
|
|
abe92e8010 | ||
|
|
30449e294b | ||
|
|
9228a8cf28 | ||
|
|
c1c438d3a8 | ||
|
|
5d3f41f6fc | ||
|
|
fb056f23ac | ||
|
|
84b5f34f2a | ||
|
|
d2e113e9a4 | ||
|
|
f73718b634 | ||
|
|
79eef3e014 | ||
|
|
11588d0fa2 | ||
|
|
e16037d11f | ||
|
|
388926ffa7 | ||
|
|
3582fdb953 | ||
|
|
4a47c002fa | ||
|
|
4f8c4b8842 | ||
|
|
0a810b6e27 | ||
|
|
bac3b6d06a | ||
|
|
8fb784b7d0 | ||
|
|
e10f3ca472 | ||
|
|
57e2165767 | ||
|
|
eb18b39cc7 | ||
|
|
d60cb724bd | ||
|
|
05ef886471 | ||
|
|
1f8d192897 | ||
|
|
ba92722539 | ||
|
|
0f98e033f2 | ||
|
|
1235ccc55b | ||
|
|
43ee674679 | ||
|
|
e3819470dc | ||
|
|
2c2a83b77a | ||
|
|
a13c2eaf16 | ||
|
|
6eb2d138e6 | ||
|
|
d1a6847368 | ||
|
|
d6631b3125 | ||
|
|
bc6899dc6f | ||
|
|
da259855ca | ||
|
|
248ef134f8 | ||
|
|
6cb321aff4 | ||
|
|
47bc09dc6a | ||
|
|
7608746040 | ||
|
|
323da0da04 | ||
|
|
53d10143f2 | ||
|
|
59681c8e9a | ||
|
|
4278b91942 | ||
|
|
34b45bc78b | ||
|
|
d18c05d5bd | ||
|
|
af828e563c | ||
|
|
b3a6c95537 | ||
|
|
9abc949979 | ||
|
|
90e62d5195 | ||
|
|
2b87c1eb7f | ||
|
|
7aa1c3bc32 | ||
|
|
99c0c0b7b8 | ||
|
|
1c087d6fcb | ||
|
|
7214f8d44b | ||
|
|
6785b2c42c | ||
|
|
72d7ed09bc | ||
|
|
abf6fb176b | ||
|
|
d3816ac315 | ||
|
|
346d3aca37 | ||
|
|
ff2317b2cb | ||
|
|
c2d9792e92 | ||
|
|
8c27a03b2e | ||
|
|
d46d729c0c | ||
|
|
924698bfd6 | ||
|
|
8939519c06 | ||
|
|
531cc2b9c6 | ||
|
|
ff13fea205 | ||
|
|
3d5c0d1fd9 | ||
|
|
56788ce462 | ||
|
|
c10da772ef | ||
|
|
1e217677df | ||
|
|
39005cfce9 | ||
|
|
755712d85e | ||
|
|
04f0eeb438 | ||
|
|
f06c1230d7 | ||
|
|
aab6e7bc8a | ||
|
|
d1d32c9747 | ||
|
|
7575694ee8 | ||
|
|
8f78b098c2 | ||
|
|
bb841fd7b0 | ||
|
|
4887683ab0 | ||
|
|
5b8ecde1a2 | ||
|
|
009a424a74 | ||
|
|
299167f059 | ||
|
|
3ec44a42c4 | ||
|
|
68cb5293f7 | ||
|
|
f144b35425 | ||
|
|
faafc79f8d | ||
|
|
c835ecc67b | ||
|
|
24f81beb27 | ||
|
|
7623b2dc0d | ||
|
|
0993940034 | ||
|
|
78ed9decdf | ||
|
|
76e775847f | ||
|
|
15b158db3a | ||
|
|
dce4683cbb | ||
|
|
61d7788b83 | ||
|
|
b7b028a77b | ||
|
|
a5b442ce01 | ||
|
|
2b584aec9e | ||
|
|
9c986353e4 | ||
|
|
ff81775f4e | ||
|
|
369dcccdfa | ||
|
|
19599883ff | ||
|
|
f322a7e0e5 | ||
|
|
458ac51a05 | ||
|
|
1e9104c180 | ||
|
|
ae81be0024 | ||
|
|
2a32bf09f5 | ||
|
|
ff1d3a67da | ||
|
|
3fcd042d26 | ||
|
|
123eaff0d5 | ||
|
|
b5a91a01e5 | ||
|
|
f290f48a62 | ||
|
|
074e2395f8 | ||
|
|
f6bc5b14bd | ||
|
|
3bbebbb29f | ||
|
|
40b387de08 | ||
|
|
66f9fa2690 | ||
|
|
107e1cecfc | ||
|
|
e6da0b81bf | ||
|
|
9ab866d562 | ||
|
|
6a737fca57 | ||
|
|
592e1f9163 | ||
|
|
15cc7d44d4 | ||
|
|
5bf48c87ca | ||
|
|
00947f4111 | ||
|
|
61b6ec8857 | ||
|
|
a2b6fb1672 | ||
|
|
817d7d1767 | ||
|
|
49705d1d8d | ||
|
|
a0d7fe4589 | ||
|
|
4c43a0b1cb | ||
|
|
d874c38335 | ||
|
|
b6c4780f73 | ||
|
|
9ca38fa1e6 | ||
|
|
66fdcf0e7c | ||
|
|
83a3ed012c | ||
|
|
70532e21a8 | ||
|
|
4f4fd1b41d | ||
|
|
3270d221a9 | ||
|
|
98b86e970a | ||
|
|
68049159f2 | ||
|
|
871f87824a | ||
|
|
5c6625bf62 | ||
|
|
6a55099e7a | ||
|
|
3b698ab6a1 | ||
|
|
3cd040cf4c | ||
|
|
7a77ae9f81 | ||
|
|
274c66c775 | ||
|
|
99d3b514e9 | ||
|
|
a6615bcb83 | ||
|
|
914d06b7c3 | ||
|
|
c5705fd476 | ||
|
|
ca9df22fe6 | ||
|
|
0d3df382d6 | ||
|
|
9f92e52c9f | ||
|
|
6fbdcefe7d | ||
|
|
a025a51ca5 | ||
|
|
ef609c26b2 | ||
|
|
3c58eb50ce | ||
|
|
e1f0aa0a9d | ||
|
|
c5da382c0b | ||
|
|
d55ab5b941 | ||
|
|
db9f39507e | ||
|
|
8d12036047 | ||
|
|
7297352e16 | ||
|
|
69434de2d5 | ||
|
|
ddf16e1209 | ||
|
|
8a9f5432d4 | ||
|
|
b73c1f95cb | ||
|
|
709458d9d9 | ||
|
|
de89dde09e | ||
|
|
38d87ecb9e | ||
|
|
82b800c955 | ||
|
|
68d39ff29f | ||
|
|
c80b1a06a9 | ||
|
|
8d621e8819 | ||
|
|
290ffcb488 | ||
|
|
b72e3be5c8 | ||
|
|
71a3172c7e | ||
|
|
025a54b789 | ||
|
|
6a56d401d2 | ||
|
|
75fcb4b560 | ||
|
|
3e7113a6b5 | ||
|
|
41688ad8ef | ||
|
|
17953b5893 | ||
|
|
0c08d7a902 | ||
|
|
19285e563a | ||
|
|
ae88d1c270 | ||
|
|
4e9269a5fc | ||
|
|
44a987e02f | ||
|
|
f22e47d873 | ||
|
|
e4c6511f46 | ||
|
|
3fd4144ae9 | ||
|
|
65193f1cc1 | ||
|
|
e25e622dec | ||
|
|
f926295f4f | ||
|
|
dc63883f08 | ||
|
|
a2f4bfe0f3 | ||
|
|
89dbba7229 | ||
|
|
afdfa9ec8e | ||
|
|
aac14e3187 | ||
|
|
60c9d4838f | ||
|
|
2f40ef66be | ||
|
|
082baa326a | ||
|
|
291ec17581 | ||
|
|
47191c287d |
7
.gitattributes
vendored
Normal file
7
.gitattributes
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# Run this to make 'git diff' on texinfo files give nicer hunk context:
|
||||
# git config diff.texinfo.funcname '^@node[ ][ ]*\\([^,][^,]*\\)'
|
||||
*.texi* diff=texinfo
|
||||
|
||||
# Run this to make 'git diff' on .m4 files give nicer hunk context:
|
||||
# git config diff.m4.xfuncname '^((AC_DEFUN|m4_define)[^,)]*)'
|
||||
*.m4 diff=m4
|
||||
23
.gitignore
vendored
23
.gitignore
vendored
@ -1,5 +1,7 @@
|
||||
*.log
|
||||
*.o
|
||||
-/lib/Makefile.am
|
||||
*.trs
|
||||
*~
|
||||
.deps/
|
||||
/.pc/
|
||||
/.version
|
||||
@ -8,24 +10,25 @@
|
||||
/ID
|
||||
/INSTALL
|
||||
/VERSION
|
||||
/[0-9]*.patch
|
||||
/aclocal.m4
|
||||
/autom4te.cache/
|
||||
/build-aux
|
||||
/build-aux/
|
||||
/config.cache
|
||||
/config.h
|
||||
/config.hin
|
||||
/config.log
|
||||
/config.status
|
||||
/configure
|
||||
/doc
|
||||
/lib
|
||||
/doc/
|
||||
/lib/
|
||||
!/lib/Makefile.am
|
||||
/m4/*.m4
|
||||
/m4/.gitignore
|
||||
!/m4/setmode.m4
|
||||
!/m4/xattr.m4
|
||||
/maint.mk
|
||||
/patch-*.tar.bz2
|
||||
/patch-*.tar.bz2.sig
|
||||
/patch-*.tar.gz
|
||||
/patch-*.tar.gz.sig
|
||||
/patch-*.tar.xz
|
||||
/patch-*.tar.xz.sig
|
||||
/patch-*.tar.*
|
||||
/src/patch
|
||||
/stamp-h1
|
||||
Makefile
|
||||
|
||||
@ -1039,7 +1039,7 @@
|
||||
* tests/asymmetric-hunks: New test case.
|
||||
* Makefile.in (TESTS): Add test case.
|
||||
|
||||
* util.c (move_file): Create backup files of nonexisting files with
|
||||
* util.c (move_file): Create backup files of nonexistent files with
|
||||
the default mode instead of mode 0: files with mode 0 cause too many
|
||||
problems with applications which do not expect unreadable files.
|
||||
* tests/create-delete: Test for this.
|
||||
@ -2030,7 +2030,7 @@
|
||||
|
||||
* util.c (move_file): Don't assume that ENOENT is reported when both
|
||||
ENOENT and EXDEV apply; this isn't true with DJGPP, and
|
||||
Posix doesn't require it.
|
||||
POSIX doesn't require it.
|
||||
|
||||
* pch.c (there_is_another_patch):
|
||||
Suggest -p when we can't intuit a file.
|
||||
@ -2185,7 +2185,7 @@
|
||||
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.
|
||||
If -T or -Z option is given, match timestamps 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;
|
||||
@ -3658,23 +3658,20 @@ Sun Dec 17 17:29:48 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
|
||||
* patch.c: Initial revision
|
||||
|
||||
|
||||
Copyright (C) 1984, 1985, 1986, 1987, 1988 Larry Wall.
|
||||
|
||||
Copyright (C) 1989-1993, 1997-2002, 2009-2012 Free Software Foundation, Inc.
|
||||
Copyright 1989-2025 Free Software Foundation, Inc.
|
||||
Copyright 1984-1988 Larry Wall.
|
||||
|
||||
This file is part of GNU Patch.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that they will be useful,
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
18
Makefile.am
18
Makefile.am
@ -1,5 +1,4 @@
|
||||
# Copyright (C) 1989-1993, 1997-1999, 2002-2003, 2006, 2009-2012 Free Software
|
||||
# Foundation, Inc.
|
||||
# Copyright 1989-2025 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -23,17 +22,19 @@ dist_man1_MANS = patch.man
|
||||
EXTRA_DIST = \
|
||||
ChangeLog-2011 \
|
||||
cfg.mk \
|
||||
m4/gnulib-cache.m4 \
|
||||
m4/mkdir.m4 \
|
||||
m4/setmode.m4 \
|
||||
m4/utimbuf.m4 \
|
||||
bootstrap \
|
||||
pc
|
||||
|
||||
if ALPHA_VERSION
|
||||
EXTRA_DIST += README-alpha
|
||||
GNU_SERVER = alpha.gnu.org
|
||||
RELEASE_TYPE = alpha
|
||||
else
|
||||
GNU_SERVER = ftp.gnu.org
|
||||
RELEASE_TYPE = stable
|
||||
endif
|
||||
|
||||
EXTRA_DIST += $(top_srcdir)/.version
|
||||
@ -52,14 +53,3 @@ gen-ChangeLog:
|
||||
rm -f $(distdir)/ChangeLog; \
|
||||
mv $(distdir)/cl-t $(distdir)/ChangeLog; \
|
||||
fi
|
||||
|
||||
tell-upload:
|
||||
echo; \
|
||||
(echo "Upload with: "; \
|
||||
for archive in $(DIST_ARCHIVES); do \
|
||||
echo "gnupload --to $(GNU_SERVER):patch $$archive"; \
|
||||
done) | \
|
||||
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'; \
|
||||
echo
|
||||
upload: dist tell-upload
|
||||
uploadcheck: distcheck tell-upload
|
||||
|
||||
66
NEWS
66
NEWS
@ -1,3 +1,50 @@
|
||||
Unreleased changes:
|
||||
|
||||
Changes in version 2.8:
|
||||
|
||||
* The --follow-symlinks option now applies to output files as well as input.
|
||||
* 'patch' now supports file timestamps after 2038 even on traditional
|
||||
GNU/Linux platforms where time_t defaults to 32 bits.
|
||||
* 'patch' no longer creates files with names containing newlines,
|
||||
as encouraged by POSIX.1-2024.
|
||||
* Patches can no longer contain NUL ('\0') bytes in diff directive lines.
|
||||
These bytes would otherwise cause unpredictable behavior.
|
||||
* Patches can now contain sequences of spaces and tabs around line numbers
|
||||
and in other places where POSIX requires support for these sequences.
|
||||
* --enable-gcc-warnings no longer uses expensive static checking.
|
||||
Use --enable-gcc-warnings=expensive if you still want it.
|
||||
* Fix undefined or ill-defined behavior in unusual cases, such as very
|
||||
large sizes, possible stack overflow, I/O errors, memory exhaustion,
|
||||
races with other processes, and signals arriving at inopportune moments.
|
||||
* Remove old "Plan B" code, designed for machines with 16-bit pointers.
|
||||
* Assume C99 or later; previously it assumed C89 or later.
|
||||
* Port to current GCC, Autoconf, Gnulib, etc.
|
||||
|
||||
Changes in version 2.7.6:
|
||||
|
||||
* Files specified on the command line are no longer verified to be inside the
|
||||
current working directory, so commands like "patch -i foo.diff ../foo" will
|
||||
work again.
|
||||
* Various fixes.
|
||||
|
||||
Changes in version 2.7.5:
|
||||
|
||||
* There are users which expect patch to follow symbolic links in the working
|
||||
directory, so patch now again follows symbolic links as long as they do not
|
||||
leave the working directory.
|
||||
|
||||
Changes until version 2.7.4:
|
||||
|
||||
* When a file isn't being deleted because the file contents don't match the
|
||||
patch, the resulting message is now "Not deleting file ... as content
|
||||
differs from patch" instead of "File ... is not empty after patch; not
|
||||
deleting".
|
||||
* Function names in hunks (from diff -p) are now preserved in reject files.
|
||||
* Patch no longer follows symbolic links to input and output files. This
|
||||
ensures that symbolic links created by git-style patches cannot cause
|
||||
patch to write outside the working directory (CVE-2015-1196).
|
||||
* Various fixes.
|
||||
|
||||
Changes in version 2.7.1:
|
||||
|
||||
* Two critical bug fixes in the "diff --git" format support.
|
||||
@ -84,7 +131,7 @@ Changes in version 2.6:
|
||||
line endings in patches. This allows to preserve CRs even in mangled
|
||||
patches, or in patches generated on non-POSIX systems and without the
|
||||
--binary option.
|
||||
* Backup files for nonexisting files are now created with default
|
||||
* Backup files for nonexistent files are now created with default
|
||||
permissions rather than with mode 0: backup files with mode 0 were
|
||||
causing problems with applications which do not expect unreadable
|
||||
files.
|
||||
@ -110,7 +157,7 @@ Changes in version 2.5.6:
|
||||
|
||||
* File names in context patches may now contain spaces, so long
|
||||
as the context patch headers use a tab to separate the file name
|
||||
from the time stamp.
|
||||
from the timestamp.
|
||||
* Perforce is now supported.
|
||||
* Patch lines beginning with "#" are comments and are ignored.
|
||||
|
||||
@ -317,22 +364,19 @@ Changes in version 2.0.12g8:
|
||||
|
||||
|
||||
|
||||
Copyright (C) 1992-1993, 1997-2003, 2006, 2009, 2011-2012 Free Software
|
||||
Foundation, Inc.
|
||||
Copyright 1992-2025 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Patch.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that they will be useful,
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
13
README
13
README
@ -16,7 +16,7 @@ README-hacking file. If this file came to you as part of a tar archive,
|
||||
then see the file INSTALL for compilation and installation instructions.
|
||||
|
||||
See the file NEWS for a list of major changes in the current release.
|
||||
A more detailed descripiton of all changes can be found in the file ChangeLog
|
||||
A more detailed description of all changes can be found in the file ChangeLog
|
||||
in tar archives, and with "git log" which shows the version control history.
|
||||
|
||||
Tutorial-style documentation for patch is included in the GNU
|
||||
@ -41,12 +41,15 @@ too busy working on other things, like Perl. He has graciously agreed
|
||||
to let GNU `patch' be distributed under the terms of the GNU General
|
||||
Public License.
|
||||
|
||||
For any copyright year range specified as YYYY-ZZZZ in this package
|
||||
note that the range specifies every single year in that closed interval.
|
||||
|
||||
Please see the file COPYING for copying conditions.
|
||||
|
||||
------
|
||||
|
||||
Copyright (C) 1984, 1985, 1986, 1987, 1988 Larry Wall
|
||||
|
||||
Copyright (C) 1989-1993, 1997, 1999, 2002, 2009, 2011-2012 Free Software
|
||||
Foundation, Inc.
|
||||
Copyright 1989-2025 Free Software Foundation, Inc.
|
||||
Copyright 1984-1988 Larry Wall
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,40 +1,47 @@
|
||||
-*- outline -*-
|
||||
Building from a Git repository -*- outline -*-
|
||||
|
||||
These notes intend to help people working on the checked-out sources.
|
||||
These requirements do not apply when building from a distribution tarball.
|
||||
If this package has a file HACKING, please also read that file for
|
||||
more detailed contribution guidelines.
|
||||
|
||||
* Requirements
|
||||
|
||||
We've opted to keep only the highest-level sources in the GIT repository.
|
||||
This eases our maintenance burden, (fewer merges etc.), but imposes more
|
||||
We've opted to keep only the highest-level sources in the Git repository.
|
||||
This eases our maintenance burden (fewer merges etc.), but imposes more
|
||||
requirements on anyone wishing to build from the just-checked-out sources.
|
||||
For example, you have to use the latest stable versions of the maintainer
|
||||
tools we depend upon, including:
|
||||
|
||||
- Automake <http://www.gnu.org/software/automake/>
|
||||
- Autoconf <http://www.gnu.org/software/autoconf/>
|
||||
- Gettext <http://www.gnu.org/software/gettext/>
|
||||
- Gzip <http://www.gnu.org/software/gzip/>
|
||||
- M4 <http://www.gnu.org/software/m4/>
|
||||
- Tar <http://www.gnu.org/software/tar/>
|
||||
- Wget <http://www.gnu.org/software/wget/>
|
||||
(The requirements to build from a release are much less and are just
|
||||
the requirements of the standard './configure && make' procedure.)
|
||||
Specific development tools and versions will be checked for and listed by
|
||||
the bootstrap script. See README-prereq for specific notes on obtaining
|
||||
these prerequisite tools.
|
||||
|
||||
Valgrind <http://valgrind.org/> is also highly recommended, if
|
||||
Valgrind supports your architecture.
|
||||
Valgrind supports your architecture. See also README-valgrind
|
||||
(if present).
|
||||
|
||||
While building from a just-cloned source tree may require installing a
|
||||
few prerequisites, later, a plain `git pull && make' should be sufficient.
|
||||
few prerequisites, later, a plain 'git pull && make' typically suffices.
|
||||
|
||||
* First GIT checkout
|
||||
* First Git checkout
|
||||
|
||||
You can get a copy of the source repository like this:
|
||||
|
||||
$ git clone git://git.sv.gnu.org/patch
|
||||
$ cd patch
|
||||
$ git clone git://git.sv.gnu.org/<packagename>
|
||||
$ cd <packagename>
|
||||
|
||||
As an optional step, if you already have a copy of the gnulib git
|
||||
repository on your hard drive, then you can use it as a reference to
|
||||
reduce download time and disk space requirements:
|
||||
where '<packagename>' stands for 'coreutils' or whatever other package
|
||||
you are building.
|
||||
|
||||
To use the most-recent Gnulib (as opposed to the Gnulib version that
|
||||
the package last synchronized to), do this next:
|
||||
|
||||
$ git submodule foreach git pull origin master
|
||||
$ git commit -m 'build: update gnulib submodule to latest' gnulib
|
||||
|
||||
As an optional step, if you already have a copy of the Gnulib Git
|
||||
repository, then you can use it as a reference to reduce download
|
||||
time and file system space requirements:
|
||||
|
||||
$ export GNULIB_SRCDIR=/path/to/gnulib
|
||||
|
||||
@ -43,20 +50,14 @@ which are extracted from other source packages:
|
||||
|
||||
$ ./bootstrap
|
||||
|
||||
To use the most-recent gnulib (as opposed to the gnulib version that
|
||||
the package last synchronized to), do this next:
|
||||
|
||||
$ git submodule foreach git pull origin master
|
||||
$ git commit -m 'build: update gnulib submodule to latest' gnulib
|
||||
|
||||
And there you are! Just
|
||||
|
||||
$ ./configure --quiet
|
||||
$ ./configure --quiet #[--disable-gcc-warnings] [*]
|
||||
$ make
|
||||
$ make check
|
||||
|
||||
At this point, there should be no difference between your local copy,
|
||||
and the GIT master copy:
|
||||
and the Git master copy:
|
||||
|
||||
$ git diff
|
||||
|
||||
@ -64,22 +65,34 @@ should output no difference.
|
||||
|
||||
Enjoy!
|
||||
|
||||
[*] By default GCC warnings are enabled when building from Git.
|
||||
If you get warnings with recent GCC and Glibc with default
|
||||
configure-time options, please report the warnings to the bug
|
||||
reporting address of this package instead of to bug-gnulib,
|
||||
even if the problem seems to originate in a Gnulib-provided file.
|
||||
If you get warnings with other configurations, you can run
|
||||
'./configure --disable-gcc-warnings' or 'make WERROR_CFLAGS='
|
||||
to build quietly or verbosely, respectively.
|
||||
-----
|
||||
|
||||
* Submitting patches
|
||||
|
||||
If you develop a fix or a new feature, please send it to the
|
||||
appropriate bug-reporting address as reported by the --help option of
|
||||
each program. One way to do this is to use vc-dwim
|
||||
<http://www.gnu.org/software/vc-dwim/>), as follows.
|
||||
<https://www.gnu.org/software/vc-dwim/>), as follows.
|
||||
|
||||
Run the command "vc-dwim --help", copy its definition of the
|
||||
"git-changelog-symlink-init" function into your shell, and then run
|
||||
this function at the top-level directory of the package.
|
||||
Run the command "vc-dwim --initialize" from the top-level directory
|
||||
of this package's git-cloned hierarchy.
|
||||
|
||||
Edit the ChangeLog file that this command creates, creating a
|
||||
Edit the (empty) ChangeLog file that this command creates, creating a
|
||||
properly-formatted entry according to the GNU coding standards
|
||||
<http://www.gnu.org/prep/standards/html_node/Change-Logs.html>.
|
||||
<https://www.gnu.org/prep/standards/html_node/Change-Logs.html>.
|
||||
|
||||
Run the command "vc-dwim" and make sure its output looks good.
|
||||
Make your changes.
|
||||
|
||||
Run the command "vc-dwim" and make sure its output (the diff of all
|
||||
your changes) looks good.
|
||||
|
||||
Run "vc-dwim --commit".
|
||||
|
||||
@ -88,7 +101,7 @@ each program. One way to do this is to use vc-dwim
|
||||
|
||||
-----
|
||||
|
||||
Copyright (C) 2002-2007, 2009-2012 Free Software Foundation, Inc.
|
||||
Copyright 2002-2025 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -101,4 +114,4 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
36
README-prereq
Normal file
36
README-prereq
Normal file
@ -0,0 +1,36 @@
|
||||
This gives some notes on obtaining the tools required for development.
|
||||
These tools can be used by the 'bootstrap' and 'configure' scripts,
|
||||
as well as by 'make'. They include:
|
||||
|
||||
- Autoconf <https://www.gnu.org/software/autoconf/>
|
||||
- Automake <https://www.gnu.org/software/automake/>
|
||||
- Git <https://git-scm.com/>
|
||||
- Gzip <https://www.gnu.org/software/gzip/>
|
||||
- M4 <https://www.gnu.org/software/m4/>
|
||||
- Make <https://www.gnu.org/software/make/>
|
||||
- Tar <https://www.gnu.org/software/tar/>
|
||||
- Texinfo <https://www.gnu.org/software/texinfo/>
|
||||
- Wget <http://www.gnu.org/software/wget/>
|
||||
- XZ Utils <https://tukaani.org/xz/>
|
||||
|
||||
It is generally better to use official packages for your system.
|
||||
If a package is not officially available you can build it from source
|
||||
and install it into a directory that you can then use to build this
|
||||
package. If some packages are available but are too old, install the
|
||||
too-old versions first as they may be needed to build newer versions.
|
||||
|
||||
Here is an example of how to build a program from source. This
|
||||
example is for Autoconf; a similar approach should work for the other
|
||||
developer prerequisites. This example assumes Autoconf 2.it; 72
|
||||
should be OK to use a later version of Autoconf, if available.
|
||||
|
||||
prefix=$HOME/prefix # (or wherever else you choose)
|
||||
export PATH=$prefix/bin:$PATH
|
||||
wget https://ftp.gnu.org/pub/gnu/autoconf/autoconf-2.72.tar.gz
|
||||
gzip -d <autoconf-2.72.tar.gz | tar xf -
|
||||
cd autoconf-2.72
|
||||
./configure --prefix=$prefix
|
||||
make install
|
||||
|
||||
Once the prerequisites are installed, you can build this package as
|
||||
described in README-hacking.
|
||||
127
bootstrap.conf
127
bootstrap.conf
@ -1,10 +1,10 @@
|
||||
# Bootstrap configuration.
|
||||
# Bootstrap configuration. -*- sh -*-
|
||||
|
||||
# Copyright (C) 2006-2007, 2009-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2006-2025 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@ -13,103 +13,92 @@
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# gnulib modules used by this package.
|
||||
gnulib_modules="
|
||||
announce-gen
|
||||
argmatch
|
||||
assert-h
|
||||
attribute
|
||||
backupfile
|
||||
clock-time
|
||||
basename-lgpl
|
||||
bool
|
||||
c-ctype
|
||||
closeout
|
||||
diffseq
|
||||
dirname
|
||||
dup2
|
||||
errno
|
||||
errno-h
|
||||
exitfail
|
||||
extensions
|
||||
faccessat
|
||||
fchownat
|
||||
fchmodat
|
||||
fcntl-h
|
||||
full-write
|
||||
getdate
|
||||
filename
|
||||
fseeko
|
||||
fstatat
|
||||
ftello
|
||||
futimens
|
||||
getopt-gnu
|
||||
gettime
|
||||
gitlog-to-changelog
|
||||
git-version-gen
|
||||
gnupload
|
||||
hash
|
||||
idx
|
||||
ignore-value
|
||||
intprops
|
||||
inttypes-h
|
||||
largefile
|
||||
lchmod
|
||||
linked-list
|
||||
lstat
|
||||
maintainer-makefile
|
||||
malloc
|
||||
malloc-gnu
|
||||
manywarnings
|
||||
memchr
|
||||
mempcpy
|
||||
minmax
|
||||
mkdir
|
||||
mkdirat
|
||||
nullptr
|
||||
openat
|
||||
parse-datetime
|
||||
progname
|
||||
quotearg
|
||||
readlink
|
||||
realloc
|
||||
rename
|
||||
rmdir
|
||||
raise
|
||||
readlinkat
|
||||
realloc-posix
|
||||
renameat
|
||||
setenv
|
||||
signal
|
||||
signal-h
|
||||
ssize_t
|
||||
stat-time
|
||||
stdbool
|
||||
stdlib
|
||||
symlink
|
||||
sys_stat
|
||||
stdckdint-h
|
||||
stdlib-h
|
||||
stpcpy
|
||||
symlinkat
|
||||
sys_stat-h
|
||||
tempname
|
||||
time
|
||||
unistd
|
||||
unlink
|
||||
test-xfail
|
||||
unistd-h
|
||||
unlinkat
|
||||
update-copyright
|
||||
utimens
|
||||
utimensat
|
||||
verror
|
||||
xalloc
|
||||
xlist
|
||||
xstdopen
|
||||
year2038-recommended
|
||||
"
|
||||
|
||||
gnulib_tool_option_extras='--symlink --makefile-name=gnulib.mk'
|
||||
# Build prerequisites
|
||||
buildreq="\
|
||||
autoconf 2.59
|
||||
automake 1.9.6
|
||||
git 1.5.5
|
||||
tar -
|
||||
"
|
||||
|
||||
# # Additional xgettext options to use. Use "\\\newline" to break lines.
|
||||
# XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
|
||||
# --from-code=UTF-8\\\
|
||||
# --flag=asprintf:2:c-format --flag=vasprintf:2:c-format\\\
|
||||
# --flag=asnprintf:3:c-format --flag=vasnprintf:3:c-format\\\
|
||||
# --flag=wrapf:1:c-format\\\
|
||||
# '
|
||||
#
|
||||
# # If "AM_GNU_GETTEXT(external" or "AM_GNU_GETTEXT([external]"
|
||||
# # appears in configure.ac, exclude some unnecessary files.
|
||||
# # Without grep's -E option (not portable enough, pre-configure),
|
||||
# # the following test is ugly. Also, this depends on the existence
|
||||
# # of configure.ac, not the obsolescent-named configure.in. But if
|
||||
# # you're using this infrastructure, you should care about such things.
|
||||
#
|
||||
# gettext_external=0
|
||||
# grep '^[ ]*AM_GNU_GETTEXT(external\>' configure.ac > /dev/null &&
|
||||
# gettext_external=1
|
||||
# grep '^[ ]*AM_GNU_GETTEXT(\[external\]' configure.ac > /dev/null &&
|
||||
# gettext_external=1
|
||||
#
|
||||
# if test $gettext_external = 1; then
|
||||
# # Gettext supplies these files, but we don't need them since
|
||||
# # we don't have an intl subdirectory.
|
||||
# excluded_files='
|
||||
# m4/glibc2.m4
|
||||
# m4/intdiv0.m4
|
||||
# m4/lcmessage.m4
|
||||
# m4/lock.m4
|
||||
# m4/printf-posix.m4
|
||||
# m4/size_max.m4
|
||||
# m4/uintmax_t.m4
|
||||
# m4/ulonglong.m4
|
||||
# m4/visibility.m4
|
||||
# m4/xsize.m4
|
||||
# '
|
||||
# fi
|
||||
|
||||
# Automake requires that ChangeLog exist.
|
||||
touch ChangeLog || exit 1
|
||||
bootstrap_post_import_hook ()
|
||||
{
|
||||
# Automake requires that ChangeLog exist.
|
||||
touch ChangeLog || exit 1
|
||||
}
|
||||
|
||||
13
cfg.mk
13
cfg.mk
@ -1,5 +1,5 @@
|
||||
# Customize maint.mk -*- makefile -*-
|
||||
# Copyright (C) 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2011-2025 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,8 +16,17 @@
|
||||
|
||||
config_h_header = <(common|config)\.h>
|
||||
|
||||
ifeq ($(RELEASE_TYPE),alpha)
|
||||
news-check-regexp = "Unreleased changes"
|
||||
else
|
||||
news-check-regexp = '^Changes in version $(VERSION_REGEXP):'
|
||||
endif
|
||||
|
||||
release-prep-hook =
|
||||
|
||||
update-copyright-env = \
|
||||
UPDATE_COPYRIGHT_USE_INTERVALS=1 \
|
||||
UPDATE_COPYRIGHT_FORCE=1 \
|
||||
UPDATE_COPYRIGHT_USE_INTERVALS=2 \
|
||||
UPDATE_COPYRIGHT_MAX_LINE_LENGTH=79
|
||||
|
||||
local-checks-to-skip = \
|
||||
|
||||
114
configure.ac
114
configure.ac
@ -1,10 +1,9 @@
|
||||
# Copyright (C) 1993, 1997-1999, 2002-2003, 2006, 2009, 2011-2012 Free Software
|
||||
# Foundation, Inc.
|
||||
# Copyright 1993-2025 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@ -12,9 +11,7 @@
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AC_PREREQ([2.65])
|
||||
|
||||
@ -33,116 +30,87 @@ AM_CONDITIONAL([ENABLE_MERGE], [test "$enableval" != no])
|
||||
AM_CONDITIONAL([ALPHA_VERSION],
|
||||
[[echo "$PACKAGE_VERSION" | grep -- "-[0-9a-f][0-9a-f]*\\(-dirty\\)\\?$" >/dev/null]])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.11.2 -Wall -Werror gnu dist-bzip2 dist-xz color-tests parallel-tests])
|
||||
AM_INIT_AUTOMAKE([1.11.2 -Wall gnu dist-bzip2 dist-xz color-tests parallel-tests subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
AC_CONFIG_HEADER([config.h:config.hin])
|
||||
AC_CONFIG_HEADERS([config.h:config.hin])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CC_STDC
|
||||
gl_EARLY
|
||||
gl_USE_SYSTEM_EXTENSIONS
|
||||
AC_HEADER_STDC
|
||||
gl_INIT
|
||||
AM_PROG_AR
|
||||
|
||||
AC_ARG_ENABLE([gcc-warnings],
|
||||
[AS_HELP_STRING([--enable-gcc-warnings],
|
||||
[turn on lots of GCC warnings (for developers)])],
|
||||
[AS_HELP_STRING([--enable-gcc-warnings@<:@=TYPE@:>@],
|
||||
[control generation of GCC warnings. The TYPE 'no' disables
|
||||
warnings (default for non-developer builds); 'yes' generates
|
||||
cheap warnings if available;
|
||||
'expensive' in addition generates expensive-to-compute warnings
|
||||
if available.])],
|
||||
[case $enableval in
|
||||
yes|no) ;;
|
||||
no|yes|expensive) ;;
|
||||
*) AC_MSG_ERROR([bad value $enableval for gcc-warnings option]) ;;
|
||||
esac
|
||||
gl_gcc_warnings=$enableval],
|
||||
[gl_gcc_warnings=no]
|
||||
)
|
||||
|
||||
if test "$gl_gcc_warnings" = yes; then
|
||||
if test $gl_gcc_warnings != no; then
|
||||
gl_WARN_ADD([-Werror], [WERROR_CFLAGS])
|
||||
AC_SUBST([WERROR_CFLAGS])
|
||||
|
||||
nw=
|
||||
ew=
|
||||
AS_IF([test $gl_gcc_warnings != expensive],
|
||||
[# -fanalyzer and related options slow GCC considerably.
|
||||
ew="$ew -fanalyzer -Wno-analyzer-malloc-leak"])
|
||||
|
||||
# This, $nw, is the list of warnings we disable.
|
||||
nw="$nw -Wdeclaration-after-statement" # too useful to forbid
|
||||
nw="$nw -Waggregate-return" # anachronistic
|
||||
nw="$nw -Wlong-long" # C90 is anachronistic (lib/gethrxtime.h)
|
||||
nw="$nw -Wc++-compat" # We don't care about C++ compilers
|
||||
nw="$nw -Wundef" # Warns on '#if GNULIB_FOO' etc in gnulib
|
||||
nw="$nw -Wtraditional" # Warns on #elif which we use often
|
||||
nw="$nw -Wcast-qual" # Too many warnings for now
|
||||
nw="$nw -Wconversion" # Too many warnings for now
|
||||
nw="$nw -Wsystem-headers" # Don't let system headers trigger warnings
|
||||
nw="$nw -Wsign-conversion" # Too many warnings for now
|
||||
nw="$nw -Wtraditional-conversion" # Too many warnings for now
|
||||
nw="$nw -Wunreachable-code" # Too many warnings for now
|
||||
nw="$nw -Wpadded" # Our structs are not padded
|
||||
nw="$nw -Wredundant-decls" # openat.h declares e.g., mkdirat
|
||||
nw="$nw -Wlogical-op" # any use of fwrite provokes this
|
||||
nw="$nw -Wformat-nonliteral" # who.c and pinky.c strftime uses
|
||||
nw="$nw -Wvla" # warnings in gettext.h
|
||||
nw="$nw -Wnested-externs" # use of XARGMATCH/verify_function__
|
||||
nw="$nw -Wswitch-enum" # Too many warnings for now
|
||||
nw="$nw -Wswitch-default" # Too many warnings for now
|
||||
nw="$nw -Wstack-protector" # not worth working around
|
||||
nw="$nw -Wmissing-format-attribute" # not worth working around in patch
|
||||
nw="$nw -Wsuggest-attribute=format" # warns about util.c
|
||||
# things to fix soon:
|
||||
nw="$nw -Wshadow"
|
||||
nw="$nw -Wstrict-overflow"
|
||||
nw="$nw -Wunsafe-loop-optimizations"
|
||||
# nw="$nw -Wfloat-equal" # sort.c, seq.c
|
||||
# nw="$nw -Wmissing-format-attribute" # copy.c
|
||||
# nw="$nw -Winline" # system.h's readdir_ignoring_dot_and_dotdot
|
||||
# ?? -Wstrict-overflow
|
||||
nw=$ew
|
||||
nw="$nw -Winline" # It's OK for a compiler to not inline.
|
||||
|
||||
# Using -Wstrict-overflow is a pain, but the alternative is worse.
|
||||
# For an example, see the code that provoked this report:
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33498
|
||||
# Code like that still infloops with gcc-4.6.0 and -O2. Scary indeed.
|
||||
|
||||
gl_MANYWARN_ALL_GCC([ws])
|
||||
gl_MANYWARN_COMPLEMENT([ws], [$ws], [$nw])
|
||||
for w in $ws; do
|
||||
gl_WARN_ADD([$w])
|
||||
done
|
||||
gl_WARN_ADD([-Wno-missing-field-initializers]) # We need this one
|
||||
gl_WARN_ADD([-Wno-sign-compare]) # Too many warnings for now
|
||||
gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now
|
||||
|
||||
# In spite of excluding -Wlogical-op above, it is enabled, as of
|
||||
# gcc 4.5.0 20090517, and it provokes warnings in cat.c, dd.c, truncate.c
|
||||
gl_WARN_ADD([-Wno-logical-op])
|
||||
|
||||
gl_WARN_ADD([-fdiagnostics-show-option])
|
||||
gl_WARN_ADD([-funit-at-a-time])
|
||||
gl_WARN_ADD([-Wno-format-nonliteral])
|
||||
|
||||
AC_SUBST([WARN_CFLAGS])
|
||||
|
||||
AC_DEFINE([lint], [1], [Define to 1 if the compiler is checking for lint.])
|
||||
AC_DEFINE([_FORTIFY_SOURCE], [2],
|
||||
[enable compile-time and run-time bounds-checking, and some warnings])
|
||||
AH_VERBATIM([FORTIFY_SOURCE],
|
||||
[/* Enable compile-time and run-time bounds-checking, and some warnings,
|
||||
without upsetting glibc 2.15+. */
|
||||
#if !defined _FORTIFY_SOURCE && defined __OPTIMIZE__ && __OPTIMIZE__
|
||||
# define _FORTIFY_SOURCE 2
|
||||
#endif
|
||||
])
|
||||
AC_DEFINE([GNULIB_PORTCHECK], [1], [enable some gnulib portability checks])
|
||||
|
||||
# We use a slightly smaller set of warning options for lib/.
|
||||
# We also use a smaller set of warning options for lib/.
|
||||
# Remove the following and save the result in GNULIB_WARN_CFLAGS.
|
||||
nw=
|
||||
nw="$nw -Wuninitialized"
|
||||
nw="$nw -Wunused-macros"
|
||||
nw="$nw -Wmissing-prototypes"
|
||||
nw="$nw -Wold-style-definition"
|
||||
nw=$ew
|
||||
gl_MANYWARN_COMPLEMENT([GNULIB_WARN_CFLAGS], [$WARN_CFLAGS], [$nw])
|
||||
AC_SUBST([GNULIB_WARN_CFLAGS])
|
||||
|
||||
# For gnulib-tests, the set is slightly smaller still.
|
||||
nw=
|
||||
nw="$nw -Wstrict-prototypes"
|
||||
gl_MANYWARN_COMPLEMENT([GNULIB_TEST_WARN_CFLAGS],
|
||||
[$GNULIB_WARN_CFLAGS], [$nw])
|
||||
AC_SUBST([GNULIB_TEST_WARN_CFLAGS])
|
||||
fi
|
||||
|
||||
# Ensure VLAs are not used.
|
||||
# Note -Wvla is implicitly added by gl_MANYWARN_ALL_GCC
|
||||
AC_DEFINE([GNULIB_NO_VLA], [1], [Define to 1 to disable use of VLAs])
|
||||
|
||||
AC_TYPE_MODE_T
|
||||
AC_TYPE_OFF_T
|
||||
|
||||
gl_FUNC_XATTR
|
||||
|
||||
AC_CHECK_FUNCS(geteuid getuid raise sigaction sigprocmask sigsetmask)
|
||||
AC_CHECK_FUNCS_ONCE([geteuid getuid sigaction sigfillset])
|
||||
AC_FUNC_SETMODE_DOS
|
||||
|
||||
AC_PATH_PROG([ED], [ed], [ed])
|
||||
|
||||
2
gnulib
2
gnulib
@ -1 +1 @@
|
||||
Subproject commit 77b054428b11be9cd76d1e3b0a7cd7cf86053173
|
||||
Subproject commit 9829f0a93c40492875f67ee738e000611bdcf0e7
|
||||
@ -1,14 +0,0 @@
|
||||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
AM_CFLAGS =
|
||||
AM_CPPFLAGS =
|
||||
BUILT_SOURCES =
|
||||
CLEANFILES =
|
||||
EXTRA_DIST =
|
||||
MAINTAINERCLEANFILES =
|
||||
MOSTLYCLEANDIRS =
|
||||
MOSTLYCLEANFILES =
|
||||
SUFFIXES =
|
||||
noinst_LIBRARIES =
|
||||
|
||||
include gnulib.mk
|
||||
250
m4/.gitignore
vendored
250
m4/.gitignore
vendored
@ -1,250 +0,0 @@
|
||||
/00gnulib.m4
|
||||
/alloca.m4
|
||||
/argmatch.m4
|
||||
/backupfile.m4
|
||||
/bison.m4
|
||||
/canonicalize.m4
|
||||
/clock_time.m4
|
||||
/closedir.m4
|
||||
/codeset.m4
|
||||
/configmake.m4
|
||||
/d-ino.m4
|
||||
/dirent-safer.m4
|
||||
/dirent_h.m4
|
||||
/dirfd.m4
|
||||
/dirname.m4
|
||||
/double-slash-root.m4
|
||||
/dup2.m4
|
||||
/eealloc.m4
|
||||
/environ.m4
|
||||
/errno_h.m4
|
||||
/error.m4
|
||||
/exponentd.m4
|
||||
/extensions.m4
|
||||
/fcntl-o.m4
|
||||
/fcntl.m4
|
||||
/fcntl_h.m4
|
||||
/float_h.m4
|
||||
/fstat.m4
|
||||
/getdtablesize.m4
|
||||
/getopt.m4
|
||||
/gettime.m4
|
||||
/gettimeofday.m4
|
||||
/glibc21.m4
|
||||
/gnulib-cache.m4
|
||||
/gnulib-common.m4
|
||||
/gnulib-comp.m4
|
||||
/gnulib-tool.m4
|
||||
/hash.m4
|
||||
/include_next.m4
|
||||
/inline.m4
|
||||
/intmax_t.m4
|
||||
/inttypes_h.m4
|
||||
/largefile.m4
|
||||
/lchmod.m4
|
||||
/localcharset.m4
|
||||
/locale-fr.m4
|
||||
/locale-ja.m4
|
||||
/locale-zh.m4
|
||||
/longlong.m4
|
||||
/lstat.m4
|
||||
/malloc.m4
|
||||
/malloca.m4
|
||||
/manywarnings.m4
|
||||
/math_h.m4
|
||||
/mbrtowc.m4
|
||||
/mbsinit.m4
|
||||
/mbstate_t.m4
|
||||
/memchr.m4
|
||||
/minmax.m4
|
||||
/mkdir.m4
|
||||
/mktime.m4
|
||||
/mmap-anon.m4
|
||||
/msvc-inval.m4
|
||||
/msvc-nothrow.m4
|
||||
/multiarch.m4
|
||||
/nocrash.m4
|
||||
/opendir.m4
|
||||
/parse-datetime.m4
|
||||
/pathmax.m4
|
||||
/printf.m4
|
||||
/quote.m4
|
||||
/quotearg.m4
|
||||
/raise.m4
|
||||
/readdir.m4
|
||||
/readlink.m4
|
||||
/realloc.m4
|
||||
/rename.m4
|
||||
/rmdir.m4
|
||||
/safe-read.m4
|
||||
/safe-write.m4
|
||||
/setenv.m4
|
||||
/signal_h.m4
|
||||
/size_max.m4
|
||||
/ssize_t.m4
|
||||
/stat-time.m4
|
||||
/stat.m4
|
||||
/stdarg.m4
|
||||
/stdbool.m4
|
||||
/stddef_h.m4
|
||||
/stdint.m4
|
||||
/stdint_h.m4
|
||||
/stdio_h.m4
|
||||
/stdlib_h.m4
|
||||
/strerror.m4
|
||||
/string_h.m4
|
||||
/strndup.m4
|
||||
/strnlen.m4
|
||||
/symlink.m4
|
||||
/sys_socket_h.m4
|
||||
/sys_stat_h.m4
|
||||
/sys_time_h.m4
|
||||
/tempname.m4
|
||||
/time_h.m4
|
||||
/time_r.m4
|
||||
/timespec.m4
|
||||
/tm_gmtoff.m4
|
||||
/unistd-safer.m4
|
||||
/unistd_h.m4
|
||||
/unlink.m4
|
||||
/utimbuf.m4
|
||||
/utimens.m4
|
||||
/utimes.m4
|
||||
/vasnprintf.m4
|
||||
/vasprintf.m4
|
||||
/warn-on-use.m4
|
||||
/warnings.m4
|
||||
/wchar_h.m4
|
||||
/wchar_t.m4
|
||||
/wctype_h.m4
|
||||
/wint_t.m4
|
||||
/write.m4
|
||||
/xalloc.m4
|
||||
/xsize.m4
|
||||
/xstrndup.m4
|
||||
/xvasprintf.m4
|
||||
00gnulib.m4
|
||||
alloca.m4
|
||||
argmatch.m4
|
||||
backupfile.m4
|
||||
bison.m4
|
||||
canonicalize.m4
|
||||
clock_time.m4
|
||||
codeset.m4
|
||||
configmake.m4
|
||||
d-ino.m4
|
||||
dirent-safer.m4
|
||||
dirent_h.m4
|
||||
dirfd.m4
|
||||
dirname.m4
|
||||
dos.m4
|
||||
double-slash-root.m4
|
||||
dup2.m4
|
||||
eealloc.m4
|
||||
environ.m4
|
||||
errno_h.m4
|
||||
error.m4
|
||||
extensions.m4
|
||||
fcntl-o.m4
|
||||
fcntl.m4
|
||||
fcntl_h.m4
|
||||
float_h.m4
|
||||
fseek.m4
|
||||
fseeko.m4
|
||||
ftell.m4
|
||||
ftello.m4
|
||||
getdate.m4
|
||||
getdtablesize.m4
|
||||
getopt.m4
|
||||
gettime.m4
|
||||
gettimeofday.m4
|
||||
glibc21.m4
|
||||
gnulib-cache.m4
|
||||
gnulib-common.m4
|
||||
gnulib-comp.m4
|
||||
gnulib-tool.m4
|
||||
hash.m4
|
||||
include_next.m4
|
||||
inline.m4
|
||||
intmax_t.m4
|
||||
inttypes_h.m4
|
||||
lchmod.m4
|
||||
localcharset.m4
|
||||
locale-fr.m4
|
||||
locale-ja.m4
|
||||
locale-zh.m4
|
||||
longlong.m4
|
||||
lseek.m4
|
||||
lstat.m4
|
||||
malloc.m4
|
||||
malloca.m4
|
||||
manywarnings.m4
|
||||
mbrtowc.m4
|
||||
mbsinit.m4
|
||||
mbstate_t.m4
|
||||
memchr.m4
|
||||
minmax.m4
|
||||
mkdir.m4
|
||||
mktime.m4
|
||||
mmap-anon.m4
|
||||
multiarch.m4
|
||||
onceonly.m4
|
||||
parse-datetime.m4
|
||||
pathmax.m4
|
||||
printf.m4
|
||||
quote.m4
|
||||
quotearg.m4
|
||||
readlink.m4
|
||||
realloc.m4
|
||||
rename.m4
|
||||
rmdir.m4
|
||||
safe-read.m4
|
||||
safe-write.m4
|
||||
setenv.m4
|
||||
size_max.m4
|
||||
ssize_t.m4
|
||||
stat-time.m4
|
||||
stat.m4
|
||||
stdarg.m4
|
||||
stdbool.m4
|
||||
stddef_h.m4
|
||||
stdint.m4
|
||||
stdint_h.m4
|
||||
stdio_h.m4
|
||||
stdlib_h.m4
|
||||
strerror.m4
|
||||
string_h.m4
|
||||
strndup.m4
|
||||
strnlen.m4
|
||||
symlink.m4
|
||||
sys_stat_h.m4
|
||||
sys_time_h.m4
|
||||
tempname.m4
|
||||
time_h.m4
|
||||
time_r.m4
|
||||
timespec.m4
|
||||
tm_gmtoff.m4
|
||||
unistd-safer.m4
|
||||
unistd_h.m4
|
||||
unlink.m4
|
||||
utimbuf.m4
|
||||
utimens.m4
|
||||
utimes.m4
|
||||
vasnprintf.m4
|
||||
vasprintf.m4
|
||||
warn-on-use.m4
|
||||
warnings.m4
|
||||
wchar_h.m4
|
||||
wchar_t.m4
|
||||
wctype_h.m4
|
||||
wint_t.m4
|
||||
write.m4
|
||||
xalloc.m4
|
||||
xsize.m4
|
||||
xstrndup.m4
|
||||
xvasprintf.m4
|
||||
/close.m4
|
||||
/gl_list.m4
|
||||
/off_t.m4
|
||||
/sys_types_h.m4
|
||||
/extern-inline.m4
|
||||
@ -1,35 +1,33 @@
|
||||
# Check for setmode, DOS style.
|
||||
|
||||
# Copyright (C) 2001-2002, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2001-2025 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
# USA.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AC_DEFUN([AC_FUNC_SETMODE_DOS],
|
||||
[AC_CHECK_HEADERS([fcntl.h unistd.h])
|
||||
[AC_CHECK_HEADERS_ONCE([fcntl.h unistd.h])
|
||||
AC_CACHE_CHECK([for DOS-style setmode],
|
||||
[ac_cv_func_setmode_dos],
|
||||
[AC_TRY_LINK(
|
||||
[#include <io.h>
|
||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <io.h>
|
||||
#if HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif],
|
||||
[int ret = setmode && setmode (1, O_BINARY);],
|
||||
#endif]],
|
||||
[int ret = setmode && setmode (1, O_BINARY);])],
|
||||
[ac_cv_func_setmode_dos=yes],
|
||||
[ac_cv_func_setmode_dos=no])])
|
||||
if test $ac_cv_func_setmode_dos = yes; then
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# xattr.m4 - check for Extended Attributes (Linux)
|
||||
# serial 3
|
||||
# serial 4
|
||||
|
||||
# Copyright (C) 2003, 2008-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2003-2025 Free Software Foundation, Inc.
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
@ -12,7 +12,7 @@
|
||||
AC_DEFUN([gl_FUNC_XATTR],
|
||||
[
|
||||
AC_ARG_ENABLE([xattr],
|
||||
AC_HELP_STRING([--disable-xattr],
|
||||
AS_HELP_STRING([--disable-xattr],
|
||||
[do not support extended attributes]),
|
||||
[use_xattr=$enableval], [use_xattr=yes])
|
||||
|
||||
|
||||
299
patch.man
299
patch.man
@ -1,14 +1,13 @@
|
||||
.\" patch man page
|
||||
.de Id
|
||||
.ds Dt \\$4
|
||||
..
|
||||
.ds = \-\^\-
|
||||
.de Sp
|
||||
.if t .sp .3
|
||||
.if n .sp
|
||||
..
|
||||
.TH PATCH 1 \*(Dt GNU
|
||||
.ta 3n
|
||||
.ds Cw CW
|
||||
.if \n(.g .if f CR .ds Cw CR
|
||||
.ds fC \f(\*(Cw
|
||||
.TH PATCH 1 "" GNU
|
||||
.SH NAME
|
||||
patch \- apply a diff file to an original
|
||||
.SH SYNOPSIS
|
||||
@ -60,7 +59,7 @@ editor via a pipe.
|
||||
.B patch
|
||||
tries to skip any leading garbage, apply the diff,
|
||||
and then skip any trailing garbage.
|
||||
Thus you could feed an article or message containing a
|
||||
Thus you could feed an email message containing a
|
||||
diff listing to
|
||||
.BR patch ,
|
||||
and it should work.
|
||||
@ -149,8 +148,8 @@ to edit is, using the following rules.
|
||||
First,
|
||||
.B patch
|
||||
takes an ordered list of candidate file names as follows:
|
||||
.TP 3
|
||||
.B " \(bu"
|
||||
.RS "\w' 'u"
|
||||
.IP \(bu "\w'\(bu 'u"
|
||||
If the header is that of a context diff,
|
||||
.B patch
|
||||
takes the old and new file names in the header.
|
||||
@ -162,8 +161,7 @@ option.
|
||||
The name
|
||||
.B /dev/null
|
||||
is also ignored.
|
||||
.TP
|
||||
.B " \(bu"
|
||||
.IP \(bu
|
||||
If there is an
|
||||
.B Index:\&
|
||||
line in the leading garbage
|
||||
@ -174,23 +172,22 @@ is conforming to \s-1POSIX\s0,
|
||||
takes the name in the
|
||||
.B Index:\&
|
||||
line.
|
||||
.TP
|
||||
.B " \(bu"
|
||||
.IP \(bu
|
||||
For the purpose of the following rules,
|
||||
the candidate file names are considered to be in the order (old, new, index),
|
||||
regardless of the order that they appear in the header.
|
||||
.RE
|
||||
.LP
|
||||
Then
|
||||
.B patch
|
||||
selects a file name from the candidate list as follows:
|
||||
.TP 3
|
||||
.B " \(bu"
|
||||
.RS "\w' 'u"
|
||||
.IP \(bu "\w'\(bu 'u"
|
||||
If some of the named files exist,
|
||||
.B patch
|
||||
selects the first name if conforming to \s-1POSIX\s0,
|
||||
and the best name otherwise.
|
||||
.TP
|
||||
.B " \(bu"
|
||||
.IP \(bu
|
||||
If
|
||||
.B patch
|
||||
is not ignoring \s-1RCS\s0, ClearCase, Perforce, and \s-1SCCS\s0 (see the
|
||||
@ -202,8 +199,7 @@ but an \s-1RCS\s0, ClearCase, Perforce, or \s-1SCCS\s0 master is found,
|
||||
.B patch
|
||||
selects the first named file
|
||||
with an \s-1RCS\s0, ClearCase, Perforce, or \s-1SCCS\s0 master.
|
||||
.TP
|
||||
.B " \(bu"
|
||||
.IP \(bu
|
||||
If no named files exist,
|
||||
no \s-1RCS\s0, ClearCase, Perforce, or \s-1SCCS\s0 master was found,
|
||||
some names are given,
|
||||
@ -212,12 +208,12 @@ is not conforming to \s-1POSIX\s0,
|
||||
and the patch appears to create a file,
|
||||
.B patch
|
||||
selects the best name requiring the creation of the fewest directories.
|
||||
.TP
|
||||
.B " \(bu"
|
||||
.IP \(bu
|
||||
If no file name results from the above heuristics, you are asked
|
||||
for the name of the file to patch, and
|
||||
.B patch
|
||||
selects that name.
|
||||
.RE
|
||||
.LP
|
||||
To determine the
|
||||
.I best
|
||||
@ -238,15 +234,16 @@ If not,
|
||||
.B patch
|
||||
asks for confirmation before proceeding.
|
||||
.PP
|
||||
The upshot of all this is that you should be able to say, while in a news
|
||||
interface, something like the following:
|
||||
The upshot of all this is that you should be able to run
|
||||
something like the following shell command:
|
||||
.Sp
|
||||
\fB| patch \-d /usr/src/local/blurfl\fP
|
||||
.RS
|
||||
\fBpatch \-d /usr/src/local/blurfl\fP
|
||||
.RE
|
||||
.Sp
|
||||
and patch a file in the
|
||||
.B blurfl
|
||||
directory directly from the article containing
|
||||
the patch.
|
||||
directory directly from a patch that is read from standard input.
|
||||
.PP
|
||||
If the patch file contains more than one patch,
|
||||
.B patch
|
||||
@ -262,9 +259,6 @@ mentioned previously.
|
||||
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.
|
||||
See the
|
||||
.B \-V
|
||||
or
|
||||
@ -342,7 +336,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 time stamps on the header to determine whether a file
|
||||
can examine the timestamps on the header to determine whether a file
|
||||
should exist after patching.
|
||||
However, if the input is not a context diff or if
|
||||
.B patch
|
||||
@ -423,21 +417,22 @@ A typical conflict will look like this:
|
||||
.LP
|
||||
.RS
|
||||
.nf
|
||||
.B <<<<<<<
|
||||
.I lines from the original file
|
||||
.B |||||||
|
||||
.I original lines from the patch
|
||||
.B =======
|
||||
.I new lines from the patch
|
||||
.B >>>>>>>
|
||||
.ne 7
|
||||
\*(fC<<<<<<<\fP
|
||||
\fIlines from the original file\fP
|
||||
\*(fC|||||||\fP
|
||||
\fIoriginal lines from the patch\fP
|
||||
\*(fC=======\fP
|
||||
\fInew lines from the patch\fP
|
||||
\*(fC>>>>>>>\fP
|
||||
.RE
|
||||
.fi
|
||||
.IP "" 3
|
||||
The optional argument of \fB\*=merge\fP determines the output format for
|
||||
conflicts: the diff3 format shows the \fB|||||||\fP section with the original
|
||||
conflicts: the diff3 format shows the \*(fC|||||||\fP section with the original
|
||||
lines from the patch; in the merge format, this section is missing. The merge
|
||||
format is the default.
|
||||
|
||||
.Sp
|
||||
This option implies \fB\*=forward\fP and does not take the
|
||||
\fB--fuzz\fR=\fInum\fP option into account.
|
||||
.TP
|
||||
@ -445,9 +440,9 @@ This option implies \fB\*=forward\fP and does not take the
|
||||
Interpret the patch file as a normal diff.
|
||||
.TP
|
||||
\fB\-N\fP or \fB\*=forward\fP
|
||||
Ignore patches that seem to be reversed or already applied. It is only checked if
|
||||
the first hunk of a patch can be reversed.
|
||||
See also
|
||||
When a patch does not apply, patch usually checks if the patch looks like it
|
||||
has been applied already by trying to reverse-apply the first hunk. The
|
||||
\fB\*=forward\fP option prevents that. See also
|
||||
.BR \-R .
|
||||
.TP
|
||||
\fB\-o\fP \fIoutfile\fP or \fB\*=output=\fP\fIoutfile\fP
|
||||
@ -470,7 +465,9 @@ you keep your files in a different directory than the person who sent
|
||||
out the patch.
|
||||
For example, supposing the file name in the patch file was
|
||||
.Sp
|
||||
\fB/u/howard/src/blurfl/blurfl.c\fP
|
||||
.RS
|
||||
\fB/u/howard/src/blurfl/blurfl.c\fP
|
||||
.RE
|
||||
.Sp
|
||||
setting
|
||||
.B \-p0
|
||||
@ -478,13 +475,17 @@ gives the entire file name unmodified,
|
||||
.B \-p1
|
||||
gives
|
||||
.Sp
|
||||
\fBu/howard/src/blurfl/blurfl.c\fP
|
||||
.RS
|
||||
\fBu/howard/src/blurfl/blurfl.c\fP
|
||||
.RE
|
||||
.Sp
|
||||
without the leading slash,
|
||||
.B \-p4
|
||||
gives
|
||||
.Sp
|
||||
\fBblurfl/blurfl.c\fP
|
||||
.RS
|
||||
\fBblurfl/blurfl.c\fP
|
||||
.RE
|
||||
.Sp
|
||||
and not specifying
|
||||
.B \-p
|
||||
@ -496,23 +497,18 @@ option.
|
||||
.TP
|
||||
.B \*=posix
|
||||
Conform more strictly to the \s-1POSIX\s0 standard, as follows.
|
||||
.RS
|
||||
.TP 3
|
||||
.B " \(bu"
|
||||
.RS "\w' 'u"
|
||||
.IP \(bu "\w'\(bu 'u"
|
||||
Take the first existing file from the list (old, new, index)
|
||||
when intuiting file names from diff headers.
|
||||
.TP
|
||||
.B " \(bu"
|
||||
.IP \(bu
|
||||
Do not remove files that are empty after patching.
|
||||
.TP
|
||||
.B " \(bu"
|
||||
.IP \(bu
|
||||
Do not ask whether to get files from \s-1RCS\s0, ClearCase, Perforce,
|
||||
or \s-1SCCS\s0.
|
||||
.TP
|
||||
.B " \(bu"
|
||||
.IP \(bu
|
||||
Require that all options precede the files in the command line.
|
||||
.TP
|
||||
.B " \(bu"
|
||||
.IP \(bu
|
||||
Do not backup files when there is a mismatch.
|
||||
.RE
|
||||
.TP
|
||||
@ -619,15 +615,15 @@ 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. Unless specified in the time stamps,
|
||||
Set the modification and access times of patched files from timestamps
|
||||
given in context diff headers. Unless specified in the timestamps,
|
||||
assume that the context diff headers use local time.
|
||||
.Sp
|
||||
Use of this option with time stamps that do not include time zones is
|
||||
Use of this option with timestamps that do not include time zones is
|
||||
not recommended, because patches using local time cannot easily be used
|
||||
by people in other time zones, and because local time stamps are
|
||||
by people in other time zones, and because local timestamps are
|
||||
ambiguous when local clocks move backwards during daylight-saving time
|
||||
adjustments. Make sure that time stamps include time zones, or generate
|
||||
adjustments. Make sure that timestamps include time zones, or generate
|
||||
patches with \s-1UTC\s0 and use the
|
||||
.B \-Z
|
||||
or
|
||||
@ -657,7 +653,7 @@ it affects only the names of any backup files that are made.
|
||||
The value of
|
||||
.I method
|
||||
is like the \s-1GNU\s0
|
||||
Emacs `version-control' variable;
|
||||
Emacs version-control variable;
|
||||
.B patch
|
||||
also recognizes synonyms that
|
||||
are more descriptive. The valid values for
|
||||
@ -754,8 +750,8 @@ is
|
||||
.BR src/patch/util.c- .
|
||||
.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. Unless specified in the time stamps,
|
||||
Set the modification and access times of patched files from timestamps
|
||||
given in context diff headers. Unless specified in the timestamps,
|
||||
assume that the context diff headers use Coordinated Universal Time
|
||||
(\s-1UTC\s0, often known as \s-1GMT\s0). Also see the
|
||||
.B \-T
|
||||
@ -847,13 +843,16 @@ controlling terminal; used to get answers to questions asked of the user
|
||||
.Sp
|
||||
Marshall T. Rose and Einar A. Stefferud,
|
||||
Proposed Standard for Message Encapsulation,
|
||||
Internet RFC 934 <URL:ftp://ftp.isi.edu/in-notes/rfc934.txt> (1985-01).
|
||||
Internet RFC 934 <https://datatracker.ietf.org/doc/html/rfc934> (1985-01).
|
||||
.SH "NOTES FOR PATCH SENDERS"
|
||||
There are several things you should bear in mind if you are going to
|
||||
be sending out patches.
|
||||
.PP
|
||||
Create your patch systematically.
|
||||
A good method is the command
|
||||
When using a version control system this should be easy;
|
||||
for example, with Git you can use
|
||||
.BR "git diff" .
|
||||
Otherwise, a good method is the command
|
||||
.BI "diff\ \-Naur\ " "old\ new"
|
||||
where
|
||||
.I old
|
||||
@ -865,18 +864,21 @@ The names
|
||||
and
|
||||
.I new
|
||||
should not contain any slashes.
|
||||
The
|
||||
.PP
|
||||
If the patch should communicate file timestamps as well as file contents, its
|
||||
.B diff
|
||||
command's headers should have dates
|
||||
commands' 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:
|
||||
Here is an example command to generate such headers, using Bourne shell syntax:
|
||||
.Sp
|
||||
\fBLC_ALL=C TZ=UTC0 diff \-Naur gcc\-2.7 gcc\-2.8\fP
|
||||
.RS
|
||||
\fBLC_ALL=C TZ=UTC0 diff \-Naur myprog\-2.7 myprog\-2.8\fP
|
||||
.RE
|
||||
.PP
|
||||
Tell your recipients how to apply the patch
|
||||
by telling them which directory to
|
||||
@ -925,14 +927,16 @@ If the recipient is supposed to use the
|
||||
.BI \-p N
|
||||
option, do not send output that looks like this:
|
||||
.Sp
|
||||
.ft B
|
||||
.RS
|
||||
.ft \*(Cw
|
||||
.ne 3
|
||||
diff \-Naur v2.0.29/prog/README prog/README
|
||||
diff \-Naur v2.0.29/prog/README prog/README
|
||||
.br
|
||||
\-\^\-\^\- v2.0.29/prog/README Mon Mar 10 15:13:12 1997
|
||||
\-\^\-\^\- v2.0.29/prog/README Mon Mar 10 15:13:12 2024
|
||||
.br
|
||||
+\^+\^+ prog/README Mon Mar 17 14:58:22 1997
|
||||
+\^+\^+ prog/README Mon Mar 17 14:58:22 2024
|
||||
.ft
|
||||
.RE
|
||||
.Sp
|
||||
because the two file names have different numbers of slashes,
|
||||
and different versions of
|
||||
@ -940,14 +944,16 @@ and different versions of
|
||||
interpret the file names differently.
|
||||
To avoid confusion, send output that looks like this instead:
|
||||
.Sp
|
||||
.ft B
|
||||
.RS
|
||||
.ft \*(Cw
|
||||
.ne 3
|
||||
diff \-Naur v2.0.29/prog/README v2.0.30/prog/README
|
||||
diff \-Naur v2.0.29/prog/README v2.0.30/prog/README
|
||||
.br
|
||||
\-\^\-\^\- v2.0.29/prog/README Mon Mar 10 15:13:12 1997
|
||||
\-\^\-\^\- v2.0.29/prog/README Mon Mar 10 15:13:12 2024
|
||||
.br
|
||||
+\^+\^+ v2.0.30/prog/README Mon Mar 17 14:58:22 1997
|
||||
+\^+\^+ v2.0.30/prog/README Mon Mar 17 14:58:22 2024
|
||||
.ft
|
||||
.RE
|
||||
.Sp
|
||||
.PP
|
||||
Avoid sending patches that compare backup file names like
|
||||
@ -968,7 +974,7 @@ Try not to have your patch modify derived files
|
||||
(e.g. the file
|
||||
.B configure
|
||||
where there is a line
|
||||
.B "configure: configure.in"
|
||||
.B "configure: configure.ac"
|
||||
in your makefile), since the recipient should be
|
||||
able to regenerate the derived files anyway.
|
||||
If you must send diffs of derived files,
|
||||
@ -1033,57 +1039,15 @@ 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
|
||||
GNU
|
||||
.BR patch .
|
||||
.RS "\w' 'u"
|
||||
.IP \(bu "\w'\(bu 'u"
|
||||
In \s-1POSIX\s0
|
||||
.B patch
|
||||
versions 2.1 and earlier, which do not conform to \s-1POSIX\s0.
|
||||
.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 ,
|
||||
backups were enabled by default.
|
||||
This behavior is now enabled with the
|
||||
when
|
||||
.B \-b
|
||||
or
|
||||
.B \*=backup
|
||||
option.
|
||||
.Sp
|
||||
Conversely, in \s-1POSIX\s0
|
||||
.BR patch ,
|
||||
backups are never made, even when there is a mismatch.
|
||||
is not used, backups are not made even when there is a mismatch.
|
||||
In \s-1GNU\s0
|
||||
.BR patch ,
|
||||
this behavior is enabled with the
|
||||
@ -1093,88 +1057,46 @@ option, or by conforming to \s-1POSIX\s0 with the
|
||||
option or by setting the
|
||||
.B POSIXLY_CORRECT
|
||||
environment variable.
|
||||
.Sp
|
||||
The
|
||||
.BI \-b "\ suffix"
|
||||
option
|
||||
of traditional
|
||||
.IP \(bu
|
||||
When intuiting the name of the file to be patched from the patch header,
|
||||
.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 did not conform to \s-1POSIX\s0, and had a few gotchas.
|
||||
Now
|
||||
.B patch
|
||||
uses a different, equally complicated (but better documented) method
|
||||
that is optionally \s-1POSIX\s0-conforming; we hope it has
|
||||
fewer gotchas. The two methods are compatible if the
|
||||
uses a complicated method
|
||||
that is optionally \s-1POSIX\s0-conforming.
|
||||
The method is equivalent to \s-1POSIX\s0 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"
|
||||
.IP \(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 ,
|
||||
.B patch
|
||||
or a
|
||||
.B patch
|
||||
that conforms to \s-1POSIX\s0.
|
||||
Spaces are significant in the following list, and operands are required.
|
||||
Spaces are optional in the following list.
|
||||
.Sp
|
||||
.nf
|
||||
.in +3
|
||||
.ne 11
|
||||
.B \-b
|
||||
.B \-c
|
||||
.BI \-d " dir"
|
||||
.BI \-D " define"
|
||||
.B \-e
|
||||
.BI \-i " patchfile"
|
||||
.B \-l
|
||||
.B \-n
|
||||
.B \-N
|
||||
.BI \-o " outfile"
|
||||
.BI \-p num
|
||||
.BI \-p " num"
|
||||
.B \-R
|
||||
.BI \-r " rejectfile"
|
||||
.BI \-u
|
||||
.in
|
||||
.fi
|
||||
.RE
|
||||
.SH BUGS
|
||||
Please report bugs via email to
|
||||
.BR <bug-patch@gnu.org> .
|
||||
@ -1194,16 +1116,9 @@ Computing how to merge a hunk is significantly harder than using the standard
|
||||
fuzzy algorithm. Bigger hunks, more context, a bigger offset from the
|
||||
original location, and a worse match all slow the algorithm down.
|
||||
.SH COPYING
|
||||
Copyright
|
||||
.ie t \(co
|
||||
.el (C)
|
||||
1984, 1985, 1986, 1988 Larry Wall.
|
||||
Copyright \(co 1989\(en2025 Free Software Foundation, Inc.
|
||||
.br
|
||||
Copyright
|
||||
.ie t \(co
|
||||
.el (C)
|
||||
1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
2000, 2001, 2002, 2009 Free Software Foundation, Inc.
|
||||
Copyright \(co 1984\(en1986, 1988 Larry Wall.
|
||||
.PP
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
@ -1229,4 +1144,4 @@ 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.
|
||||
Andreas Gr\[:u]nbacher added support for merging.
|
||||
Andreas Gruenbacher added support for merging.
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
# Copyright (C) 1989-1993, 1997-1999, 2002-2003, 2006, 2009-2012 Free Software
|
||||
# Foundation, Inc.
|
||||
# Copyright 1989-2025 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -27,14 +26,19 @@ patch_SOURCES = \
|
||||
patch.c \
|
||||
pch.c \
|
||||
pch.h \
|
||||
safe.c \
|
||||
safe.h \
|
||||
util.c \
|
||||
util.h \
|
||||
version.c \
|
||||
version.h
|
||||
version.h \
|
||||
list.h
|
||||
|
||||
AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib
|
||||
patch_LDADD = $(LDADD) $(top_builddir)/lib/libpatch.a $(LIB_CLOCK_GETTIME) \
|
||||
$(LIB_XATTR)
|
||||
patch_LDADD = $(LDADD) $(top_builddir)/lib/libpatch.a \
|
||||
$(CLOCK_TIME_LIB) $(EUIDACCESS_LIBGEN) $(GETRANDOM_LIB) \
|
||||
$(HARD_LOCALE_LIB) $(LIBINTL) $(MBRTOWC_LIB) $(SETLOCALE_NULL_LIB) \
|
||||
$(LIB_XATTR)
|
||||
|
||||
if ENABLE_MERGE
|
||||
patch_SOURCES += merge.c
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* Find a best match between two vectors.
|
||||
|
||||
Copyright (C) 2009-2012 Free Software Foundation, Inc.
|
||||
Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
Written by Andreas Gruenbacher <agruen@gnu.org>, 2009.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@ -64,7 +64,7 @@ bestmatch(OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim,
|
||||
OFFSET fmid_plus_2_min, ymax = -1;
|
||||
OFFSET c;
|
||||
|
||||
V = malloc ((2 * max + 3) * sizeof (OFFSET));
|
||||
V = xmalloc ((2 * max + 3) * sizeof (OFFSET));
|
||||
fd = V + max + 1 - fmid;
|
||||
|
||||
/*
|
||||
|
||||
191
src/common.h
191
src/common.h
@ -1,9 +1,7 @@
|
||||
/* common definitions for 'patch' */
|
||||
|
||||
/* Copyright (C) 1986, 1988 Larry Wall
|
||||
|
||||
Copyright (C) 1990-1993, 1997-1999, 2002-2003, 2006, 2009-2012 Free Software
|
||||
Foundation, Inc.
|
||||
/* Copyright 1990-2025 Free Software Foundation, Inc.
|
||||
Copyright 1986, 1988 Larry Wall
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -24,39 +22,26 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <attribute.h>
|
||||
#include <c-ctype.h>
|
||||
#include <idx.h>
|
||||
#include <intprops.h>
|
||||
#include <progname.h>
|
||||
#include <minmax.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdckdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#elif HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
/* CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
|
||||
as an argument to <ctype.h> macros like 'isspace'. */
|
||||
#if STDC_HEADERS
|
||||
#define CTYPE_DOMAIN(c) 1
|
||||
#else
|
||||
#define CTYPE_DOMAIN(c) ((unsigned) (c) <= 0177)
|
||||
#endif
|
||||
#ifndef ISSPACE
|
||||
#define ISSPACE(c) (CTYPE_DOMAIN (c) && isspace (c))
|
||||
#endif
|
||||
|
||||
#ifndef ISDIGIT
|
||||
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
|
||||
#endif
|
||||
|
||||
#include <progname.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* handy definitions */
|
||||
|
||||
@ -66,52 +51,60 @@
|
||||
|
||||
/* typedefs */
|
||||
|
||||
typedef off_t lin; /* must be signed */
|
||||
/* A description of an output file. It may be temporary. */
|
||||
struct outfile
|
||||
{
|
||||
/* Name of the file. */
|
||||
char *name;
|
||||
|
||||
/* Equal to NAME if the file exists; otherwise a null pointer.
|
||||
When non-null, the storage it points to is safe to access in
|
||||
a signal handler. */
|
||||
char volatile *volatile exists;
|
||||
|
||||
/* Equal to NAME if NAME should be freed when this structure is
|
||||
freed or reused; otherwise, a null pointer. */
|
||||
char *alloc;
|
||||
|
||||
/* Whether the file is intended to be temporary, and therefore
|
||||
should be cleaned up before exit, if it exists. */
|
||||
bool temporary;
|
||||
};
|
||||
|
||||
/* globals */
|
||||
|
||||
XTERN char *buf; /* general purpose buffer */
|
||||
XTERN size_t bufsize; /* allocated size of buf */
|
||||
extern char *inname;
|
||||
extern char *outfile;
|
||||
extern int inerrno;
|
||||
extern signed char invc;
|
||||
extern struct stat instat;
|
||||
extern bool dry_run;
|
||||
extern bool posixly_correct;
|
||||
|
||||
XTERN bool using_plan_a; /* try to keep everything in memory */
|
||||
extern char const *origprae;
|
||||
extern char const *origbase;
|
||||
extern char const *origsuff;
|
||||
|
||||
XTERN char *inname;
|
||||
XTERN char *outfile;
|
||||
XTERN int inerrno;
|
||||
XTERN int invc;
|
||||
XTERN struct stat instat;
|
||||
XTERN bool dry_run;
|
||||
XTERN bool posixly_correct;
|
||||
extern struct outfile tmped;
|
||||
extern struct outfile tmppat;
|
||||
|
||||
XTERN char const *origprae;
|
||||
XTERN char const *origbase;
|
||||
XTERN char const *origsuff;
|
||||
|
||||
XTERN char const * TMPINNAME;
|
||||
XTERN char const * TMPOUTNAME;
|
||||
XTERN char const * TMPPATNAME;
|
||||
|
||||
XTERN bool TMPINNAME_needs_removal;
|
||||
XTERN bool TMPOUTNAME_needs_removal;
|
||||
XTERN bool TMPPATNAME_needs_removal;
|
||||
|
||||
#ifdef DEBUGGING
|
||||
XTERN int debug;
|
||||
#if DEBUGGING
|
||||
extern unsigned short int debug;
|
||||
#else
|
||||
# define debug 0
|
||||
#endif
|
||||
XTERN bool force;
|
||||
XTERN bool batch;
|
||||
XTERN bool noreverse;
|
||||
XTERN bool reverse;
|
||||
XTERN enum { DEFAULT_VERBOSITY, SILENT, VERBOSE } verbosity;
|
||||
XTERN bool skip_rest_of_patch;
|
||||
XTERN int strippath;
|
||||
XTERN bool canonicalize;
|
||||
XTERN int patch_get;
|
||||
XTERN bool set_time;
|
||||
XTERN bool set_utc;
|
||||
XTERN bool follow_symlinks;
|
||||
extern bool force;
|
||||
extern bool batch;
|
||||
extern bool noreverse_flag;
|
||||
extern bool reverse_flag;
|
||||
extern enum verbosity { DEFAULT_VERBOSITY, SILENT, VERBOSE } verbosity;
|
||||
extern bool skip_rest_of_patch;
|
||||
extern intmax_t strippath;
|
||||
extern bool canonicalize_ws;
|
||||
extern intmax_t patch_get;
|
||||
extern bool set_time;
|
||||
extern bool set_utc;
|
||||
extern bool follow_symlinks;
|
||||
|
||||
enum diff
|
||||
{
|
||||
@ -124,42 +117,12 @@ enum diff
|
||||
GIT_BINARY_DIFF
|
||||
};
|
||||
|
||||
XTERN enum diff diff_type;
|
||||
extern enum diff diff_type;
|
||||
|
||||
XTERN char *revision; /* prerequisite revision, if any */
|
||||
extern char *revision; /* prerequisite revision, if any */
|
||||
|
||||
#ifndef __attribute__
|
||||
/* The __attribute__ feature is available in gcc versions 2.5 and later.
|
||||
The __-protected variants of the attributes 'format' and 'printf' are
|
||||
accepted by gcc versions 2.6.4 (effectively 2.7) and later.
|
||||
We enable __attribute__ only if these are supported too, because
|
||||
gnulib and libintl do '#define printf __printf__' when they override
|
||||
the 'printf' function. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
void fatal_exit (int) __attribute__ ((noreturn));
|
||||
|
||||
#include <errno.h>
|
||||
#if !STDC_HEADERS && !defined errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if HAVE_FSEEKO
|
||||
typedef off_t file_offset;
|
||||
# define file_seek fseeko
|
||||
# define file_tell ftello
|
||||
#else
|
||||
typedef long file_offset;
|
||||
# define file_seek fseek
|
||||
# define file_tell ftell
|
||||
#endif
|
||||
void fatal_cleanup (void);
|
||||
_Noreturn void fatal_exit (void);
|
||||
|
||||
#if ! (HAVE_GETEUID || defined geteuid)
|
||||
# if ! (HAVE_GETUID || defined getuid)
|
||||
@ -169,16 +132,14 @@ extern int errno;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef HAVE_SETMODE_DOS
|
||||
XTERN int binary_transput; /* O_BINARY if binary i/o is desired */
|
||||
extern int binary_transput; /* O_BINARY if binary i/o is desired */
|
||||
#else
|
||||
# define binary_transput 0
|
||||
#endif
|
||||
|
||||
/* Disable the CR stripping heuristic? */
|
||||
XTERN bool no_strip_trailing_cr;
|
||||
extern bool no_strip_trailing_cr;
|
||||
|
||||
#ifndef NULL_DEVICE
|
||||
#define NULL_DEVICE "/dev/null"
|
||||
@ -197,20 +158,20 @@ struct outstate
|
||||
};
|
||||
|
||||
/* offset in the input and output at which the previous hunk matched */
|
||||
XTERN lin in_offset;
|
||||
XTERN lin out_offset;
|
||||
extern ptrdiff_t in_offset;
|
||||
extern ptrdiff_t out_offset;
|
||||
|
||||
/* how many input lines have been irretractably output */
|
||||
XTERN lin last_frozen_line;
|
||||
extern idx_t last_frozen_line;
|
||||
|
||||
bool copy_till (struct outstate *, lin);
|
||||
bool similar (char const *, size_t, char const *, size_t) _GL_ATTRIBUTE_PURE;
|
||||
bool copy_till (struct outstate *, idx_t);
|
||||
bool similar (char const *, idx_t, char const *, idx_t) ATTRIBUTE_PURE;
|
||||
|
||||
#ifdef ENABLE_MERGE
|
||||
enum conflict_style { MERGE_MERGE, MERGE_DIFF3 };
|
||||
XTERN enum conflict_style conflict_style;
|
||||
extern enum conflict_style conflict_style;
|
||||
|
||||
bool merge_hunk (int hunk, struct outstate *, lin where, bool *);
|
||||
bool merge_hunk (intmax_t hunk, struct outstate *, idx_t where, bool *);
|
||||
#else
|
||||
# define merge_hunk(hunk, outstate, where, somefailed) false
|
||||
#endif
|
||||
|
||||
321
src/inp.c
321
src/inp.c
@ -1,8 +1,7 @@
|
||||
/* inputting files to be patched */
|
||||
|
||||
/* Copyright (C) 1986, 1988 Larry Wall
|
||||
Copyright (C) 1991-1993, 1997-1999, 2002-2003, 2006, 2009-2012 Free Software
|
||||
Foundation, Inc.
|
||||
/* Copyright 1991-2025 Free Software Foundation, Inc.
|
||||
Copyright 1986, 1988 Larry Wall
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -17,78 +16,34 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define XTERN extern
|
||||
#include <common.h>
|
||||
|
||||
#include <quotearg.h>
|
||||
#include <util.h>
|
||||
#include <xalloc.h>
|
||||
#undef XTERN
|
||||
#define XTERN
|
||||
|
||||
#include <inp.h>
|
||||
#include <safe.h>
|
||||
|
||||
/* Input-file-with-indexable-lines abstract type */
|
||||
|
||||
static char *i_buffer; /* plan A buffer */
|
||||
static char const **i_ptr; /* pointers to lines in plan A buffer */
|
||||
static char *i_buffer; /* buffer of input file lines */
|
||||
static char const **i_ptr; /* pointers to lines in buffer */
|
||||
idx_t input_lines; /* how long is input file in lines */
|
||||
|
||||
static size_t tibufsize; /* size of plan b buffers */
|
||||
#ifndef TIBUFSIZE_MINIMUM
|
||||
#define TIBUFSIZE_MINIMUM (8 * 1024) /* minimum value for tibufsize */
|
||||
#endif
|
||||
static int tifd = -1; /* plan b virtual string array */
|
||||
static char *tibuf[2]; /* plan b buffers */
|
||||
static lin tiline[2] = {-1, -1}; /* 1st line in each buffer */
|
||||
static lin lines_per_buf; /* how many lines per buffer */
|
||||
static size_t tireclen; /* length of records in tmp file */
|
||||
static size_t last_line_size; /* size of last input line */
|
||||
|
||||
static bool plan_a (char const *); /* yield false if memory runs out */
|
||||
static void plan_b (char const *);
|
||||
static void report_revision (bool);
|
||||
static void too_many_lines (char const *) __attribute__((noreturn));
|
||||
|
||||
/* New patch--prepare to edit another file. */
|
||||
|
||||
void
|
||||
re_input (void)
|
||||
{
|
||||
if (using_plan_a) {
|
||||
if (i_buffer)
|
||||
{
|
||||
free (i_buffer);
|
||||
i_buffer = 0;
|
||||
free (i_ptr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tifd >= 0)
|
||||
close (tifd);
|
||||
tifd = -1;
|
||||
if (tibuf[0])
|
||||
{
|
||||
free (tibuf[0]);
|
||||
tibuf[0] = 0;
|
||||
}
|
||||
tiline[0] = tiline[1] = -1;
|
||||
tireclen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct the line index, somehow or other. */
|
||||
|
||||
void
|
||||
scan_input (char *filename, mode_t file_type)
|
||||
{
|
||||
using_plan_a = ! (debug & 16) && plan_a (filename);
|
||||
if (!using_plan_a)
|
||||
{
|
||||
if (! S_ISREG (file_type))
|
||||
{
|
||||
assert (S_ISLNK (file_type));
|
||||
fatal ("Can't handle %s %s", "symbolic link", quotearg (filename));
|
||||
}
|
||||
plan_b(filename);
|
||||
}
|
||||
}
|
||||
|
||||
/* Report whether a desired revision was found. */
|
||||
@ -114,23 +69,16 @@ report_revision (bool found_revision)
|
||||
rev);
|
||||
else
|
||||
{
|
||||
ask ("This file doesn't appear to be the %s version -- patch anyway? [n] ",
|
||||
rev);
|
||||
if (*buf != 'y')
|
||||
if (*ask (("This file doesn't appear to be the %s version"
|
||||
" -- patch anyway? [n] "),
|
||||
rev)
|
||||
!= 'y')
|
||||
fatal ("aborted");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
too_many_lines (char const *filename)
|
||||
{
|
||||
fatal ("File %s has too many lines", quotearg (filename));
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
get_input_file (char const *filename, char const *outname, mode_t file_type)
|
||||
get_input_file (char *filename, char const *outname, mode_t file_type)
|
||||
{
|
||||
bool elsewhere = strcmp (filename, outname) != 0;
|
||||
char const *cs;
|
||||
@ -207,38 +155,29 @@ get_input_file (char const *filename, char const *outname, mode_t file_type)
|
||||
}
|
||||
|
||||
|
||||
/* Try keeping everything in memory. */
|
||||
/* Read input and build its line index. */
|
||||
|
||||
static bool
|
||||
plan_a (char const *filename)
|
||||
void
|
||||
scan_input (char *filename, mode_t file_type, int ifd)
|
||||
{
|
||||
char const *s;
|
||||
char const *lim;
|
||||
char const **ptr;
|
||||
char *buffer;
|
||||
lin iline;
|
||||
size_t size = instat.st_size;
|
||||
|
||||
/* Fail if the file size doesn't fit in a size_t,
|
||||
/* Fail if the file size doesn't fit,
|
||||
or if storage isn't available. */
|
||||
if (! (size == instat.st_size
|
||||
&& (buffer = malloc (size ? size : (size_t) 1))))
|
||||
return false;
|
||||
idx_t size;
|
||||
if (ckd_add (&size, instat.st_size, 0))
|
||||
xalloc_die ();
|
||||
char *buffer = ximalloc (size);
|
||||
|
||||
/* Read the input file, but don't bother reading it if it's empty.
|
||||
When creating files, the files do not actually exist. */
|
||||
if (size)
|
||||
{
|
||||
if (S_ISREG (instat.st_mode))
|
||||
if (S_ISREG (file_type))
|
||||
{
|
||||
int ifd = open (filename, O_RDONLY|binary_transput);
|
||||
size_t buffered = 0, n;
|
||||
if (ifd < 0)
|
||||
pfatal ("can't open file %s", quotearg (filename));
|
||||
idx_t buffered = 0;
|
||||
|
||||
while (size - buffered != 0)
|
||||
{
|
||||
n = read (ifd, buffer + buffered, size - buffered);
|
||||
ssize_t n = Read (ifd, buffer + buffered, size - buffered);
|
||||
if (n == 0)
|
||||
{
|
||||
/* Some non-POSIX hosts exaggerate st_size in text mode;
|
||||
@ -246,52 +185,30 @@ plan_a (char const *filename)
|
||||
size = buffered;
|
||||
break;
|
||||
}
|
||||
if (n == (size_t) -1)
|
||||
{
|
||||
/* Perhaps size is too large for this host. */
|
||||
close (ifd);
|
||||
free (buffer);
|
||||
return false;
|
||||
}
|
||||
buffered += n;
|
||||
}
|
||||
|
||||
if (close (ifd) != 0)
|
||||
read_fatal ();
|
||||
}
|
||||
else if (S_ISLNK (instat.st_mode))
|
||||
else
|
||||
{
|
||||
ssize_t n;
|
||||
n = readlink (filename, buffer, size);
|
||||
ssize_t n = safe_readlink (filename, buffer, size);
|
||||
if (n < 0)
|
||||
pfatal ("can't read %s %s", "symbolic link", quotearg (filename));
|
||||
size = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
free (buffer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan the buffer and build array of pointers to lines. */
|
||||
lim = buffer + size;
|
||||
iline = 3; /* 1 unused, 1 for SOF, 1 for EOF if last line is incomplete */
|
||||
for (s = buffer; (s = (char *) memchr (s, '\n', lim - s)); s++)
|
||||
if (++iline < 0)
|
||||
too_many_lines (filename);
|
||||
if (! (iline == (size_t) iline
|
||||
&& (size_t) iline * sizeof *ptr / sizeof *ptr == (size_t) iline
|
||||
&& (ptr = (char const **) malloc ((size_t) iline * sizeof *ptr))))
|
||||
{
|
||||
free (buffer);
|
||||
return false;
|
||||
}
|
||||
char const *lim = buffer + size;
|
||||
idx_t iline = 3; /* 1 unused, 1 for SOF,
|
||||
1 for EOF if last line is incomplete. */
|
||||
for (char const *s = buffer; (s = memchr (s, '\n', lim - s)); s++)
|
||||
iline++;
|
||||
char const **ptr = xireallocarray (nullptr, iline, sizeof *ptr);
|
||||
iline = 0;
|
||||
for (s = buffer; ; s++)
|
||||
for (char const *s = buffer; ; s++)
|
||||
{
|
||||
ptr[++iline] = s;
|
||||
if (! (s = (char *) memchr (s, '\n', lim - s)))
|
||||
if (! (s = memchr (s, '\n', lim - s)))
|
||||
break;
|
||||
}
|
||||
if (size && lim[-1] != '\n')
|
||||
@ -301,18 +218,18 @@ plan_a (char const *filename)
|
||||
if (revision)
|
||||
{
|
||||
char const *rev = revision;
|
||||
int rev0 = rev[0];
|
||||
char rev0 = rev[0];
|
||||
bool found_revision = false;
|
||||
size_t revlen = strlen (rev);
|
||||
idx_t revlen = strlen (rev);
|
||||
|
||||
if (revlen <= size)
|
||||
{
|
||||
char const *limrev = lim - revlen;
|
||||
|
||||
for (s = buffer; (s = (char *) memchr (s, rev0, limrev - s)); s++)
|
||||
for (char const *s = buffer; (s = memchr (s, rev0, limrev - s)); s++)
|
||||
if (memcmp (s, rev, revlen) == 0
|
||||
&& (s == buffer || ISSPACE ((unsigned char) s[-1]))
|
||||
&& (s + 1 == limrev || ISSPACE ((unsigned char) s[revlen])))
|
||||
&& (s == buffer || c_isspace (s[-1]))
|
||||
&& (s + 1 == limrev || c_isspace (s[revlen])))
|
||||
{
|
||||
found_revision = true;
|
||||
break;
|
||||
@ -322,164 +239,18 @@ plan_a (char const *filename)
|
||||
report_revision (found_revision);
|
||||
}
|
||||
|
||||
/* Plan A will work. */
|
||||
i_buffer = buffer;
|
||||
i_ptr = ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Keep (virtually) nothing in memory. */
|
||||
/* Fetch a line from the input file. */
|
||||
|
||||
static void
|
||||
plan_b (char const *filename)
|
||||
struct iline
|
||||
ifetch (idx_t line)
|
||||
{
|
||||
FILE *ifp;
|
||||
int c;
|
||||
size_t len;
|
||||
size_t maxlen;
|
||||
bool found_revision;
|
||||
size_t i;
|
||||
char const *rev;
|
||||
size_t revlen;
|
||||
lin line = 1;
|
||||
if (! (1 <= line && line <= input_lines))
|
||||
return (struct iline) { .ptr = "", .size = 0 };
|
||||
|
||||
if (instat.st_size == 0)
|
||||
filename = NULL_DEVICE;
|
||||
if (! (ifp = fopen (filename, binary_transput ? "rb" : "r")))
|
||||
pfatal ("Can't open file %s", quotearg (filename));
|
||||
if (TMPINNAME_needs_removal)
|
||||
{
|
||||
/* Reopen the existing temporary file. */
|
||||
tifd = create_file (TMPINNAME, O_RDWR | O_BINARY, 0, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
tifd = make_tempfile (&TMPINNAME, 'i', NULL, O_RDWR | O_BINARY,
|
||||
S_IRUSR | S_IWUSR);
|
||||
TMPINNAME_needs_removal = true;
|
||||
}
|
||||
i = 0;
|
||||
len = 0;
|
||||
maxlen = 1;
|
||||
rev = revision;
|
||||
found_revision = !rev;
|
||||
revlen = rev ? strlen (rev) : 0;
|
||||
|
||||
while ((c = getc (ifp)) != EOF)
|
||||
{
|
||||
len++;
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
if (++line < 0)
|
||||
too_many_lines (filename);
|
||||
if (maxlen < len)
|
||||
maxlen = len;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
if (!found_revision)
|
||||
{
|
||||
if (i == revlen)
|
||||
{
|
||||
found_revision = ISSPACE ((unsigned char) c);
|
||||
i = (size_t) -1;
|
||||
}
|
||||
else if (i != (size_t) -1)
|
||||
i = rev[i]==c ? i + 1 : (size_t) -1;
|
||||
|
||||
if (i == (size_t) -1 && ISSPACE ((unsigned char) c))
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (revision)
|
||||
report_revision (found_revision);
|
||||
Fseek (ifp, 0, SEEK_SET); /* rewind file */
|
||||
for (tibufsize = TIBUFSIZE_MINIMUM; tibufsize < maxlen; tibufsize <<= 1)
|
||||
/* do nothing */ ;
|
||||
lines_per_buf = tibufsize / maxlen;
|
||||
tireclen = maxlen;
|
||||
tibuf[0] = xmalloc (2 * tibufsize);
|
||||
tibuf[1] = tibuf[0] + tibufsize;
|
||||
|
||||
for (line = 1; ; line++)
|
||||
{
|
||||
char *p = tibuf[0] + maxlen * (line % lines_per_buf);
|
||||
char const *p0 = p;
|
||||
if (! (line % lines_per_buf)) /* new block */
|
||||
if (write (tifd, tibuf[0], tibufsize) != tibufsize)
|
||||
write_fatal ();
|
||||
if ((c = getc (ifp)) == EOF)
|
||||
break;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
*p++ = c;
|
||||
if (c == '\n')
|
||||
{
|
||||
last_line_size = p - p0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((c = getc (ifp)) == EOF)
|
||||
{
|
||||
last_line_size = p - p0;
|
||||
line++;
|
||||
goto EOF_reached;
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF_reached:
|
||||
if (ferror (ifp) || fclose (ifp) != 0)
|
||||
read_fatal ();
|
||||
|
||||
if (line % lines_per_buf != 0)
|
||||
if (write (tifd, tibuf[0], tibufsize) != tibufsize)
|
||||
write_fatal ();
|
||||
input_lines = line - 1;
|
||||
}
|
||||
|
||||
/* Fetch a line from the input file.
|
||||
WHICHBUF is ignored when the file is in memory. */
|
||||
|
||||
char const *
|
||||
ifetch (lin line, bool whichbuf, size_t *psize)
|
||||
{
|
||||
char const *q;
|
||||
char const *p;
|
||||
|
||||
if (line < 1 || line > input_lines) {
|
||||
*psize = 0;
|
||||
return "";
|
||||
}
|
||||
if (using_plan_a) {
|
||||
p = i_ptr[line];
|
||||
*psize = i_ptr[line + 1] - p;
|
||||
return p;
|
||||
} else {
|
||||
lin offline = line % lines_per_buf;
|
||||
lin baseline = line - offline;
|
||||
|
||||
if (tiline[0] == baseline)
|
||||
whichbuf = false;
|
||||
else if (tiline[1] == baseline)
|
||||
whichbuf = true;
|
||||
else {
|
||||
tiline[whichbuf] = baseline;
|
||||
if ((lseek (tifd, baseline/lines_per_buf * tibufsize, SEEK_SET)
|
||||
== -1)
|
||||
|| read (tifd, tibuf[whichbuf], tibufsize) < 0)
|
||||
read_fatal ();
|
||||
}
|
||||
p = tibuf[whichbuf] + (tireclen*offline);
|
||||
if (line == input_lines)
|
||||
*psize = last_line_size;
|
||||
else {
|
||||
for (q = p; *q++ != '\n'; )
|
||||
/* do nothing */ ;
|
||||
*psize = q - p;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
char const *ptr = i_ptr[line];
|
||||
return (struct iline) { .ptr = ptr, .size = i_ptr[line + 1] - ptr };
|
||||
}
|
||||
|
||||
18
src/inp.h
18
src/inp.h
@ -1,8 +1,7 @@
|
||||
/* inputting files to be patched */
|
||||
|
||||
/* Copyright (C) 1986, 1988 Larry Wall
|
||||
Copyright (C) 1991-1993, 1997-1999, 2002-2003, 2009-2012 Free Software
|
||||
Foundation, Inc.
|
||||
/* Copyright 1991-2025 Free Software Foundation, Inc.
|
||||
Copyright 1986, 1988 Larry Wall
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -17,9 +16,14 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
XTERN lin input_lines; /* how long is input file in lines */
|
||||
/* Number of lines in input file. */
|
||||
extern idx_t input_lines;
|
||||
|
||||
char const *ifetch (lin, bool, size_t *);
|
||||
bool get_input_file (char const *, char const *, mode_t);
|
||||
/* Description of an input line: a pointer to its start, and the
|
||||
number of bytes in it (including any trailing newline). */
|
||||
struct iline { char const *ptr; idx_t size; };
|
||||
|
||||
struct iline ifetch (idx_t) ATTRIBUTE_PURE;
|
||||
bool get_input_file (char *, char const *, mode_t);
|
||||
void re_input (void);
|
||||
void scan_input (char *, mode_t);
|
||||
void scan_input (char *, mode_t, int);
|
||||
|
||||
67
src/list.h
Normal file
67
src/list.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef __LIST_H
|
||||
#define __LIST_H
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
_GL_INLINE_HEADER_BEGIN
|
||||
#ifndef LIST_INLINE
|
||||
# define LIST_INLINE _GL_INLINE
|
||||
#endif
|
||||
|
||||
LIST_INLINE void
|
||||
INIT_LIST_HEAD (struct list_head *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
LIST_INLINE void
|
||||
list_add (struct list_head *entry, struct list_head *head)
|
||||
{
|
||||
struct list_head *next = head->next;
|
||||
entry->prev = head;
|
||||
entry->next = next;
|
||||
next->prev = head->next = entry;
|
||||
}
|
||||
|
||||
LIST_INLINE void
|
||||
list_del (struct list_head *entry)
|
||||
{
|
||||
struct list_head *next = entry->next;
|
||||
struct list_head *prev = entry->prev;
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
LIST_INLINE void
|
||||
list_del_init (struct list_head *entry)
|
||||
{
|
||||
list_del (entry);
|
||||
INIT_LIST_HEAD (entry);
|
||||
}
|
||||
|
||||
LIST_INLINE bool
|
||||
list_empty (const struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
/* Return PTR - OFFSET, ignoring the type of PTR and treating OFFSET
|
||||
as a byte offset. */
|
||||
LIST_INLINE void *
|
||||
list_entry (void *ptr, idx_t offset)
|
||||
{
|
||||
char *p = ptr;
|
||||
return p - offset;
|
||||
}
|
||||
|
||||
_GL_INLINE_HEADER_END
|
||||
|
||||
#endif /* __LIST_H */
|
||||
219
src/merge.c
219
src/merge.c
@ -1,6 +1,6 @@
|
||||
/* Merge a patch
|
||||
|
||||
Copyright (C) 2009-2012 Free Software Foundation, Inc.
|
||||
Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
Written by Andreas Gruenbacher <agruen@gnu.org>, 2009.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@ -16,24 +16,22 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define XTERN extern
|
||||
#include <common.h>
|
||||
#include <minmax.h>
|
||||
#include <xalloc.h>
|
||||
#include <inp.h>
|
||||
#include <pch.h>
|
||||
#include <util.h>
|
||||
|
||||
static lin count_context_lines (void);
|
||||
static bool context_matches_file (lin, lin);
|
||||
static void compute_changes (lin, lin, lin, lin, char *, char *);
|
||||
static idx_t count_context_lines (void);
|
||||
static bool context_matches_file (idx_t, idx_t);
|
||||
static void compute_changes (idx_t, idx_t, idx_t, idx_t, char *, char *);
|
||||
|
||||
#define OFFSET lin
|
||||
#define OFFSET ptrdiff_t
|
||||
#define EQUAL_IDX(x, y) (context_matches_file (x, y))
|
||||
#include "bestmatch.h"
|
||||
|
||||
#define XVECREF_YVECREF_EQUAL(ctxt, x, y) (context_matches_file (x, y))
|
||||
#define OFFSET lin
|
||||
#define OFFSET ptrdiff_t
|
||||
#define EXTRA_CONTEXT_FIELDS \
|
||||
char *xchar; \
|
||||
char *ychar;
|
||||
@ -42,21 +40,19 @@ static void compute_changes (lin, lin, lin, lin, char *, char *);
|
||||
#define USE_HEURISTIC 1
|
||||
#include "diffseq.h"
|
||||
|
||||
static lin
|
||||
locate_merge (lin *matched)
|
||||
static idx_t
|
||||
locate_merge (idx_t *matched)
|
||||
{
|
||||
lin first_guess = pch_first () + in_offset;
|
||||
lin pat_lines = pch_ptrn_lines ();
|
||||
lin context_lines = count_context_lines ();
|
||||
lin max_where = input_lines - pat_lines + context_lines + 1;
|
||||
lin min_where = last_frozen_line + 1;
|
||||
lin max_pos_offset = max_where - first_guess;
|
||||
lin max_neg_offset = first_guess - min_where;
|
||||
lin max_offset = (max_pos_offset < max_neg_offset
|
||||
? max_neg_offset : max_pos_offset);
|
||||
lin where = first_guess, max_matched = 0;
|
||||
lin min, max;
|
||||
lin offset;
|
||||
idx_t first_guess = pch_first () + in_offset;
|
||||
idx_t pat_lines = pch_ptrn_lines ();
|
||||
idx_t context_lines = count_context_lines ();
|
||||
idx_t max_where = input_lines - pat_lines + context_lines + 1;
|
||||
idx_t min_where = last_frozen_line + 1;
|
||||
ptrdiff_t max_pos_offset = max_where - first_guess;
|
||||
ptrdiff_t max_neg_offset = first_guess - min_where;
|
||||
ptrdiff_t max_offset = MAX (max_pos_offset, max_neg_offset);
|
||||
idx_t where = first_guess;
|
||||
idx_t max_matched = 0;
|
||||
bool match_until_eof;
|
||||
|
||||
/* Note: we need to preserve patch's property that it applies hunks at the
|
||||
@ -70,21 +66,15 @@ locate_merge (lin *matched)
|
||||
|
||||
/* Allow at most CONTEXT_LINES lines to be replaced (replacing counts
|
||||
as insert + delete), and require the remaining MIN lines to match. */
|
||||
max = 2 * context_lines;
|
||||
min = pat_lines - context_lines;
|
||||
idx_t max = 2 * context_lines;
|
||||
idx_t min = pat_lines - context_lines;
|
||||
|
||||
if (debug & 1)
|
||||
{
|
||||
char numbuf0[LINENUM_LENGTH_BOUND + 1];
|
||||
char numbuf1[LINENUM_LENGTH_BOUND + 1];
|
||||
say ("locating merge: min=%s max=%s ",
|
||||
format_linenum (numbuf0, min),
|
||||
format_linenum (numbuf1, max));
|
||||
}
|
||||
say ("locating merge: min=%td max=%td ", min, max);
|
||||
|
||||
/* Hunks from the start or end of the file have less context. Anchor them
|
||||
to the start or end, trying to make up for this disadvantage. */
|
||||
offset = pch_suffix_context () - pch_prefix_context ();
|
||||
ptrdiff_t offset = pch_suffix_context () - pch_prefix_context ();
|
||||
if (offset > 0 && pch_first () <= 1)
|
||||
max_pos_offset = 0;
|
||||
match_until_eof = offset < 0;
|
||||
@ -97,9 +87,7 @@ locate_merge (lin *matched)
|
||||
{
|
||||
if (offset <= max_pos_offset)
|
||||
{
|
||||
lin guess = first_guess + offset;
|
||||
lin last;
|
||||
lin changes;
|
||||
idx_t guess = first_guess + offset, last, changes;
|
||||
|
||||
changes = bestmatch (1, pat_lines + 1, guess, input_lines + 1,
|
||||
match_until_eof ? input_lines - guess + 1 : min,
|
||||
@ -116,9 +104,7 @@ locate_merge (lin *matched)
|
||||
}
|
||||
if (0 < offset && offset <= max_neg_offset)
|
||||
{
|
||||
lin guess = first_guess - offset;
|
||||
lin last;
|
||||
lin changes;
|
||||
idx_t guess = first_guess - offset, last, changes;
|
||||
|
||||
changes = bestmatch (1, pat_lines + 1, guess, input_lines + 1,
|
||||
match_until_eof ? input_lines - guess + 1 : min,
|
||||
@ -135,15 +121,7 @@ locate_merge (lin *matched)
|
||||
}
|
||||
}
|
||||
if (debug & 1)
|
||||
{
|
||||
char numbuf0[LINENUM_LENGTH_BOUND + 1];
|
||||
char numbuf1[LINENUM_LENGTH_BOUND + 1];
|
||||
char numbuf2[LINENUM_LENGTH_BOUND + 1];
|
||||
say ("where=%s matched=%s changes=%s\n",
|
||||
format_linenum (numbuf0, where),
|
||||
format_linenum (numbuf1, max_matched),
|
||||
format_linenum (numbuf2, max + 1));
|
||||
}
|
||||
say ("where=%td matched=%td changes=%td\n", where, max_matched, max + 1);
|
||||
|
||||
out:
|
||||
*matched = max_matched;
|
||||
@ -153,72 +131,66 @@ locate_merge (lin *matched)
|
||||
}
|
||||
|
||||
static void
|
||||
print_linerange (lin from, lin to)
|
||||
print_linerange (idx_t from, idx_t to)
|
||||
{
|
||||
char numbuf0[LINENUM_LENGTH_BOUND + 1];
|
||||
char numbuf1[LINENUM_LENGTH_BOUND + 1];
|
||||
|
||||
if (to <= from)
|
||||
printf ("%s",
|
||||
format_linenum (numbuf0, from));
|
||||
Fprintf (stdout, "%td", from);
|
||||
else
|
||||
printf ("%s-%s",
|
||||
format_linenum (numbuf0, from),
|
||||
format_linenum (numbuf1, to));
|
||||
Fprintf (stdout, "%td-%td", from, to);
|
||||
}
|
||||
|
||||
static void
|
||||
merge_result (bool *first_result, int hunk, char const *what, lin from, lin to)
|
||||
merge_result (bool *first_result, intmax_t hunk, char const *what,
|
||||
idx_t from, idx_t to)
|
||||
{
|
||||
static char const *last_what;
|
||||
|
||||
if (*first_result && what)
|
||||
{
|
||||
printf ("Hunk #%d %s at ", hunk, what);
|
||||
Fprintf (stdout, "Hunk #%jd %s at ", hunk, what);
|
||||
last_what = what;
|
||||
}
|
||||
else if (! what)
|
||||
{
|
||||
if (! *first_result)
|
||||
{
|
||||
fputs (".\n", stdout);
|
||||
fflush (stdout);
|
||||
Fputs (".\n", stdout);
|
||||
Fflush (stdout);
|
||||
last_what = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (last_what == what)
|
||||
fputs (",", stdout);
|
||||
Fputc (',', stdout);
|
||||
else
|
||||
printf (", %s at ", what);
|
||||
Fprintf (stdout, ", %s at ", what);
|
||||
|
||||
print_linerange (from + out_offset, to + out_offset);
|
||||
*first_result = false;
|
||||
}
|
||||
|
||||
bool
|
||||
merge_hunk (int hunk, struct outstate *outstate, lin where, bool *somefailed)
|
||||
merge_hunk (intmax_t hunk, struct outstate *outstate,
|
||||
idx_t where, bool *somefailed)
|
||||
{
|
||||
bool applies_cleanly;
|
||||
bool first_result = true;
|
||||
bool already_applied;
|
||||
FILE *fp = outstate->ofp;
|
||||
lin old = 1;
|
||||
lin firstold = pch_ptrn_lines ();
|
||||
lin new = firstold + 1;
|
||||
lin firstnew = pch_end ();
|
||||
lin in;
|
||||
lin firstin;
|
||||
idx_t old = 1;
|
||||
idx_t firstold = pch_ptrn_lines ();
|
||||
idx_t new = firstold + 1;
|
||||
char *oldin;
|
||||
lin matched;
|
||||
lin lastwhere;
|
||||
idx_t lastwhere;
|
||||
|
||||
/* Convert '!' markers into '-' and '+' to simplify things here. */
|
||||
pch_normalize (UNI_DIFF);
|
||||
|
||||
assert (pch_char (firstnew + 1) == '^');
|
||||
assert (pch_char (pch_end () + 1) == '^');
|
||||
while (pch_char (new) == '=' || pch_char (new) == '\n')
|
||||
new++;
|
||||
|
||||
idx_t matched;
|
||||
if (where)
|
||||
{
|
||||
applies_cleanly = true;
|
||||
@ -230,7 +202,7 @@ merge_hunk (int hunk, struct outstate *outstate, lin where, bool *somefailed)
|
||||
applies_cleanly = false;
|
||||
}
|
||||
|
||||
in = firstold + 2;
|
||||
idx_t in = firstold + 2;
|
||||
oldin = xmalloc (in + matched + 1);
|
||||
memset (oldin, ' ', in + matched);
|
||||
oldin[0] = '*';
|
||||
@ -241,40 +213,29 @@ merge_hunk (int hunk, struct outstate *outstate, lin where, bool *somefailed)
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
char numbuf0[LINENUM_LENGTH_BOUND + 1];
|
||||
char numbuf1[LINENUM_LENGTH_BOUND + 1];
|
||||
lin n;
|
||||
|
||||
fputc ('\n', stderr);
|
||||
for (n = 0; n <= in + matched; n++)
|
||||
Fputc ('\n', stderr);
|
||||
for (idx_t n = 0; n <= in + matched; n++)
|
||||
{
|
||||
fprintf (stderr, "%s %c",
|
||||
format_linenum (numbuf0, n),
|
||||
oldin[n]);
|
||||
Fprintf (stderr, "%td %c", n, oldin[n]);
|
||||
if (n == 0)
|
||||
fprintf(stderr, " %s,%s\n",
|
||||
format_linenum (numbuf0, pch_first()),
|
||||
format_linenum (numbuf1, pch_ptrn_lines()));
|
||||
Fprintf (stderr, " %td,%td\n", pch_first (), pch_ptrn_lines ());
|
||||
else if (n <= firstold)
|
||||
fprintf (stderr, " |%.*s",
|
||||
(int) pch_line_len (n), pfetch (n));
|
||||
{
|
||||
Fputs (" |", stderr);
|
||||
Fwrite (pfetch (n), 1, pch_line_len (n), stderr);
|
||||
}
|
||||
else if (n == in - 1)
|
||||
fprintf(stderr, " %s,%s\n",
|
||||
format_linenum (numbuf0, where),
|
||||
format_linenum (numbuf1, matched));
|
||||
Fprintf (stderr, " %td,%td\n", where, matched);
|
||||
else if (n >= in && n < in + matched)
|
||||
{
|
||||
size_t size;
|
||||
const char *line;
|
||||
|
||||
line = ifetch (where + n - in, false, &size);
|
||||
fprintf (stderr, " |%.*s",
|
||||
(int) size, line);
|
||||
struct iline line = ifetch (where + n - in);
|
||||
Fputs (" |", stderr);
|
||||
Fwrite (line.ptr, 1, line.size, stderr);
|
||||
}
|
||||
else
|
||||
fputc('\n', stderr);
|
||||
Fputc ('\n', stderr);
|
||||
}
|
||||
fflush (stderr);
|
||||
Fflush (stderr);
|
||||
}
|
||||
|
||||
if (last_frozen_line < where - 1)
|
||||
@ -284,13 +245,11 @@ merge_hunk (int hunk, struct outstate *outstate, lin where, bool *somefailed)
|
||||
for (;;)
|
||||
{
|
||||
firstold = old;
|
||||
firstnew = new;
|
||||
firstin = in;
|
||||
idx_t firstnew = new;
|
||||
idx_t firstin = in;
|
||||
|
||||
if (pch_char (old) == '-' || pch_char (new) == '+')
|
||||
{
|
||||
lin lines;
|
||||
|
||||
while (pch_char (old) == '-')
|
||||
{
|
||||
if (oldin[old] == '-' || oldin[in] == '+')
|
||||
@ -307,7 +266,7 @@ merge_hunk (int hunk, struct outstate *outstate, lin where, bool *somefailed)
|
||||
while (pch_char (new) == '+')
|
||||
new++;
|
||||
|
||||
lines = new - firstnew;
|
||||
idx_t lines = new - firstnew;
|
||||
if (verbosity == VERBOSE
|
||||
|| ((verbosity != SILENT) && ! applies_cleanly))
|
||||
merge_result (&first_result, hunk, "merged",
|
||||
@ -432,7 +391,7 @@ merge_hunk (int hunk, struct outstate *outstate, lin where, bool *somefailed)
|
||||
where, lastwhere - 1);
|
||||
if (conflict_style == MERGE_DIFF3)
|
||||
{
|
||||
lin common_prefix = lastwhere - where;
|
||||
idx_t common_prefix = lastwhere - where;
|
||||
|
||||
/* Forget about common prefix lines. */
|
||||
firstin -= common_prefix;
|
||||
@ -448,8 +407,7 @@ merge_hunk (int hunk, struct outstate *outstate, lin where, bool *somefailed)
|
||||
|
||||
if (! already_applied)
|
||||
{
|
||||
lin common_suffix = 0;
|
||||
lin lines;
|
||||
idx_t common_suffix = 0;
|
||||
|
||||
if (conflict_style == MERGE_MERGE)
|
||||
{
|
||||
@ -461,14 +419,14 @@ merge_hunk (int hunk, struct outstate *outstate, lin where, bool *somefailed)
|
||||
/* do nothing */ ;
|
||||
}
|
||||
|
||||
lines = 3 + (in - firstin) + (new - firstnew);
|
||||
idx_t lines = 3 + (in - firstin) + (new - firstnew);
|
||||
if (conflict_style == MERGE_DIFF3)
|
||||
lines += 1 + (old - firstold);
|
||||
merge_result (&first_result, hunk, "NOT MERGED",
|
||||
where, where + lines - 1);
|
||||
out_offset += lines - (in - firstin);
|
||||
|
||||
fputs (outstate->after_newline + "\n<<<<<<<\n", fp);
|
||||
Fputs (&"\n<<<<<<<\n"[outstate->after_newline], fp);
|
||||
outstate->after_newline = true;
|
||||
if (firstin < in)
|
||||
{
|
||||
@ -479,7 +437,7 @@ merge_hunk (int hunk, struct outstate *outstate, lin where, bool *somefailed)
|
||||
|
||||
if (conflict_style == MERGE_DIFF3)
|
||||
{
|
||||
fputs (outstate->after_newline + "\n|||||||\n", fp);
|
||||
Fputs (&"\n|||||||\n"[outstate->after_newline], fp);
|
||||
outstate->after_newline = true;
|
||||
while (firstold < old)
|
||||
{
|
||||
@ -488,14 +446,14 @@ merge_hunk (int hunk, struct outstate *outstate, lin where, bool *somefailed)
|
||||
}
|
||||
}
|
||||
|
||||
fputs (outstate->after_newline + "\n=======\n", fp);
|
||||
Fputs (&"\n=======\n"[outstate->after_newline], fp);
|
||||
outstate->after_newline = true;
|
||||
while (firstnew < new)
|
||||
{
|
||||
outstate->after_newline = pch_write_line (firstnew, fp);
|
||||
firstnew++;
|
||||
}
|
||||
fputs (outstate->after_newline + "\n>>>>>>>\n", fp);
|
||||
Fputs (&"\n>>>>>>>\n"[outstate->after_newline], fp);
|
||||
outstate->after_newline = true;
|
||||
outstate->zero_output = false;
|
||||
if (ferror (fp))
|
||||
@ -520,53 +478,48 @@ merge_hunk (int hunk, struct outstate *outstate, lin where, bool *somefailed)
|
||||
return true;
|
||||
}
|
||||
|
||||
static lin
|
||||
static idx_t
|
||||
count_context_lines (void)
|
||||
{
|
||||
lin old;
|
||||
lin lastold = pch_ptrn_lines ();
|
||||
lin context;
|
||||
idx_t lastold = pch_ptrn_lines ();
|
||||
idx_t context = 0;
|
||||
|
||||
for (context = 0, old = 1; old <= lastold; old++)
|
||||
for (idx_t old = 1; old <= lastold; old++)
|
||||
if (pch_char (old) == ' ')
|
||||
context++;
|
||||
return context;
|
||||
}
|
||||
|
||||
static bool
|
||||
context_matches_file (lin old, lin where)
|
||||
context_matches_file (idx_t old, idx_t where)
|
||||
{
|
||||
size_t size;
|
||||
const char *line;
|
||||
|
||||
line = ifetch (where, false, &size);
|
||||
return size &&
|
||||
(canonicalize ?
|
||||
similar (pfetch (old), pch_line_len (old), line, size) :
|
||||
(size == pch_line_len (old) &&
|
||||
memcmp (line, pfetch (old), size) == 0));
|
||||
struct iline line = ifetch (where);
|
||||
return line.size &&
|
||||
(canonicalize_ws ?
|
||||
similar (pfetch (old), pch_line_len (old), line.ptr, line.size) :
|
||||
(line.size == pch_line_len (old) &&
|
||||
memcmp (line.ptr, pfetch (old), line.size) == 0));
|
||||
}
|
||||
|
||||
static void
|
||||
compute_changes (lin xmin, lin xmax, lin ymin, lin ymax,
|
||||
compute_changes (idx_t xmin, idx_t xmax, idx_t ymin, idx_t ymax,
|
||||
char *xchar, char *ychar)
|
||||
{
|
||||
struct context ctxt;
|
||||
lin diags;
|
||||
|
||||
ctxt.xchar = xchar - xmin;
|
||||
ctxt.ychar = ychar - ymin;
|
||||
|
||||
diags = xmax + ymax + 3;
|
||||
ctxt.fdiag = xmalloc (2 * diags * sizeof (*ctxt.fdiag));
|
||||
idx_t diags;
|
||||
if (ckd_add (&diags, xmax, ymax) || ckd_add (&diags, diags, 3))
|
||||
xalloc_die ();
|
||||
ctxt.fdiag = xinmalloc (diags, 2 * sizeof *ctxt.fdiag);
|
||||
ctxt.bdiag = ctxt.fdiag + diags;
|
||||
ctxt.fdiag += ymax + 1;
|
||||
ctxt.bdiag += ymax + 1;
|
||||
|
||||
ctxt.heuristic = true;
|
||||
ctxt.too_expensive = xmax + ymax;
|
||||
|
||||
compareseq (xmin, xmax, ymin, ymax, true, &ctxt);
|
||||
compareseq (xmin, xmax, ymin, ymax, false, &ctxt);
|
||||
|
||||
ctxt.fdiag -= ymax + 1;
|
||||
free (ctxt.fdiag);
|
||||
|
||||
1347
src/patch.c
1347
src/patch.c
File diff suppressed because it is too large
Load Diff
71
src/pch.h
71
src/pch.h
@ -1,8 +1,7 @@
|
||||
/* reading patches */
|
||||
|
||||
/* Copyright (C) 1986, 1987, 1988 Larry Wall
|
||||
|
||||
Copyright (C) 1990-1993, 1997-2003, 2009-2012 Free Software Foundation, Inc.
|
||||
/* Copyright 1990-2025 Free Software Foundation, Inc.
|
||||
Copyright 1986-1988 Larry Wall
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -19,43 +18,39 @@
|
||||
|
||||
enum nametype { OLD, NEW, INDEX, NONE };
|
||||
|
||||
lin pch_end (void) _GL_ATTRIBUTE_PURE;
|
||||
lin pch_first (void) _GL_ATTRIBUTE_PURE;
|
||||
lin pch_hunk_beg (void) _GL_ATTRIBUTE_PURE;
|
||||
char const *pch_c_function (void) _GL_ATTRIBUTE_PURE;
|
||||
bool pch_git_diff (void) _GL_ATTRIBUTE_PURE;
|
||||
char const * pch_timestr (bool which) _GL_ATTRIBUTE_PURE;
|
||||
char const *pch_sha1 (bool which) _GL_ATTRIBUTE_PURE;
|
||||
mode_t pch_mode (bool which) _GL_ATTRIBUTE_PURE;
|
||||
lin pch_newfirst (void) _GL_ATTRIBUTE_PURE;
|
||||
lin pch_prefix_context (void) _GL_ATTRIBUTE_PURE;
|
||||
lin pch_ptrn_lines (void) _GL_ATTRIBUTE_PURE;
|
||||
lin pch_repl_lines (void) _GL_ATTRIBUTE_PURE;
|
||||
lin pch_suffix_context (void) _GL_ATTRIBUTE_PURE;
|
||||
bool pch_swap (void);
|
||||
bool pch_write_line (lin, FILE *);
|
||||
/* General purpose buffer. */
|
||||
extern char *patchbuf;
|
||||
|
||||
/* Allocated size of buf. It is at least IO_BUFSIZE. */
|
||||
extern idx_t patchbufsize;
|
||||
|
||||
void grow_patchbuf (void);
|
||||
idx_t pch_end (void) ATTRIBUTE_PURE;
|
||||
idx_t pch_first (void) ATTRIBUTE_PURE;
|
||||
idx_t pch_hunk_beg (void) ATTRIBUTE_PURE;
|
||||
char const *pch_c_function (void) ATTRIBUTE_PURE;
|
||||
bool pch_git_diff (void) ATTRIBUTE_PURE;
|
||||
char const * pch_timestr (bool which) ATTRIBUTE_PURE;
|
||||
mode_t pch_mode (bool which) ATTRIBUTE_PURE;
|
||||
idx_t pch_newfirst (void) ATTRIBUTE_PURE;
|
||||
idx_t pch_prefix_context (void) ATTRIBUTE_PURE;
|
||||
idx_t pch_ptrn_lines (void) ATTRIBUTE_PURE;
|
||||
idx_t pch_repl_lines (void) ATTRIBUTE_PURE;
|
||||
idx_t pch_suffix_context (void) ATTRIBUTE_PURE;
|
||||
void pch_swap (void);
|
||||
bool pch_write_line (idx_t, FILE *);
|
||||
bool there_is_another_patch (bool, mode_t *);
|
||||
char *pfetch (lin) _GL_ATTRIBUTE_PURE;
|
||||
char pch_char (lin) _GL_ATTRIBUTE_PURE;
|
||||
int another_hunk (enum diff, bool);
|
||||
int pch_says_nonexistent (bool) _GL_ATTRIBUTE_PURE;
|
||||
size_t pch_line_len (lin) _GL_ATTRIBUTE_PURE;
|
||||
const char *pch_name(enum nametype) _GL_ATTRIBUTE_PURE;
|
||||
bool pch_copy (void) _GL_ATTRIBUTE_PURE;
|
||||
bool pch_rename (void) _GL_ATTRIBUTE_PURE;
|
||||
void do_ed_script (char const *, char const *, bool *, FILE *);
|
||||
char *pfetch (idx_t) ATTRIBUTE_PURE;
|
||||
char pch_char (idx_t) ATTRIBUTE_PURE;
|
||||
bool another_hunk (enum diff, bool);
|
||||
char pch_says_nonexistent (bool) ATTRIBUTE_PURE;
|
||||
idx_t pch_line_len (idx_t) ATTRIBUTE_PURE;
|
||||
char *pch_name (enum nametype) ATTRIBUTE_PURE;
|
||||
bool pch_copy (void) ATTRIBUTE_PURE;
|
||||
bool pch_rename (void) ATTRIBUTE_PURE;
|
||||
void do_ed_script (char *, struct outfile *, FILE *);
|
||||
void open_patch_file (char const *);
|
||||
void re_patch (void);
|
||||
void set_hunkmax (void);
|
||||
void pch_normalize (enum diff);
|
||||
|
||||
XTERN struct timespec p_timestamp[2]; /* timestamps in patch headers */
|
||||
|
||||
/* Return timestamp of patch header for file WHICH (false = old, true = new),
|
||||
or a timestamp with tv_sec == -1 if there was no timestamp or an error in
|
||||
the timestamp. */
|
||||
|
||||
static inline struct timespec pch_timestamp (bool which)
|
||||
{
|
||||
return p_timestamp[which];
|
||||
}
|
||||
extern struct timespec p_timestamp[2]; /* timestamps in patch headers */
|
||||
|
||||
729
src/safe.c
Normal file
729
src/safe.c
Normal file
@ -0,0 +1,729 @@
|
||||
/* safe path traversal functions for 'patch' */
|
||||
|
||||
/* Copyright 2015-2025 Free Software Foundation, Inc.
|
||||
|
||||
Written by Tim Waugh <twaugh@redhat.com> and
|
||||
Andreas Gruenbacher <agruenba@redhat.com>.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <safe.h>
|
||||
|
||||
#include <basename-lgpl.h>
|
||||
#include <hash.h>
|
||||
#include <filename.h>
|
||||
#include <xalloc.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#define LIST_INLINE _GL_EXTERN_INLINE
|
||||
#include "list.h"
|
||||
|
||||
#ifndef EFTYPE
|
||||
# define EFTYPE 0
|
||||
#endif
|
||||
|
||||
#ifdef O_PATH
|
||||
enum { O_PATHSEARCH = O_PATH };
|
||||
#else
|
||||
enum { O_PATHSEARCH = O_SEARCH };
|
||||
#endif
|
||||
|
||||
enum { MAX_PATH_COMPONENTS = 1024 };
|
||||
|
||||
/* Flag to turn the safe_* functions into their unsafe variants; files may then
|
||||
lie outside the current working directory. */
|
||||
bool unsafe;
|
||||
|
||||
/* Path lookup results are cached in a hash table + LRU list. When the
|
||||
cache is full, the oldest entries are removed. */
|
||||
|
||||
static intmax_t dirfd_cache_misses;
|
||||
|
||||
struct cached_dirfd {
|
||||
struct list_head lru_link;
|
||||
struct list_head children_link, children;
|
||||
struct cached_dirfd *parent;
|
||||
|
||||
char *name;
|
||||
int fd;
|
||||
};
|
||||
|
||||
static Hash_table *cached_dirfds;
|
||||
static rlim_t min_cached_fds = 8;
|
||||
static rlim_t max_cached_fds;
|
||||
static LIST_HEAD (lru_list);
|
||||
|
||||
static size_t hash_cached_dirfd (const void *entry, size_t table_size)
|
||||
{
|
||||
const struct cached_dirfd *d = entry;
|
||||
size_t strhash = hash_string (d->name, table_size);
|
||||
return (strhash * 31 + d->parent->fd) % table_size;
|
||||
}
|
||||
|
||||
static bool compare_cached_dirfds (const void *_a,
|
||||
const void *_b)
|
||||
{
|
||||
const struct cached_dirfd *a = _a;
|
||||
const struct cached_dirfd *b = _b;
|
||||
|
||||
return (a->parent->fd == b->parent->fd &&
|
||||
!strcmp (a->name, b->name));
|
||||
}
|
||||
|
||||
static void free_cached_dirfd (struct cached_dirfd *entry)
|
||||
{
|
||||
list_del (&entry->children_link);
|
||||
free (entry->name);
|
||||
free (entry);
|
||||
}
|
||||
|
||||
static void init_dirfd_cache (void)
|
||||
{
|
||||
struct rlimit nofile;
|
||||
|
||||
if (getrlimit (RLIMIT_NOFILE, &nofile) == 0)
|
||||
{
|
||||
if (nofile.rlim_cur == RLIM_INFINITY)
|
||||
max_cached_fds = RLIM_INFINITY;
|
||||
else
|
||||
max_cached_fds = MAX (nofile.rlim_cur / 4, min_cached_fds);
|
||||
}
|
||||
else
|
||||
max_cached_fds = min_cached_fds;
|
||||
|
||||
cached_dirfds = hash_initialize (min_cached_fds, nullptr,
|
||||
hash_cached_dirfd,
|
||||
compare_cached_dirfds, nullptr);
|
||||
|
||||
if (!cached_dirfds)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
static struct cached_dirfd *lookup_cached_dirfd (struct cached_dirfd *dir, const char *name)
|
||||
{
|
||||
struct cached_dirfd *entry = nullptr;
|
||||
|
||||
if (cached_dirfds)
|
||||
{
|
||||
struct cached_dirfd key;
|
||||
key.parent = dir;
|
||||
key.name = (char *) name;
|
||||
entry = hash_lookup (cached_dirfds, &key);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static void remove_cached_dirfd (struct cached_dirfd *entry)
|
||||
{
|
||||
while (! list_empty (&entry->children))
|
||||
{
|
||||
struct cached_dirfd *child =
|
||||
list_entry (entry->children.next,
|
||||
offsetof (struct cached_dirfd, children_link));
|
||||
list_del_init (&child->children_link);
|
||||
/* assert (list_empty (&child->children_link)); */
|
||||
hash_remove (cached_dirfds, child); /* noop when not hashed */
|
||||
}
|
||||
list_del (&entry->lru_link);
|
||||
hash_remove (cached_dirfds, entry); /* noop when not hashed */
|
||||
close (entry->fd);
|
||||
free_cached_dirfd (entry);
|
||||
}
|
||||
|
||||
static void insert_cached_dirfd (struct cached_dirfd *entry, int keepfd)
|
||||
{
|
||||
if (!cached_dirfds)
|
||||
init_dirfd_cache ();
|
||||
|
||||
if (max_cached_fds != RLIM_INFINITY)
|
||||
{
|
||||
/* Trim off the least recently used entries */
|
||||
while (hash_get_n_entries (cached_dirfds) >= max_cached_fds)
|
||||
{
|
||||
struct cached_dirfd *last =
|
||||
list_entry (lru_list.prev,
|
||||
offsetof (struct cached_dirfd, lru_link));
|
||||
if (&last->lru_link == &lru_list)
|
||||
break;
|
||||
if (last->fd == keepfd)
|
||||
{
|
||||
last = list_entry (last->lru_link.prev,
|
||||
offsetof (struct cached_dirfd, lru_link));
|
||||
if (&last->lru_link == &lru_list)
|
||||
break;
|
||||
}
|
||||
remove_cached_dirfd (last);
|
||||
}
|
||||
}
|
||||
|
||||
/* Only insert if the parent still exists. */
|
||||
if (! list_empty (&entry->children_link))
|
||||
if (hash_insert (cached_dirfds, entry) != entry)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
static void invalidate_cached_dirfd (int dirfd, const char *name)
|
||||
{
|
||||
struct cached_dirfd dir, key, *entry;
|
||||
if (!cached_dirfds)
|
||||
return;
|
||||
|
||||
dir.fd = dirfd;
|
||||
key.parent = &dir;
|
||||
key.name = (char *) name;
|
||||
entry = hash_lookup (cached_dirfds, &key);
|
||||
if (entry)
|
||||
remove_cached_dirfd (entry);
|
||||
}
|
||||
|
||||
/* Put the looked up path back onto the lru list. Return the file descriptor
|
||||
of the top entry. */
|
||||
static int put_path (struct cached_dirfd *entry)
|
||||
{
|
||||
int fd = entry->fd;
|
||||
|
||||
while (entry)
|
||||
{
|
||||
struct cached_dirfd *parent = entry->parent;
|
||||
if (! parent)
|
||||
break;
|
||||
list_add (&entry->lru_link, &lru_list);
|
||||
entry = parent;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static struct cached_dirfd *
|
||||
new_cached_dirfd (struct cached_dirfd *dir, char *name, int fd)
|
||||
{
|
||||
struct cached_dirfd *entry = xmalloc (sizeof (struct cached_dirfd));
|
||||
|
||||
INIT_LIST_HEAD (&entry->lru_link);
|
||||
list_add (&entry->children_link, &dir->children);
|
||||
INIT_LIST_HEAD (&entry->children);
|
||||
entry->parent = dir;
|
||||
entry->name = name;
|
||||
entry->fd = fd;
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* In DIR, look up NAME as a subdirectory.
|
||||
Return the corresponding cache entry if found, a null pointer otherwise.
|
||||
If KEEPFD is nonnegative, make sure that any cache entry for it is not
|
||||
removed from the cache (and KEEPFD remains open). */
|
||||
static struct cached_dirfd *
|
||||
openat_cached (struct cached_dirfd *dir, char const *name, int keepfd)
|
||||
{
|
||||
int fd;
|
||||
struct cached_dirfd *entry = lookup_cached_dirfd (dir, name);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
list_del_init (&entry->lru_link);
|
||||
/* assert (list_empty (&entry->lru_link)); */
|
||||
return entry;
|
||||
}
|
||||
dirfd_cache_misses++;
|
||||
|
||||
/* Actually get the new directory file descriptor. Don't follow
|
||||
symbolic links. */
|
||||
fd = openat (dir->fd, name, O_PATHSEARCH | O_DIRECTORY | O_NOFOLLOW);
|
||||
|
||||
/* Don't cache errors. */
|
||||
if (fd < 0)
|
||||
return nullptr;
|
||||
|
||||
/* Store new cache entry */
|
||||
entry = new_cached_dirfd (dir, xstrdup (name), fd);
|
||||
insert_cached_dirfd (entry, keepfd);
|
||||
return entry;
|
||||
}
|
||||
|
||||
static idx_t ATTRIBUTE_PURE
|
||||
count_path_components (const char *path)
|
||||
{
|
||||
while (ISSLASH (*path))
|
||||
path++;
|
||||
if (! *path)
|
||||
return 1;
|
||||
for (idx_t components = 0; ; components++)
|
||||
{
|
||||
if (!*path)
|
||||
return components;
|
||||
while (*path && ! ISSLASH (*path))
|
||||
path++;
|
||||
while (ISSLASH (*path))
|
||||
path++;
|
||||
}
|
||||
}
|
||||
|
||||
/* A symlink to resolve. */
|
||||
struct symlink {
|
||||
struct symlink *prev;
|
||||
char *path;
|
||||
};
|
||||
|
||||
static void push_symlink (struct symlink **stack, struct symlink *symlink)
|
||||
{
|
||||
symlink->prev = *stack;
|
||||
*stack = symlink;
|
||||
}
|
||||
|
||||
static void pop_symlink (struct symlink **stack)
|
||||
{
|
||||
struct symlink *top = *stack;
|
||||
*stack = top->prev;
|
||||
free (top);
|
||||
}
|
||||
|
||||
static int cwd_stat_errno = -1;
|
||||
static struct stat cwd_stat;
|
||||
|
||||
static struct symlink *read_symlink(int dirfd, const char *name)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
struct stat st;
|
||||
struct symlink *symlink;
|
||||
char *buffer;
|
||||
ssize_t ret;
|
||||
|
||||
if (fstatat (dirfd, name, &st, AT_SYMLINK_NOFOLLOW)
|
||||
|| ! S_ISLNK (st.st_mode))
|
||||
{
|
||||
errno = saved_errno;
|
||||
return nullptr;
|
||||
}
|
||||
idx_t symlinksize;
|
||||
if (ckd_add (&symlinksize, st.st_size, 1 + sizeof *symlink))
|
||||
xalloc_die ();
|
||||
symlink = ximalloc (symlinksize);
|
||||
buffer = (char *)(symlink + 1);
|
||||
ret = readlinkat (dirfd, name, buffer, st.st_size);
|
||||
if (ret <= 0)
|
||||
goto fail;
|
||||
buffer[ret] = 0;
|
||||
symlink->path = buffer;
|
||||
if (ISSLASH (*buffer))
|
||||
{
|
||||
char *end;
|
||||
|
||||
if (cwd_stat_errno == -1)
|
||||
{
|
||||
cwd_stat_errno = stat (".", &cwd_stat) == 0 ? 0 : errno;
|
||||
if (cwd_stat_errno)
|
||||
goto fail_exdev;
|
||||
}
|
||||
end = buffer + ret;
|
||||
for (;;)
|
||||
{
|
||||
char slash;
|
||||
int rv;
|
||||
|
||||
slash = *end; *end = 0;
|
||||
rv = stat (symlink->path, &st);
|
||||
*end = slash;
|
||||
|
||||
if (rv == 0
|
||||
&& st.st_dev == cwd_stat.st_dev
|
||||
&& st.st_ino == cwd_stat.st_ino)
|
||||
{
|
||||
while (ISSLASH (*end))
|
||||
end++;
|
||||
symlink->path = end;
|
||||
return symlink;
|
||||
}
|
||||
end--;
|
||||
if (end == symlink->path)
|
||||
break;
|
||||
while (end != symlink->path + 1 && ! ISSLASH (*end))
|
||||
end--;
|
||||
while (end != symlink->path + 1 && ISSLASH (*(end - 1)))
|
||||
end--;
|
||||
}
|
||||
goto fail_exdev;
|
||||
}
|
||||
return symlink;
|
||||
|
||||
fail_exdev:
|
||||
errno = EXDEV;
|
||||
fail:
|
||||
free (symlink);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Resolve the next path component in PATH inside DIR. If it is a symlink,
|
||||
read it and returned it in TOP. */
|
||||
static struct cached_dirfd *
|
||||
traverse_next (struct cached_dirfd *dir, char **path, int keepfd,
|
||||
struct symlink **symlink)
|
||||
{
|
||||
char *p = *path;
|
||||
struct cached_dirfd *entry = dir;
|
||||
|
||||
while (*p && ! ISSLASH (*p))
|
||||
p++;
|
||||
if (**path == '.' && *path + 1 == p)
|
||||
;
|
||||
else if (**path == '.' && *(*path + 1) == '.' && *path + 2 == p)
|
||||
{
|
||||
entry = dir->parent;
|
||||
if (! entry)
|
||||
{
|
||||
/* Must not leave the working tree. */
|
||||
errno = EXDEV;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (list_empty (&dir->lru_link));
|
||||
list_add (&dir->lru_link, &lru_list);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char slash_or_nul = *p;
|
||||
*p = '\0';
|
||||
entry = openat_cached (dir, *path, keepfd);
|
||||
if (! entry)
|
||||
{
|
||||
if (errno == ELOOP
|
||||
|| errno == EMLINK /* FreeBSD 10.1: Too many links */
|
||||
|| (errno == EFTYPE
|
||||
/* NetBSD 6.1: Inappropriate file type or format. */)
|
||||
|| errno == ENOTDIR)
|
||||
{
|
||||
*symlink = read_symlink (dir->fd, *path);
|
||||
if (*symlink)
|
||||
entry = dir;
|
||||
errno = ELOOP;
|
||||
}
|
||||
}
|
||||
*p = slash_or_nul;
|
||||
}
|
||||
if (entry)
|
||||
while (ISSLASH (*p))
|
||||
p++;
|
||||
*path = p;
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Traverse PATHNAME.
|
||||
|
||||
If REJECT_NL, fail if the PATHNAME's last component contains a newline.
|
||||
Otherwise, if unsafe or PATHNAME is absolute, just return AT_FDCWD.
|
||||
Otherwise, update PATHNAME to point to the last path component and
|
||||
return a file descriptor to its parent directory (which can be AT_FDCWD).
|
||||
If KEEPFD is nonnegative, make sure that any cache entry for it is not
|
||||
removed from the cache (and KEEPFD remains open).
|
||||
|
||||
When this function is not running, all cache entries are on the lru list,
|
||||
and all cache entries which still have a parent are also in the hash table.
|
||||
While this function is running, all cache entries on the path being looked
|
||||
up are off the lru list but in the hash table.
|
||||
*/
|
||||
static int
|
||||
traverse_another_path (char **pathname, bool reject_nl, int keepfd)
|
||||
{
|
||||
char *path = *pathname;
|
||||
char *last = last_component (path);
|
||||
if (reject_nl && strchr (last, '\n'))
|
||||
{
|
||||
errno = EILSEQ;
|
||||
return DIRFD_INVALID;
|
||||
}
|
||||
if (unsafe || last == path || IS_ABSOLUTE_FILE_NAME (path))
|
||||
return AT_FDCWD;
|
||||
|
||||
static struct cached_dirfd cwd = {
|
||||
.fd = AT_FDCWD,
|
||||
};
|
||||
|
||||
intmax_t misses = dirfd_cache_misses;
|
||||
struct cached_dirfd *dir = &cwd;
|
||||
struct symlink *stack = nullptr;
|
||||
idx_t steps = count_path_components (path);
|
||||
struct cached_dirfd *traversed_symlink = nullptr;
|
||||
|
||||
INIT_LIST_HEAD (&cwd.children);
|
||||
|
||||
if (steps > MAX_PATH_COMPONENTS)
|
||||
{
|
||||
errno = ELOOP;
|
||||
return DIRFD_INVALID;
|
||||
}
|
||||
|
||||
if (debug & 32)
|
||||
{
|
||||
idx_t full_pathlen = last - path;
|
||||
int pathlen = ckd_sub (&pathlen, full_pathlen, 0) ? -1 : pathlen;
|
||||
Fprintf (stdout, "Resolving path \"%.*s\"", pathlen, path);
|
||||
}
|
||||
|
||||
while (stack || path != last)
|
||||
{
|
||||
struct cached_dirfd *entry;
|
||||
struct symlink *symlink = nullptr;
|
||||
char *prev = path;
|
||||
|
||||
entry = traverse_next (dir, stack ? &stack->path : &path, keepfd, &symlink);
|
||||
if (! entry)
|
||||
{
|
||||
if (debug & 32)
|
||||
{
|
||||
Fputs (" (failed)\n", stdout);
|
||||
Fflush (stdout);
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
dir = entry;
|
||||
if (! stack && symlink)
|
||||
{
|
||||
const char *p = prev;
|
||||
while (*p && ! ISSLASH (*p))
|
||||
p++;
|
||||
char *name = ximemdup0 (prev, p - prev);
|
||||
traversed_symlink = new_cached_dirfd (dir, name, DIRFD_INVALID);
|
||||
}
|
||||
if (stack && ! *stack->path)
|
||||
pop_symlink (&stack);
|
||||
if (symlink && *symlink->path)
|
||||
{
|
||||
push_symlink (&stack, symlink);
|
||||
steps += count_path_components (symlink->path);
|
||||
if (steps > MAX_PATH_COMPONENTS)
|
||||
{
|
||||
errno = ELOOP;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else if (symlink)
|
||||
pop_symlink (&symlink);
|
||||
if (traversed_symlink && ! stack)
|
||||
{
|
||||
traversed_symlink->fd =
|
||||
entry->fd == AT_FDCWD ? AT_FDCWD : dup (entry->fd);
|
||||
if (traversed_symlink->fd < 0)
|
||||
free_cached_dirfd (traversed_symlink);
|
||||
else
|
||||
{
|
||||
insert_cached_dirfd (traversed_symlink, keepfd);
|
||||
list_add (&traversed_symlink->lru_link, &lru_list);
|
||||
}
|
||||
traversed_symlink = nullptr;
|
||||
}
|
||||
}
|
||||
*pathname = last;
|
||||
if (debug & 32)
|
||||
{
|
||||
misses = dirfd_cache_misses - misses;
|
||||
if (! misses)
|
||||
Fprintf (stdout, " (cached)\n");
|
||||
else
|
||||
Fprintf (stdout, " (%jd miss%s)\n", misses, misses == 1 ? "" : "es");
|
||||
Fflush (stdout);
|
||||
}
|
||||
return put_path (dir);
|
||||
|
||||
fail:
|
||||
if (traversed_symlink)
|
||||
free_cached_dirfd (traversed_symlink);
|
||||
put_path (dir);
|
||||
while (stack)
|
||||
pop_symlink (&stack);
|
||||
return DIRFD_INVALID;
|
||||
}
|
||||
|
||||
/* Just traverse PATHNAME; see traverse_another_path(). */
|
||||
static int
|
||||
traverse_path (char **pathname, bool reject_nl)
|
||||
{
|
||||
return traverse_another_path (pathname, reject_nl, DIRFD_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
safe_xstat (char *pathname, struct stat *buf, int flags)
|
||||
{
|
||||
int dirfd = traverse_path (&pathname, false);
|
||||
if (dirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
if (! strcmp (pathname, ""))
|
||||
return EINVAL;
|
||||
return fstatat (dirfd, pathname, buf, flags);
|
||||
}
|
||||
|
||||
/* Replacement for stat() */
|
||||
int
|
||||
safe_stat (char *pathname, struct stat *buf)
|
||||
{
|
||||
return safe_xstat (pathname, buf, 0);
|
||||
}
|
||||
|
||||
/* Replacement for lstat() */
|
||||
int
|
||||
safe_lstat (char *pathname, struct stat *buf)
|
||||
{
|
||||
return safe_xstat (pathname, buf, AT_SYMLINK_NOFOLLOW);
|
||||
}
|
||||
|
||||
/* Replacement for open() */
|
||||
int
|
||||
safe_open (char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
int creat_excl = flags & (O_CREAT | O_EXCL);
|
||||
int dirfd = traverse_path (&pathname, creat_excl == (O_CREAT | O_EXCL));
|
||||
if (dirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
|
||||
/* If O_CREAT is set but O_EXCL is not, traverse_path does not
|
||||
suffice for checking file names with '\n', so check by hand. */
|
||||
if (creat_excl == O_CREAT
|
||||
&& strchr (last_component (pathname), '\n')
|
||||
&& faccessat (dirfd, pathname, F_OK, AT_EACCESS) < 0
|
||||
&& errno == ENOENT)
|
||||
{
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return openat (dirfd, pathname, flags, mode);
|
||||
}
|
||||
|
||||
/* Replacement for rename() */
|
||||
int
|
||||
safe_rename (char *oldpath, char *newpath)
|
||||
{
|
||||
int olddirfd = traverse_path (&oldpath, false);
|
||||
if (olddirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
|
||||
int newdirfd = traverse_another_path (&newpath, true, olddirfd);
|
||||
if (newdirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
|
||||
int ret = renameat (olddirfd, oldpath, newdirfd, newpath);
|
||||
if (! ret)
|
||||
{
|
||||
invalidate_cached_dirfd (olddirfd, oldpath);
|
||||
invalidate_cached_dirfd (newdirfd, newpath);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Replacement for mkdir() */
|
||||
int
|
||||
safe_mkdir (char *pathname, mode_t mode)
|
||||
{
|
||||
int dirfd = traverse_path (&pathname, true);
|
||||
if (dirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
return mkdirat (dirfd, pathname, mode);
|
||||
}
|
||||
|
||||
/* Replacement for rmdir() */
|
||||
int
|
||||
safe_rmdir (char *pathname)
|
||||
{
|
||||
int dirfd = traverse_path (&pathname, false);
|
||||
if (dirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
|
||||
int ret = unlinkat (dirfd, pathname, AT_REMOVEDIR);
|
||||
if (! ret)
|
||||
invalidate_cached_dirfd (dirfd, pathname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Replacement for unlink() */
|
||||
int
|
||||
safe_unlink (char *pathname)
|
||||
{
|
||||
int dirfd = traverse_path (&pathname, false);
|
||||
if (dirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
return unlinkat (dirfd, pathname, 0);
|
||||
}
|
||||
|
||||
/* Replacement for symlink() */
|
||||
int
|
||||
safe_symlink (char const *target, char *linkpath)
|
||||
{
|
||||
int dirfd = traverse_path (&linkpath, true);
|
||||
if (dirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
return symlinkat (target, dirfd, linkpath);
|
||||
}
|
||||
|
||||
/* Replacement for chmod() */
|
||||
int
|
||||
safe_chmod (char *pathname, mode_t mode)
|
||||
{
|
||||
int dirfd = traverse_path (&pathname, false);
|
||||
if (dirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
return fchmodat (dirfd, pathname, mode, 0);
|
||||
}
|
||||
|
||||
/* Replacement for lchown() */
|
||||
int
|
||||
safe_lchown (char *pathname, uid_t owner, gid_t group)
|
||||
{
|
||||
int dirfd = traverse_path (&pathname, false);
|
||||
if (dirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
return fchownat (dirfd, pathname, owner, group, AT_SYMLINK_NOFOLLOW);
|
||||
}
|
||||
|
||||
/* Replacement for lutimens() */
|
||||
int
|
||||
safe_lutimens (char *pathname, struct timespec const times[2])
|
||||
{
|
||||
int dirfd = traverse_path (&pathname, false);
|
||||
if (dirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
return utimensat (dirfd, pathname, times, AT_SYMLINK_NOFOLLOW);
|
||||
}
|
||||
|
||||
/* Replacement for readlink() */
|
||||
ssize_t
|
||||
safe_readlink (char *pathname, char *buf, size_t bufsiz)
|
||||
{
|
||||
int dirfd = traverse_path (&pathname, false);
|
||||
if (dirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
return readlinkat (dirfd, pathname, buf, bufsiz);
|
||||
}
|
||||
|
||||
/* Replacement for access() */
|
||||
int
|
||||
safe_access (char *pathname, int mode)
|
||||
{
|
||||
int dirfd = traverse_path (&pathname, false);
|
||||
if (dirfd == DIRFD_INVALID)
|
||||
return -1;
|
||||
return faccessat (dirfd, pathname, mode, AT_EACCESS);
|
||||
}
|
||||
42
src/safe.h
Normal file
42
src/safe.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* safe path traversal functions for 'patch' */
|
||||
|
||||
/* Copyright 2015-2025 Free Software Foundation, Inc.
|
||||
|
||||
Written by Tim Waugh <twaugh@redhat.com> and
|
||||
Andreas Gruenbacher <agruenba@redhat.com>.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* A constant that cannot be successfully passed as a directory file
|
||||
descriptor to openat etc. Its value is negative but does not equal
|
||||
AT_FDCWD. Normally the value is -1, but it is -2 on perverse
|
||||
platforms where AT_FDCWD == -1. */
|
||||
|
||||
enum { DIRFD_INVALID = -1 - (AT_FDCWD == -1) };
|
||||
|
||||
extern bool unsafe;
|
||||
|
||||
int safe_stat (char *pathname, struct stat *buf);
|
||||
int safe_lstat (char *pathname, struct stat *buf);
|
||||
int safe_open (char *pathname, int flags, mode_t mode);
|
||||
int safe_rename (char *oldpath, char *newpath);
|
||||
int safe_mkdir (char *pathname, mode_t mode);
|
||||
int safe_rmdir (char *pathname);
|
||||
int safe_unlink (char *pathname);
|
||||
int safe_symlink (const char *target, char *linkpath);
|
||||
int safe_chmod (char *pathname, mode_t mode);
|
||||
int safe_lchown (char *pathname, uid_t owner, gid_t group);
|
||||
int safe_lutimens (char *pathname, struct timespec const times[2]);
|
||||
ssize_t safe_readlink(char *pathname, char *buf, size_t bufsiz);
|
||||
int safe_access(char *pathname, int mode);
|
||||
1244
src/util.c
1244
src/util.c
File diff suppressed because it is too large
Load Diff
142
src/util.h
142
src/util.h
@ -1,9 +1,7 @@
|
||||
/* utility functions for 'patch' */
|
||||
|
||||
/* Copyright (C) 1986 Larry Wall
|
||||
|
||||
Copyright (C) 1992-1993, 1997-1999, 2001-2003, 2009-2012 Free Software
|
||||
Foundation, Inc.
|
||||
/* Copyright 1992-2025 Free Software Foundation, Inc.
|
||||
Copyright 1986 Larry Wall
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -18,58 +16,12 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <utimens.h>
|
||||
#include <timespec.h>
|
||||
#include <stat-time.h>
|
||||
#include <backupfile.h>
|
||||
|
||||
/* An upper bound on the print length of a signed decimal line number.
|
||||
Add one for the sign. */
|
||||
#define LINENUM_LENGTH_BOUND (sizeof (lin) * CHAR_BIT / 3 + 1)
|
||||
|
||||
enum file_id_type { UNKNOWN, CREATED, DELETE_LATER, OVERWRITTEN };
|
||||
|
||||
XTERN enum backup_type backup_type;
|
||||
|
||||
bool ok_to_reverse (char const *, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
void ask (char const *, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
void say (char const *, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
void fatal (char const *, ...)
|
||||
__attribute__ ((noreturn, format (printf, 1, 2)));
|
||||
void pfatal (char const *, ...)
|
||||
__attribute__ ((noreturn, format (printf, 1, 2)));
|
||||
|
||||
void fetchname (char const *, int, char **, char **, struct timespec *);
|
||||
char *parse_name (char const *, int, char const **);
|
||||
char *savebuf (char const *, size_t);
|
||||
char *savestr (char const *);
|
||||
char const *version_controller (char const *, bool, struct stat const *, char **, char **);
|
||||
bool version_get (char const *, char const *, bool, bool, char const *, struct stat *);
|
||||
int create_file (char const *, int, mode_t, bool);
|
||||
int systemic (char const *);
|
||||
char *format_linenum (char[LINENUM_LENGTH_BOUND + 1], lin);
|
||||
void Fseek (FILE *, file_offset, int);
|
||||
void copy_file (char const *, char const *, struct stat *, int, mode_t, bool);
|
||||
void append_to_file (char const *, char const *);
|
||||
void exit_with_signal (int) __attribute__ ((noreturn));
|
||||
void ignore_signals (void);
|
||||
void init_backup_hash_table (void);
|
||||
void init_time (void);
|
||||
void xalloc_die (void) __attribute__ ((noreturn));
|
||||
void create_backup (char const *, const struct stat *, bool);
|
||||
void move_file (char const *, bool *, struct stat const *, char const *, mode_t, bool);
|
||||
void read_fatal (void) __attribute__ ((noreturn));
|
||||
void remove_prefix (char *, size_t);
|
||||
void removedirs (char const *);
|
||||
void set_signals (bool);
|
||||
void write_fatal (void) __attribute__ ((noreturn));
|
||||
void insert_file_id (struct stat const *, enum file_id_type);
|
||||
enum file_id_type lookup_file_id (struct stat const *);
|
||||
void set_queued_output (struct stat const *, bool);
|
||||
bool has_queued_output (struct stat const *);
|
||||
int stat_file (char const *, struct stat *);
|
||||
|
||||
enum file_attributes {
|
||||
FA_TIMES = 1,
|
||||
FA_IDS = 2,
|
||||
@ -77,15 +29,89 @@ enum file_attributes {
|
||||
FA_XATTRS = 8
|
||||
};
|
||||
|
||||
void set_file_attributes (char const *, enum file_attributes, char const *,
|
||||
const struct stat *, mode_t, struct timespec *);
|
||||
/* Exit status for trouble, such as write failure. */
|
||||
enum { EXIT_TROUBLE = 2 };
|
||||
|
||||
static inline char const * _GL_ATTRIBUTE_PURE
|
||||
skip_spaces (char const *str)
|
||||
/* Read or write at most IO_BUFSIZE bytes at a time.
|
||||
In 2024 256 KiB was determined to be the best blocksize
|
||||
to minimize system call overhead across most systems
|
||||
when copying files. See coreutils/src/ioblksize.h. */
|
||||
enum { IO_BUFSIZE = 256 * 1024 };
|
||||
|
||||
/* POSIX says behavior is implementation-defined for I/O requests
|
||||
larger than SSIZE_MAX. IO_BUFSIZE is OK on all known platforms.
|
||||
Check it to be sure. */
|
||||
static_assert (IO_BUFSIZE <= SSIZE_MAX);
|
||||
|
||||
extern enum backup_type backup_type;
|
||||
|
||||
_GL_INLINE_HEADER_BEGIN
|
||||
#ifndef UTIL_INLINE
|
||||
# define UTIL_INLINE _GL_INLINE
|
||||
#endif
|
||||
|
||||
char volatile *volatilize (char *);
|
||||
|
||||
/* Convert S to a pointer to non-volatile. This is the inverse of volatilize.
|
||||
S’s contents must not be updated by a signal handler. */
|
||||
UTIL_INLINE char *
|
||||
devolatilize (char volatile *s)
|
||||
{
|
||||
while (ISSPACE ((unsigned char) *str))
|
||||
str++;
|
||||
return str;
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
int make_tempfile(char const **, char, char const *, int, mode_t);
|
||||
bool ok_to_reverse (char const *, ...) ATTRIBUTE_FORMAT ((printf, 1, 2));
|
||||
char *ask (char const *, ...) ATTRIBUTE_FORMAT ((printf, 1, 2));
|
||||
void say (char const *, ...) ATTRIBUTE_FORMAT ((printf, 1, 2));
|
||||
|
||||
_Noreturn void fatal (char const *, ...) ATTRIBUTE_FORMAT ((printf, 1, 2));
|
||||
_Noreturn void pfatal (char const *, ...) ATTRIBUTE_FORMAT ((printf, 1, 2));
|
||||
|
||||
void fetchname (char const *, intmax_t, char **, char **, struct timespec *);
|
||||
char *parse_name (char const *, intmax_t, char const **);
|
||||
char *savebuf (char const *, idx_t)
|
||||
ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE ATTRIBUTE_ALLOC_SIZE ((2));
|
||||
char const *version_controller (char const *, bool, struct stat const *, char **, char **);
|
||||
bool version_get (char *, char const *, bool, bool, char const *, struct stat *);
|
||||
int create_file (struct outfile *, int, mode_t, bool);
|
||||
int systemic (char const *);
|
||||
void Fclose (FILE *);
|
||||
void Fflush (FILE *);
|
||||
void Fprintf (FILE *, char const *, ...) ATTRIBUTE_FORMAT ((printf, 2, 3));
|
||||
void Fputc (int, FILE *);
|
||||
void Fputs (char const *restrict, FILE *restrict);
|
||||
void Fseeko (FILE *, off_t, int);
|
||||
off_t Ftello (FILE *);
|
||||
void Fwrite (void const *restrict, size_t, size_t, FILE *restrict);
|
||||
idx_t Read (int, void *, idx_t);
|
||||
void copy_file (char *, struct stat const *, struct outfile *, struct stat *,
|
||||
int, mode_t, enum file_attributes, bool);
|
||||
void append_to_file (char *, char *);
|
||||
idx_t quote_system_arg (char *, char const *);
|
||||
void init_signals (void);
|
||||
void defer_signals (void);
|
||||
void undefer_signals (void);
|
||||
void init_backup_hash_table (void);
|
||||
void init_time (void);
|
||||
_Noreturn void xalloc_die (void);
|
||||
void create_backup (char *, const struct stat *, bool);
|
||||
void move_file (struct outfile *, struct stat const *,
|
||||
char *, mode_t, bool);
|
||||
_Noreturn void read_fatal (void);
|
||||
void removedirs (char const *);
|
||||
_Noreturn void write_fatal (void);
|
||||
void putline (FILE *, ...);
|
||||
void insert_file_id (struct stat const *, enum file_id_type);
|
||||
enum file_id_type lookup_file_id (struct stat const *);
|
||||
void set_queued_output (struct stat const *, bool);
|
||||
bool has_queued_output (struct stat const *);
|
||||
int stat_file (char *, struct stat *);
|
||||
bool filename_is_safe (char const *) ATTRIBUTE_PURE;
|
||||
bool cwd_is_root (char const *);
|
||||
|
||||
void set_file_attributes (char *, int, enum file_attributes, char const *, int,
|
||||
const struct stat *, mode_t, struct timespec *);
|
||||
|
||||
int make_tempfile (struct outfile *, char, char const *, int, mode_t);
|
||||
|
||||
_GL_INLINE_HEADER_END
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
/* Print the version number. */
|
||||
|
||||
#define XTERN extern
|
||||
#include <common.h>
|
||||
#include <version.h>
|
||||
#include <util.h>
|
||||
|
||||
static char const copyright_string[] = "\
|
||||
Copyright (C) 2003, 2009-2012 Free Software Foundation, Inc.\n\
|
||||
Copyright (C) 1988 Larry Wall";
|
||||
Copyright 1989-2025 Free Software Foundation, Inc.\n\
|
||||
Copyright 1984-1988 Larry Wall";
|
||||
|
||||
static char const free_software_msgid[] = "\
|
||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n\
|
||||
@ -19,6 +19,6 @@ Written by Larry Wall and Paul Eggert";
|
||||
void
|
||||
version (void)
|
||||
{
|
||||
printf ("%s %s\n%s\n\n%s\n\n%s\n", PACKAGE_NAME, PACKAGE_VERSION,
|
||||
copyright_string, free_software_msgid, authorship_msgid);
|
||||
Fprintf (stdout, "%s %s\n%s\n\n%s\n\n%s\n", PACKAGE_NAME, PACKAGE_VERSION,
|
||||
copyright_string, free_software_msgid, authorship_msgid);
|
||||
}
|
||||
|
||||
2
tests/.gitignore
vendored
2
tests/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
*.log
|
||||
*.trs
|
||||
@ -1,5 +1,4 @@
|
||||
# Copyright (C) 1989-1993, 1997-1999, 2002-2003, 2006, 2009-2012 Free Software
|
||||
# Foundation, Inc.
|
||||
# Copyright 1989-2025 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -20,20 +19,30 @@ TESTS = \
|
||||
asymmetric-hunks \
|
||||
backup-prefix-suffix \
|
||||
bad-filenames \
|
||||
bad-usage \
|
||||
concat-git-diff \
|
||||
context-format \
|
||||
copy-rename \
|
||||
corrupt-patch \
|
||||
corrupt-reject-files \
|
||||
create-delete \
|
||||
create-directory \
|
||||
criss-cross \
|
||||
crlf-handling \
|
||||
dash-o-append \
|
||||
deep-directories \
|
||||
ed-style \
|
||||
empty-files \
|
||||
false-match \
|
||||
fifo \
|
||||
file-create-modes \
|
||||
file-modes \
|
||||
filename-choice \
|
||||
git-binary-diff \
|
||||
git-cleanup \
|
||||
garbage \
|
||||
global-reject-files \
|
||||
hardlinks \
|
||||
inname \
|
||||
line-numbers \
|
||||
merge \
|
||||
@ -41,19 +50,29 @@ TESTS = \
|
||||
mixed-patch-types \
|
||||
munged-context-format \
|
||||
need-filename \
|
||||
no-backup \
|
||||
no-mode-change-git-diff \
|
||||
no-newline-triggers-assert \
|
||||
preserve-c-function-names \
|
||||
preserve-mode-and-timestamp \
|
||||
quoted-filenames \
|
||||
read-only-files \
|
||||
regression-abe92e8010ab \
|
||||
reject-format \
|
||||
remember-backup-files \
|
||||
remember-reject-files \
|
||||
remove-directories \
|
||||
symlinks \
|
||||
unmodified-files
|
||||
unmodified-files \
|
||||
unusual-blanks
|
||||
|
||||
XFAIL_TESTS = \
|
||||
dash-o-append
|
||||
dash-o-append \
|
||||
context-format
|
||||
if OS_IS_HAIKU
|
||||
XFAIL_TESTS += \
|
||||
preserve-mode-and-timestamp
|
||||
endif
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(TESTS) \
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2011-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -126,6 +126,57 @@ check 'patch -f -p1 --dry-run < d.diff || echo status: $?' <<EOF
|
||||
checking file g
|
||||
EOF
|
||||
|
||||
fixup='s/ file ab\.[^ ]*/ file ab.*/'
|
||||
check_ignoring_temp_file_name() {
|
||||
pat=\'$1\'
|
||||
unset arg1; eval ${2+"arg1=\\''$2'\\'"}
|
||||
unset arg2; eval ${3+"arg2=\\''$3'\\'"}
|
||||
check '
|
||||
emit_patch '"$pat"' | patch '"$arg1"' '"$arg2"' >patch.out 2>&1
|
||||
status=$?
|
||||
sed "$fixup" patch.out
|
||||
echo status: $status
|
||||
'
|
||||
}
|
||||
|
||||
nl='
|
||||
'
|
||||
nlname="a${nl}b"
|
||||
quoted_nlname='"a\nb"'
|
||||
|
||||
check_ignoring_temp_file_name "$quoted_nlname" <<EOF
|
||||
patching file 'a
|
||||
b'
|
||||
$PATCH: **** Can't rename file ab.* to 'a
|
||||
b' : Invalid byte sequence
|
||||
status: 2
|
||||
EOF
|
||||
|
||||
check_ignoring_temp_file_name foo "$nlname" <<EOF
|
||||
patching file 'a
|
||||
b'
|
||||
$PATCH: **** Can't rename file ab.* to 'a
|
||||
b' : Invalid byte sequence
|
||||
status: 2
|
||||
EOF
|
||||
|
||||
check_ignoring_temp_file_name foo -o "$nlname" <<EOF
|
||||
$PATCH: **** Can't create file 'a
|
||||
b' : Invalid byte sequence
|
||||
status: 2
|
||||
EOF
|
||||
|
||||
emit_patch_with_NUL()
|
||||
{
|
||||
printf '%s\n' '--- /dev/null'
|
||||
printf '+++ a\0b\n'
|
||||
printf '%s\n' '@@ -0,0 +1 @@' '+x'
|
||||
}
|
||||
check 'emit_patch_with_NUL | patch; echo status: $?' <<EOF
|
||||
$PATCH: **** patch line 2 contains NUL byte
|
||||
status: 2
|
||||
EOF
|
||||
|
||||
mkdir d
|
||||
cd d
|
||||
cat > d.diff <<EOF
|
||||
@ -149,3 +200,11 @@ No file to patch. Skipping patch.
|
||||
1 out of 1 hunk ignored
|
||||
status: 1
|
||||
EOF
|
||||
|
||||
# Empty filenames are not allowed:
|
||||
|
||||
check 'emit_patch f | patch -r- "" || echo status: $?' <<EOF
|
||||
File '' is not a regular file -- refusing to patch
|
||||
1 out of 1 hunk ignored
|
||||
status: 1
|
||||
EOF
|
||||
|
||||
18
tests/bad-usage
Normal file
18
tests/bad-usage
Normal file
@ -0,0 +1,18 @@
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
check 'patch -px || echo "status: $?"' <<EOF
|
||||
$PATCH: **** strip count x is not a number
|
||||
status: 2
|
||||
EOF
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2010-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
122
tests/context-format
Normal file
122
tests/context-format
Normal file
@ -0,0 +1,122 @@
|
||||
# Copyright 2016-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
printf "%s\n" 1 2 4 5 > a
|
||||
cat > ab.diff <<EOF
|
||||
*** a
|
||||
--- b
|
||||
***************
|
||||
*** 1,4 ****
|
||||
--- 1,5 ----
|
||||
1
|
||||
2
|
||||
+ 3
|
||||
4
|
||||
5
|
||||
EOF
|
||||
|
||||
check 'patch < ab.diff' <<EOF
|
||||
patching file a
|
||||
EOF
|
||||
|
||||
printf "%s\n" 1 2 3 4 5 > a
|
||||
cat > ab.diff <<EOF
|
||||
*** a
|
||||
--- b
|
||||
***************
|
||||
*** 1,5 ****
|
||||
1
|
||||
2
|
||||
- 3
|
||||
4
|
||||
5
|
||||
--- 1,4 ----
|
||||
EOF
|
||||
|
||||
check 'patch < ab.diff' <<EOF
|
||||
patching file a
|
||||
EOF
|
||||
|
||||
# --------------------------------------------------------------
|
||||
|
||||
printf "%s\n" a a a a a b a a a a a > a
|
||||
|
||||
cat > ab.diff <<EOF
|
||||
*** a
|
||||
--- b
|
||||
***************
|
||||
*** 6 ****
|
||||
- b
|
||||
--- 5 ----
|
||||
EOF
|
||||
|
||||
check 'patch < ab.diff' <<EOF
|
||||
patching file a
|
||||
EOF
|
||||
|
||||
check 'echo `cat a`' <<EOF
|
||||
a a a a a a a a a a
|
||||
EOF
|
||||
|
||||
cat > ba.diff <<EOF
|
||||
*** b
|
||||
--- a
|
||||
***************
|
||||
*** 5 ****
|
||||
--- 6 ----
|
||||
+ b
|
||||
EOF
|
||||
|
||||
check 'patch < ba.diff' <<EOF
|
||||
patching file a
|
||||
EOF
|
||||
|
||||
check 'echo `cat a`' <<EOF
|
||||
a a a a a b a a a a a
|
||||
EOF
|
||||
|
||||
printf "%s\n" a a a a a a a a a a b > a
|
||||
|
||||
cat > ab.diff <<EOF
|
||||
*** a
|
||||
--- b
|
||||
***************
|
||||
*** 11 ****
|
||||
- b
|
||||
--- 10 ----
|
||||
EOF
|
||||
|
||||
check 'patch < ab.diff' <<EOF
|
||||
patching file a
|
||||
EOF
|
||||
|
||||
check 'echo `cat a`' <<EOF
|
||||
a a a a a a a a a a
|
||||
EOF
|
||||
|
||||
cat > ba.diff <<EOF
|
||||
*** b
|
||||
--- a
|
||||
***************
|
||||
*** 10 ****
|
||||
--- 11 ----
|
||||
+ b
|
||||
EOF
|
||||
|
||||
check 'patch < ba.diff' <<EOF
|
||||
patching file a
|
||||
EOF
|
||||
|
||||
check 'echo `cat a`' <<EOF
|
||||
a a a a a a a a a a b
|
||||
EOF
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2010-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
@ -63,6 +63,30 @@ check 'cat h' <<EOF
|
||||
new
|
||||
EOF
|
||||
|
||||
echo old > h
|
||||
|
||||
check 'patch -p1 < rename.diff || echo "Status: $?"' <<EOF
|
||||
patching file h (already renamed from f)
|
||||
EOF
|
||||
|
||||
ncheck 'test ! -e f'
|
||||
|
||||
check 'cat h' <<EOF
|
||||
new
|
||||
EOF
|
||||
|
||||
mv h f
|
||||
|
||||
check 'patch -p1 -R < rename.diff || echo "Status: $?"' <<EOF
|
||||
patching file f (already renamed from h)
|
||||
EOF
|
||||
|
||||
ncheck 'test ! -e h'
|
||||
|
||||
check 'cat f' <<EOF
|
||||
old
|
||||
EOF
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# Patches with no hunks
|
||||
|
||||
|
||||
33
tests/corrupt-patch
Normal file
33
tests/corrupt-patch
Normal file
@ -0,0 +1,33 @@
|
||||
# Copyright 2015-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
# Patch missing the traditional "--- old\n+++ new\n" header
|
||||
|
||||
cat > test.diff <<EOF
|
||||
diff --git a/test b/test
|
||||
index 8e139fc..4c03766 100644
|
||||
@@ -1 +1 @@
|
||||
-a
|
||||
+b
|
||||
EOF
|
||||
|
||||
echo a > test
|
||||
|
||||
check 'patch -p1 -i test.diff' <<EOF
|
||||
patching file test
|
||||
EOF
|
||||
|
||||
check 'cat test' <<EOF
|
||||
b
|
||||
EOF
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,8 +6,8 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require_sed
|
||||
require cat
|
||||
require sed
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
@ -182,7 +182,7 @@ EOF
|
||||
|
||||
check 'patch -p0 < p.diff || echo status: $?' <<EOF
|
||||
patching file target
|
||||
File target is not empty after patch; not deleting
|
||||
Not deleting file target as content differs from patch
|
||||
status: 1
|
||||
EOF
|
||||
|
||||
@ -202,7 +202,7 @@ EOF
|
||||
|
||||
check 'patch -p0 < p.diff || echo status: $?' <<EOF
|
||||
patching file target
|
||||
File target is not empty after patch; not deleting
|
||||
Not deleting file target as content differs from patch
|
||||
status: 1
|
||||
EOF
|
||||
|
||||
@ -212,23 +212,27 @@ EOF
|
||||
|
||||
# --------------------------------------------------------------
|
||||
printf '\0' > target
|
||||
cat > p.diff <<EOF
|
||||
if ! test -s target; then
|
||||
echo "Failed to printf a null character; skipping this test"
|
||||
else
|
||||
cat > p.diff <<EOF
|
||||
diff --git a/target b/target
|
||||
deleted file mode 100644
|
||||
index f76dd23..0000000
|
||||
Binary files a/target and /dev/null differ
|
||||
EOF
|
||||
|
||||
check 'patch -p1 -b < p.diff || echo status: $?' <<EOF
|
||||
check 'patch -p1 -b < p.diff || echo status: $?' <<EOF
|
||||
patching file target
|
||||
File target is not empty after patch; not deleting
|
||||
Not deleting file target as content differs from patch
|
||||
status: 1
|
||||
EOF
|
||||
|
||||
ncheck 'test -e target'
|
||||
ncheck 'test -e target'
|
||||
|
||||
# Patch creates a backup file even when the original file remains unchanged:
|
||||
ncheck 'test -e target.orig'
|
||||
ncheck 'test -e target.orig'
|
||||
fi
|
||||
|
||||
# ================================================================
|
||||
# File not expected to become empty does become empty
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
# Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2010-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
# Check whether patch correctly creates directories before creating
|
||||
# new files.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
# Check whether patch correctly creates directories before creating
|
||||
# new files.
|
||||
|
||||
cat > f.diff <<EOF
|
||||
--- /dev/null
|
||||
@ -25,3 +24,20 @@ EOF
|
||||
check 'patch -p0 < f.diff' <<EOF
|
||||
patching file b/newfile
|
||||
EOF
|
||||
|
||||
# ==============================================================
|
||||
# Make sure it doesn't create files or directories in the target
|
||||
# location in --dry-run mode
|
||||
mkdir d
|
||||
cat > f.diff <<EOF
|
||||
--- /dev/null
|
||||
+++ d/e/f
|
||||
@@ -0,0 +1 @@
|
||||
+f
|
||||
EOF
|
||||
|
||||
chmod u-w d
|
||||
check 'patch -p0 --dry-run < f.diff' <<EOF
|
||||
checking file d/e/f
|
||||
EOF
|
||||
chmod u+w d
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2010-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,13 +8,13 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_gnu_diff
|
||||
require_sed
|
||||
require gnu_diff
|
||||
require sed
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
lf2crlf() {
|
||||
while read l; do echo -e "$l\r"; done
|
||||
while read l; do printf "%s\r\n" "$l"; done
|
||||
}
|
||||
|
||||
echo 1 > a
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
28
tests/deep-directories
Executable file
28
tests/deep-directories
Executable file
@ -0,0 +1,28 @@
|
||||
# Copyright 2015-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
# Exercise the directory file descriptor cache
|
||||
|
||||
# Artificially limit to 8 cache entries
|
||||
ulimit -n 32 > /dev/null 2>&1 || exit 77
|
||||
|
||||
cat > ab.diff <<EOF
|
||||
--- /dev/null
|
||||
+++ b/1/2/3/4/5/6/7/8/9/foo
|
||||
@@ -0,0 +1 @@
|
||||
+foo
|
||||
EOF
|
||||
|
||||
check 'patch -p1 < ab.diff || echo Status: $?' <<EOF
|
||||
patching file 1/2/3/4/5/6/7/8/9/foo
|
||||
EOF
|
||||
72
tests/ed-style
Normal file
72
tests/ed-style
Normal file
@ -0,0 +1,72 @@
|
||||
# Copyright 2018-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
require ed
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
cat > ed1.diff <<EOF
|
||||
0a
|
||||
foo
|
||||
.
|
||||
EOF
|
||||
|
||||
check 'patch -e foo -i ed1.diff' <<EOF
|
||||
EOF
|
||||
|
||||
check 'cat foo' <<EOF
|
||||
foo
|
||||
EOF
|
||||
|
||||
cat > ed2.diff <<EOF
|
||||
1337a
|
||||
r !echo bar
|
||||
,p
|
||||
EOF
|
||||
|
||||
check 'patch -e foo -i ed2.diff > /dev/null 2> /dev/null || echo "Status: $?"' <<EOF
|
||||
Status: 2
|
||||
EOF
|
||||
|
||||
check 'cat foo' <<EOF
|
||||
foo
|
||||
EOF
|
||||
|
||||
# Test the case where one ed-style patch modifies several files
|
||||
|
||||
cat > ed3.diff <<EOF
|
||||
--- foo
|
||||
+++ foo
|
||||
1c
|
||||
bar
|
||||
.
|
||||
--- baz
|
||||
+++ baz
|
||||
0a
|
||||
baz
|
||||
.
|
||||
EOF
|
||||
|
||||
# Apparently we can't create a file with such a patch, while it works fine
|
||||
# when the file name is provided on the command line
|
||||
cat > baz <<EOF
|
||||
EOF
|
||||
|
||||
check 'patch -e -i ed3.diff' <<EOF
|
||||
EOF
|
||||
|
||||
check 'cat foo' <<EOF
|
||||
bar
|
||||
EOF
|
||||
|
||||
check 'cat baz' <<EOF
|
||||
baz
|
||||
EOF
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2010-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
umask 022
|
||||
|
||||
55
tests/false-match
Normal file
55
tests/false-match
Normal file
@ -0,0 +1,55 @@
|
||||
# Copyright 2017-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
# Check if patch incorrectly applies overlapping hunks: after the
|
||||
# first hunk is applied, the second hunk should not apply
|
||||
# anymore. Older versions of patch didn't recognize that and did
|
||||
# apply the second hunk on top of the first one, leading to the
|
||||
# following incorrect result, with no information about hunk 2:
|
||||
#
|
||||
# Hunk #1 succeeded at 7 (offset 6 lines).
|
||||
#
|
||||
# printf '%s\n' x x x x x x 1 2 3 a a 4 5 6
|
||||
|
||||
cat > a.diff <<EOF
|
||||
--- a
|
||||
+++ a
|
||||
@@ -1,6 +1,7 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
+a
|
||||
4
|
||||
5
|
||||
6
|
||||
@@ -7,6 +8,7 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
+a
|
||||
4
|
||||
5
|
||||
6
|
||||
EOF
|
||||
|
||||
printf "%s\n" x x x x x x > a
|
||||
seq 1 6 >> a
|
||||
|
||||
check 'patch < a.diff || echo status: $?' <<EOF
|
||||
patching file a
|
||||
Hunk #1 succeeded at 7 (offset 6 lines).
|
||||
Hunk #2 FAILED at 8.
|
||||
1 out of 2 hunks FAILED -- saving rejects to file a.rej
|
||||
status: 1
|
||||
EOF
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
52
tests/file-create-modes
Normal file
52
tests/file-create-modes
Normal file
@ -0,0 +1,52 @@
|
||||
# Copyright 2010-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
# Test if git diffs can create files with proper modes
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
require sed
|
||||
require chmod
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
cat > f.diff <<EOF
|
||||
diff --git a/f b/f
|
||||
new file mode 100710
|
||||
index 0000000..3e75765
|
||||
--- /dev/null
|
||||
+++ b/f
|
||||
@@ -0,0 +1 @@
|
||||
+new
|
||||
|
||||
diff --git a/g b/g
|
||||
new file mode 100654
|
||||
index 0000000..3e75765
|
||||
--- /dev/null
|
||||
+++ b/g
|
||||
@@ -0,0 +1 @@
|
||||
+new
|
||||
EOF
|
||||
|
||||
check 'patch -p1 < f.diff' <<EOF
|
||||
patching file f
|
||||
patching file g
|
||||
EOF
|
||||
|
||||
check 'ls -l f g | sed "s,\(..........\).*,\1,"' <<EOF
|
||||
-rwx--x---
|
||||
-rw-r-xr--
|
||||
EOF
|
||||
|
||||
check 'patch -p1 -R < f.diff' <<EOF
|
||||
patching file f
|
||||
patching file g
|
||||
EOF
|
||||
|
||||
ncheck '! test -e f -o -e g || echo fail'
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2010-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,8 +8,9 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require_sed
|
||||
require cat
|
||||
require sed
|
||||
require chmod
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
25
tests/garbage
Normal file
25
tests/garbage
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright 2015-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
cat > bad.diff <<EOF
|
||||
***************
|
||||
*** 0 ****
|
||||
--- 1 ----
|
||||
+ foo
|
||||
EOF
|
||||
|
||||
check 'patch foo -i bad.diff || echo "Status: $?"' <<EOF
|
||||
$PATCH: **** Only garbage was found in the patch input.
|
||||
Status: 2
|
||||
EOF
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2010-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
75
tests/git-cleanup
Normal file
75
tests/git-cleanup
Normal file
@ -0,0 +1,75 @@
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
cat > 1.diff <<EOF
|
||||
diff --git a/f b/f
|
||||
--- f
|
||||
+++ f
|
||||
@@ -1 +1 @@
|
||||
-1
|
||||
+1a
|
||||
@@ -5 +5 @@
|
||||
-out
|
||||
+in
|
||||
diff --git a/g b/g
|
||||
--- g
|
||||
+++ g
|
||||
@@ -1 +1 @@
|
||||
-out
|
||||
+in
|
||||
diff --git a/h b/h
|
||||
--- h
|
||||
+++ h
|
||||
@@ -1 +1 @@
|
||||
BAD PATCH
|
||||
EOF
|
||||
|
||||
echo 1 > f
|
||||
printf '' > g
|
||||
printf '' > h
|
||||
|
||||
check 'patch -f -i 1.diff || echo status: $?' <<EOF
|
||||
patching file f
|
||||
Hunk #2 FAILED at 5.
|
||||
1 out of 2 hunks FAILED -- saving rejects to file f.rej
|
||||
patching file g
|
||||
Hunk #1 FAILED at 1.
|
||||
1 out of 1 hunk FAILED -- saving rejects to file g.rej
|
||||
patching file h
|
||||
$PATCH: **** malformed patch at line 20: BAD PATCH
|
||||
|
||||
status: 2
|
||||
EOF
|
||||
|
||||
check 'cat f' <<EOF
|
||||
1a
|
||||
EOF
|
||||
|
||||
check 'cat f.rej' <<EOF
|
||||
--- f
|
||||
+++ f
|
||||
@@ -5 +5 @@
|
||||
-out
|
||||
+in
|
||||
EOF
|
||||
|
||||
ncheck 'cat g'
|
||||
|
||||
check 'cat g.rej' <<EOF
|
||||
--- g
|
||||
+++ g
|
||||
@@ -1 +1 @@
|
||||
-out
|
||||
+in
|
||||
EOF
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
50
tests/hardlinks
Normal file
50
tests/hardlinks
Normal file
@ -0,0 +1,50 @@
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
# Patch must not overwrite backup files it has created itself.
|
||||
# (Backup file tests for symlinks are in tests/symlinks.)
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
require hardlinks
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
# Hardlinks between source files
|
||||
|
||||
echo one > f
|
||||
ln f g
|
||||
|
||||
cat > fg.diff <<EOF
|
||||
--- f.orig
|
||||
+++ f
|
||||
@@ -2 +2 @@
|
||||
-one
|
||||
+two
|
||||
--- g.orig
|
||||
+++ g
|
||||
@@ -2 +2 @@
|
||||
-one
|
||||
+two
|
||||
EOF
|
||||
|
||||
check 'patch -p0 < fg.diff' <<EOF
|
||||
patching file f
|
||||
Hunk #1 succeeded at 1 (offset -1 lines).
|
||||
patching file g
|
||||
Hunk #1 succeeded at 1 (offset -1 lines).
|
||||
EOF
|
||||
|
||||
check 'cat f.orig' <<EOF
|
||||
one
|
||||
EOF
|
||||
|
||||
check 'cat g.orig' <<EOF
|
||||
one
|
||||
EOF
|
||||
24
tests/inname
24
tests/inname
@ -1,14 +1,12 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
# Don't recognize hunks before a filename has been specified/seen
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
@ -37,3 +35,21 @@ EOF
|
||||
check 'cat x' <<EOF
|
||||
three
|
||||
EOF
|
||||
|
||||
# --------------------------------------------------------------
|
||||
|
||||
echo aa > file1
|
||||
|
||||
mkdir 1
|
||||
cd 1
|
||||
cat > g.diff <<EOF
|
||||
--- file1
|
||||
+++ file2
|
||||
@@ -1 +1 @@
|
||||
-aa
|
||||
+bb
|
||||
EOF
|
||||
|
||||
check 'patch ../file1 < g.diff' <<EOF
|
||||
patching file ../file1
|
||||
EOF
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,8 +6,8 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require_sed
|
||||
require cat
|
||||
require sed
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2011-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
28
tests/merge
28
tests/merge
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,9 +8,9 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require_gnu_diff
|
||||
require_sed
|
||||
require cat
|
||||
require gnu_diff
|
||||
require sed
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
@ -30,30 +30,28 @@ x2() {
|
||||
while test $# -gt 0 && test "$1" != -- ; do
|
||||
echo "$1"
|
||||
shift
|
||||
done > a.sed
|
||||
echo "$body" | sed -f a.sed > b
|
||||
shift
|
||||
done > b.sed
|
||||
echo "$body" | sed -f b.sed > b
|
||||
test $# -eq 0 || shift
|
||||
while test $# -gt 0 ; do
|
||||
echo "$1"
|
||||
shift
|
||||
done > b.sed
|
||||
echo "$body" | sed -f b.sed > c
|
||||
rm -f a.sed b.sed
|
||||
done > c.sed
|
||||
echo "$body" | sed -f c.sed > c
|
||||
rm -f b.sed c.sed
|
||||
output=`diff -u a b | patch $ARGS -f c`
|
||||
status=$?
|
||||
echo "$output" | sed -e '/^$/d' -e '/^patching file c$/d'
|
||||
cat c
|
||||
test $status == 0 || echo "Status: $status"
|
||||
test $status = 0 || echo "Status: $status"
|
||||
}
|
||||
|
||||
x() {
|
||||
ARGS="$ARGS --merge" x2 "$@"
|
||||
ARGS="--merge" x2 "$@"
|
||||
echo
|
||||
ARGS="$ARGS --merge=diff3" x2 "$@"
|
||||
ARGS="--merge=diff3" x2 "$@"
|
||||
}
|
||||
|
||||
unset ARGS
|
||||
|
||||
# ==============================================================
|
||||
|
||||
check 'x 3' <<EOF
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2010-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
umask 022
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,8 +8,8 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require_sed
|
||||
require cat
|
||||
require sed
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,8 +8,8 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require_sed
|
||||
require cat
|
||||
require sed
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
56
tests/no-backup
Normal file
56
tests/no-backup
Normal file
@ -0,0 +1,56 @@
|
||||
# Copyright 2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
# Test the --no-backup-if-mismatch option
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
cat >my_file <<'EOF'
|
||||
/* ... */
|
||||
void baz();
|
||||
|
||||
|
||||
void baz() {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
int main() {
|
||||
int foo;
|
||||
int bar;
|
||||
|
||||
/* ... */
|
||||
baz();
|
||||
}
|
||||
EOF
|
||||
|
||||
cat >my_file.patch <<'EOF'
|
||||
--- my_file 2025-02-16 11:22:12.881765792 +0000
|
||||
+++ my_file_new 2025-02-16 11:22:12.881796732 +0000
|
||||
@@ -2,7 +2,7 @@
|
||||
void baz();
|
||||
|
||||
void baz() {
|
||||
- /* ... */
|
||||
+ // ...
|
||||
}
|
||||
|
||||
int main() {
|
||||
EOF
|
||||
|
||||
unset POSIXLY_CORRECT
|
||||
|
||||
check 'patch -N --no-backup-if-mismatch <my_file.patch || echo "Status: $?"' <<'EOF'
|
||||
patching file my_file
|
||||
Hunk #1 succeeded at 3 with fuzz 1 (offset 1 line).
|
||||
EOF
|
||||
|
||||
ncheck 'test ! -f my_file.orig'
|
||||
35
tests/no-mode-change-git-diff
Normal file
35
tests/no-mode-change-git-diff
Normal file
@ -0,0 +1,35 @@
|
||||
# Copyright 2010-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
require chmod
|
||||
require stat
|
||||
require chmod
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
echo 'ksplice' > f
|
||||
chmod 755 f
|
||||
|
||||
cat > simple.diff <<EOF
|
||||
diff --git a/f b/f
|
||||
index 422a422a..736b6c7063690a 100644
|
||||
--- a/f
|
||||
+++ b/f
|
||||
@@ -1 +1 @@
|
||||
-ksplice
|
||||
+ksplice rocks!
|
||||
EOF
|
||||
|
||||
check 'patch -p1 < simple.diff || echo "Status: $?"' <<EOF
|
||||
patching file f
|
||||
EOF
|
||||
|
||||
check 'ls -l f | sed "s,\(..........\).*,\1,"' <<EOF
|
||||
-rwxr-xr-x
|
||||
EOF
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,8 +8,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require_gnu_diff
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
@ -33,7 +32,23 @@ EOF
|
||||
|
||||
preserve_trailing_blank=
|
||||
|
||||
diff -p -c -L a -L b a b > ab.diff
|
||||
cat > ab.diff <<EOF
|
||||
*** a
|
||||
--- b
|
||||
*************** int foo()
|
||||
*** 2,6 ****
|
||||
{
|
||||
/* waste a line */
|
||||
$preserve_trailing_blank
|
||||
! return 1;
|
||||
}
|
||||
--- 2,6 ----
|
||||
{
|
||||
/* waste a line */
|
||||
$preserve_trailing_blank
|
||||
! return 2;
|
||||
}
|
||||
EOF
|
||||
touch c
|
||||
check 'patch c < ab.diff || cat c.rej' <<EOF
|
||||
patching file c
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,8 +6,12 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require_sed
|
||||
# Note: This test fails on Haiku. This is normal; it is caused by
|
||||
# Haiku bug <https://dev.haiku-os.org/ticket/19213>.
|
||||
|
||||
require cat
|
||||
require sed
|
||||
require chmod
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
@ -52,7 +56,7 @@ EOF
|
||||
# Some non-GNU versions of date can't show a file's timestamp
|
||||
timestamp2_touch=`echo "$timestamp2" | sed -e "$sed_expr"`
|
||||
TZ=UTC touch -t $timestamp2_touch f.compare
|
||||
ncheck 'test ! \( f -ot f.compare -o f -nt f.compare \) || echo "timstamp differs"'
|
||||
ncheck 'test ! \( f -ot f.compare -o f -nt f.compare \) || echo "timestamp differs"'
|
||||
|
||||
# POSIX allows a byte like '+' or '.' in position 11 to indicate the
|
||||
# presence of extended permissions like ACLs.
|
||||
@ -118,4 +122,4 @@ check 'patch -p1 --backup --set-utc < f.diff' <<EOF
|
||||
patching file f
|
||||
EOF
|
||||
|
||||
ncheck 'test ! \( f -ot f.compare -o f -nt f.compare \) || echo "timstamp differs"'
|
||||
ncheck 'test ! \( f -ot f.compare -o f -nt f.compare \) || echo "timestamp differs"'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,14 +8,16 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
require special_characters
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
# Forbidden characters in Windows filenames:
|
||||
# \ / : * ? " < > |
|
||||
# \ / : * ? " < > | TAB
|
||||
# Filenames with trailing space characters
|
||||
|
||||
cat > d.diff <<EOF
|
||||
--- "\\t \\040"
|
||||
@ -31,3 +33,25 @@ ncheck 'patch -s -p0 < d.diff'
|
||||
check 'cat " "' <<EOF
|
||||
two
|
||||
EOF
|
||||
|
||||
cat > e.diff <<\EOF
|
||||
*** /dev/null Sat Sep 14 08:47:53 2024
|
||||
--- "f\000g" Tue Sep 17 10:21:17 2024
|
||||
***************
|
||||
*** 0 ****
|
||||
--- 1 ----
|
||||
+
|
||||
EOF
|
||||
|
||||
check 'patch -f < e.diff; echo status: $?' <<EOF
|
||||
can't find file to patch at input line 3
|
||||
Perhaps you should have used the -p or --strip option?
|
||||
The text leading up to this was:
|
||||
--------------------------
|
||||
|*** /dev/null Sat Sep 14 08:47:53 2024
|
||||
|--- "f\000g" Tue Sep 17 10:21:17 2024
|
||||
--------------------------
|
||||
No file to patch. Skipping patch.
|
||||
1 out of 1 hunk ignored
|
||||
status: 1
|
||||
EOF
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,7 +8,8 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
require chmod
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
@ -16,7 +17,7 @@ use_tmpdir
|
||||
|
||||
: > read-only
|
||||
chmod a-w read-only
|
||||
if : 2> /dev/null > read-only; then
|
||||
if ( : 2> /dev/null > read-only ); then
|
||||
echo "Files with read-only permissions are writable" \
|
||||
"(probably running as superuser)" >&2
|
||||
exit 77
|
||||
@ -66,3 +67,8 @@ check 'patch -f -p0 --read-only=ignore < f.diff || echo "Status: $?"' <<EOF
|
||||
patching file f
|
||||
patching file f
|
||||
EOF
|
||||
|
||||
check 'patch -o - f /dev/null || echo "Status: $?"' <<EOF
|
||||
patching file - (read from f)
|
||||
three
|
||||
EOF
|
||||
|
||||
33
tests/regression-abe92e8010ab
Normal file
33
tests/regression-abe92e8010ab
Normal file
@ -0,0 +1,33 @@
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
cat > f <<EOF
|
||||
1
|
||||
2
|
||||
test:
|
||||
a
|
||||
4
|
||||
EOF
|
||||
|
||||
cat > f.diff <<EOF
|
||||
2,3c2
|
||||
< test:
|
||||
< a
|
||||
---
|
||||
> 3
|
||||
EOF
|
||||
|
||||
check 'patch f < f.diff' <<EOF
|
||||
patching file f
|
||||
Hunk #1 succeeded at 3 (offset 1 line).
|
||||
EOF
|
||||
|
||||
check 'cat f' <<EOF
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
EOF
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,12 +8,13 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require_sed
|
||||
require_gnu_diff
|
||||
require cat
|
||||
require sed
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
preserve_trailing_blank=
|
||||
|
||||
# ==============================================================
|
||||
|
||||
cat > f.orig <<EOF
|
||||
@ -27,7 +28,26 @@ a() {
|
||||
EOF
|
||||
|
||||
sed -e 's/5/5a/' f.orig > f
|
||||
diff -p -c -L f.orig -L f f.orig f > f.diff
|
||||
|
||||
cat > f.diff <<EOF
|
||||
*** f.orig
|
||||
--- f
|
||||
*************** a() {
|
||||
*** 2,7 ****
|
||||
2
|
||||
3
|
||||
$preserve_trailing_blank
|
||||
! 5
|
||||
6
|
||||
}
|
||||
--- 2,7 ----
|
||||
2
|
||||
3
|
||||
$preserve_trailing_blank
|
||||
! 5a
|
||||
6
|
||||
}
|
||||
EOF
|
||||
|
||||
check 'patch -f -F0 --no-backup-if-mismatch --dry-run f < f.diff || echo "Status: $?"' <<EOF
|
||||
checking file f
|
||||
@ -43,8 +63,6 @@ Hunk #1 FAILED at 2.
|
||||
Status: 1
|
||||
EOF
|
||||
|
||||
preserve_trailing_blank=
|
||||
|
||||
check 'cat f.rej' <<EOF
|
||||
*** f.orig
|
||||
--- f
|
||||
@ -67,8 +85,20 @@ EOF
|
||||
|
||||
# --------------------------------------------------------------
|
||||
|
||||
( echo "Index: f"; diff -p -u -L f.orig -L f f.orig f ) > f.diff
|
||||
check 'patch -f -F0 --no-backup-if-mismatch f < f.diff || echo "Status: $?"' <<EOF
|
||||
cat > f1.diff <<EOF
|
||||
Index: f
|
||||
--- f.orig
|
||||
+++ f
|
||||
@@ -2,6 +2,6 @@ a() {
|
||||
2
|
||||
3
|
||||
$preserve_trailing_blank
|
||||
-5
|
||||
+5a
|
||||
6
|
||||
}
|
||||
EOF
|
||||
check 'patch -f -F0 --no-backup-if-mismatch f < f1.diff || echo "Status: $?"' <<EOF
|
||||
patching file f
|
||||
Hunk #1 FAILED at 2.
|
||||
1 out of 1 hunk FAILED -- saving rejects to file f.rej
|
||||
@ -79,7 +109,7 @@ check 'cat f.rej' <<EOF
|
||||
Index: f
|
||||
--- f.orig
|
||||
+++ f
|
||||
@@ -2,6 +2,6 @@
|
||||
@@ -2,6 +2,6 @@ a() {
|
||||
2
|
||||
3
|
||||
$preserve_trailing_blank
|
||||
@ -91,7 +121,6 @@ EOF
|
||||
|
||||
# --------------------------------------------------------------
|
||||
|
||||
diff -p -c -L f.orig -L f f.orig f > f.diff
|
||||
check 'patch -f -F0 --no-backup-if-mismatch --reject-format=unified f < f.diff || echo "Status: $?"' <<EOF
|
||||
patching file f
|
||||
Hunk #1 FAILED at 2.
|
||||
@ -102,7 +131,7 @@ EOF
|
||||
check 'cat f.rej' <<EOF
|
||||
--- f.orig
|
||||
+++ f
|
||||
@@ -2,6 +2,6 @@
|
||||
@@ -2,6 +2,6 @@ a() {
|
||||
2
|
||||
3
|
||||
$preserve_trailing_blank
|
||||
@ -114,8 +143,7 @@ EOF
|
||||
|
||||
# --------------------------------------------------------------
|
||||
|
||||
( echo "Index: f"; diff -p -u -L f.orig -L f f.orig f ) > f.diff
|
||||
check 'patch -f -F0 --no-backup-if-mismatch --reject-format=context f < f.diff || echo "Status: $?"' <<EOF
|
||||
check 'patch -f -F0 --no-backup-if-mismatch --reject-format=context f < f1.diff || echo "Status: $?"' <<EOF
|
||||
patching file f
|
||||
Hunk #1 FAILED at 2.
|
||||
1 out of 1 hunk FAILED -- saving rejects to file f.rej
|
||||
@ -147,7 +175,13 @@ EOF
|
||||
|
||||
echo one > a
|
||||
echo two > b
|
||||
diff -u -L "a label of a" -L "b label of b" a b > ab.diff
|
||||
cat > ab.diff <<EOF
|
||||
--- a label of a
|
||||
+++ b label of b
|
||||
@@ -1 +1 @@
|
||||
-one
|
||||
+two
|
||||
EOF
|
||||
mv b a
|
||||
|
||||
check 'patch -f < ab.diff || echo "Status: $?"' <<EOF
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
@ -50,41 +50,6 @@ EOF
|
||||
|
||||
# ==============================================================
|
||||
|
||||
# Hardlinks between source files
|
||||
|
||||
echo one > f
|
||||
ln f g
|
||||
|
||||
cat > fg.diff <<EOF
|
||||
--- f.orig
|
||||
+++ f
|
||||
@@ -2 +2 @@
|
||||
-one
|
||||
+two
|
||||
--- g.orig
|
||||
+++ g
|
||||
@@ -2 +2 @@
|
||||
-one
|
||||
+two
|
||||
EOF
|
||||
|
||||
check 'patch -p0 < fg.diff' <<EOF
|
||||
patching file f
|
||||
Hunk #1 succeeded at 1 (offset -1 lines).
|
||||
patching file g
|
||||
Hunk #1 succeeded at 1 (offset -1 lines).
|
||||
EOF
|
||||
|
||||
check 'cat f.orig' <<EOF
|
||||
one
|
||||
EOF
|
||||
|
||||
check 'cat g.orig' <<EOF
|
||||
one
|
||||
EOF
|
||||
|
||||
# ==============================================================
|
||||
|
||||
echo one > f
|
||||
|
||||
cat > f.diff <<EOF
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
29
tests/remove-directories
Normal file
29
tests/remove-directories
Normal file
@ -0,0 +1,29 @@
|
||||
# Copyright 2013-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
# Remove empty parent directories when removing a file.
|
||||
|
||||
mkdir dir
|
||||
echo foobar > dir/file
|
||||
cat > apatch <<EOF
|
||||
--- dir/file
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
-foobar
|
||||
EOF
|
||||
|
||||
check 'patch -p0 -E < apatch' <<EOF
|
||||
patching file dir/file
|
||||
EOF
|
||||
|
||||
ncheck '! test -e dir'
|
||||
258
tests/symlinks
258
tests/symlinks
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2010-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -8,7 +8,8 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
require symlinks
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
@ -59,6 +60,14 @@ check 'patch --follow-symlinks < modify.diff || echo "Status: $?"' <<EOF
|
||||
patching file l
|
||||
EOF
|
||||
|
||||
check 'cat f' <<EOF
|
||||
one
|
||||
EOF
|
||||
|
||||
check 'cat l' <<EOF
|
||||
two
|
||||
EOF
|
||||
|
||||
# --------------------------------------------------------------
|
||||
|
||||
rm -f f l
|
||||
@ -146,6 +155,234 @@ ncheck 'test ! -L symlink'
|
||||
|
||||
# --------------------------------------------------------------
|
||||
|
||||
# Recursive symlinks
|
||||
|
||||
ln -s l1 l2
|
||||
ln -s l2 l1
|
||||
|
||||
cat > f.diff <<EOF
|
||||
--- l1/f
|
||||
+++ l1/f
|
||||
@@ -0,0 +1 @@
|
||||
+new
|
||||
EOF
|
||||
|
||||
check 'patch -p0 < f.diff || echo "Status: $?"' <<EOF
|
||||
Invalid file name l1/f -- skipping patch
|
||||
Status: 1
|
||||
EOF
|
||||
|
||||
rm -f l1 l2
|
||||
|
||||
# --------------------------------------------------------------
|
||||
|
||||
cat > retraverse.diff <<EOF
|
||||
--- abc/def/ghi/jkl
|
||||
+++ abc/def/ghi/jkl
|
||||
@@ -0,0 +1 @@
|
||||
+Parent directory traversal
|
||||
EOF
|
||||
|
||||
ncheck 'mkdir abc'
|
||||
ncheck 'mkdir abc/def'
|
||||
ln -sf ../../abc/def abc/def/ghi
|
||||
check 'patch -p0 < retraverse.diff || echo "Status: $?"' << EOF
|
||||
patching file abc/def/ghi/jkl
|
||||
EOF
|
||||
|
||||
# --------------------------------------------------------------
|
||||
|
||||
# Patch should not create symlinks which point outside the working directory.
|
||||
|
||||
mkdir d
|
||||
echo one > d/f
|
||||
ln -s d ld
|
||||
|
||||
cat > ld.diff <<EOF
|
||||
--- ld/f
|
||||
+++ ld/f
|
||||
@@ -1 +1 @@
|
||||
-one
|
||||
+two
|
||||
EOF
|
||||
|
||||
check 'patch -p0 < ld.diff' <<EOF
|
||||
patching file ld/f
|
||||
EOF
|
||||
|
||||
mkdir e
|
||||
ln -s ../d e/ld
|
||||
|
||||
cat > eld.diff <<EOF
|
||||
--- e/ld/f
|
||||
+++ e/ld/f
|
||||
@@ -1 +1 @@
|
||||
-two
|
||||
+three
|
||||
EOF
|
||||
|
||||
check 'patch -p0 < eld.diff' <<EOF
|
||||
patching file e/ld/f
|
||||
EOF
|
||||
|
||||
rm -f e/ld
|
||||
ln -sf ../ld e/ld
|
||||
|
||||
check 'patch -p0 -R < eld.diff' <<EOF
|
||||
patching file e/ld/f
|
||||
EOF
|
||||
|
||||
mkdir g
|
||||
ln -sf ../../z g/bad-rel
|
||||
ln -sf .. bad-rel-step2
|
||||
ln -sf ../bad-rel-step2/z g/bad-rel-step1
|
||||
ln -sf /z g/bad-abs
|
||||
|
||||
cat > follow-bad-symlink.diff <<EOF
|
||||
--- g/bad-rel/x
|
||||
+++ g/bad-rel/x
|
||||
@@ -0,0 +1 @@
|
||||
+relative
|
||||
--- g/bad-rel-step1/x
|
||||
+++ g/bad-rel-step1/x
|
||||
@@ -0,0 +1 @@
|
||||
+relative, 2 steps
|
||||
--- g/bad-abs/x
|
||||
+++ g/bad-abs/x
|
||||
@@ -0,0 +1 @@
|
||||
+absolute
|
||||
EOF
|
||||
|
||||
check 'patch -p0 < follow-bad-symlink.diff || echo "Status: $?"' <<EOF
|
||||
Invalid file name g/bad-rel/x -- skipping patch
|
||||
Invalid file name g/bad-rel-step1/x -- skipping patch
|
||||
Invalid file name g/bad-abs/x -- skipping patch
|
||||
Status: 1
|
||||
EOF
|
||||
|
||||
rm -rf ld d e g
|
||||
|
||||
cat > symlink-target.diff <<EOF
|
||||
diff --git a/dir/foo b/dir/foo
|
||||
new file mode 120000
|
||||
index 0000000..cad2309
|
||||
--- /dev/null
|
||||
+++ b/dir/foo
|
||||
@@ -0,0 +1 @@
|
||||
+../foo
|
||||
\ No newline at end of file
|
||||
EOF
|
||||
|
||||
check 'patch -p1 < symlink-target.diff || echo "Status: $?"' <<EOF
|
||||
patching symbolic link dir/foo
|
||||
EOF
|
||||
|
||||
rm -f dir/foo
|
||||
cat > follow-symlink.diff <<EOF
|
||||
diff --git a/dir/foo b/dir/foo
|
||||
new file mode 120000
|
||||
index 0000000..cad2309
|
||||
--- /dev/null
|
||||
+++ b/dir/foo
|
||||
@@ -0,0 +1 @@
|
||||
+..
|
||||
\ No newline at end of file
|
||||
diff --git a/dir/foo/bar b/dir/foo/bar
|
||||
new file mode 100644
|
||||
index 0000000..2ab772d
|
||||
--- /dev/null
|
||||
+++ b/dir/foo/bar
|
||||
@@ -0,0 +1 @@
|
||||
+created in ..
|
||||
diff --git a/dir/bad b/dir/bad
|
||||
new file mode 120000
|
||||
index 0000000..cad2309
|
||||
--- /dev/null
|
||||
+++ b/dir/bad
|
||||
@@ -0,0 +1 @@
|
||||
+../..
|
||||
\ No newline at end of file
|
||||
diff --git a/dir/bad/baz b/dir/bad/baz
|
||||
new file mode 100644
|
||||
index 0000000..2ab772d
|
||||
--- /dev/null
|
||||
+++ b/dir/bad/baz
|
||||
@@ -0,0 +1 @@
|
||||
+created in ../..
|
||||
EOF
|
||||
|
||||
check 'patch -f -p1 < follow-symlink.diff || echo "Status: $?"' <<EOF
|
||||
patching symbolic link dir/foo
|
||||
patching file dir/foo/bar
|
||||
patching symbolic link dir/bad
|
||||
Invalid file name dir/bad/baz -- skipping patch
|
||||
Status: 1
|
||||
EOF
|
||||
|
||||
check 'cat bar' <<EOF
|
||||
created in ..
|
||||
EOF
|
||||
|
||||
rm -f bar
|
||||
|
||||
cat > bad-symlink-target1.diff <<EOF
|
||||
diff --git a/bar b/bar
|
||||
new file mode 120000
|
||||
index 0000000..cad2309
|
||||
--- /dev/null
|
||||
+++ b/bar
|
||||
@@ -0,0 +1 @@
|
||||
+/bar
|
||||
\ No newline at end of file
|
||||
EOF
|
||||
|
||||
check 'patch -p1 < bad-symlink-target1.diff || echo "Status: $?"' <<EOF
|
||||
patching symbolic link bar
|
||||
EOF
|
||||
|
||||
cat > bad-symlink-target2.diff <<EOF
|
||||
diff --git a/baz b/baz
|
||||
new file mode 120000
|
||||
index 0000000..cad2309
|
||||
--- /dev/null
|
||||
+++ b/baz
|
||||
@@ -0,0 +1 @@
|
||||
+../baz
|
||||
\ No newline at end of file
|
||||
EOF
|
||||
|
||||
check 'patch -p1 < bad-symlink-target2.diff || echo "Status: $?"' <<EOF
|
||||
patching symbolic link baz
|
||||
EOF
|
||||
|
||||
# --------------------------------------------------------------
|
||||
|
||||
# Absolute symlinks that point back into the working directory
|
||||
|
||||
mkdir d
|
||||
ln -s $PWD here
|
||||
ln -s $PWD/here/d here_d
|
||||
|
||||
cat > good-absolute.diff <<EOF
|
||||
--- /dev/null
|
||||
+++ here/d/foo
|
||||
@@ -0,0 +1 @@
|
||||
+foo
|
||||
--- /dev/null
|
||||
+++ here_d/bar
|
||||
@@ -0,0 +1 @@
|
||||
+bar
|
||||
EOF
|
||||
|
||||
check 'patch -p0 < good-absolute.diff' <<EOF
|
||||
patching file here/d/foo
|
||||
patching file here_d/bar
|
||||
EOF
|
||||
|
||||
rm -rf d
|
||||
|
||||
# --------------------------------------------------------------
|
||||
|
||||
# The backup file of a new symlink is an empty regular file.
|
||||
|
||||
check 'patch -p1 --backup < create-symlink.diff || echo "Status: $?"' <<EOF
|
||||
@ -181,3 +418,20 @@ check 'echo b > symlink.orig && cat target2' <<EOF
|
||||
b
|
||||
EOF
|
||||
rm -f target2
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# Make sure we do follow symlinks to patch files.
|
||||
|
||||
ncheck 'mkdir d'
|
||||
cat > d/ab.diff <<EOF
|
||||
--- /dev/null
|
||||
+++ b/foo
|
||||
@@ -0,0 +1 @@
|
||||
+foo
|
||||
EOF
|
||||
|
||||
ncheck 'ln -sf d l'
|
||||
|
||||
check 'patch -p1 -i l/ab.diff' <<EOF
|
||||
patching file foo
|
||||
EOF
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# Library for simple test scripts
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -7,14 +7,7 @@
|
||||
|
||||
# FIXME: Requires a version of diff that understands "-u".
|
||||
|
||||
require_cat() {
|
||||
if ! type cat > /dev/null 2> /dev/null; then
|
||||
echo "This test requires the cat utility" >&2
|
||||
exit 77
|
||||
fi
|
||||
}
|
||||
|
||||
require_gnu_diff() {
|
||||
_require_gnu_diff() {
|
||||
case "`diff --version 2> /dev/null`" in
|
||||
*GNU*)
|
||||
;;
|
||||
@ -24,9 +17,57 @@ require_gnu_diff() {
|
||||
esac
|
||||
}
|
||||
|
||||
require_sed() {
|
||||
if ! type sed > /dev/null 2> /dev/null; then
|
||||
echo "This test requires the sed utility" >&2
|
||||
_try_chmod() {
|
||||
chmod "$1" "$2" && test "`ls -l "$2" | cut -b2-10`" = "$3"
|
||||
}
|
||||
|
||||
_require_chmod() {
|
||||
tmp=`mktemp working-chmod.XXXXXXXX`
|
||||
if ! _try_chmod 644 "$tmp" "rw-r--r--" || \
|
||||
! _try_chmod 600 "$tmp" "rw-------"; then
|
||||
rm -f "$tmp"
|
||||
echo "This test requires chmod support" >&2
|
||||
exit 77
|
||||
fi
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
_require_hardlinks() {
|
||||
tmpdir=`mktemp -d hardlinks.XXXXXXXX`
|
||||
if ! touch "$tmpdir/f" ||
|
||||
! ln "$tmpdir/f" "$tmpdir/g"; then
|
||||
rm -rf "$tmpdir"
|
||||
echo "This test requires hardlink support" >&2
|
||||
exit 77
|
||||
fi
|
||||
rm -rf "$tmpdir"
|
||||
}
|
||||
|
||||
_require_symlinks() {
|
||||
tmpdir=`mktemp -d hardlinks.XXXXXXXX`
|
||||
if ! touch "$tmpdir/f" ||
|
||||
! ln -s "f" "$tmpdir/g"; then
|
||||
rm -rf "$tmpdir"
|
||||
echo "This test requires symlink support" >&2
|
||||
exit 77
|
||||
fi
|
||||
rm -rf "$tmpdir"
|
||||
}
|
||||
|
||||
_require_special_characters() {
|
||||
if ! tmp=`mktemp ' '.XXXXXXXX`; then
|
||||
echo "This test requires special character support in filenames" >&2
|
||||
exit 77
|
||||
fi
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
require() {
|
||||
utility="$1"
|
||||
if type _require_${utility} > /dev/null 2> /dev/null; then
|
||||
_require_${utility}
|
||||
elif ! type "${utility}" > /dev/null 2> /dev/null; then
|
||||
echo "This test requires the ${utility} utility" >&2
|
||||
exit 77
|
||||
fi
|
||||
}
|
||||
@ -45,7 +86,7 @@ use_local_patch() {
|
||||
|
||||
eval 'patch() {
|
||||
if test -n "$GDB" ; then
|
||||
echo -e "\n" >&3
|
||||
printf "\n\n" >&3
|
||||
gdbserver localhost:53153 $PATCH "$@" 2>&3
|
||||
else
|
||||
$PATCH "$@"
|
||||
@ -117,22 +158,15 @@ cleanup() {
|
||||
exit $status
|
||||
}
|
||||
|
||||
if test -z "`echo -n`"; then
|
||||
if eval 'test -n "${BASH_LINENO[0]}" 2>/dev/null'; then
|
||||
eval '
|
||||
_start_test() {
|
||||
echo -n "[${BASH_LINENO[2]}] $* -- "
|
||||
}'
|
||||
else
|
||||
eval '
|
||||
_start_test() {
|
||||
echo -n "* $* -- "
|
||||
}'
|
||||
fi
|
||||
if ( eval 'test -n "${BASH_LINENO[0]}"' 2>/dev/null ); then
|
||||
eval '
|
||||
_start_test() {
|
||||
printf "[${BASH_LINENO[2]}] %s -- " "$*"
|
||||
}'
|
||||
else
|
||||
eval '
|
||||
_start_test() {
|
||||
echo "* $*"
|
||||
printf "* %s -- " "$*"
|
||||
}'
|
||||
fi
|
||||
|
||||
@ -163,7 +197,7 @@ if ! type seq > /dev/null 2> /dev/null; then
|
||||
)}
|
||||
fi
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
clean_env
|
||||
|
||||
checks_succeeded=0
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc.
|
||||
# Copyright 2009-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
@ -6,7 +6,8 @@
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require_cat
|
||||
require cat
|
||||
require hardlinks
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
|
||||
45
tests/unusual-blanks
Normal file
45
tests/unusual-blanks
Normal file
@ -0,0 +1,45 @@
|
||||
# Copyright 2024-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# in any medium, are permitted without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
require cat
|
||||
use_local_patch
|
||||
use_tmpdir
|
||||
|
||||
# ==============================================================
|
||||
|
||||
# Patch missing the traditional "--- old\n+++ new\n" header
|
||||
|
||||
cat > test <<\EOF
|
||||
m
|
||||
n
|
||||
o
|
||||
EOF
|
||||
|
||||
cat > test.diff <<\EOF
|
||||
*** a/test Tue Sep 3 17:39:19 2024
|
||||
--- b/test Tue Sep 3 17:39:26 2024
|
||||
***************
|
||||
*** 1 , 3 ****
|
||||
m
|
||||
! n
|
||||
o
|
||||
--- 1 , 3 ----
|
||||
m
|
||||
! o
|
||||
o
|
||||
EOF
|
||||
|
||||
check 'patch -p1 -i test.diff' <<\EOF
|
||||
patching file test
|
||||
EOF
|
||||
|
||||
check 'cat test' <<\EOF
|
||||
m
|
||||
o
|
||||
o
|
||||
EOF
|
||||
Loading…
x
Reference in New Issue
Block a user