On 2026-09-01 01:47, Jim Meyering wrote:
Here's what I hope is a final snapshot before 1.15.
Some bad news and some good news. Darren Carreras recently reminded me of a
security bug in gzip he privately told me about on August 1, which I hadn't
gotten around to fixing. The good news is that I have a fix somewhere in the
attached patches. The bad news is that the fix is not simple and is combined
with fixes to other bugs that I discovered while fixing the security isssue.
Ordinarily I would just install this patch series, but if you want a new 1.15
release now I can wait until after 1.15 is published. Not every patch in this
series is essential to fixing gzip bugs, but I'd rather not spend a lot of time
to try to separate out just the essential bits.
From 462e9277fad07e4758a1ad6dcab82d2cfea3de3e Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Thu, 3 Sep 2026 13:09:09 -0700
Subject: [PATCH 01/14] gzip: fix flags used to open directories
* gzip.c (dfd): Now AT_FDCWD, not -1, when negative.
All uses changed.
(syncdfd): New static var.
(atdir_set): Return AT_FDCWD, not 1, when returning negative.
All uses changed. For dfd prefer O_PATH to O_SEARCH on GNU platforms,
as O_SEARCH incorrectly limits gzip to readable directories there.
Set syncdfd to a file descriptor opened with O_RDONLY,
as GNU platforms reject fdatasync with an O_PATH descriptor,
and even without the O_PATH change,
FreeBSD platforms reject fdatasync with an O_SEARCH descriptor.
(treat_file): Use syncdfd, not dfd, to sync directory.
---
NEWS | 6 ++++++
gzip.c | 30 +++++++++++++++++++++++-------
2 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/NEWS b/NEWS
index 4710307..6fe0821 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,12 @@ GNU gzip NEWS -*- outline -*-
no longer corrupted by the previous file's decoding table.
[bug present since the beginning]
+ gzip --synchronous no longer fails to synchronize unreadable parent
+ directories on platforms like GNU/Linux that have O_PATH, or to
+ synchronize any parent directories on platforms like FreeBSD that
+ have O_SEARCH but not O_PATH.
+ [bug introduced in gzip-1.7]
+
On old-fashioned or limited platforms lacking mktemp, gzexe, zdiff
and znew no longer have a race when creating a temporary file.
[bug present since the beginning]
diff --git a/gzip.c b/gzip.c
index a302c88..e003e2d 100644
--- a/gzip.c
+++ b/gzip.c
@@ -215,7 +215,8 @@ static char dfname[MAX_PATH_LEN]; /* name of dir containing output file */
static struct stat istat; /* status for input file */
int ifd; /* input file descriptor */
int ofd; /* output file descriptor */
-static int dfd = -1; /* output directory file descriptor */
+static int dfd = AT_FDCWD; /* output directory file descriptor */
+static int syncdfd = -1; /* likewise, but for --synchronous */
unsigned insize; /* valid bytes in inbuf */
unsigned inptr; /* index of next byte to be processed in inbuf */
unsigned outcnt; /* bytes in output buffer */
@@ -804,7 +805,8 @@ atdir_eq (char const *dir, ptrdiff_t dirlen)
/* Set the directory used for calls to openat etc. to be the directory
DIR, with length DIRLEN. DIR need not be null-terminated.
DIRLEN must be less than MAX_PATH_LEN. Return a file descriptor for
- the directory, or -1 if one could not be obtained. */
+ the directory, or AT_FDCWD if one could not be obtained or if it
+ is not needed. */
static int
atdir_set (char const *dir, ptrdiff_t dirlen)
{
@@ -818,13 +820,25 @@ atdir_set (char const *dir, ptrdiff_t dirlen)
if (try_opening_directories && ! atdir_eq (dir, dirlen))
{
- if (0 <= dfd)
+ if (0 <= syncdfd)
+ close (syncdfd);
+ if (0 <= dfd && dfd != syncdfd)
close (dfd);
if (dirlen == 0)
dir = &dot, dirlen = 1;
memcpy (dfname, dir, dirlen);
dfname[dirlen] = '\0';
- dfd = open (dfname, O_SEARCH | O_DIRECTORY);
+ syncdfd = synchronous ? open (dfname, O_RDONLY | O_DIRECTORY) : -1;
+ #if defined O_PATH && O_SEARCH == O_RDONLY
+ enum { search_flag = O_PATH };
+ #else
+ enum { search_flag = O_SEARCH };
+ #endif
+ dfd = (!synchronous || (search_flag != O_RDONLY && syncdfd < 0)
+ ? open (dfname, search_flag | O_DIRECTORY)
+ : syncdfd);
+ if (dfd < 0)
+ dfd = AT_FDCWD;
}
return dfd;
@@ -986,9 +1000,11 @@ treat_file (char *iname)
copy_stat (&istat);
if ((synchronous
- && ((0 <= dfd && fdatasync (dfd) != 0 && errno != EINVAL)
- || (fsync (ofd) != 0 && errno != EINVAL)))
- || close (ofd) != 0)
+ && ((0 <= syncdfd && fdatasync (syncdfd) < 0
+ && ((errno != EINVAL && errno != EBADF)
+ || (fsync (syncdfd) < 0 && errno != EINVAL)))
+ || (fsync (ofd) < 0 && errno != EINVAL)))
+ || close (ofd) < 0)
write_error ();
if (!keep)
--
2.55.0
From 7938d450b00c3ec59a3712a35c3d53ba69c08d7f Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Thu, 3 Sep 2026 23:07:46 -0700
Subject: [PATCH 02/14] build: update gnulib submodule to latest
---
gnulib | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gnulib b/gnulib
index 7bf0471..331c8d0 160000
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit 7bf0471db6b2e1011de49d42c1786c0e63ffc010
+Subproject commit 331c8d065a8a753de71f084f068473ccd5e4c34a
--
2.55.0
From 66b229015298398e701ee44e711bd41fbf3ffdfe Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Thu, 3 Sep 2026 23:32:03 -0700
Subject: [PATCH 03/14] maint: prefer stdopen to *-safer
This should simplify future maintenance.
* bootstrap.conf (gnulib_modules): Replace fcntl-safer,
openat-safer, unistd-safer with fcntl-h, openat, unistd-h.
Add stdopen.
* gzip.c: Include <stdopen.h>, <fcntl.h> instead of <fcntl--.h>.
(main): Call stdopen as soon as practical.
---
bootstrap.conf | 7 ++++---
gzip.c | 11 ++++++++++-
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/bootstrap.conf b/bootstrap.conf
index ed46279..fc0e8b2 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -27,7 +27,7 @@ crc-x86_64
dirname-lgpl
fclose
fcntl
-fcntl-safer
+fcntl-h
fdatasync
fdopendir
filename
@@ -49,7 +49,7 @@ lstat
maintainer-makefile
malloc-gnu
manywarnings
-openat-safer
+openat
quotearg
readme-release
realloc-posix
@@ -58,10 +58,11 @@ sigaction
sigprocmask
stat-time
stdcountof-h
+stdopen
strerror
sys_stat-h
time
-unistd-safer
+unistd-h
unlinkat
unlocked-io
update-copyright
diff --git a/gzip.c b/gzip.c
index e003e2d..38bed6c 100644
--- a/gzip.c
+++ b/gzip.c
@@ -64,16 +64,17 @@ static char const license_msg[] =
#include "version.h"
#include <dirname.h>
-#include <fcntl--.h>
#include <filename.h>
#include <ignore-value.h>
#include <intprops.h>
#include <stat-time.h>
+#include <stdopen.h>
#include <timespec.h>
#include <xalloc.h>
#include <yesno.h>
#include <errno.h>
+#include <fcntl.h>
#include <getopt.h>
#include <inttypes.h>
#include <limits.h>
@@ -617,6 +618,14 @@ int main (int argc, char **argv)
ALLOC(ush, tab_prefix1, 1L<<(BITS-1));
#endif
+ int stdopen_err = stdopen ();
+ if (stdopen_err)
+ {
+ fprintf (stdout, "%s: standard file descriptors: %s\n",
+ program_name, strerror (stdopen_err));
+ do_exit (ERROR);
+ }
+
/* And get to work */
if (file_count != 0) {
if (to_stdout && !test && (!decompress || !ascii)) {
--
2.55.0
From 6ab17e9e4863d9f4bd679ba60428614a6e741db7 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Thu, 3 Sep 2026 23:58:51 -0700
Subject: [PATCH 04/14] build: avoid openat, unlinkat modules
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Instead of using Gnulib’s openat and unlinkat modules,
simplify gzip by not call8ing the functions if the
operating system does not have them natively.
This simplifies gzip and shrinks its attack surface.
* bootstrap.conf (gnulib_modules): Remove openat, unlinkat.
* configure.ac: Check for openat, unlinkat.
* gzip.c (TRY_OPENING_DIRECTORIES): New macro,
taken from atdir_set body.
(gzip_openat, gzip_unlinkat, openat, unlinkat)
[!TRY_OPENING_DIRECTORIES]: New functions and macros, that ignore
the directory file descriptor and flags. This simplifies later code.
(atdir_set): Use TRY_OPENING_DIRECTORIES instead.
(open_and_stat): Pass 0 mode to openat, in case
TRY_OPENING_DIRECTORIEs is in use.
---
bootstrap.conf | 2 --
configure.ac | 2 +-
gzip.c | 40 ++++++++++++++++++++++++++++++----------
3 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/bootstrap.conf b/bootstrap.conf
index fc0e8b2..cba3d7e 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -49,7 +49,6 @@ lstat
maintainer-makefile
malloc-gnu
manywarnings
-openat
quotearg
readme-release
realloc-posix
@@ -63,7 +62,6 @@ strerror
sys_stat-h
time
unistd-h
-unlinkat
unlocked-io
update-copyright
utimens
diff --git a/configure.ac b/configure.ac
index e6b0e8f..8c5161c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -314,7 +314,7 @@ AM_CONDITIONAL([ZGREP_IS_TRANSFORMED], [test "$ZGREP_TRANSFORMED" != zgrep])
AC_C_CONST
AC_CHECK_HEADERS_ONCE(fcntl.h limits.h memory.h time.h sys/sdt.h)
-AC_CHECK_FUNCS_ONCE([chown fchmod fchown lstat siginterrupt])
+AC_CHECK_FUNCS_ONCE([chown fchmod fchown lstat openat siginterrupt unlinkat])
AC_HEADER_DIRENT
AC_TYPE_SIZE_T
AC_TYPE_OFF_T
diff --git a/gzip.c b/gzip.c
index 38bed6c..fc4b299 100644
--- a/gzip.c
+++ b/gzip.c
@@ -115,6 +115,34 @@ static char const license_msg[] =
# define HAVE_WORKING_O_NOFOLLOW 0
#endif
+/* Don't bother opening directories on older systems that
+ lack openat etc. It's not worth the porting hassle. */
+#if HAVE_OPENAT && HAVE_UNLINKAT
+# define TRY_OPENING_DIRECTORIES true
+#else
+# define TRY_OPENING_DIRECTORIES false
+#endif
+
+#if !TRY_OPENING_DIRECTORIES
+static int
+gzip_openat (_GL_ATTRIBUTE_MAYBE_UNUSED int fd,
+ char const *file, int flags, mode_t mode)
+{
+ return open (file, flags, mode);
+}
+static int
+gzip_unlinkat (_GL_ATTRIBUTE_MAYBE_UNUSED int fd,
+ char const *file,
+ _GL_ATTRIBUTE_MAYBE_UNUSED int flags)
+{
+ return unlink (file);
+}
+# undef openat
+# define openat gzip_openat
+# undef unlinkat
+# define unlinkat gzip_unlinkat
+#endif
+
/* Separator for file name parts (see shorten_name()) */
#ifdef NO_MULTIPLE_DOTS
# define PART_SEP "-"
@@ -819,15 +847,7 @@ atdir_eq (char const *dir, ptrdiff_t dirlen)
static int
atdir_set (char const *dir, ptrdiff_t dirlen)
{
- /* Don't bother opening directories on older systems that
- lack openat and unlinkat. It's not worth the porting hassle. */
- #if HAVE_OPENAT && HAVE_UNLINKAT
- enum { try_opening_directories = true };
- #else
- enum { try_opening_directories = false };
- #endif
-
- if (try_opening_directories && ! atdir_eq (dir, dirlen))
+ if (TRY_OPENING_DIRECTORIES && ! atdir_eq (dir, dirlen))
{
if (0 <= syncdfd)
close (syncdfd);
@@ -1253,7 +1273,7 @@ open_and_stat (char *name, int flags, struct stat *st)
}
}
- fd = openat (atfd, base, flags);
+ fd = openat (atfd, base, flags, 0);
if (0 <= fd && fstat (fd, st) != 0)
{
int e = errno;
--
2.55.0
From 8daa649ddabea2127040980257a03376b98ea6fb Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Fri, 4 Sep 2026 07:41:11 -0700
Subject: [PATCH 05/14] build: avoid fdopendir module
This further simplifies gzip and shrinks attack surface
on older platforms. gzip no longer needs the old code
to save and restore working directories.
Reverts some of commit b5f88a3a283655adfc6c03fcb61031367e6d6d88
dated 2009-11-19 13:59:11 +0100.
* bootstrap.conf (gnulib_modules): Remove fdopendir.
* configure.ac: Check for fdopendir and opendir.
* gzip.c (NO_DIR): Default to (!HAVE_FDOPENDIR && !HAVE_OPENDIR).
(treat_dir) [!NO_DIR && !HAVE_FDOPENDIR]: Fall back on opendir.
---
bootstrap.conf | 1 -
configure.ac | 3 ++-
gzip.c | 9 ++++++++-
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/bootstrap.conf b/bootstrap.conf
index cba3d7e..0c3792d 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -29,7 +29,6 @@ fclose
fcntl
fcntl-h
fdatasync
-fdopendir
filename
fsync
getopt-gnu
diff --git a/configure.ac b/configure.ac
index 8c5161c..fd7edb9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -314,7 +314,8 @@ AM_CONDITIONAL([ZGREP_IS_TRANSFORMED], [test "$ZGREP_TRANSFORMED" != zgrep])
AC_C_CONST
AC_CHECK_HEADERS_ONCE(fcntl.h limits.h memory.h time.h sys/sdt.h)
-AC_CHECK_FUNCS_ONCE([chown fchmod fchown lstat openat siginterrupt unlinkat])
+AC_CHECK_FUNCS_ONCE(
+ [chown fchmod fchown fdopendir lstat openat opendir siginterrupt unlinkat])
AC_HEADER_DIRENT
AC_TYPE_SIZE_T
AC_TYPE_OFF_T
diff --git a/gzip.c b/gzip.c
index fc4b299..b54b98a 100644
--- a/gzip.c
+++ b/gzip.c
@@ -88,7 +88,7 @@ static char const license_msg[] =
#include <unistd.h>
#ifndef NO_DIR
-# define NO_DIR 0
+# define NO_DIR (!HAVE_FDOPENDIR && !HAVE_OPENDIR)
#endif
#if !NO_DIR
# include <dirent.h>
@@ -1993,11 +1993,18 @@ treat_dir (int fd, char *dir)
char const *entry;
size_t entrylen;
+# if HAVE_FDOPENDIR
dirp = fdopendir (fd);
+# else
+ close (fd);
+ dirp = opendir (dir);
+# endif
if (dirp == NULL) {
progerror(dir);
+# if HAVE_FDOPENDIR
close (fd);
+# endif
return ;
}
--
2.55.0
From 726990d012603aca01a6034b5661636c42b6ba39 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Fri, 4 Sep 2026 08:35:17 -0700
Subject: [PATCH 06/14] gzip: refactor unlink calls
This should simplify future improvements.
* configure.ac: Check for fchmodat.
* gzip.c (TRY_OPENING_DIRECTORIES) [UNLINK_READONLY_BUG]:
Now false instead of true.
(gzip_unlinkat, unlinkat): Remove.
All callers changed to use xunlinkat.
* util.c (xunlinkat): New function, replacing xunlink.
All callers changed.
---
gzip.c | 19 +++++--------------
gzip.h | 2 +-
util.c | 6 +++++-
3 files changed, 11 insertions(+), 16 deletions(-)
diff --git a/gzip.c b/gzip.c
index b54b98a..9851b84 100644
--- a/gzip.c
+++ b/gzip.c
@@ -117,7 +117,7 @@ static char const license_msg[] =
/* Don't bother opening directories on older systems that
lack openat etc. It's not worth the porting hassle. */
-#if HAVE_OPENAT && HAVE_UNLINKAT
+#if HAVE_OPENAT && HAVE_UNLINKAT && !defined UNLINK_READONLY_BUG
# define TRY_OPENING_DIRECTORIES true
#else
# define TRY_OPENING_DIRECTORIES false
@@ -130,17 +130,8 @@ gzip_openat (_GL_ATTRIBUTE_MAYBE_UNUSED int fd,
{
return open (file, flags, mode);
}
-static int
-gzip_unlinkat (_GL_ATTRIBUTE_MAYBE_UNUSED int fd,
- char const *file,
- _GL_ATTRIBUTE_MAYBE_UNUSED int flags)
-{
- return unlink (file);
-}
# undef openat
# define openat gzip_openat
-# undef unlinkat
-# define unlinkat gzip_unlinkat
#endif
/* Separator for file name parts (see shorten_name()) */
@@ -1041,12 +1032,12 @@ treat_file (char *iname)
sigset_t oldset;
int unlink_errno;
char *ifbase = last_component (ifname);
- int ufd = atdir_eq (ifname, ifbase - ifname) ? dfd : -1;
+ int ufd = atdir_eq (ifname, ifbase - ifname) ? dfd : AT_FDCWD;
int res;
sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
remove_ofname_fd = -1;
- res = ufd < 0 ? xunlink (ifname) : unlinkat (ufd, ifbase, 0);
+ res = xunlinkat (ufd, ufd < 0 ? ifname : ifbase);
unlink_errno = res == 0 ? 0 : errno;
sigprocmask (SIG_SETMASK, &oldset, NULL);
@@ -1901,7 +1892,7 @@ check_ofname ()
return ERROR;
}
}
- if (xunlink (ofname)) {
+ if (xunlinkat (AT_FDCWD, ofname) < 0) {
progerror(ofname);
return ERROR;
}
@@ -2121,7 +2112,7 @@ remove_output_file (bool signals_already_blocked)
remove_ofname_fd = -1;
close (fd);
volatile_strcpy (fname, remove_ofname);
- xunlink (fname);
+ xunlinkat (AT_FDCWD, fname);
}
if (!signals_already_blocked)
sigprocmask (SIG_SETMASK, &oldset, NULL);
diff --git a/gzip.h b/gzip.h
index 6689da1..583af21 100644
--- a/gzip.h
+++ b/gzip.h
@@ -310,7 +310,7 @@ extern void write_buf (int fd, voidp buf, unsigned cnt);
extern int read_buffer (int fd, voidp buf, unsigned int cnt);
extern char *strlwr (char *s);
extern char *gzip_base_name (char *fname) _GL_ATTRIBUTE_PURE;
-extern int xunlink (char *fname);
+extern int xunlinkat (int fd, char const *name);
extern void make_simple_name (char *name);
extern char *add_envopt (int *argcp, char ***argvp, char const *env);
_Noreturn extern void gzip_error (char const *m);
diff --git a/util.c b/util.c
index eca9fbe..b4e8e26 100644
--- a/util.c
+++ b/util.c
@@ -257,9 +257,13 @@ gzip_base_name (char *fname)
* Unlink a file, working around the unlink readonly bug (if present).
*/
int
-xunlink (char *filename)
+xunlinkat (_GL_ATTRIBUTE_MAYBE_UNUSED int fd, char const *filename)
{
+#if HAVE_UNLINKAT
+ int r = unlinkat (fd, filename, 0);
+#else
int r = unlink (filename);
+#endif
#ifdef UNLINK_READONLY_BUG
if (r != 0)
--
2.55.0
From 1d60de8386b9eb36056f852469a0fd86f8852c6d Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Fri, 4 Sep 2026 23:20:32 -0700
Subject: [PATCH 07/14] * THANKS: Sort.
---
THANKS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/THANKS b/THANKS
index dac5ae8..b70027f 100644
--- a/THANKS
+++ b/THANKS
@@ -81,7 +81,6 @@ John Eaton [email protected]
Will Edgington [email protected]
Brian Edmonds [email protected]
Paul Eggert [email protected]
-Elias Hasas [email protected]
Enami [email protected]
Kristoffer Eriksson [email protected]
Daniel Eriksson [email protected]
@@ -113,6 +112,7 @@ Junio Hamano [email protected]
Harald Hanche-Olsen [email protected]
Darrel R. Hankerson [email protected]
Mark Hanning-Lee [email protected]
+Elias Hasas [email protected]
Lars Hecking [email protected]
Aki Helin [email protected]
Rüdiger Helsch [email protected]
--
2.55.0
From b8db4342c6d5ac0b1f04793ef607e0165008f137 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Fri, 4 Sep 2026 08:58:26 -0700
Subject: [PATCH 08/14] gzip: use relative unlinkat
* gzip.c (treat_file): Simplify and pull name calculation out of
critical section. No need to call atdir_eq here
(check_ofname, remove_output_file): Unlink relative to dfd
if dfd is nonnegative.
---
NEWS | 4 ++++
THANKS | 1 +
gzip.c | 11 ++++-------
3 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/NEWS b/NEWS
index 6fe0821..e6fce60 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,10 @@ GNU gzip NEWS -*- outline -*-
** Bug fixes
+ gzip no longer can mistakenly remove the wrong file if some other
+ process simultaneously renames a gzip destination's ancestor.
+ [bug present since the beginning]
+
gzip -d no longer rejects PKZIP signatures, local header, and data
descriptors. These can appear in well-formed streamed zip files.
[bug present since the beginning]
diff --git a/THANKS b/THANKS
index b70027f..c2ebeab 100644
--- a/THANKS
+++ b/THANKS
@@ -48,6 +48,7 @@ Roger Butenuth [email protected]
Rodrigo Campos [email protected]
Jon Cargille [email protected]
Bud Carlson [email protected]
+Darren Carreras [email protected]
Lim Fung Chai [email protected]
Wes Chalfant [email protected]
Andrew A. Chernov [email protected]
diff --git a/gzip.c b/gzip.c
index 9851b84..abf3e56 100644
--- a/gzip.c
+++ b/gzip.c
@@ -1031,14 +1031,11 @@ treat_file (char *iname)
{
sigset_t oldset;
int unlink_errno;
- char *ifbase = last_component (ifname);
- int ufd = atdir_eq (ifname, ifbase - ifname) ? dfd : AT_FDCWD;
- int res;
+ char *ifbase = dfd < 0 ? ifname : last_component (ifname);
sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
remove_ofname_fd = -1;
- res = xunlinkat (ufd, ufd < 0 ? ifname : ifbase);
- unlink_errno = res == 0 ? 0 : errno;
+ unlink_errno = xunlinkat (dfd, ifbase) < 0 ? errno : 0;
sigprocmask (SIG_SETMASK, &oldset, NULL);
if (unlink_errno)
@@ -1892,7 +1889,7 @@ check_ofname ()
return ERROR;
}
}
- if (xunlinkat (AT_FDCWD, ofname) < 0) {
+ if (xunlinkat (dfd, dfd < 0 ? ofname : last_component (ofname)) < 0) {
progerror(ofname);
return ERROR;
}
@@ -2112,7 +2109,7 @@ remove_output_file (bool signals_already_blocked)
remove_ofname_fd = -1;
close (fd);
volatile_strcpy (fname, remove_ofname);
- xunlinkat (AT_FDCWD, fname);
+ xunlinkat (dfd, dfd < 0 ? fname : last_component (fname));
}
if (!signals_already_blocked)
sigprocmask (SIG_SETMASK, &oldset, NULL);
--
2.55.0
From 0a481c578d51cff16cb29d78ee4026b3b1d82ff2 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Fri, 4 Sep 2026 09:38:17 -0700
Subject: [PATCH 09/14] gzip: shrink critical section
* gzip.c (remove_output_file): Move non-critical code
out of the critical section.
---
gzip.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/gzip.c b/gzip.c
index abf3e56..bda7b1e 100644
--- a/gzip.c
+++ b/gzip.c
@@ -2098,21 +2098,22 @@ static void
remove_output_file (bool signals_already_blocked)
{
int fd;
- sigset_t oldset;
- if (!signals_already_blocked)
- sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
fd = remove_ofname_fd;
if (0 <= fd)
{
char fname[MAX_PATH_LEN];
+ volatile_strcpy (fname, remove_ofname);
+ char *base = dfd < 0 ? fname : last_component (fname);
+ sigset_t oldset;
+ if (!signals_already_blocked)
+ sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
remove_ofname_fd = -1;
close (fd);
- volatile_strcpy (fname, remove_ofname);
- xunlinkat (dfd, dfd < 0 ? fname : last_component (fname));
+ xunlinkat (dfd, base);
+ if (!signals_already_blocked)
+ sigprocmask (SIG_SETMASK, &oldset, NULL);
}
- if (!signals_already_blocked)
- sigprocmask (SIG_SETMASK, &oldset, NULL);
}
/* ========================================================================
--
2.55.0
From bfaf51df5cc266d5b4a6695b22db7337cd7af6bd Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Fri, 4 Sep 2026 09:54:02 -0700
Subject: [PATCH 10/14] gzip: fix race in attacker-controlled directory
Do not let an attacker cause you to remove a victim file
merely because they can control an ancestor directory.
* gzip.c (remove_ofname_dfd): New var.
(atdir_set): Do not open directories if sending to stdout,
as we are not destructive in this case.
(create_outfile, open_and_stat): Use atdir_set even if KEEP, as we
need it for the output file now.
(create_outfile): Save atfd and base, not ofname.
(remove_output_file): Use remove_ofname_dfd, not dfd,
because dfd is not volatile and so is unsafe in a signal handler.
---
gzip.c | 43 +++++++++++++++----------------------------
1 file changed, 15 insertions(+), 28 deletions(-)
diff --git a/gzip.c b/gzip.c
index bda7b1e..1cbfe19 100644
--- a/gzip.c
+++ b/gzip.c
@@ -218,9 +218,10 @@ struct timespec time_stamp;
/* The set of signals that are caught. */
static sigset_t caught_signals;
-/* If nonnegative, close this file descriptor and unlink remove_ofname
- on error. */
+/* If remove_ofname_fd is nonnegative, close it and call
+ unlinkat (remove_ofname_dfd, remove_ofname, 0) on error. */
static int volatile remove_ofname_fd = -1;
+static int volatile remove_ofname_dfd = AT_FDCWD;
static char volatile remove_ofname[MAX_PATH_LEN];
static bool stdin_was_read;
@@ -838,7 +839,7 @@ atdir_eq (char const *dir, ptrdiff_t dirlen)
static int
atdir_set (char const *dir, ptrdiff_t dirlen)
{
- if (TRY_OPENING_DIRECTORIES && ! atdir_eq (dir, dirlen))
+ if (TRY_OPENING_DIRECTORIES && !to_stdout && !atdir_eq (dir, dirlen))
{
if (0 <= syncdfd)
close (syncdfd);
@@ -1090,18 +1091,11 @@ create_outfile ()
int flags = (O_WRONLY | O_CREAT | O_EXCL
| (ascii && decompress ? 0 : O_BINARY));
char const *base = ofname;
- int atfd = AT_FDCWD;
- if (!keep)
- {
- char const *b = last_component (ofname);
- int f = atdir_set (ofname, b - ofname);
- if (0 <= f)
- {
- base = b;
- atfd = f;
- }
- }
+ char const *ofbase = last_component (ofname);
+ int atfd = atdir_set (ofname, ofbase - ofname);
+ if (0 <= atfd)
+ base = ofbase;
if (!signal_handlers_installed)
{
@@ -1114,7 +1108,8 @@ create_outfile ()
int open_errno;
sigset_t oldset;
- volatile_strcpy (remove_ofname, ofname);
+ remove_ofname_dfd = atfd;
+ volatile_strcpy (remove_ofname, base);
sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
remove_ofname_fd = ofd = openat (atfd, base, flags, S_IRUSR | S_IWUSR);
@@ -1228,7 +1223,6 @@ static int
open_and_stat (char *name, int flags, struct stat *st)
{
int fd;
- int atfd = AT_FDCWD;
char const *base = name;
/* Refuse to follow symbolic links unless -c or -f. */
@@ -1250,16 +1244,10 @@ open_and_stat (char *name, int flags, struct stat *st)
}
}
- if (!keep)
- {
- char const *b = last_component (name);
- int f = atdir_set (name, b - name);
- if (0 <= f)
- {
- base = b;
- atfd = f;
- }
- }
+ char const *namebase = last_component (name);
+ int atfd = atdir_set (name, namebase - name);
+ if (0 <= atfd)
+ base = namebase;
fd = openat (atfd, base, flags, 0);
if (0 <= fd && fstat (fd, st) != 0)
@@ -2104,13 +2092,12 @@ remove_output_file (bool signals_already_blocked)
{
char fname[MAX_PATH_LEN];
volatile_strcpy (fname, remove_ofname);
- char *base = dfd < 0 ? fname : last_component (fname);
sigset_t oldset;
if (!signals_already_blocked)
sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
remove_ofname_fd = -1;
close (fd);
- xunlinkat (dfd, base);
+ xunlinkat (remove_ofname_dfd, fname);
if (!signals_already_blocked)
sigprocmask (SIG_SETMASK, &oldset, NULL);
}
--
2.55.0
From 343a617e614166b5edc61c754a7d39e0fd66ce14 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Fri, 4 Sep 2026 14:30:58 -0700
Subject: [PATCH 11/14] gzip: be more cautious about using AT_FDCWD
Without this change, gzip was more vulnerables to attackers
changing the directory hierarchy while gzip walks through it.
* gzip.c (ATDIR_SET_ERROR): New constant.
(atdir_set): Return it on failure, so that callers can distinguish
failure from AT_FDCWD. All uses changed. Do not update the cache
if the new call fails.
(create_outfile, open_and_stat): Report directory failures
instead of silently ignoring them and falling back on AT_FDCWD.
---
gzip.c | 75 +++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 51 insertions(+), 24 deletions(-)
diff --git a/gzip.c b/gzip.c
index 1cbfe19..d3187d3 100644
--- a/gzip.c
+++ b/gzip.c
@@ -831,38 +831,57 @@ atdir_eq (char const *dir, ptrdiff_t dirlen)
return memcmp (dfname, dir, dirlen) == 0 && !dfname[dirlen];
}
+enum { ATDIR_SET_ERROR = -1 - (AT_FDCWD == -1) };
+
/* Set the directory used for calls to openat etc. to be the directory
DIR, with length DIRLEN. DIR need not be null-terminated.
- DIRLEN must be less than MAX_PATH_LEN. Return a file descriptor for
- the directory, or AT_FDCWD if one could not be obtained or if it
- is not needed. */
+ DIRLEN must be less than MAX_PATH_LEN. Return AT_FDCWD if that
+ suffices, otherwise a file descriptor for the directory,
+ or ATDIR_SET_ERR if the fd could not be obtained. */
static int
atdir_set (char const *dir, ptrdiff_t dirlen)
{
- if (TRY_OPENING_DIRECTORIES && !to_stdout && !atdir_eq (dir, dirlen))
+ if (!TRY_OPENING_DIRECTORIES || to_stdout || atdir_eq (dir, dirlen))
+ return dfd;
+
+ int new_dfd = 0;
+ if (dirlen == 0)
+ dir = &dot, dirlen = 1, new_dfd = AT_FDCWD;
+ char dirbuf[sizeof dfname];
+ memcpy (dirbuf, dir, dirlen);
+ dirbuf[dirlen] = '\0';
+
+ int new_syncdfd = synchronous ? open (dirbuf, O_RDONLY | O_DIRECTORY) : -1;
+ if (synchronous && new_syncdfd < 0)
+ return ATDIR_SET_ERROR;
+
+ if (!new_dfd)
{
- if (0 <= syncdfd)
- close (syncdfd);
- if (0 <= dfd && dfd != syncdfd)
- close (dfd);
- if (dirlen == 0)
- dir = &dot, dirlen = 1;
- memcpy (dfname, dir, dirlen);
- dfname[dirlen] = '\0';
- syncdfd = synchronous ? open (dfname, O_RDONLY | O_DIRECTORY) : -1;
- #if defined O_PATH && O_SEARCH == O_RDONLY
- enum { search_flag = O_PATH };
- #else
- enum { search_flag = O_SEARCH };
- #endif
- dfd = (!synchronous || (search_flag != O_RDONLY && syncdfd < 0)
- ? open (dfname, search_flag | O_DIRECTORY)
- : syncdfd);
- if (dfd < 0)
- dfd = AT_FDCWD;
+ if (0 <= new_syncdfd)
+ new_dfd = new_syncdfd;
+ else
+ {
+ #if defined O_PATH && O_SEARCH == O_RDONLY
+ enum { search_flag = O_PATH };
+ #else
+ enum { search_flag = O_SEARCH };
+ #endif
+ new_dfd = open (dirbuf, search_flag | O_DIRECTORY);
+ if (new_dfd < 0)
+ return ATDIR_SET_ERROR;
+ }
}
- return dfd;
+ if (0 <= syncdfd)
+ close (syncdfd);
+ if (0 <= dfd && dfd != syncdfd)
+ close (dfd);
+
+ memcpy (dfname, dirbuf, dirlen + 1);
+ syncdfd = new_syncdfd;
+ dfd = new_dfd;
+
+ return new_dfd;
}
/* ========================================================================
@@ -1096,6 +1115,12 @@ create_outfile ()
int atfd = atdir_set (ofname, ofbase - ofname);
if (0 <= atfd)
base = ofbase;
+ else if (atfd == ATDIR_SET_ERROR)
+ {
+ fprintf(stderr, "%s: %.*s: %s\n", program_name,
+ (int) {ofbase - ofname}, ofname, strerror (errno));
+ return ERROR;
+ }
if (!signal_handlers_installed)
{
@@ -1248,6 +1273,8 @@ open_and_stat (char *name, int flags, struct stat *st)
int atfd = atdir_set (name, namebase - name);
if (0 <= atfd)
base = namebase;
+ else if (atfd == ATDIR_SET_ERROR)
+ return -1;
fd = openat (atfd, base, flags, 0);
if (0 <= fd && fstat (fd, st) != 0)
--
2.55.0
From 9d66e08c0733a428dc632b6a9ca11c7adb0dc4b3 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Fri, 4 Sep 2026 16:40:36 -0700
Subject: [PATCH 12/14] =?UTF-8?q?gzip:=20don=E2=80=99t=20open=20same=20dir?=
=?UTF-8?q?=20twice=20when=20recursive?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Opening it multiple times can lead to races.
* gzip.c (treat_file, create_outfile, open_and_stat, open_input_file):
New arg parentfd. All uses changed. If nonnegative, treat it as
the parent directory file descriptor, instead of dfd or syncdfd.
(check_ofname): New arg atfd. All uses changed.
(treat_dir): Do not close fd until after processing subsidiaries.
Instead, pass it as the parent fd to subroutines.
Report any streamsavedir failure.
---
gzip.c | 76 +++++++++++++++++++++++++++++++---------------------------
1 file changed, 41 insertions(+), 35 deletions(-)
diff --git a/gzip.c b/gzip.c
index d3187d3..4f33ccc 100644
--- a/gzip.c
+++ b/gzip.c
@@ -318,16 +318,16 @@ static void license (void);
static void version (void);
static int input_eof (void);
static void treat_stdin (void);
-static void treat_file (char *iname);
-static int create_outfile (void);
+static void treat_file (int parentfd, char *iname);
+static int create_outfile (int parentfd);
static char *get_suffix (char *name);
-static int open_input_file (char *iname, struct stat *sbuf);
+static int open_input_file (int parentfd, char *iname, struct stat *sbuf);
static void discard_input_bytes (size_t nbytes, unsigned int flags);
static int make_ofname (void);
static void shorten_name (char *name);
static int get_method (int in, bool first);
static void do_list (int method);
-static int check_ofname (void);
+static int check_ofname (int parentfd);
static void copy_stat (struct stat *ifstat);
static void install_signal_handlers (void);
static void remove_output_file (bool);
@@ -652,7 +652,7 @@ int main (int argc, char **argv)
SET_BINARY_MODE (STDOUT_FILENO);
}
while (optind < argc) {
- treat_file(argv[optind++]);
+ treat_file(-1, argv[optind++]);
}
} else { /* Standard input */
treat_stdin();
@@ -888,7 +888,7 @@ atdir_set (char const *dir, ptrdiff_t dirlen)
* Compress or decompress the given file
*/
static void
-treat_file (char *iname)
+treat_file (int parentfd, char *iname)
{
/* Accept "-" as synonym for stdin */
if (strequ(iname, "-")) {
@@ -899,7 +899,7 @@ treat_file (char *iname)
}
/* Check if the input file is present, set ifname and istat: */
- ifd = open_input_file (iname, &istat);
+ ifd = open_input_file (parentfd, iname, &istat);
if (ifd < 0)
return;
@@ -997,7 +997,8 @@ treat_file (char *iname)
ofd = STDOUT_FILENO;
/* Keep remove_ofname_fd negative. */
} else {
- if (create_outfile() != OK) return;
+ if (create_outfile (parentfd) != OK)
+ return;
if (!decompress && save_orig_name && !verbose && !quiet) {
fprintf(stderr, "%s: %s compressed to %s\n",
@@ -1039,10 +1040,12 @@ treat_file (char *iname)
{
copy_stat (&istat);
+ int sfd = parentfd < 0 ? syncdfd : parentfd;
+
if ((synchronous
- && ((0 <= syncdfd && fdatasync (syncdfd) < 0
+ && ((0 <= sfd && fdatasync (sfd) < 0
&& ((errno != EINVAL && errno != EBADF)
- || (fsync (syncdfd) < 0 && errno != EINVAL)))
+ || (fsync (sfd) < 0 && errno != EINVAL)))
|| (fsync (ofd) < 0 && errno != EINVAL)))
|| close (ofd) < 0)
write_error ();
@@ -1051,11 +1054,12 @@ treat_file (char *iname)
{
sigset_t oldset;
int unlink_errno;
- char *ifbase = dfd < 0 ? ifname : last_component (ifname);
+ int atfd = parentfd < 0 ? dfd : parentfd;
+ char *ifbase = atfd < 0 ? ifname : last_component (ifname);
sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
remove_ofname_fd = -1;
- unlink_errno = xunlinkat (dfd, ifbase) < 0 ? errno : 0;
+ unlink_errno = xunlinkat (atfd, ifbase) < 0 ? errno : 0;
sigprocmask (SIG_SETMASK, &oldset, NULL);
if (unlink_errno)
@@ -1103,7 +1107,7 @@ volatile_strcpy (char volatile *dst, char const volatile *src)
* OUT assertions: ifd and ofd are closed in case of error.
*/
static int
-create_outfile ()
+create_outfile (int parentfd)
{
static bool signal_handlers_installed;
int name_shortened = 0;
@@ -1112,7 +1116,7 @@ create_outfile ()
char const *base = ofname;
char const *ofbase = last_component (ofname);
- int atfd = atdir_set (ofname, ofbase - ofname);
+ int atfd = parentfd < 0 ? atdir_set (ofname, ofbase - ofname) : parentfd;
if (0 <= atfd)
base = ofbase;
else if (atfd == ATDIR_SET_ERROR)
@@ -1154,7 +1158,7 @@ create_outfile ()
#endif
case EEXIST:
- if (check_ofname () != OK)
+ if (check_ofname (atfd) != OK)
{
close (ifd);
return ERROR;
@@ -1245,7 +1249,7 @@ get_suffix (char *name)
into *ST. Return a file descriptor to the newly opened file, or -1
(setting errno) on failure. */
static int
-open_and_stat (char *name, int flags, struct stat *st)
+open_and_stat (int parentfd, char *name, int flags, struct stat *st)
{
int fd;
char const *base = name;
@@ -1270,7 +1274,7 @@ open_and_stat (char *name, int flags, struct stat *st)
}
char const *namebase = last_component (name);
- int atfd = atdir_set (name, namebase - name);
+ int atfd = parentfd < 0 ? atdir_set (name, namebase - name) : parentfd;
if (0 <= atfd)
base = namebase;
else if (atfd == ATDIR_SET_ERROR)
@@ -1296,7 +1300,7 @@ open_and_stat (char *name, int flags, struct stat *st)
* Return an open file descriptor or -1.
*/
static int
-open_input_file (char *iname, struct stat *sbuf)
+open_input_file (int parentfd, char *iname, struct stat *sbuf)
{
int ilen; /* strlen(ifname) */
int z_suffix_errno = 0;
@@ -1318,7 +1322,7 @@ open_input_file (char *iname, struct stat *sbuf)
strcpy(ifname, iname);
/* If input file exists, return OK. */
- fd = open_and_stat (ifname, open_flags, sbuf);
+ fd = open_and_stat (parentfd, ifname, open_flags, sbuf);
if (0 <= fd)
return fd;
@@ -1357,7 +1361,7 @@ open_input_file (char *iname, struct stat *sbuf)
if (sizeof ifname <= ilen + strlen (s))
goto name_too_long;
strcat(ifname, s);
- fd = open_and_stat (ifname, open_flags, sbuf);
+ fd = open_and_stat (parentfd, ifname, open_flags, sbuf);
if (0 <= fd)
return fd;
if (errno != ENOENT)
@@ -1886,7 +1890,7 @@ shorten_name (char *name)
* Return ERROR if the file must be skipped.
*/
static int
-check_ofname ()
+check_ofname (int atfd)
{
/* Ask permission to overwrite the existing file */
if (!force) {
@@ -1904,7 +1908,7 @@ check_ofname ()
return ERROR;
}
}
- if (xunlinkat (dfd, dfd < 0 ? ofname : last_component (ofname)) < 0) {
+ if (xunlinkat (atfd, atfd < 0 ? ofname : last_component (ofname)) < 0) {
progerror(ofname);
return ERROR;
}
@@ -1999,27 +2003,22 @@ treat_dir (int fd, char *dir)
# if HAVE_FDOPENDIR
dirp = fdopendir (fd);
# else
- close (fd);
dirp = opendir (dir);
# endif
if (dirp == NULL) {
progerror(dir);
-# if HAVE_FDOPENDIR
close (fd);
-# endif
return ;
}
entries = streamsavedir (dirp, SAVEDIR_SORT_NONE);
- if (! entries)
- progerror (dir);
- if (closedir (dirp) != 0)
- progerror (dir);
- if (! entries)
- return;
- for (entry = entries; *entry; entry += entrylen + 1) {
+ if (!entries)
+ progerror (dir);
+ else
+ {
+ for (entry = entries; *entry; entry += entrylen + 1) {
size_t len = strlen (dir);
entrylen = strlen (entry);
if (strequ (entry, ".") || strequ (entry, ".."))
@@ -2029,14 +2028,21 @@ treat_dir (int fd, char *dir)
if (*last_component (nbuf) && !ISSLASH (nbuf[len - 1]))
nbuf[len++] = '/';
strcpy (nbuf + len, entry);
- treat_file(nbuf);
+ treat_file (fd, nbuf);
} else {
fprintf(stderr,"%s: %s/%s: pathname too long\n",
program_name, quotef_n (0, dir), quotef_n (1, entry));
exit_code = ERROR;
}
- }
- free (entries);
+ }
+ free (entries);
+ }
+ if (closedir (dirp) < 0)
+ progerror (dir);
+# if !HAVE_FDOPENDIR
+ if (close (fd) < 0)
+ progerror (dir);
+# endif
}
#endif /* ! NO_DIR */
--
2.55.0
From 337e7b1bfa7736ca1f112554e2d5017eecb1cf2e Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Fri, 4 Sep 2026 17:03:58 -0700
Subject: [PATCH 13/14] build: configure.ac cruft removal
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* configure.ac: Do not call AC_PROG_RANLIB, as we no longer use
its results ourselves. Do not use AC_C_CONST or AC_TYPE_SIZE_T,
as it’s safe to assume C89 now. Do not check for fcntl.h,
limits.h, memory.h, time.h, as we no longer use the corresponding
HAVE_FCNTL_H etc. macros. Do not check for lstat or siginterrupt,
as we no longer use HAVE_LSTAT or HAVE_SIGINTERRUPT. Do not use
AC_HEADER_DIRENT, as we no longer use any symbols that it defines.
---
configure.ac | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/configure.ac b/configure.ac
index fd7edb9..eb90c6f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -64,7 +64,6 @@ AC_CHECK_PROG([MORE], [more], [more])
AM_CONDITIONAL([MORE], [test "$MORE"])
AC_CHECK_TOOL([NM], [nm], [nm])
AC_PROG_LN_S
-AC_PROG_RANLIB
AC_PROG_SHELL
gl_EARLY
@@ -312,12 +311,8 @@ AM_CONDITIONAL([GZIP_IS_TRANSFORMED], [test "$GZIP_TRANSFORMED" != gzip])
AM_CONDITIONAL([ZDIFF_IS_TRANSFORMED], [test "$ZDIFF_TRANSFORMED" != zdiff])
AM_CONDITIONAL([ZGREP_IS_TRANSFORMED], [test "$ZGREP_TRANSFORMED" != zgrep])
-AC_C_CONST
-AC_CHECK_HEADERS_ONCE(fcntl.h limits.h memory.h time.h sys/sdt.h)
-AC_CHECK_FUNCS_ONCE(
- [chown fchmod fchown fdopendir lstat openat opendir siginterrupt unlinkat])
-AC_HEADER_DIRENT
-AC_TYPE_SIZE_T
+AC_CHECK_HEADERS_ONCE([sys/sdt.h])
+AC_CHECK_FUNCS_ONCE([chown fchmod fchown fdopendir openat opendir unlinkat])
AC_TYPE_OFF_T
AC_CONFIG_FILES([Makefile doc/Makefile lib/Makefile tests/Makefile])
--
2.55.0
From 8b20d0fcf110c05e70e87d0d098a1ed00c92bb47 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Fri, 4 Sep 2026 17:19:53 -0700
Subject: [PATCH 14/14] maint: update .gitignore files
---
lib/.gitignore | 42 ++----------------------------------------
m4/.gitignore | 23 -----------------------
2 files changed, 2 insertions(+), 63 deletions(-)
diff --git a/lib/.gitignore b/lib/.gitignore
index 4ffbdb0..cbfa9a9 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -7,8 +7,6 @@
/arg-nonnull.h
/assert.h
/assert.in.h
-/assure.h
-/at-func.c
/attribute.h
/basename-lgpl.c
/basename-lgpl.h
@@ -19,8 +17,6 @@
/c-ctype.c
/c-ctype.h
/calloc.c
-/chdir-long.c
-/chdir-long.h
/cloexec.c
/cloexec.h
/close.c
@@ -35,15 +31,12 @@
/crc-x86_64.h
/crc.c
/crc.h
-/creat-safer.c
/dirent-private.h
/dirent.h
/dirent.in.h
/dirfd.c
/dirname-lgpl.c
/dirname.h
-/dup-safer.c
-/dup.c
/dup2.c
/endian.c
/endian.h
@@ -55,22 +48,15 @@
/error.in.h
/exitfail.c
/exitfail.h
-/fchdir.c
/fclose.c
-/fcntl--.h
-/fcntl-safer.h
/fcntl.c
/fcntl.h
/fcntl.in.h
/fd-hook.c
/fd-hook.h
-/fd-safer.c
/fdatasync.c
-/fdopendir.c
/fflush.c
/filename.h
-/filenamecat-lgpl.c
-/filenamecat.h
/fopen.c
/fpurge.c
/freading.c
@@ -81,11 +67,9 @@
/fseterr.c
/fseterr.h
/fstat.c
-/fstatat.c
/fsync.c
/ftell.c
/ftello.c
-/getcwd-lgpl.c
/getdtablesize.c
/getopt-cdefs.h
/getopt-cdefs.in.h
@@ -114,8 +98,6 @@
/inttypes.in.h
/issymlink.c
/issymlink.h
-/issymlinkat.c
-/issymlinkat.h
/libgzip.a
/limits.h
/limits.in.h
@@ -124,28 +106,15 @@
/malloc.c
/malloca.c
/malloca.h
-/memchr.c
-/memchr.valgrind
/memeq.c
-/mempcpy.c
-/memrchr.c
/minmax.h
/msvc-inval.c
/msvc-inval.h
/msvc-nothrow.c
/msvc-nothrow.h
-/open-safer.c
/open.c
-/openat-die.c
-/openat-priv.h
-/openat-proc.c
-/openat-safer.c
-/openat.c
-/openat.h
/opendir.c
/pathmax.h
-/pipe-safer.c
-/pipe.c
/pthread_sigmask.c
/qsort.c
/qsort_r.c
@@ -155,12 +124,8 @@
/raise.c
/readdir.c
/readlink.c
-/readlinkat.c
/realloc.c
/reallocarray.c
-/rmdir.c
-/save-cwd.c
-/save-cwd.h
/savedir.c
/savedir.h
/sig-handler.c
@@ -195,8 +160,9 @@
/stdlib.c
/stdlib.h
/stdlib.in.h
+/stdopen.c
+/stdopen.h
/stpcpy.c
-/strdup.c
/streq.c
/strerror-override.c
/strerror-override.h
@@ -214,13 +180,9 @@
/time.in.h
/timespec.c
/timespec.h
-/unistd--.h
-/unistd-safer.h
/unistd.c
/unistd.h
/unistd.in.h
-/unlink.c
-/unlinkat.c
/unlocked-io.h
/utime.c
/utime.h
diff --git a/m4/.gitignore b/m4/.gitignore
index c90f0f3..5d78a78 100644
--- a/m4/.gitignore
+++ b/m4/.gitignore
@@ -6,7 +6,6 @@
/byteswap.m4
/c-bool.m4
/calloc.m4
-/chdir-long.m4
/clock_time.m4
/close.m4
/closedir.m4
@@ -16,7 +15,6 @@
/dirent_h.m4
/dirfd.m4
/double-slash-root.m4
-/dup.m4
/dup2.m4
/endian_h.m4
/errno_h.m4
@@ -25,16 +23,12 @@
/extensions-aix.m4
/extensions.m4
/extern-inline.m4
-/fchdir.m4
/fclose.m4
/fcntl-o.m4
-/fcntl-safer.m4
/fcntl.m4
/fcntl_h.m4
/fdatasync.m4
-/fdopendir.m4
/fflush.m4
-/filenamecat.m4
/fopen.m4
/fpurge.m4
/freading.m4
@@ -43,11 +37,9 @@
/fseeko.m4
/fseterr.m4
/fstat.m4
-/fstatat.m4
/fsync.m4
/ftell.m4
/ftello.m4
-/getcwd.m4
/getdtablesize.m4
/getopt.m4
/getprogname.m4
@@ -71,12 +63,8 @@
/malloca.m4
/manywarnings-c++.m4
/manywarnings.m4
-/memchr.m4
/memeq.m4
-/mempcpy.m4
-/memrchr.m4
/minmax.m4
-/mmap-anon.m4
/mode_t.m4
/msvc-inval.m4
/msvc-nothrow.m4
@@ -88,22 +76,17 @@
/open-cloexec.m4
/open-slash.m4
/open.m4
-/openat.m4
/opendir.m4
/pathmax.m4
/pid_t.m4
-/pipe.m4
/pthread_sigmask.m4
/qsort_r.m4
/quotearg.m4
/raise.m4
/readdir.m4
/readlink.m4
-/readlinkat.m4
/realloc.m4
/reallocarray.m4
-/rmdir.m4
-/save-cwd.m4
/savedir.m4
/sigaction.m4
/signal_h.m4
@@ -121,7 +104,6 @@
/stdio_h.m4
/stdlib_h.m4
/stpcpy.m4
-/strdup.m4
/streq.m4
/strerror.m4
/string_h.m4
@@ -134,10 +116,7 @@
/time_h.m4
/timespec.m4
/ungetc.m4
-/unistd-safer.m4
/unistd_h.m4
-/unlink.m4
-/unlinkat.m4
/unlocked-io.m4
/utime.m4
/utime_h.m4
@@ -149,5 +128,3 @@
/xalloc.m4
/yesno.m4
/zzgnulib.m4
-/locale-en.m4
-/wint_t.m4
--
2.55.0