accdf3d3fb
Add an LLVM 22.1.6 runtimes patch for building libc++, libc++abi, and llvm-libgcc together. The patch lets libc++abi accept llvm-libgcc as the provider of the LLVM unwinder, keeps the libgcc_s version script private to libunwind so it does not leak into libc++abi links, and adds an opt-out for building compiler-rt inside llvm-libgcc when an exported external builtins archive is available. Add libxcrypt patches for current Clang/glibc builds: avoid treating Clang as old GCC in yescrypt assembly selection and adjust yescrypt strchr call sites for the newer glibc const-correct prototype behavior. Add a mandoc 1.14.6 patch for zstd-compressed manual pages, including configure checks, linker flags, documentation, section matching, and decompression handling. Remove the obsolete Perl 5.42.2 LBI patch from the patch set.
461 lines
12 KiB
Diff
461 lines
12 KiB
Diff
diff -ruN a/INSTALL b/INSTALL
|
|
--- a/INSTALL 2021-09-23 13:03:23.000000000 -0500
|
|
+++ b/INSTALL 2026-05-29 18:09:12.237717849 -0500
|
|
@@ -103,7 +103,9 @@
|
|
|
|
1. zlib for decompressing gzipped manual pages.
|
|
|
|
-2. The fts(3) directory traversion functions.
|
|
+2. libzstd for decompressing zstd-compressed manual pages.
|
|
+
|
|
+3. The fts(3) directory traversion functions.
|
|
If your system does not have them, the bundled compatibility version
|
|
will be used, so you need not worry in that case. But be careful: old
|
|
glibc versions of fts(3) were known to be broken on 32bit platforms,
|
|
@@ -111,7 +113,7 @@
|
|
That was presumably fixed in glibc-2.23.
|
|
If you run into that problem, set "HAVE_FTS=0" in configure.local.
|
|
|
|
-3. Marc Espie's ohash(3) library.
|
|
+4. Marc Espie's ohash(3) library.
|
|
If your system does not have it, the bundled compatibility version
|
|
will be used, so you probably need not worry about it.
|
|
|
|
diff -ruN a/Makefile b/Makefile
|
|
--- a/Makefile 2021-09-23 13:03:23.000000000 -0500
|
|
+++ b/Makefile 2026-05-29 18:06:59.682203510 -0500
|
|
@@ -54,7 +54,8 @@
|
|
test-strsep.c \
|
|
test-strtonum.c \
|
|
test-vasprintf.c \
|
|
- test-wchar.c
|
|
+ test-wchar.c \
|
|
+ test-zstd.c
|
|
|
|
SRCS = arch.c \
|
|
att.c \
|
|
diff -ruN a/configure b/configure
|
|
--- a/configure 2021-09-23 13:03:23.000000000 -0500
|
|
+++ b/configure 2026-05-29 18:06:59.682203510 -0500
|
|
@@ -50,6 +50,7 @@
|
|
LD_NANOSLEEP=
|
|
LD_OHASH=
|
|
LD_RECVMSG=
|
|
+LD_ZSTD=-lzstd
|
|
STATIC=
|
|
|
|
BUILD_CGI=0
|
|
@@ -94,6 +95,7 @@
|
|
HAVE_SYS_ENDIAN=
|
|
HAVE_VASPRINTF=
|
|
HAVE_WCHAR=
|
|
+HAVE_ZSTD=
|
|
|
|
NEED_GNU_SOURCE=0
|
|
NEED_OPENBSD_SOURCE=0
|
|
@@ -331,6 +333,7 @@
|
|
runtest strsep STRSEP || true
|
|
runtest strtonum STRTONUM "" -D_OPENBSD_SOURCE || true
|
|
runtest vasprintf VASPRINTF "" -D_GNU_SOURCE || true
|
|
+runtest zstd ZSTD "${LD_ZSTD}" || true
|
|
|
|
# --- fts ---
|
|
if [ "${1}" = "-depend" ]; then
|
|
@@ -415,6 +418,11 @@
|
|
echo "FATAL: nanosleep: no" 1>&3
|
|
FATAL=1
|
|
fi
|
|
+if [ "${HAVE_ZSTD}" -eq 0 ]; then
|
|
+ echo "FATAL: zstd: no" 1>&2
|
|
+ echo "FATAL: zstd: no" 1>&3
|
|
+ FATAL=1
|
|
+fi
|
|
if [ ${BUILD_CATMAN} -gt 0 -a "${HAVE_RECVMSG}" -eq 0 ]; then
|
|
echo "FATAL: recvmsg: no" 1>&2
|
|
echo "FATAL: recvmsg: no" 1>&3
|
|
@@ -430,7 +438,7 @@
|
|
[ "${FATAL}" -eq 0 ] || exit 1
|
|
|
|
# --- LDADD ---
|
|
-LDADD="${LDADD} ${LD_NANOSLEEP} ${LD_RECVMSG} ${LD_OHASH} -lz"
|
|
+LDADD="${LDADD} ${LD_NANOSLEEP} ${LD_RECVMSG} ${LD_OHASH} -lz ${LD_ZSTD}"
|
|
echo "selected LDADD=\"${LDADD}\"" 1>&2
|
|
echo "selected LDADD=\"${LDADD}\"" 1>&3
|
|
echo 1>&3
|
|
@@ -506,6 +514,7 @@
|
|
#define HAVE_SYS_ENDIAN ${HAVE_SYS_ENDIAN}
|
|
#define HAVE_VASPRINTF ${HAVE_VASPRINTF}
|
|
#define HAVE_WCHAR ${HAVE_WCHAR}
|
|
+#define HAVE_ZSTD ${HAVE_ZSTD}
|
|
#define HAVE_OHASH ${HAVE_OHASH}
|
|
#define NEED_XPG4_2 ${NEED_XPG4_2}
|
|
|
|
diff -ruN a/main.c b/main.c
|
|
--- a/main.c 2021-09-23 13:03:23.000000000 -0500
|
|
+++ b/main.c 2026-05-29 18:08:19.108307544 -0500
|
|
@@ -538,7 +538,10 @@
|
|
prio += 10; /* Wrong dir name. */
|
|
if (search.sec != NULL) {
|
|
ep = strchr(sec, '\0');
|
|
- if (ep - sec > 3 &&
|
|
+ if (ep - sec > 4 &&
|
|
+ strncmp(ep - 4, ".zst", 4) == 0)
|
|
+ ep -= 4;
|
|
+ else if (ep - sec > 3 &&
|
|
strncmp(ep - 3, ".gz", 3) == 0)
|
|
ep -= 3;
|
|
if ((size_t)(ep - sec) < ssz + 3 ||
|
|
diff -ruN a/mandoc.3 b/mandoc.3
|
|
--- a/mandoc.3 2021-09-23 13:03:23.000000000 -0500
|
|
+++ b/mandoc.3 2026-05-29 18:09:19.497910732 -0500
|
|
@@ -273,10 +273,14 @@
|
|
If that fails and
|
|
.Fa fname
|
|
does not already end in
|
|
-.Ql .gz ,
|
|
+.Ql .gz
|
|
+or
|
|
+.Ql .zst ,
|
|
try again after appending
|
|
-.Ql .gz .
|
|
-Save the information whether the file is zipped or not.
|
|
+.Ql .gz
|
|
+and
|
|
+.Ql .zst .
|
|
+Save the information whether the file is compressed or not.
|
|
Return a file descriptor open for reading or -1 on failure.
|
|
It can be passed to
|
|
.Fn mparse_readfd
|
|
diff -ruN a/mandocdb.c b/mandocdb.c
|
|
--- a/mandocdb.c 2021-09-23 13:03:23.000000000 -0500
|
|
+++ b/mandocdb.c 2026-05-29 18:09:00.199398109 -0500
|
|
@@ -102,7 +102,7 @@
|
|
char *fsec; /* section from file name suffix */
|
|
struct mlink *next; /* singly linked list */
|
|
struct mpage *mpage; /* parent */
|
|
- int gzip; /* filename has a .gz suffix */
|
|
+ int gzip; /* filename has a compression suffix */
|
|
enum form dform; /* format from directory */
|
|
enum form fform; /* format from file name suffix */
|
|
};
|
|
@@ -580,7 +580,7 @@
|
|
FTS *f;
|
|
FTSENT *ff;
|
|
struct mlink *mlink;
|
|
- int gzip;
|
|
+ int compressed;
|
|
enum form dform;
|
|
char *dsec, *arch, *fsec, *cp;
|
|
const char *path;
|
|
@@ -645,13 +645,15 @@
|
|
say(path, "Extraneous file");
|
|
continue;
|
|
}
|
|
- gzip = 0;
|
|
+ compressed = 0;
|
|
fsec = NULL;
|
|
while (fsec == NULL) {
|
|
fsec = strrchr(ff->fts_name, '.');
|
|
- if (fsec == NULL || strcmp(fsec+1, "gz"))
|
|
+ if (fsec == NULL ||
|
|
+ (strcmp(fsec + 1, "gz") &&
|
|
+ strcmp(fsec + 1, "zst")))
|
|
break;
|
|
- gzip = 1;
|
|
+ compressed = 1;
|
|
*fsec = '\0';
|
|
fsec = NULL;
|
|
}
|
|
@@ -697,7 +699,7 @@
|
|
mlink->arch = arch;
|
|
mlink->name = ff->fts_name;
|
|
mlink->fsec = fsec;
|
|
- mlink->gzip = gzip;
|
|
+ mlink->gzip = compressed;
|
|
mlink_add(mlink, ff->fts_statp);
|
|
continue;
|
|
|
|
@@ -962,9 +964,19 @@
|
|
* Now check the file suffix.
|
|
* Suffix of `.0' indicates a catpage, `.1-9' is a manpage.
|
|
*/
|
|
- p = strrchr(start, '\0');
|
|
- while (p-- > start && *p != '/' && *p != '.')
|
|
- continue;
|
|
+ if ((p = strrchr(start, '/')) == NULL)
|
|
+ p = start;
|
|
+ else
|
|
+ p++;
|
|
+ if ((p = strrchr(p, '.')) != NULL &&
|
|
+ (strcmp(p + 1, "gz") == 0 || strcmp(p + 1, "zst") == 0))
|
|
+ *p = '\0';
|
|
+
|
|
+ for (p = strchr(start, '\0'); p > start; ) {
|
|
+ p--;
|
|
+ if (*p == '/' || *p == '.')
|
|
+ break;
|
|
+ }
|
|
|
|
if (*p == '.') {
|
|
*p++ = '\0';
|
|
@@ -1213,6 +1225,12 @@
|
|
mlink_dest = ohash_find(&mlinks,
|
|
ohash_qlookup(&mlinks, cp));
|
|
free(cp);
|
|
+ }
|
|
+ if (mlink_dest == NULL) {
|
|
+ mandoc_asprintf(&cp, "%s.zst", meta->sodest);
|
|
+ mlink_dest = ohash_find(&mlinks,
|
|
+ ohash_qlookup(&mlinks, cp));
|
|
+ free(cp);
|
|
}
|
|
if (mlink_dest != NULL) {
|
|
|
|
diff -ruN a/read.c b/read.c
|
|
--- a/read.c 2021-09-23 13:03:23.000000000 -0500
|
|
+++ b/read.c 2026-05-29 18:09:41.222488117 -0500
|
|
@@ -38,6 +38,7 @@
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <zlib.h>
|
|
+#include <zstd.h>
|
|
|
|
#include "mandoc_aux.h"
|
|
#include "mandoc.h"
|
|
@@ -60,6 +61,7 @@
|
|
const char *os_s; /* default operating system */
|
|
int options; /* parser options */
|
|
int gzip; /* current input file is gzipped */
|
|
+ int zstd; /* current input file is zstd-compressed */
|
|
int filenc; /* encoding of the current file */
|
|
int reparse_count; /* finite interp. stack */
|
|
int line; /* line number in the file */
|
|
@@ -70,6 +72,7 @@
|
|
static void resize_buf(struct buf *, size_t);
|
|
static int mparse_buf_r(struct mparse *, struct buf, size_t, int);
|
|
static int read_whole_file(struct mparse *, int, struct buf *, int *);
|
|
+static int read_zstd_file(struct mparse *, int, struct buf *);
|
|
static void mparse_end(struct mparse *);
|
|
|
|
|
|
@@ -432,6 +435,89 @@
|
|
}
|
|
|
|
static int
|
|
+read_zstd_file(struct mparse *curp, int fd, struct buf *fb)
|
|
+{
|
|
+ ZSTD_DStream *zds;
|
|
+ ZSTD_inBuffer zin;
|
|
+ ZSTD_outBuffer zout;
|
|
+ char *ibuf;
|
|
+ size_t ibufsz, off, ret;
|
|
+ ssize_t ssz;
|
|
+ int eof, retval;
|
|
+
|
|
+ if ((zds = ZSTD_createDStream()) == NULL) {
|
|
+ mandoc_msg(MANDOCERR_READ, 0, 0,
|
|
+ "zstd: unable to allocate decompressor");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ ibufsz = ZSTD_DStreamInSize();
|
|
+ ibuf = mandoc_malloc(ibufsz);
|
|
+ zin.src = ibuf;
|
|
+ zin.size = 0;
|
|
+ zin.pos = 0;
|
|
+
|
|
+ fb->sz = 0;
|
|
+ fb->buf = NULL;
|
|
+ off = 0;
|
|
+ ret = 1;
|
|
+ eof = 0;
|
|
+ retval = -1;
|
|
+
|
|
+ while (eof == 0 || zin.pos < zin.size) {
|
|
+ if (zin.pos == zin.size && eof == 0) {
|
|
+ if ((ssz = read(fd, ibuf, ibufsz)) == -1) {
|
|
+ mandoc_msg(MANDOCERR_READ, 0, 0,
|
|
+ "%s", strerror(errno));
|
|
+ goto out;
|
|
+ }
|
|
+ if (ssz == 0) {
|
|
+ eof = 1;
|
|
+ continue;
|
|
+ }
|
|
+ zin.size = (size_t)ssz;
|
|
+ zin.pos = 0;
|
|
+ }
|
|
+
|
|
+ if (off == fb->sz) {
|
|
+ if (fb->sz == (1U << 31)) {
|
|
+ mandoc_msg(MANDOCERR_TOOLARGE, 0, 0, NULL);
|
|
+ goto out;
|
|
+ }
|
|
+ resize_buf(fb, 65536);
|
|
+ }
|
|
+
|
|
+ zout.dst = fb->buf + off;
|
|
+ zout.size = fb->sz - off;
|
|
+ zout.pos = 0;
|
|
+ ret = ZSTD_decompressStream(zds, &zout, &zin);
|
|
+ if (ZSTD_isError(ret)) {
|
|
+ mandoc_msg(MANDOCERR_READ, 0, 0,
|
|
+ "zstd: %s", ZSTD_getErrorName(ret));
|
|
+ goto out;
|
|
+ }
|
|
+ off += zout.pos;
|
|
+ }
|
|
+
|
|
+ if (ret != 0)
|
|
+ mandoc_msg(MANDOCERR_READ, 0, 0,
|
|
+ "zstd: unexpected end of file");
|
|
+ else {
|
|
+ fb->sz = off;
|
|
+ retval = 0;
|
|
+ }
|
|
+
|
|
+out:
|
|
+ free(ibuf);
|
|
+ ZSTD_freeDStream(zds);
|
|
+ if (retval == -1) {
|
|
+ free(fb->buf);
|
|
+ fb->buf = NULL;
|
|
+ }
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+static int
|
|
read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
|
|
{
|
|
struct stat st;
|
|
@@ -452,7 +538,7 @@
|
|
* concerned that this is going to tank any machines.
|
|
*/
|
|
|
|
- if (curp->gzip == 0 && S_ISREG(st.st_mode)) {
|
|
+ if (curp->gzip == 0 && curp->zstd == 0 && S_ISREG(st.st_mode)) {
|
|
if (st.st_size > 0x7fffffff) {
|
|
mandoc_msg(MANDOCERR_TOOLARGE, 0, 0, NULL);
|
|
return -1;
|
|
@@ -464,6 +550,11 @@
|
|
return 0;
|
|
}
|
|
|
|
+ if (curp->zstd) {
|
|
+ *with_mmap = 0;
|
|
+ return read_zstd_file(curp, fd, fb);
|
|
+ }
|
|
+
|
|
if (curp->gzip) {
|
|
/*
|
|
* Duplicating the file descriptor is required
|
|
@@ -557,7 +648,7 @@
|
|
|
|
struct buf blk;
|
|
struct buf *save_primary;
|
|
- const char *save_filename, *cp;
|
|
+ const char *save_filename, *cp, *ep;
|
|
size_t offset;
|
|
int save_filenc, save_lineno;
|
|
int with_mmap;
|
|
@@ -565,12 +656,26 @@
|
|
if (recursion_depth > 64) {
|
|
mandoc_msg(MANDOCERR_ROFFLOOP, curp->line, 0, NULL);
|
|
return;
|
|
- } else if (recursion_depth == 0 &&
|
|
- (cp = strrchr(filename, '.')) != NULL &&
|
|
- cp[1] >= '1' && cp[1] <= '9')
|
|
- curp->man->filesec = cp[1];
|
|
- else
|
|
- curp->man->filesec = '\0';
|
|
+ } else if (recursion_depth == 0) {
|
|
+ ep = strrchr(filename, '.');
|
|
+ if (ep != NULL &&
|
|
+ (strcmp(ep + 1, "gz") == 0 ||
|
|
+ strcmp(ep + 1, "zst") == 0)) {
|
|
+ for (cp = ep; cp > filename; cp--)
|
|
+ if (cp[-1] == '.') {
|
|
+ cp--;
|
|
+ break;
|
|
+ }
|
|
+ if (cp == filename)
|
|
+ cp = NULL;
|
|
+ } else
|
|
+ cp = ep;
|
|
+ if (cp != NULL && cp[1] >= '1' && cp[1] <= '9')
|
|
+ curp->man->filesec = cp[1];
|
|
+ else
|
|
+ curp->man->filesec = '\0';
|
|
+ } else
|
|
+ curp->man->filesec = '\0';
|
|
|
|
if (read_whole_file(curp, fd, &blk, &with_mmap) == -1)
|
|
return;
|
|
@@ -623,11 +728,13 @@
|
|
int
|
|
mparse_open(struct mparse *curp, const char *file)
|
|
{
|
|
+ const char *ep;
|
|
char *cp;
|
|
int fd, save_errno;
|
|
|
|
- cp = strrchr(file, '.');
|
|
- curp->gzip = (cp != NULL && ! strcmp(cp + 1, "gz"));
|
|
+ ep = strrchr(file, '.');
|
|
+ curp->gzip = (ep != NULL && ! strcmp(ep + 1, "gz"));
|
|
+ curp->zstd = (ep != NULL && ! strcmp(ep + 1, "zst"));
|
|
|
|
/* First try to use the filename as it is. */
|
|
|
|
@@ -635,20 +742,27 @@
|
|
return fd;
|
|
|
|
/*
|
|
- * If that doesn't work and the filename doesn't
|
|
- * already end in .gz, try appending .gz.
|
|
+ * If that doesn't work and the filename doesn't already
|
|
+ * end in .gz or .zst, try appending these suffixes.
|
|
*/
|
|
|
|
- if ( ! curp->gzip) {
|
|
+ if ( ! curp->gzip && ! curp->zstd) {
|
|
save_errno = errno;
|
|
mandoc_asprintf(&cp, "%s.gz", file);
|
|
fd = open(cp, O_RDONLY);
|
|
free(cp);
|
|
- errno = save_errno;
|
|
if (fd != -1) {
|
|
curp->gzip = 1;
|
|
return fd;
|
|
}
|
|
+ mandoc_asprintf(&cp, "%s.zst", file);
|
|
+ fd = open(cp, O_RDONLY);
|
|
+ free(cp);
|
|
+ errno = save_errno;
|
|
+ if (fd != -1) {
|
|
+ curp->zstd = 1;
|
|
+ return fd;
|
|
+ }
|
|
}
|
|
|
|
/* Neither worked, give up. */
|
|
@@ -693,6 +807,7 @@
|
|
free_buf_list(curp->secondary);
|
|
curp->secondary = NULL;
|
|
curp->gzip = 0;
|
|
+ curp->zstd = 0;
|
|
tag_alloc();
|
|
}
|
|
|
|
diff -ruN a/test-zstd.c b/test-zstd.c
|
|
--- a/test-zstd.c 1969-12-31 18:00:00.000000000 -0600
|
|
+++ b/test-zstd.c 2026-05-29 18:06:59.682203510 -0500
|
|
@@ -0,0 +1,7 @@
|
|
+#include <zstd.h>
|
|
+
|
|
+int
|
|
+main(void)
|
|
+{
|
|
+ return ZSTD_versionNumber() == 0;
|
|
+}
|