* [gentoo-commits] proj/sandbox:master commit in: /, libsbutil/gnulib/malloc/, libsbutil/, libsbutil/gnulib/
@ 2025-01-21 20:36 Mike Gilbert
0 siblings, 0 replies; only message in thread
From: Mike Gilbert @ 2025-01-21 20:36 UTC (permalink / raw
To: gentoo-commits
commit: 266b8c563c13dff8b12496178eda0043bc90466d
Author: Mike Gilbert <floppym <AT> gentoo <DOT> org>
AuthorDate: Sun Jan 19 21:15:50 2025 +0000
Commit: Mike Gilbert <floppym <AT> gentoo <DOT> org>
CommitDate: Tue Jan 21 19:57:29 2025 +0000
URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=266b8c56
libsbutil: update gnulib code
Bug: https://bugs.gentoo.org/925032
Signed-off-by: Mike Gilbert <floppym <AT> gentoo.org>
configure.ac | 3 +-
| 2 +
libsbutil/gnulib/areadlink-with-size.c | 104 ---
libsbutil/gnulib/areadlink.h | 33 -
libsbutil/gnulib/attribute.h | 320 +++++++++
libsbutil/gnulib/bitrotate.c | 18 +
libsbutil/gnulib/bitrotate.h | 46 +-
libsbutil/gnulib/canonicalize.c | 430 ++++++++-----
libsbutil/gnulib/canonicalize.h | 25 +-
libsbutil/gnulib/careadlinkat.h | 67 --
libsbutil/gnulib/cdefs.h | 715 +++++++++++++++++++++
libsbutil/gnulib/dosname.h | 53 --
libsbutil/gnulib/file-set.c | 8 +-
libsbutil/gnulib/file-set.h | 33 +-
libsbutil/gnulib/filename.h | 112 ++++
libsbutil/gnulib/gl-inline.h | 40 +-
libsbutil/gnulib/glue.h | 63 ++
libsbutil/gnulib/hash-pjw.c | 20 +-
libsbutil/gnulib/hash-pjw.h | 33 +-
.../gnulib/{hash-triple.c => hash-triple-simple.c} | 19 +-
libsbutil/gnulib/hash-triple.h | 44 +-
libsbutil/gnulib/hash.c | 179 ++----
libsbutil/gnulib/hash.h | 294 +++++++--
libsbutil/gnulib/idx.h | 144 +++++
libsbutil/gnulib/intprops-internal.h | 400 ++++++++++++
libsbutil/gnulib/intprops.h | 335 ++++++++++
libsbutil/gnulib/libc-config.h | 209 ++++++
libsbutil/gnulib/malloc/scratch_buffer.gl.h | 133 ++++
libsbutil/gnulib/malloc/scratch_buffer_grow.c | 56 ++
.../gnulib/malloc/scratch_buffer_grow_preserve.c | 67 ++
libsbutil/gnulib/pathmax.h | 83 ---
libsbutil/gnulib/rawmemchr.c | 135 ++++
libsbutil/gnulib/same-inode.h | 104 ++-
libsbutil/gnulib/scratch_buffer.h | 117 ++++
libsbutil/gnulib/xalloc-oversized.h | 79 ++-
libsbutil/gnulib/xalloc.h | 4 +-
libsbutil/gnulib/xgetcwd.h | 17 -
libsbutil/local.mk | 55 +-
38 files changed, 3734 insertions(+), 865 deletions(-)
diff --git a/configure.ac b/configure.ac
index 3db9441..a32e580 100644
--- a/configure.ac
+++ b/configure.ac
@@ -149,7 +149,7 @@ AC_C_CONST
AC_TYPE_UID_T
AC_TYPE_MODE_T
AC_TYPE_SIZE_T
-AC_CHECK_DECLS_ONCE([environ])
+AC_CHECK_DECLS_ONCE([environ, rawmemchr])
AC_CHECK_TYPES([ptrdiff_t])
AC_CHECK_TYPES([sighandler_t, sig_t, __sighandler_t],,,[#include <signal.h>])
@@ -208,6 +208,7 @@ AC_CHECK_FUNCS_ONCE(m4_flatten([
prctl
process_vm_readv
ptrace
+ rawmemchr
realpath
remove
removexattr
--git a/headers.h b/headers.h
index 7a17415..03c93ba 100644
--- a/headers.h
+++ b/headers.h
@@ -167,4 +167,6 @@
# include "localdecls.h"
#endif
+#include "libsbutil/gnulib/glue.h"
+
#endif
diff --git a/libsbutil/gnulib/areadlink-with-size.c b/libsbutil/gnulib/areadlink-with-size.c
deleted file mode 100644
index e3a8c50..0000000
--- a/libsbutil/gnulib/areadlink-with-size.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* readlink wrapper to return the link name in malloc'd storage.
- Unlike xreadlink and xreadlink_with_size, don't ever call exit.
-
- Copyright (C) 2001, 2003-2007, 2009-2015 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
- (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/>. */
-
-/* Written by Jim Meyering <jim@meyering.net> */
-
-#include <config.h>
-
-#include "areadlink.h"
-
-#include <errno.h>
-#include <limits.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#ifndef SSIZE_MAX
-# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
-#endif
-
-/* SYMLINK_MAX is used only for an initial memory-allocation sanity
- check, so it's OK to guess too small on hosts where there is no
- arbitrary limit to symbolic link length. */
-#ifndef SYMLINK_MAX
-# define SYMLINK_MAX 1024
-#endif
-
-#define MAXSIZE (SIZE_MAX < SSIZE_MAX ? SIZE_MAX : SSIZE_MAX)
-
-/* Call readlink to get the symbolic link value of FILE.
- SIZE is a hint as to how long the link is expected to be;
- typically it is taken from st_size. It need not be correct.
- Return a pointer to that NUL-terminated string in malloc'd storage.
- If readlink fails, malloc fails, or if the link value is longer
- than SSIZE_MAX, return NULL (caller may use errno to diagnose). */
-
-char *
-areadlink_with_size (char const *file, size_t size)
-{
- /* Some buggy file systems report garbage in st_size. Defend
- against them by ignoring outlandish st_size values in the initial
- memory allocation. */
- size_t symlink_max = SYMLINK_MAX;
- size_t INITIAL_LIMIT_BOUND = 8 * 1024;
- size_t initial_limit = (symlink_max < INITIAL_LIMIT_BOUND
- ? symlink_max + 1
- : INITIAL_LIMIT_BOUND);
-
- /* The initial buffer size for the link value. */
- size_t buf_size = size < initial_limit ? size + 1 : initial_limit;
-
- while (1)
- {
- ssize_t r;
- size_t link_length;
- char *buffer = malloc (buf_size);
-
- if (buffer == NULL)
- return NULL;
- r = readlink (file, buffer, buf_size);
- link_length = r;
-
- /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1
- with errno == ERANGE if the buffer is too small. */
- if (r < 0 && errno != ERANGE)
- {
- int saved_errno = errno;
- free (buffer);
- errno = saved_errno;
- return NULL;
- }
-
- if (link_length < buf_size)
- {
- buffer[link_length] = 0;
- return buffer;
- }
-
- free (buffer);
- if (buf_size <= MAXSIZE / 2)
- buf_size *= 2;
- else if (buf_size < MAXSIZE)
- buf_size = MAXSIZE;
- else
- {
- errno = ENOMEM;
- return NULL;
- }
- }
-}
diff --git a/libsbutil/gnulib/areadlink.h b/libsbutil/gnulib/areadlink.h
deleted file mode 100644
index d9e0fa1..0000000
--- a/libsbutil/gnulib/areadlink.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Read symbolic links without size limitation.
-
- Copyright (C) 2001, 2003-2004, 2007, 2009-2015 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
- (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/>. */
-
-/* Written by Jim Meyering <jim@meyering.net> */
-
-#include <stddef.h>
-
-extern char *areadlink (char const *filename);
-extern char *areadlink_with_size (char const *filename, size_t size_hint);
-
-#if GNULIB_AREADLINKAT
-extern char *areadlinkat (int fd, char const *filename);
-#endif
-
-#if GNULIB_AREADLINKAT_WITH_SIZE
-extern char *areadlinkat_with_size (int fd, char const *filename,
- size_t size_hint);
-#endif
diff --git a/libsbutil/gnulib/attribute.h b/libsbutil/gnulib/attribute.h
new file mode 100644
index 0000000..4939d77
--- /dev/null
+++ b/libsbutil/gnulib/attribute.h
@@ -0,0 +1,320 @@
+/* ATTRIBUTE_* macros for using attributes in GCC and similar compilers
+
+ Copyright 2020-2025 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+/* Provide public ATTRIBUTE_* names for the private _GL_ATTRIBUTE_*
+ macros used within Gnulib. */
+
+/* The placement of these attributes depends on the kind of declaration
+ and, in some cases, also on the programming language (C vs. C++).
+
+ In function declarations and function definitions:
+
+ * ATTRIBUTE_NOTHROW must come after the parameter list.
+
+ * The macros
+ ATTRIBUTE_CONST
+ ATTRIBUTE_PURE
+ DEPRECATED
+ MAYBE_UNUSED
+ NODISCARD
+ REPRODUCIBLE
+ UNSEQUENCED
+ must come before the return type, and more precisely:
+ - In a function declaration/definition without a storage-class
+ specifier: at the beginning of the declaration/definition.
+ - In a function declaration/definition with a storage-class
+ specifier:
+ - In C: before the storage-class specifier.
+ - In C++: between the storage-class specifier and the return type.
+
+ * The other macros can be placed
+ - Either
+ - In a function declaration/definition without a storage-class
+ specifier: at the beginning of the declaration/definition.
+ - In a function declaration/definition with a storage-class
+ specifier: between the storage-class specifier and the return
+ type.
+ - Or after the parameter list,
+ ∙ but after ATTRIBUTE_NOTHROW if present.
+
+ In other declarations, such as variable declarations:
+
+ * Either
+ - In C: before the storage-class specifier.
+ - In C++: between the storage-class specifier and the return type.
+ Then they apply to all entities that are declared by the declaration.
+
+ * Or immediately after the name of an entity being declared by the
+ declaration. Then they apply to that entity only.
+ */
+
+#ifndef _GL_ATTRIBUTE_H
+#define _GL_ATTRIBUTE_H
+
+
+/* This file defines two types of attributes:
+ * C23 standard attributes. These have macro names that do not begin with
+ 'ATTRIBUTE_'.
+ * Selected GCC attributes; see:
+ https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
+ https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
+ https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html
+ These names begin with 'ATTRIBUTE_' to avoid name clashes. */
+
+
+/* This file uses _GL_ATTRIBUTE_ALLOC_SIZE, _GL_ATTRIBUTE_ALWAYS_INLINE,
+ _GL_ATTRIBUTE_ARTIFICIAL, _GL_ATTRIBUTE_COLD, _GL_ATTRIBUTE_CONST,
+ _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_DEPRECATED, _GL_ATTRIBUTE_ERROR,
+ _GL_ATTRIBUTE_WARNING, _GL_ATTRIBUTE_EXTERNALLY_VISIBLE,
+ _GL_ATTRIBUTE_FALLTHROUGH, _GL_ATTRIBUTE_FORMAT, _GL_ATTRIBUTE_LEAF,
+ _GL_ATTRIBUTE_MALLOC, _GL_ATTRIBUTE_MAY_ALIAS, _GL_ATTRIBUTE_MAYBE_UNUSED,
+ _GL_ATTRIBUTE_NODISCARD, _GL_ATTRIBUTE_NOINLINE, _GL_ATTRIBUTE_NONNULL,
+ _GL_ATTRIBUTE_NONSTRING, _GL_ATTRIBUTE_NOTHROW, _GL_ATTRIBUTE_PACKED,
+ _GL_ATTRIBUTE_PURE, _GL_ATTRIBUTE_REPRODUCIBLE,
+ _GL_ATTRIBUTE_RETURNS_NONNULL, _GL_ATTRIBUTE_SENTINEL,
+ _GL_ATTRIBUTE_UNSEQUENCED. */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
+
+/* =============== Attributes for specific kinds of functions =============== */
+
+/* Attributes for functions that should not be used. */
+
+/* Warn if the entity is used. */
+/* Applies to:
+ - function, variable,
+ - struct, union, struct/union member,
+ - enumeration, enumeration item,
+ - typedef,
+ in C++ also: namespace, class, template specialization. */
+#define DEPRECATED _GL_ATTRIBUTE_DEPRECATED
+
+/* If a function call is not optimized way, warn with MSG. */
+/* Applies to: functions. */
+#define ATTRIBUTE_WARNING(msg) _GL_ATTRIBUTE_WARNING (msg)
+
+/* If a function call is not optimized way, report an error with MSG. */
+/* Applies to: functions. */
+#define ATTRIBUTE_ERROR(msg) _GL_ATTRIBUTE_ERROR (msg)
+
+
+/* Attributes for memory-allocating functions. */
+
+/* The function returns a pointer to freshly allocated memory. */
+/* Applies to: functions. */
+#define ATTRIBUTE_MALLOC _GL_ATTRIBUTE_MALLOC
+
+/* ATTRIBUTE_ALLOC_SIZE ((N)) - The Nth argument of the function
+ is the size of the returned memory block.
+ ATTRIBUTE_ALLOC_SIZE ((M, N)) - Multiply the Mth and Nth arguments
+ to determine the size of the returned memory block. */
+/* Applies to: functions, pointer to functions, function types. */
+#define ATTRIBUTE_ALLOC_SIZE(args) _GL_ATTRIBUTE_ALLOC_SIZE (args)
+
+/* ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
+ that can be freed by passing them as the Ith argument to the
+ function F.
+ ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that
+ can be freed via 'free'; it can be used only after declaring 'free'. */
+/* Applies to: functions. Cannot be used on inline functions. */
+#define ATTRIBUTE_DEALLOC(f, i) _GL_ATTRIBUTE_DEALLOC(f, i)
+#define ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC_FREE
+
+/* Attributes for variadic functions. */
+
+/* The variadic function expects a trailing NULL argument.
+ ATTRIBUTE_SENTINEL () - The last argument is NULL (requires C99).
+ ATTRIBUTE_SENTINEL ((N)) - The (N+1)st argument from the end is NULL. */
+/* Applies to: functions. */
+#define ATTRIBUTE_SENTINEL(pos) _GL_ATTRIBUTE_SENTINEL (pos)
+
+
+/* ================== Attributes for compiler diagnostics ================== */
+
+/* Attributes that help the compiler diagnose programmer mistakes.
+ Some of them may also help for some compiler optimizations. */
+
+/* ATTRIBUTE_FORMAT ((ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)) -
+ The STRING-INDEXth function argument is a format string of style
+ ARCHETYPE, which is one of:
+ printf, gnu_printf
+ scanf, gnu_scanf,
+ strftime, gnu_strftime,
+ strfmon,
+ or the same thing prefixed and suffixed with '__'.
+ If FIRST-TO-CHECK is not 0, arguments starting at FIRST-TO_CHECK
+ are suitable for the format string. */
+/* Applies to: functions. */
+#define ATTRIBUTE_FORMAT(spec) _GL_ATTRIBUTE_FORMAT (spec)
+
+/* ATTRIBUTE_NONNULL ((N1, N2,...)) - Arguments N1, N2,... must not be NULL.
+ ATTRIBUTE_NONNULL () - All pointer arguments must not be null. */
+/* Applies to: functions. */
+#define ATTRIBUTE_NONNULL(args) _GL_ATTRIBUTE_NONNULL (args)
+
+/* The function's return value is a non-NULL pointer. */
+/* Applies to: functions. */
+#define ATTRIBUTE_RETURNS_NONNULL _GL_ATTRIBUTE_RETURNS_NONNULL
+
+/* Warn if the caller does not use the return value,
+ unless the caller uses something like ignore_value. */
+/* Applies to: function, enumeration, class. */
+#define NODISCARD _GL_ATTRIBUTE_NODISCARD
+
+
+/* Attributes that disable false alarms when the compiler diagnoses
+ programmer "mistakes". */
+
+/* Do not warn if the entity is not used. */
+/* Applies to:
+ - function, variable,
+ - struct, union, struct/union member,
+ - enumeration, enumeration item,
+ - typedef,
+ in C++ also: class. */
+#define MAYBE_UNUSED _GL_ATTRIBUTE_MAYBE_UNUSED
+
+/* The contents of a character array is not meant to be NUL-terminated. */
+/* Applies to: struct/union members and variables that are arrays of element
+ type '[[un]signed] char'. */
+#define ATTRIBUTE_NONSTRING _GL_ATTRIBUTE_NONSTRING
+
+/* Do not warn if control flow falls through to the immediately
+ following 'case' or 'default' label. */
+/* Applies to: Empty statement (;), inside a 'switch' statement. */
+#define FALLTHROUGH _GL_ATTRIBUTE_FALLTHROUGH
+
+
+/* ================== Attributes for debugging information ================== */
+
+/* Attributes regarding debugging information emitted by the compiler. */
+
+/* Omit the function from stack traces when debugging. */
+/* Applies to: functions. */
+#define ATTRIBUTE_ARTIFICIAL _GL_ATTRIBUTE_ARTIFICIAL
+
+/* Make the entity visible to debuggers etc., even with '-fwhole-program'. */
+/* Applies to: functions, variables. */
+#define ATTRIBUTE_EXTERNALLY_VISIBLE _GL_ATTRIBUTE_EXTERNALLY_VISIBLE
+
+
+/* ========== Attributes that mainly direct compiler optimizations ========== */
+
+/* The function does not throw exceptions. */
+/* Applies to: functions. */
+/* After a function's parameter list, this attribute must come first, before
+ other attributes. */
+#define ATTRIBUTE_NOTHROW _GL_ATTRIBUTE_NOTHROW
+
+/* Do not inline the function. */
+/* Applies to: functions. */
+#define ATTRIBUTE_NOINLINE _GL_ATTRIBUTE_NOINLINE
+
+/* Always inline the function, and report an error if the compiler
+ cannot inline. */
+/* Applies to: functions. */
+#define ATTRIBUTE_ALWAYS_INLINE _GL_ATTRIBUTE_ALWAYS_INLINE
+
+/* It is OK for a compiler to move calls to the function and to omit
+ calls to the function if another call has the same arguments or the
+ result is not used.
+ This attribute is safe for a function that neither depends on
+ nor affects state, and always returns exactly once -
+ e.g., does not raise an exception, call longjmp, or loop forever.
+ (This attribute is stricter than ATTRIBUTE_PURE because the
+ function cannot observe state. It is stricter than UNSEQUENCED
+ because the function must return exactly once and cannot depend on
+ state addressed by its arguments.) */
+/* Applies to: functions. */
+#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
+
+/* It is OK for a compiler to move calls to the function and to omit duplicate
+ calls to the function with the same arguments, so long as the state
+ addressed by its arguments is the same.
+ This attribute is safe for a function that is effectless, idempotent,
+ stateless, and independent; see ISO C 23 § 6.7.12.7 for a definition of
+ these terms.
+ (This attribute is stricter than REPRODUCIBLE because the function
+ must be stateless and independent. It is looser than ATTRIBUTE_CONST
+ because the function need not return exactly once and can depend
+ on state addressed by its arguments.)
+ See also <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2956.htm> and
+ <https://stackoverflow.com/questions/76847905/>. */
+/* Applies to: functions, pointer to functions, function type. */
+#define UNSEQUENCED _GL_ATTRIBUTE_UNSEQUENCED
+
+/* It is OK for a compiler to move calls to the function and to omit
+ calls to the function if another call has the same arguments or the
+ result is not used, and if observable state is the same.
+ This attribute is safe for a function that does not affect observable state
+ and always returns exactly once.
+ (This attribute is looser than ATTRIBUTE_CONST because the function
+ can depend on observable state. It is stricter than REPRODUCIBLE
+ because the function must return exactly once and cannot affect
+ state addressed by its arguments.) */
+/* Applies to: functions. */
+#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE
+
+/* It is OK for a compiler to move calls to the function and to omit duplicate
+ calls to the function with the same arguments, so long as the state
+ addressed by its arguments is the same and is updated in time for
+ the rest of the program.
+ This attribute is safe for a function that is effectless and idempotent; see
+ ISO C 23 § 6.7.12.7 for a definition of these terms.
+ (This attribute is looser than UNSEQUENCED because the function need
+ not be stateless and idempotent. It is looser than ATTRIBUTE_PURE
+ because the function need not return exactly once and can affect
+ state addressed by its arguments.)
+ See also <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2956.htm> and
+ <https://stackoverflow.com/questions/76847905/>. */
+/* Applies to: functions, pointer to functions, function type. */
+#define REPRODUCIBLE _GL_ATTRIBUTE_REPRODUCIBLE
+
+/* The function is rarely executed. */
+/* Applies to: functions. */
+#define ATTRIBUTE_COLD _GL_ATTRIBUTE_COLD
+
+/* If called from some other compilation unit, the function executes
+ code from that unit only by return or by exception handling,
+ letting the compiler optimize that unit more aggressively. */
+/* Applies to: functions. */
+#define ATTRIBUTE_LEAF _GL_ATTRIBUTE_LEAF
+
+/* For struct members: The member has the smallest possible alignment.
+ For struct, union, class: All members have the smallest possible alignment,
+ minimizing the memory required. */
+/* Applies to: struct members, struct, union,
+ in C++ also: class. */
+#define ATTRIBUTE_PACKED _GL_ATTRIBUTE_PACKED
+
+
+/* ================ Attributes that make invalid code valid ================ */
+
+/* Attributes that prevent fatal compiler optimizations for code that is not
+ fully ISO C compliant. */
+
+/* Pointers to the type may point to the same storage as pointers to
+ other types, thus disabling strict aliasing optimization. */
+/* Applies to: types. */
+#define ATTRIBUTE_MAY_ALIAS _GL_ATTRIBUTE_MAY_ALIAS
+
+
+#endif /* _GL_ATTRIBUTE_H */
diff --git a/libsbutil/gnulib/bitrotate.c b/libsbutil/gnulib/bitrotate.c
index a8f6028..6f6d306 100644
--- a/libsbutil/gnulib/bitrotate.c
+++ b/libsbutil/gnulib/bitrotate.c
@@ -1,3 +1,21 @@
+/* Rotate bits in integers.
+
+ Copyright (C) 2012-2025 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#include <config.h>
+
#define BITROTATE_INLINE _GL_EXTERN_INLINE
#include "bitrotate.h"
diff --git a/libsbutil/gnulib/bitrotate.h b/libsbutil/gnulib/bitrotate.h
index 1665e99..f855ad7 100644
--- a/libsbutil/gnulib/bitrotate.h
+++ b/libsbutil/gnulib/bitrotate.h
@@ -1,36 +1,43 @@
/* bitrotate.h - Rotate bits in integers
- Copyright (C) 2008-2015 Free Software Foundation, Inc.
+ Copyright (C) 2008-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
- (at your option) any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser 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/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Simon Josefsson <simon@josefsson.org>, 2008. */
#ifndef _GL_BITROTATE_H
#define _GL_BITROTATE_H
+/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE. */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
#include <limits.h>
#include <stdint.h>
#include <sys/types.h>
-#ifndef _GL_INLINE_HEADER_BEGIN
- #error "Please include config.h first."
-#endif
_GL_INLINE_HEADER_BEGIN
#ifndef BITROTATE_INLINE
# define BITROTATE_INLINE _GL_INLINE
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
#ifdef UINT64_MAX
/* Given an unsigned 64-bit argument X, return the value corresponding
to rotating the bits N steps to the left. N must be between 1 and
@@ -95,7 +102,8 @@ rotr_sz (size_t x, int n)
BITROTATE_INLINE uint16_t
rotl16 (uint16_t x, int n)
{
- return ((x << n) | (x >> (16 - n))) & UINT16_MAX;
+ return (((unsigned int) x << n) | ((unsigned int) x >> (16 - n)))
+ & UINT16_MAX;
}
/* Given an unsigned 16-bit argument X, return the value corresponding
@@ -106,7 +114,8 @@ rotl16 (uint16_t x, int n)
BITROTATE_INLINE uint16_t
rotr16 (uint16_t x, int n)
{
- return ((x >> n) | (x << (16 - n))) & UINT16_MAX;
+ return (((unsigned int) x >> n) | ((unsigned int) x << (16 - n)))
+ & UINT16_MAX;
}
/* Given an unsigned 8-bit argument X, return the value corresponding
@@ -117,7 +126,7 @@ rotr16 (uint16_t x, int n)
BITROTATE_INLINE uint8_t
rotl8 (uint8_t x, int n)
{
- return ((x << n) | (x >> (8 - n))) & UINT8_MAX;
+ return (((unsigned int) x << n) | ((unsigned int) x >> (8 - n))) & UINT8_MAX;
}
/* Given an unsigned 8-bit argument X, return the value corresponding
@@ -128,8 +137,13 @@ rotl8 (uint8_t x, int n)
BITROTATE_INLINE uint8_t
rotr8 (uint8_t x, int n)
{
- return ((x >> n) | (x << (8 - n))) & UINT8_MAX;
+ return (((unsigned int) x >> n) | ((unsigned int) x << (8 - n))) & UINT8_MAX;
+}
+
+
+#ifdef __cplusplus
}
+#endif
_GL_INLINE_HEADER_END
diff --git a/libsbutil/gnulib/canonicalize.c b/libsbutil/gnulib/canonicalize.c
index 397ac76..88472cc 100644
--- a/libsbutil/gnulib/canonicalize.c
+++ b/libsbutil/gnulib/canonicalize.c
@@ -1,9 +1,9 @@
/* Return the canonical absolute name of a given file.
- Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ Copyright (C) 1996-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,
@@ -12,36 +12,37 @@
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/>. */
#include <config.h>
#include "canonicalize.h"
#include <errno.h>
-#include <stdlib.h>
+#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
-#include "areadlink.h"
+#include <filename.h>
+#include <idx.h>
+#include <intprops.h>
+#include <scratch_buffer.h>
+
+#include "attribute.h"
#include "file-set.h"
#include "hash-triple.h"
-#include "pathmax.h"
#include "xalloc.h"
-#include "xgetcwd.h"
-#include "dosname.h"
-
-#define MULTIPLE_BITS_SET(i) (((i) & ((i) - 1)) != 0)
-/* In this file, we cannot handle file names longer than PATH_MAX.
- On systems with no file name length limit, use a fallback. */
-#ifndef PATH_MAX
-# define PATH_MAX 8192
+/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
+#if defined GCC_LINT || defined lint
+# define IF_LINT(Code) Code
+#else
+# define IF_LINT(Code) /* empty */
#endif
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
-# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
+# define DOUBLE_SLASH_IS_DISTINCT_ROOT false
#endif
#if ISSLASH ('\\')
@@ -50,6 +51,78 @@
# define SLASHES "/"
#endif
+/* Avoid false GCC warning "'end_idx' may be used uninitialized". */
+#if _GL_GNUC_PREREQ (4, 7)
+# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+
+/* Return true if FILE's existence can be shown, false (setting errno)
+ otherwise. Follow symbolic links. */
+static bool
+file_accessible (char const *file)
+{
+# if HAVE_FACCESSAT
+ return faccessat (AT_FDCWD, file, F_OK, AT_EACCESS) == 0;
+# else
+ struct stat st;
+ return stat (file, &st) == 0 || errno == EOVERFLOW;
+# endif
+}
+
+/* True if concatenating END as a suffix to a file name means that the
+ code needs to check that the file name is that of a searchable
+ directory, since the canonicalize_filename_mode_stk code won't
+ check this later anyway when it checks an ordinary file name
+ component within END. END must either be empty, or start with a
+ slash. */
+
+static bool _GL_ATTRIBUTE_PURE
+suffix_requires_dir_check (char const *end)
+{
+ /* If END does not start with a slash, the suffix is OK. */
+ while (ISSLASH (*end))
+ {
+ /* Two or more slashes act like a single slash. */
+ do
+ end++;
+ while (ISSLASH (*end));
+
+ switch (*end++)
+ {
+ default: return false; /* An ordinary file name component is OK. */
+ case '\0': return true; /* Trailing "/" is trouble. */
+ case '.': break; /* Possibly "." or "..". */
+ }
+ /* Trailing "/.", or "/.." even if not trailing, is trouble. */
+ if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1]))))
+ return true;
+ }
+
+ return false;
+}
+
+/* Append this to a file name to test whether it is a searchable directory.
+ On POSIX platforms "/" suffices, but "/./" is sometimes needed on
+ macOS 10.13 <https://bugs.gnu.org/30350>, and should also work on
+ platforms like AIX 7.2 that need at least "/.". */
+
+#ifdef LSTAT_FOLLOWS_SLASHED_SYMLINK
+static char const dir_suffix[] = "/";
+#else
+static char const dir_suffix[] = "/./";
+#endif
+
+/* Return true if DIR is a searchable dir, false (setting errno) otherwise.
+ DIREND points to the NUL byte at the end of the DIR string.
+ Store garbage into DIREND[0 .. strlen (dir_suffix)]. */
+
+static bool
+dir_check (char *dir, char *dirend)
+{
+ strcpy (dirend, dir_suffix);
+ return file_accessible (dir);
+}
+
#if !((HAVE_CANONICALIZE_FILE_NAME && FUNC_REALPATH_WORKS) \
|| GNULIB_CANONICALIZE_LGPL)
/* Return the canonical absolute name of file NAME. A canonical name
@@ -64,6 +137,12 @@ canonicalize_file_name (const char *name)
}
#endif /* !HAVE_CANONICALIZE_FILE_NAME */
+static bool
+multiple_bits_set (canonicalize_mode_t i)
+{
+ return (i & (i - 1)) != 0;
+}
+
/* Return true if we've already seen the triple, <FILENAME, dev, ino>.
If *HT is not initialized, initialize it. */
static bool
@@ -71,7 +150,7 @@ seen_triple (Hash_table **ht, char const *filename, struct stat const *st)
{
if (*ht == NULL)
{
- size_t initial_capacity = 7;
+ idx_t initial_capacity = 7;
*ht = hash_initialize (initial_capacity,
NULL,
triple_hash,
@@ -88,30 +167,28 @@ seen_triple (Hash_table **ht, char const *filename, struct stat const *st)
return false;
}
-/* Return the canonical absolute name of file NAME, while treating
- missing elements according to CAN_MODE. A canonical name
- does not contain any ".", ".." components nor any repeated file name
- separators ('/') or, depending on other CAN_MODE flags, symlinks.
- Whether components must exist or not depends on canonicalize mode.
- The result is malloc'd. */
-
-char *
-canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
+/* Scratch buffers used by canonicalize_filename_mode_stk and managed
+ by __realpath. */
+struct realpath_bufs
{
- char *rname, *dest, *extra_buf = NULL;
+ struct scratch_buffer rname;
+ struct scratch_buffer extra;
+ struct scratch_buffer link;
+};
+
+static char *
+canonicalize_filename_mode_stk (const char *name, canonicalize_mode_t can_mode,
+ struct realpath_bufs *bufs)
+{
+ char *dest;
char const *start;
char const *end;
- char const *rname_limit;
- size_t extra_len = 0;
Hash_table *ht = NULL;
- int saved_errno;
- int can_flags = can_mode & ~CAN_MODE_MASK;
- bool logical = can_flags & CAN_NOLINKS;
- size_t prefix_len;
-
- can_mode &= CAN_MODE_MASK;
+ bool logical = (can_mode & CAN_NOLINKS) != 0;
+ int num_links = 0;
- if (MULTIPLE_BITS_SET (can_mode))
+ canonicalize_mode_t can_exist = can_mode & CAN_MODE_MASK;
+ if (multiple_bits_set (can_exist))
{
errno = EINVAL;
return NULL;
@@ -129,45 +206,71 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
return NULL;
}
+ char *rname = bufs->rname.data;
+ bool end_in_extra_buffer = false;
+ bool failed = true;
+
/* This is always zero for Posix hosts, but can be 2 for MS-Windows
and MS-DOS X:/foo/bar file names. */
- prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
+ idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
if (!IS_ABSOLUTE_FILE_NAME (name))
{
- rname = xgetcwd ();
- if (!rname)
- return NULL;
- dest = strchr (rname, '\0');
- if (dest - rname < PATH_MAX)
- {
- char *p = xrealloc (rname, PATH_MAX);
- dest = p + (dest - rname);
- rname = p;
- rname_limit = rname + PATH_MAX;
- }
- else
+ while (!getcwd (bufs->rname.data, bufs->rname.length))
{
- rname_limit = dest;
+ switch (errno)
+ {
+ case ERANGE:
+ if (scratch_buffer_grow (&bufs->rname))
+ break;
+ FALLTHROUGH;
+ case ENOMEM:
+ xalloc_die ();
+
+ default:
+ dest = rname;
+ goto error;
+ }
+ rname = bufs->rname.data;
}
+ dest = rawmemchr (rname, '\0');
start = name;
prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
}
else
{
- rname = xmalloc (PATH_MAX);
- rname_limit = rname + PATH_MAX;
- dest = rname;
- if (prefix_len)
- {
- memcpy (rname, name, prefix_len);
- dest += prefix_len;
- }
+ dest = mempcpy (rname, name, prefix_len);
*dest++ = '/';
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
{
- if (ISSLASH (name[1]) && !ISSLASH (name[2]) && !prefix_len)
- *dest++ = '/';
+ if (prefix_len == 0 /* implies ISSLASH (name[0]) */
+ && ISSLASH (name[1]) && !ISSLASH (name[2]))
+ {
+ *dest++ = '/';
+#if defined _WIN32 && !defined __CYGWIN__
+ /* For UNC file names '\\server\path\to\file', extend the prefix
+ to include the server: '\\server\'. */
+ {
+ idx_t i;
+ for (i = 2; name[i] != '\0' && !ISSLASH (name[i]); )
+ i++;
+ if (name[i] != '\0' /* implies ISSLASH (name[i]) */
+ && i + 1 < bufs->rname.length)
+ {
+ prefix_len = i;
+ memcpy (dest, name + 2, i - 2 + 1);
+ dest += i - 2 + 1;
+ }
+ else
+ {
+ /* Either name = '\\server'; this is an invalid file name.
+ Or name = '\\server\...' and server is more than
+ bufs->rname.length - 4 bytes long. In either
+ case, stop the UNC processing. */
+ }
+ }
+#endif
+ }
*dest = '\0';
}
start = name + prefix_len;
@@ -183,119 +286,119 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
for (end = start; *end && !ISSLASH (*end); ++end)
/* Nothing. */;
- if (end - start == 0)
+ /* Length of this file name component; it can be zero if a file
+ name ends in '/'. */
+ idx_t startlen = end - start;
+
+ if (startlen == 0)
break;
- else if (end - start == 1 && start[0] == '.')
+ else if (startlen == 1 && start[0] == '.')
/* nothing */;
- else if (end - start == 2 && start[0] == '.' && start[1] == '.')
+ else if (startlen == 2 && start[0] == '.' && start[1] == '.')
{
/* Back up to previous component, ignore if at root already. */
if (dest > rname + prefix_len + 1)
for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
continue;
- if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
- && !prefix_len && ISSLASH (*dest) && !ISSLASH (dest[1]))
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT
+ && dest == rname + 1 && !prefix_len
+ && ISSLASH (*dest) && !ISSLASH (dest[1]))
dest++;
}
else
{
- struct stat st;
-
if (!ISSLASH (dest[-1]))
*dest++ = '/';
- if (dest + (end - start) >= rname_limit)
+ while (rname + bufs->rname.length - dest
+ < startlen + sizeof dir_suffix)
{
- ptrdiff_t dest_offset = dest - rname;
- size_t new_size = rname_limit - rname;
-
- if (end - start + 1 > PATH_MAX)
- new_size += end - start + 1;
- else
- new_size += PATH_MAX;
- rname = xrealloc (rname, new_size);
- rname_limit = rname + new_size;
-
+ idx_t dest_offset = dest - rname;
+ if (!scratch_buffer_grow_preserve (&bufs->rname))
+ xalloc_die ();
+ rname = bufs->rname.data;
dest = rname + dest_offset;
}
- dest = memcpy (dest, start, end - start);
- dest += end - start;
+ dest = mempcpy (dest, start, startlen);
*dest = '\0';
- if (logical && (can_mode == CAN_MISSING))
- {
- /* Avoid the stat in this case as it's inconsequential.
- i.e. we're neither resolving symlinks or testing
- component existence. */
- st.st_mode = 0;
- }
- else if ((logical ? stat (rname, &st) : lstat (rname, &st)) != 0)
+ char *buf;
+ ssize_t n = -1;
+ if (!logical)
{
- saved_errno = errno;
- if (can_mode == CAN_EXISTING)
- goto error;
- if (can_mode == CAN_ALL_BUT_LAST)
+ while (true)
{
- if (end[strspn (end, SLASHES)] || saved_errno != ENOENT)
- goto error;
- continue;
+ buf = bufs->link.data;
+ idx_t bufsize = bufs->link.length;
+ n = readlink (rname, buf, bufsize - 1);
+ if (n < bufsize - 1)
+ break;
+ if (!scratch_buffer_grow (&bufs->link))
+ xalloc_die ();
}
- st.st_mode = 0;
}
-
- if (S_ISLNK (st.st_mode))
+ if (0 <= n)
{
- char *buf;
- size_t n, len;
-
- /* Detect loops. We cannot use the cycle-check module here,
- since it's actually possible to encounter the same symlink
- more than once in a given traversal. However, encountering
- the same symlink,NAME pair twice does indicate a loop. */
- if (seen_triple (&ht, name, &st))
- {
- if (can_mode == CAN_MISSING)
- continue;
- saved_errno = ELOOP;
- goto error;
- }
+ /* A physical traversal and RNAME is a symbolic link. */
- buf = areadlink_with_size (rname, st.st_size);
- if (!buf)
+ if (num_links < 20)
+ num_links++;
+ else if (*start)
{
- if (can_mode == CAN_MISSING && errno != ENOMEM)
- continue;
- saved_errno = errno;
- goto error;
+ /* Enough symlinks have been seen that it is time to
+ worry about being in a symlink cycle.
+ Get the device and inode of the parent directory, as
+ pre-2017 POSIX says this info is not reliable for
+ symlinks. */
+ struct stat st;
+ dest[- startlen] = '\0';
+ if (stat (*rname ? rname : ".", &st) != 0)
+ goto error;
+ dest[- startlen] = *start;
+
+ /* Detect loops. We cannot use the cycle-check module here,
+ since it's possible to encounter the same parent
+ directory more than once in a given traversal. However,
+ encountering the same (parentdir, START) pair twice does
+ indicate a loop. */
+ if (seen_triple (&ht, start, &st))
+ {
+ if (can_exist == CAN_MISSING)
+ continue;
+ errno = ELOOP;
+ goto error;
+ }
}
- n = strlen (buf);
- len = strlen (end);
+ buf[n] = '\0';
- if (!extra_len)
+ char *extra_buf = bufs->extra.data;
+ idx_t end_idx IF_LINT (= 0);
+ if (end_in_extra_buffer)
+ end_idx = end - extra_buf;
+ size_t len = strlen (end);
+ if (INT_ADD_OVERFLOW (len, n))
+ xalloc_die ();
+ while (bufs->extra.length <= len + n)
{
- extra_len =
- ((n + len + 1) > PATH_MAX) ? (n + len + 1) : PATH_MAX;
- extra_buf = xmalloc (extra_len);
- }
- else if ((n + len + 1) > extra_len)
- {
- extra_len = n + len + 1;
- extra_buf = xrealloc (extra_buf, extra_len);
+ if (!scratch_buffer_grow_preserve (&bufs->extra))
+ xalloc_die ();
+ extra_buf = bufs->extra.data;
}
+ if (end_in_extra_buffer)
+ end = extra_buf + end_idx;
/* Careful here, end may be a pointer into extra_buf... */
memmove (&extra_buf[n], end, len + 1);
name = end = memcpy (extra_buf, buf, n);
+ end_in_extra_buffer = true;
if (IS_ABSOLUTE_FILE_NAME (buf))
{
- size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
+ idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
- if (pfxlen)
- memcpy (rname, buf, pfxlen);
- dest = rname + pfxlen;
+ dest = mempcpy (rname, buf, pfxlen);
*dest++ = '/'; /* It's an absolute symlink */
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
{
@@ -317,17 +420,17 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
&& ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
dest++;
}
-
- free (buf);
- }
- else
- {
- if (!S_ISDIR (st.st_mode) && *end && (can_mode != CAN_MISSING))
- {
- saved_errno = ENOTDIR;
- goto error;
- }
}
+ else if (! (can_exist == CAN_MISSING
+ || (suffix_requires_dir_check (end)
+ ? dir_check (rname, dest)
+ : !logical
+ ? errno == EINVAL
+ : *end || file_accessible (rname))
+ || (can_exist == CAN_ALL_BUT_LAST
+ && errno == ENOENT
+ && !end[strspn (end, SLASHES)])))
+ goto error;
}
}
if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
@@ -335,20 +438,39 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
dest++;
- *dest = '\0';
- if (rname_limit != dest + 1)
- rname = xrealloc (rname, dest - rname + 1);
-
- free (extra_buf);
- if (ht)
- hash_free (ht);
- return rname;
+ failed = false;
error:
- free (extra_buf);
- free (rname);
if (ht)
hash_free (ht);
- errno = saved_errno;
- return NULL;
+
+ if (failed)
+ return NULL;
+
+ *dest++ = '\0';
+ char *result = malloc (dest - rname);
+ if (!result)
+ xalloc_die ();
+ return memcpy (result, rname, dest - rname);
+}
+
+/* Return the canonical absolute name of file NAME, while treating
+ missing elements according to CAN_MODE. A canonical name
+ does not contain any ".", ".." components nor any repeated file name
+ separators ('/') or, depending on other CAN_MODE flags, symlinks.
+ Whether components must exist or not depends on canonicalize mode.
+ The result is malloc'd. */
+
+char *
+canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
+{
+ struct realpath_bufs bufs;
+ scratch_buffer_init (&bufs.rname);
+ scratch_buffer_init (&bufs.extra);
+ scratch_buffer_init (&bufs.link);
+ char *result = canonicalize_filename_mode_stk (name, can_mode, &bufs);
+ scratch_buffer_free (&bufs.link);
+ scratch_buffer_free (&bufs.extra);
+ scratch_buffer_free (&bufs.rname);
+ return result;
}
diff --git a/libsbutil/gnulib/canonicalize.h b/libsbutil/gnulib/canonicalize.h
index 236cba5..3fb8d7a 100644
--- a/libsbutil/gnulib/canonicalize.h
+++ b/libsbutil/gnulib/canonicalize.h
@@ -1,9 +1,9 @@
/* Return the canonical absolute name of a given file.
- Copyright (C) 1996-2007, 2009-2015 Free Software Foundation, Inc.
+ Copyright (C) 1996-2007, 2009-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,
@@ -12,15 +12,24 @@
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/>. */
#ifndef CANONICALIZE_H_
# define CANONICALIZE_H_
+/* This file uses _GL_ATTRIBUTE_MALLOC. */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
#include <stdlib.h> /* for canonicalize_file_name */
#define CAN_MODE_MASK (CAN_EXISTING | CAN_ALL_BUT_LAST | CAN_MISSING)
+#ifdef __cplusplus
+extern "C" {
+#endif
+
enum canonicalize_mode_t
{
/* All components must exist. */
@@ -42,7 +51,13 @@ typedef enum canonicalize_mode_t canonicalize_mode_t;
does not contain any `.', `..' components nor any repeated file name
separators ('/') or, depending on other CAN_MODE flags, symlinks.
Whether components must exist or not depends on canonicalize mode.
- The result is malloc'd. */
-char *canonicalize_filename_mode (const char *, canonicalize_mode_t);
+ The result is malloc'd.
+ Upon failure, return NULL with errno set. */
+char *canonicalize_filename_mode (const char *, canonicalize_mode_t)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
+
+#ifdef __cplusplus
+}
+#endif
#endif /* !CANONICALIZE_H_ */
diff --git a/libsbutil/gnulib/careadlinkat.h b/libsbutil/gnulib/careadlinkat.h
deleted file mode 100644
index 4eb9fcc..0000000
--- a/libsbutil/gnulib/careadlinkat.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Read symbolic links into a buffer without size limitation, relative to fd.
-
- Copyright (C) 2011-2015 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
- (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/>. */
-
-/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */
-
-#ifndef _GL_CAREADLINKAT_H
-#define _GL_CAREADLINKAT_H
-
-#include <fcntl.h>
-#include <unistd.h>
-
-struct allocator;
-
-/* Assuming the current directory is FD, get the symbolic link value
- of FILENAME as a null-terminated string and put it into a buffer.
- If FD is AT_FDCWD, FILENAME is interpreted relative to the current
- working directory, as in openat.
-
- If the link is small enough to fit into BUFFER put it there.
- BUFFER's size is BUFFER_SIZE, and BUFFER can be null
- if BUFFER_SIZE is zero.
-
- If the link is not small, put it into a dynamically allocated
- buffer managed by ALLOC. It is the caller's responsibility to free
- the returned value if it is nonnull and is not BUFFER.
-
- The PREADLINKAT function specifies how to read links. It operates
- like POSIX readlinkat()
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>
- but can assume that its first argument is the same as FD.
-
- If successful, return the buffer address; otherwise return NULL and
- set errno. */
-
-char *careadlinkat (int fd, char const *filename,
- char *buffer, size_t buffer_size,
- struct allocator const *alloc,
- ssize_t (*preadlinkat) (int, char const *,
- char *, size_t));
-
-/* Suitable value for careadlinkat's FD argument. */
-#if HAVE_READLINKAT
-/* AT_FDCWD is declared in <fcntl.h>. */
-#else
-/* Define AT_FDCWD independently, so that the careadlinkat module does
- not depend on the fcntl-h module. We might as well use the same value
- as fcntl-h. */
-# ifndef AT_FDCWD
-# define AT_FDCWD (-3041965)
-# endif
-#endif
-
-#endif /* _GL_CAREADLINKAT_H */
diff --git a/libsbutil/gnulib/cdefs.h b/libsbutil/gnulib/cdefs.h
new file mode 100644
index 0000000..5326903
--- /dev/null
+++ b/libsbutil/gnulib/cdefs.h
@@ -0,0 +1,715 @@
+/* Copyright (C) 1992-2025 Free Software Foundation, Inc.
+ Copyright The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_CDEFS_H
+#define _SYS_CDEFS_H 1
+
+/* We are almost always included from features.h. */
+#ifndef _FEATURES_H
+# include <features.h>
+#endif
+
+/* The GNU libc does not support any K&R compilers or the traditional mode
+ of ISO C compilers anymore. Check for some of the combinations not
+ supported anymore. */
+#if defined __GNUC__ && !defined __STDC__
+# error "You need a ISO C conforming compiler to use the glibc headers"
+#endif
+
+/* Some user header file might have defined this before. */
+#undef __P
+#undef __PMT
+
+/* Compilers that lack __has_attribute may object to
+ #if defined __has_attribute && __has_attribute (...)
+ even though they do not need to evaluate the right-hand side of the &&.
+ Similarly for __has_builtin, etc. */
+#if (defined __has_attribute \
+ && (!defined __clang_minor__ \
+ || (defined __apple_build_version__ \
+ ? 7000000 <= __apple_build_version__ \
+ : 5 <= __clang_major__)))
+# define __glibc_has_attribute(attr) __has_attribute (attr)
+#else
+# define __glibc_has_attribute(attr) 0
+#endif
+#ifdef __has_builtin
+# define __glibc_has_builtin(name) __has_builtin (name)
+#else
+# define __glibc_has_builtin(name) 0
+#endif
+#ifdef __has_extension
+# define __glibc_has_extension(ext) __has_extension (ext)
+#else
+# define __glibc_has_extension(ext) 0
+#endif
+
+#if defined __GNUC__ || defined __clang__
+
+/* All functions, except those with callbacks or those that
+ synchronize memory, are leaf functions. */
+# if __GNUC_PREREQ (4, 6) && !defined _LIBC
+# define __LEAF , __leaf__
+# define __LEAF_ATTR __attribute__ ((__leaf__))
+# else
+# define __LEAF
+# define __LEAF_ATTR
+# endif
+
+/* GCC can always grok prototypes. For C++ programs we add throw()
+ to help it optimize the function calls. But this only works with
+ gcc 2.8.x and egcs. For gcc 3.4 and up we even mark C functions
+ as non-throwing using a function attribute since programs can use
+ the -fexceptions options for C code as well. */
+# if !defined __cplusplus \
+ && (__GNUC_PREREQ (3, 4) || __glibc_has_attribute (__nothrow__))
+# define __THROW __attribute__ ((__nothrow__ __LEAF))
+# define __THROWNL __attribute__ ((__nothrow__))
+# define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct
+# define __NTHNL(fct) __attribute__ ((__nothrow__)) fct
+# else
+# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major__ >= 4)
+# if __cplusplus >= 201103L
+# define __THROW noexcept (true)
+# else
+# define __THROW throw ()
+# endif
+# define __THROWNL __THROW
+# define __NTH(fct) __LEAF_ATTR fct __THROW
+# define __NTHNL(fct) fct __THROW
+# else
+# define __THROW
+# define __THROWNL
+# define __NTH(fct) fct
+# define __NTHNL(fct) fct
+# endif
+# endif
+
+#else /* Not GCC or clang. */
+
+# if (defined __cplusplus \
+ || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
+# define __inline inline
+# else
+# define __inline /* No inline functions. */
+# endif
+
+# define __THROW
+# define __THROWNL
+# define __NTH(fct) fct
+
+#endif /* GCC || clang. */
+
+/* These two macros are not used in glibc anymore. They are kept here
+ only because some other projects expect the macros to be defined. */
+#define __P(args) args
+#define __PMT(args) args
+
+/* For these things, GCC behaves the ANSI way normally,
+ and the non-ANSI way under -traditional. */
+
+#define __CONCAT(x,y) x ## y
+#define __STRING(x) #x
+
+/* This is not a typedef so `const __ptr_t' does the right thing. */
+#define __ptr_t void *
+
+
+/* C++ needs to know that types and declarations are C, not C++. */
+#ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+#else
+# define __BEGIN_DECLS
+# define __END_DECLS
+#endif
+
+
+/* Gnulib avoids these definitions, as they don't work on non-glibc platforms.
+ In particular, __bos and __bos0 are defined differently in the Android libc.
+ */
+#ifndef __GNULIB_CDEFS
+
+/* Fortify support. */
+# define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1)
+# define __bos0(ptr) __builtin_object_size (ptr, 0)
+
+/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available. */
+# if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0) \
+ || __GNUC_PREREQ (12, 0))
+# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0)
+# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1)
+# else
+# define __glibc_objsize0(__o) __bos0 (__o)
+# define __glibc_objsize(__o) __bos (__o)
+# endif
+
+/* Compile time conditions to choose between the regular, _chk and _chk_warn
+ variants. These conditions should get evaluated to constant and optimized
+ away. */
+
+# define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s))
+# define __glibc_unsigned_or_positive(__l) \
+ ((__typeof (__l)) 0 < (__typeof (__l)) -1 \
+ || (__builtin_constant_p (__l) && (__l) > 0))
+
+/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ
+ condition can be folded to a constant and if it is true, or unknown (-1) */
+# define __glibc_safe_or_unknown_len(__l, __s, __osz) \
+ ((__osz) == (__SIZE_TYPE__) -1 \
+ || (__glibc_unsigned_or_positive (__l) \
+ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \
+ (__s), (__osz))) \
+ && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), (__s), (__osz))))
+
+/* Conversely, we know at compile time that the length is unsafe if the
+ __L * __S <= __OBJSZ condition can be folded to a constant and if it is
+ false. */
+# define __glibc_unsafe_len(__l, __s, __osz) \
+ (__glibc_unsigned_or_positive (__l) \
+ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \
+ __s, __osz)) \
+ && !__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz))
+
+/* Fortify function f. __f_alias, __f_chk and __f_chk_warn must be
+ declared. */
+
+# define __glibc_fortify(f, __l, __s, __osz, ...) \
+ (__glibc_safe_or_unknown_len (__l, __s, __osz) \
+ ? __ ## f ## _alias (__VA_ARGS__) \
+ : (__glibc_unsafe_len (__l, __s, __osz) \
+ ? __ ## f ## _chk_warn (__VA_ARGS__, __osz) \
+ : __ ## f ## _chk (__VA_ARGS__, __osz))) \
+
+/* Fortify function f, where object size argument passed to f is the number of
+ elements and not total size. */
+
+# define __glibc_fortify_n(f, __l, __s, __osz, ...) \
+ (__glibc_safe_or_unknown_len (__l, __s, __osz) \
+ ? __ ## f ## _alias (__VA_ARGS__) \
+ : (__glibc_unsafe_len (__l, __s, __osz) \
+ ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s)) \
+ : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s)))) \
+
+#endif
+
+
+#if __GNUC_PREREQ (4,3)
+# define __warnattr(msg) __attribute__((__warning__ (msg)))
+# define __errordecl(name, msg) \
+ extern void name (void) __attribute__((__error__ (msg)))
+#else
+# define __warnattr(msg)
+# define __errordecl(name, msg) extern void name (void)
+#endif
+
+/* Support for flexible arrays.
+ Headers that should use flexible arrays only if they're "real"
+ (e.g. only if they won't affect sizeof()) should test
+ #if __glibc_c99_flexarr_available. */
+#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L && !defined __HP_cc
+# define __flexarr []
+# define __glibc_c99_flexarr_available 1
+#elif __GNUC_PREREQ (2,97) || defined __clang__
+/* GCC 2.97 and clang support C99 flexible array members as an extension,
+ even when in C89 mode or compiling C++ (any version). */
+# define __flexarr []
+# define __glibc_c99_flexarr_available 1
+#elif defined __GNUC__
+/* Pre-2.97 GCC did not support C99 flexible arrays but did have
+ an equivalent extension with slightly different notation. */
+# define __flexarr [0]
+# define __glibc_c99_flexarr_available 1
+#else
+/* Some other non-C99 compiler. Approximate with [1]. */
+# define __flexarr [1]
+# define __glibc_c99_flexarr_available 0
+#endif
+
+
+/* __asm__ ("xyz") is used throughout the headers to rename functions
+ at the assembly language level. This is wrapped by the __REDIRECT
+ macro, in order to support compilers that can do this some other
+ way. When compilers don't support asm-names at all, we have to do
+ preprocessor tricks instead (which don't have exactly the right
+ semantics, but it's the best we can do).
+
+ Example:
+ int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */
+
+#if (defined __GNUC__ && __GNUC__ >= 2) || (__clang_major__ >= 4)
+
+# define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias))
+# ifdef __cplusplus
+# define __REDIRECT_NTH(name, proto, alias) \
+ name proto __THROW __asm__ (__ASMNAME (#alias))
+# define __REDIRECT_NTHNL(name, proto, alias) \
+ name proto __THROWNL __asm__ (__ASMNAME (#alias))
+# else
+# define __REDIRECT_NTH(name, proto, alias) \
+ name proto __asm__ (__ASMNAME (#alias)) __THROW
+# define __REDIRECT_NTHNL(name, proto, alias) \
+ name proto __asm__ (__ASMNAME (#alias)) __THROWNL
+# endif
+# define __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+# define __ASMNAME2(prefix, cname) __STRING (prefix) cname
+
+/*
+#elif __SOME_OTHER_COMPILER__
+
+# define __REDIRECT(name, proto, alias) name proto; \
+ _Pragma("let " #name " = " #alias)
+*/
+#endif
+
+/* GCC and clang have various useful declarations that can be made with
+ the '__attribute__' syntax. All of the ways we use this do fine if
+ they are omitted for compilers that don't understand it. */
+#if !(defined __GNUC__ || defined __clang__)
+# define __attribute__(xyz) /* Ignore */
+#endif
+
+/* At some point during the gcc 2.96 development the `malloc' attribute
+ for functions was introduced. We don't want to use it unconditionally
+ (although this would be possible) since it generates warnings. */
+#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__malloc__)
+# define __attribute_malloc__ __attribute__ ((__malloc__))
+#else
+# define __attribute_malloc__ /* Ignore */
+#endif
+
+/* Tell the compiler which arguments to an allocation function
+ indicate the size of the allocation. */
+#if __GNUC_PREREQ (4, 3)
+# define __attribute_alloc_size__(params) \
+ __attribute__ ((__alloc_size__ params))
+#else
+# define __attribute_alloc_size__(params) /* Ignore. */
+#endif
+
+/* Tell the compiler which argument to an allocation function
+ indicates the alignment of the allocation. */
+#if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__alloc_align__)
+# define __attribute_alloc_align__(param) \
+ __attribute__ ((__alloc_align__ param))
+#else
+# define __attribute_alloc_align__(param) /* Ignore. */
+#endif
+
+/* At some point during the gcc 2.96 development the `pure' attribute
+ for functions was introduced. We don't want to use it unconditionally
+ (although this would be possible) since it generates warnings. */
+#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__pure__)
+# define __attribute_pure__ __attribute__ ((__pure__))
+#else
+# define __attribute_pure__ /* Ignore */
+#endif
+
+/* This declaration tells the compiler that the value is constant. */
+#if __GNUC_PREREQ (2,5) || __glibc_has_attribute (__const__)
+# define __attribute_const__ __attribute__ ((__const__))
+#else
+# define __attribute_const__ /* Ignore */
+#endif
+
+#if __GNUC_PREREQ (2,7) || __glibc_has_attribute (__unused__)
+# define __attribute_maybe_unused__ __attribute__ ((__unused__))
+#else
+# define __attribute_maybe_unused__ /* Ignore */
+#endif
+
+/* At some point during the gcc 3.1 development the `used' attribute
+ for functions was introduced. We don't want to use it unconditionally
+ (although this would be possible) since it generates warnings. */
+#if __GNUC_PREREQ (3,1) || __glibc_has_attribute (__used__)
+# define __attribute_used__ __attribute__ ((__used__))
+# define __attribute_noinline__ __attribute__ ((__noinline__))
+#else
+# define __attribute_used__ __attribute__ ((__unused__))
+# define __attribute_noinline__ /* Ignore */
+#endif
+
+/* Since version 3.2, gcc allows marking deprecated functions. */
+#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__deprecated__)
+# define __attribute_deprecated__ __attribute__ ((__deprecated__))
+#else
+# define __attribute_deprecated__ /* Ignore */
+#endif
+
+/* Since version 4.5, gcc also allows one to specify the message printed
+ when a deprecated function is used. clang claims to be gcc 4.2, but
+ may also support this feature. */
+#if __GNUC_PREREQ (4,5) \
+ || __glibc_has_extension (__attribute_deprecated_with_message__)
+# define __attribute_deprecated_msg__(msg) \
+ __attribute__ ((__deprecated__ (msg)))
+#else
+# define __attribute_deprecated_msg__(msg) __attribute_deprecated__
+#endif
+
+/* At some point during the gcc 2.8 development the `format_arg' attribute
+ for functions was introduced. We don't want to use it unconditionally
+ (although this would be possible) since it generates warnings.
+ If several `format_arg' attributes are given for the same function, in
+ gcc-3.0 and older, all but the last one are ignored. In newer gccs,
+ all designated arguments are considered. */
+#if __GNUC_PREREQ (2,8) || __glibc_has_attribute (__format_arg__)
+# define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x)))
+#else
+# define __attribute_format_arg__(x) /* Ignore */
+#endif
+
+/* At some point during the gcc 2.97 development the `strfmon' format
+ attribute for functions was introduced. We don't want to use it
+ unconditionally (although this would be possible) since it
+ generates warnings. */
+#if __GNUC_PREREQ (2,97) || __glibc_has_attribute (__format__)
+# define __attribute_format_strfmon__(a,b) \
+ __attribute__ ((__format__ (__strfmon__, a, b)))
+#else
+# define __attribute_format_strfmon__(a,b) /* Ignore */
+#endif
+
+/* The nonnull function attribute marks pointer parameters that
+ must not be NULL. This has the name __nonnull in glibc,
+ and __attribute_nonnull__ in files shared with Gnulib to avoid
+ collision with a different __nonnull in DragonFlyBSD 5.9. */
+#ifndef __attribute_nonnull__
+# if __GNUC_PREREQ (3,3) || __glibc_has_attribute (__nonnull__)
+# define __attribute_nonnull__(params) __attribute__ ((__nonnull__ params))
+# else
+# define __attribute_nonnull__(params)
+# endif
+#endif
+#ifndef __nonnull
+# define __nonnull(params) __attribute_nonnull__ (params)
+#endif
+
+/* The returns_nonnull function attribute marks the return type of the function
+ as always being non-null. */
+#ifndef __returns_nonnull
+# if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__returns_nonnull__)
+# define __returns_nonnull __attribute__ ((__returns_nonnull__))
+# else
+# define __returns_nonnull
+# endif
+#endif
+
+/* If fortification mode, we warn about unused results of certain
+ function calls which can lead to problems. */
+#if __GNUC_PREREQ (3,4) || __glibc_has_attribute (__warn_unused_result__)
+# define __attribute_warn_unused_result__ \
+ __attribute__ ((__warn_unused_result__))
+# if defined __USE_FORTIFY_LEVEL && __USE_FORTIFY_LEVEL > 0
+# define __wur __attribute_warn_unused_result__
+# endif
+#else
+# define __attribute_warn_unused_result__ /* empty */
+#endif
+#ifndef __wur
+# define __wur /* Ignore */
+#endif
+
+/* Forces a function to be always inlined. */
+#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__always_inline__)
+/* The Linux kernel defines __always_inline in stddef.h (283d7573), and
+ it conflicts with this definition. Therefore undefine it first to
+ allow either header to be included first. */
+# undef __always_inline
+# define __always_inline __inline __attribute__ ((__always_inline__))
+#else
+# undef __always_inline
+# define __always_inline __inline
+#endif
+
+/* Associate error messages with the source location of the call site rather
+ than with the source location inside the function. */
+#if __GNUC_PREREQ (4,3) || __glibc_has_attribute (__artificial__)
+# define __attribute_artificial__ __attribute__ ((__artificial__))
+#else
+# define __attribute_artificial__ /* Ignore */
+#endif
+
+/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
+ inline semantics, unless -fgnu89-inline is used. Using __GNUC_STDC_INLINE__
+ or __GNUC_GNU_INLINE is not a good enough check for gcc because gcc versions
+ older than 4.3 may define these macros and still not guarantee GNU inlining
+ semantics.
+
+ clang++ identifies itself as gcc-4.2, but has support for GNU inlining
+ semantics, that can be checked for by using the __GNUC_STDC_INLINE_ and
+ __GNUC_GNU_INLINE__ macro definitions. */
+#if (!defined __cplusplus || __GNUC_PREREQ (4,3) \
+ || (defined __clang__ && (defined __GNUC_STDC_INLINE__ \
+ || defined __GNUC_GNU_INLINE__)))
+# if defined __GNUC_STDC_INLINE__ || defined __cplusplus
+# define __extern_inline extern __inline __attribute__ ((__gnu_inline__))
+# define __extern_always_inline \
+ extern __always_inline __attribute__ ((__gnu_inline__))
+# else
+# define __extern_inline extern __inline
+# define __extern_always_inline extern __always_inline
+# endif
+#endif
+
+#ifdef __extern_always_inline
+# define __fortify_function __extern_always_inline __attribute_artificial__
+#endif
+
+/* GCC 4.3 and above allow passing all anonymous arguments of an
+ __extern_always_inline function to some other vararg function. */
+#if __GNUC_PREREQ (4,3)
+# define __va_arg_pack() __builtin_va_arg_pack ()
+# define __va_arg_pack_len() __builtin_va_arg_pack_len ()
+#endif
+
+/* It is possible to compile containing GCC extensions even if GCC is
+ run in pedantic mode if the uses are carefully marked using the
+ `__extension__' keyword. But this is not generally available before
+ version 2.8. */
+#if !(__GNUC_PREREQ (2,8) || defined __clang__)
+# define __extension__ /* Ignore */
+#endif
+
+/* __restrict is known in EGCS 1.2 and above, and in clang.
+ It works also in C++ mode (outside of arrays), but only when spelled
+ as '__restrict', not 'restrict'. */
+#if !(__GNUC_PREREQ (2,92) || __clang_major__ >= 3)
+# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+# define __restrict restrict
+# else
+# define __restrict /* Ignore */
+# endif
+#endif
+
+/* ISO C99 also allows to declare arrays as non-overlapping. The syntax is
+ array_name[restrict]
+ GCC 3.1 and clang support this.
+ This syntax is not usable in C++ mode. */
+#if (__GNUC_PREREQ (3,1) || __clang_major__ >= 3) && !defined __cplusplus
+# define __restrict_arr __restrict
+#else
+# ifdef __GNUC__
+# define __restrict_arr /* Not supported in old GCC. */
+# else
+# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+# define __restrict_arr restrict
+# else
+/* Some other non-C99 compiler. */
+# define __restrict_arr /* Not supported. */
+# endif
+# endif
+#endif
+
+#if (__GNUC__ >= 3) || __glibc_has_builtin (__builtin_expect)
+# define __glibc_unlikely(cond) __builtin_expect ((cond), 0)
+# define __glibc_likely(cond) __builtin_expect ((cond), 1)
+#else
+# define __glibc_unlikely(cond) (cond)
+# define __glibc_likely(cond) (cond)
+#endif
+
+#if (!defined _Noreturn \
+ && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
+ && !(__GNUC_PREREQ (4,7) \
+ || (3 < __clang_major__ + (5 <= __clang_minor__))))
+# if __GNUC_PREREQ (2,8)
+# define _Noreturn __attribute__ ((__noreturn__))
+# else
+# define _Noreturn
+# endif
+#endif
+
+#if __GNUC_PREREQ (8, 0)
+/* Describes a char array whose address can safely be passed as the first
+ argument to strncpy and strncat, as the char array is not necessarily
+ a NUL-terminated string. */
+# define __attribute_nonstring__ __attribute__ ((__nonstring__))
+#else
+# define __attribute_nonstring__
+#endif
+
+/* Undefine (also defined in libc-symbols.h). */
+#undef __attribute_copy__
+#if __GNUC_PREREQ (9, 0)
+/* Copies attributes from the declaration or type referenced by
+ the argument. */
+# define __attribute_copy__(arg) __attribute__ ((__copy__ (arg)))
+#else
+# define __attribute_copy__(arg)
+#endif
+
+#if (!defined _Static_assert && !defined __cplusplus \
+ && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
+ && (!(__GNUC_PREREQ (4, 6) || __clang_major__ >= 4) \
+ || defined __STRICT_ANSI__))
+# define _Static_assert(expr, diagnostic) \
+ extern int (*__Static_assert_function (void)) \
+ [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })]
+#endif
+
+/* Gnulib avoids including these, as they don't work on non-glibc or
+ older glibc platforms. */
+#ifndef __GNULIB_CDEFS
+# include <bits/wordsize.h>
+# include <bits/long-double.h>
+#endif
+
+#if __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
+# ifdef __REDIRECT
+
+/* Alias name defined automatically. */
+# define __LDBL_REDIR(name, proto) ... unused__ldbl_redir
+# define __LDBL_REDIR_DECL(name) \
+ extern __typeof (name) name __asm (__ASMNAME ("__" #name "ieee128"));
+
+/* Alias name defined automatically, with leading underscores. */
+# define __LDBL_REDIR2_DECL(name) \
+ extern __typeof (__##name) __##name \
+ __asm (__ASMNAME ("__" #name "ieee128"));
+
+/* Alias name defined manually. */
+# define __LDBL_REDIR1(name, proto, alias) ... unused__ldbl_redir1
+# define __LDBL_REDIR1_DECL(name, alias) \
+ extern __typeof (name) name __asm (__ASMNAME (#alias));
+
+# define __LDBL_REDIR1_NTH(name, proto, alias) \
+ __REDIRECT_NTH (name, proto, alias)
+# define __REDIRECT_NTH_LDBL(name, proto, alias) \
+ __LDBL_REDIR1_NTH (name, proto, __##alias##ieee128)
+
+/* Unused. */
+# define __REDIRECT_LDBL(name, proto, alias) ... unused__redirect_ldbl
+# define __LDBL_REDIR_NTH(name, proto) ... unused__ldbl_redir_nth
+
+# else
+_Static_assert (0, "IEEE 128-bits long double requires redirection on this platform");
+# endif
+#elif defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH
+# define __LDBL_COMPAT 1
+# ifdef __REDIRECT
+# define __LDBL_REDIR1(name, proto, alias) __REDIRECT (name, proto, alias)
+# define __LDBL_REDIR(name, proto) \
+ __LDBL_REDIR1 (name, proto, __nldbl_##name)
+# define __LDBL_REDIR1_NTH(name, proto, alias) __REDIRECT_NTH (name, proto, alias)
+# define __LDBL_REDIR_NTH(name, proto) \
+ __LDBL_REDIR1_NTH (name, proto, __nldbl_##name)
+# define __LDBL_REDIR2_DECL(name) \
+ extern __typeof (__##name) __##name __asm (__ASMNAME ("__nldbl___" #name));
+# define __LDBL_REDIR1_DECL(name, alias) \
+ extern __typeof (name) name __asm (__ASMNAME (#alias));
+# define __LDBL_REDIR_DECL(name) \
+ extern __typeof (name) name __asm (__ASMNAME ("__nldbl_" #name));
+# define __REDIRECT_LDBL(name, proto, alias) \
+ __LDBL_REDIR1 (name, proto, __nldbl_##alias)
+# define __REDIRECT_NTH_LDBL(name, proto, alias) \
+ __LDBL_REDIR1_NTH (name, proto, __nldbl_##alias)
+# endif
+#endif
+#if (!defined __LDBL_COMPAT && __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 0) \
+ || !defined __REDIRECT
+# define __LDBL_REDIR1(name, proto, alias) name proto
+# define __LDBL_REDIR(name, proto) name proto
+# define __LDBL_REDIR1_NTH(name, proto, alias) name proto __THROW
+# define __LDBL_REDIR_NTH(name, proto) name proto __THROW
+# define __LDBL_REDIR2_DECL(name)
+# define __LDBL_REDIR_DECL(name)
+# ifdef __REDIRECT
+# define __REDIRECT_LDBL(name, proto, alias) __REDIRECT (name, proto, alias)
+# define __REDIRECT_NTH_LDBL(name, proto, alias) \
+ __REDIRECT_NTH (name, proto, alias)
+# endif
+#endif
+
+/* __glibc_macro_warning (MESSAGE) issues warning MESSAGE. This is
+ intended for use in preprocessor macros.
+
+ Note: MESSAGE must be a _single_ string; concatenation of string
+ literals is not supported. */
+#if __GNUC_PREREQ (4,8) || __glibc_clang_prereq (3,5)
+# define __glibc_macro_warning1(message) _Pragma (#message)
+# define __glibc_macro_warning(message) \
+ __glibc_macro_warning1 (GCC warning message)
+#else
+# define __glibc_macro_warning(msg)
+#endif
+
+/* Generic selection (ISO C11) is a C-only feature, available in GCC
+ since version 4.9. Previous versions do not provide generic
+ selection, even though they might set __STDC_VERSION__ to 201112L,
+ when in -std=c11 mode. Thus, we must check for !defined __GNUC__
+ when testing __STDC_VERSION__ for generic selection support.
+ On the other hand, Clang also defines __GNUC__, so a clang-specific
+ check is required to enable the use of generic selection. */
+#if !defined __cplusplus \
+ && (__GNUC_PREREQ (4, 9) \
+ || __glibc_has_extension (c_generic_selections) \
+ || (!defined __GNUC__ && defined __STDC_VERSION__ \
+ && __STDC_VERSION__ >= 201112L))
+# define __HAVE_GENERIC_SELECTION 1
+#else
+# define __HAVE_GENERIC_SELECTION 0
+#endif
+
+#if __GNUC_PREREQ (10, 0)
+/* Designates a 1-based positional argument ref-index of pointer type
+ that can be used to access size-index elements of the pointed-to
+ array according to access mode, or at least one element when
+ size-index is not provided:
+ access (access-mode, <ref-index> [, <size-index>]) */
+# define __attr_access(x) __attribute__ ((__access__ x))
+/* For _FORTIFY_SOURCE == 3 we use __builtin_dynamic_object_size, which may
+ use the access attribute to get object sizes from function definition
+ arguments, so we can't use them on functions we fortify. Drop the object
+ size hints for such functions. */
+# if __USE_FORTIFY_LEVEL == 3
+# define __fortified_attr_access(a, o, s) __attribute__ ((__access__ (a, o)))
+# else
+# define __fortified_attr_access(a, o, s) __attr_access ((a, o, s))
+# endif
+# if __GNUC_PREREQ (11, 0)
+# define __attr_access_none(argno) __attribute__ ((__access__ (__none__, argno)))
+# else
+# define __attr_access_none(argno)
+# endif
+#else
+# define __fortified_attr_access(a, o, s)
+# define __attr_access(x)
+# define __attr_access_none(argno)
+#endif
+
+#if __GNUC_PREREQ (11, 0)
+/* Designates dealloc as a function to call to deallocate objects
+ allocated by the declared function. */
+# define __attr_dealloc(dealloc, argno) \
+ __attribute__ ((__malloc__ (dealloc, argno)))
+# define __attr_dealloc_free __attr_dealloc (__builtin_free, 1)
+#else
+# define __attr_dealloc(dealloc, argno)
+# define __attr_dealloc_free
+#endif
+
+/* Specify that a function such as setjmp or vfork may return
+ twice. */
+#if __GNUC_PREREQ (4, 1)
+# define __attribute_returns_twice__ __attribute__ ((__returns_twice__))
+#else
+# define __attribute_returns_twice__ /* Ignore. */
+#endif
+
+#endif /* sys/cdefs.h */
diff --git a/libsbutil/gnulib/dosname.h b/libsbutil/gnulib/dosname.h
deleted file mode 100644
index 893baf6..0000000
--- a/libsbutil/gnulib/dosname.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* File names on MS-DOS/Windows systems.
-
- Copyright (C) 2000-2001, 2004-2006, 2009-2015 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
- (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/>.
-
- From Paul Eggert and Jim Meyering. */
-
-#ifndef _DOSNAME_H
-#define _DOSNAME_H
-
-#if (defined _WIN32 || defined __WIN32__ || \
- defined __MSDOS__ || defined __CYGWIN__ || \
- defined __EMX__ || defined __DJGPP__)
- /* This internal macro assumes ASCII, but all hosts that support drive
- letters use ASCII. */
-# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \
- <= 'z' - 'a')
-# define FILE_SYSTEM_PREFIX_LEN(Filename) \
- (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
-# ifndef __CYGWIN__
-# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
-# endif
-# define ISSLASH(C) ((C) == '/' || (C) == '\\')
-#else
-# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
-# define ISSLASH(C) ((C) == '/')
-#endif
-
-#ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
-# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
-#endif
-
-#if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
-# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
-# else
-# define IS_ABSOLUTE_FILE_NAME(F) \
- (ISSLASH ((F)[0]) || FILE_SYSTEM_PREFIX_LEN (F) != 0)
-#endif
-#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
-
-#endif /* DOSNAME_H_ */
diff --git a/libsbutil/gnulib/file-set.c b/libsbutil/gnulib/file-set.c
index 1cf2f0c..0d9e920 100644
--- a/libsbutil/gnulib/file-set.c
+++ b/libsbutil/gnulib/file-set.c
@@ -1,9 +1,9 @@
/* Specialized functions to manipulate a set of files.
- Copyright (C) 2007, 2009-2015 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009-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,
@@ -12,7 +12,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, see <http://www.gnu.org/licenses/>. */
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering */
@@ -48,7 +48,7 @@ record_file (Hash_table *ht, char const *file, struct stat const *stats)
if (ent_from_table != ent)
{
- /* There was alread a matching entry in the table, so ENT was
+ /* There was already a matching entry in the table, so ENT was
not inserted. Free it. */
triple_free (ent);
}
diff --git a/libsbutil/gnulib/file-set.h b/libsbutil/gnulib/file-set.h
index 4e47d95..36d66e5 100644
--- a/libsbutil/gnulib/file-set.h
+++ b/libsbutil/gnulib/file-set.h
@@ -1,15 +1,42 @@
+/* Very specialized set-of-files code.
+ Copyright (C) 2007-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
+ (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 <https://www.gnu.org/licenses/>. */
+
+/* Written by Jim Meyering, 2007. */
+
#include <sys/types.h>
#include <sys/stat.h>
-#include <stdbool.h>
#include "hash.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
extern void record_file (Hash_table *ht, char const *file,
struct stat const *stats)
-#if defined __GNUC__ && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3)
- __attribute__ ((nonnull (2, 3)))
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || defined __clang__
+ __attribute__ ((__nonnull__ (2, 3)))
#endif
;
extern bool seen_file (Hash_table const *ht, char const *file,
struct stat const *stats);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libsbutil/gnulib/filename.h b/libsbutil/gnulib/filename.h
new file mode 100644
index 0000000..e353363
--- /dev/null
+++ b/libsbutil/gnulib/filename.h
@@ -0,0 +1,112 @@
+/* Basic filename support macros.
+ Copyright (C) 2001-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* From Paul Eggert and Jim Meyering. */
+
+#ifndef _FILENAME_H
+#define _FILENAME_H
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Filename support.
+ ISSLASH(C) tests whether C is a directory separator
+ character.
+ HAS_DEVICE(Filename) tests whether Filename contains a device
+ specification.
+ FILE_SYSTEM_PREFIX_LEN(Filename) length of the device specification
+ at the beginning of Filename,
+ index of the part consisting of
+ alternating components and slashes.
+ FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+ 1 when a non-empty device specification
+ can be followed by an empty or relative
+ part,
+ 0 when a non-empty device specification
+ must be followed by a slash,
+ 0 when device specification don't exist.
+ IS_ABSOLUTE_FILE_NAME(Filename)
+ tests whether Filename is independent of
+ any notion of "current directory".
+ IS_RELATIVE_FILE_NAME(Filename)
+ tests whether Filename may be concatenated
+ to a directory filename.
+ Note: On native Windows, OS/2, DOS, "c:" is neither an absolute nor a
+ relative file name!
+ IS_FILE_NAME_WITH_DIR(Filename) tests whether Filename contains a device
+ or directory specification.
+ */
+#if defined _WIN32 || defined __CYGWIN__ \
+ || defined __EMX__ || defined __MSDOS__ || defined __DJGPP__
+ /* Native Windows, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+ /* Internal macro: Tests whether a character is a drive letter. */
+# define _IS_DRIVE_LETTER(C) \
+ (((C) >= 'A' && (C) <= 'Z') || ((C) >= 'a' && (C) <= 'z'))
+ /* Help the compiler optimizing it. This assumes ASCII. */
+# undef _IS_DRIVE_LETTER
+# define _IS_DRIVE_LETTER(C) \
+ (((unsigned int) (C) | ('a' - 'A')) - 'a' <= 'z' - 'a')
+# define HAS_DEVICE(Filename) \
+ (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':')
+# define FILE_SYSTEM_PREFIX_LEN(Filename) (HAS_DEVICE (Filename) ? 2 : 0)
+# ifdef __CYGWIN__
+# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
+# else
+ /* On native Windows, OS/2, DOS, the system has the notion of a
+ "current directory" on each drive. */
+# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
+# endif
+# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+# define IS_ABSOLUTE_FILE_NAME(Filename) \
+ ISSLASH ((Filename)[FILE_SYSTEM_PREFIX_LEN (Filename)])
+# else
+# define IS_ABSOLUTE_FILE_NAME(Filename) \
+ (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename))
+# endif
+# define IS_RELATIVE_FILE_NAME(Filename) \
+ (! (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename)))
+# define IS_FILE_NAME_WITH_DIR(Filename) \
+ (strchr ((Filename), '/') != NULL || strchr ((Filename), '\\') != NULL \
+ || HAS_DEVICE (Filename))
+#else
+ /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define HAS_DEVICE(Filename) ((void) (Filename), 0)
+# define FILE_SYSTEM_PREFIX_LEN(Filename) ((void) (Filename), 0)
+# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
+# define IS_ABSOLUTE_FILE_NAME(Filename) ISSLASH ((Filename)[0])
+# define IS_RELATIVE_FILE_NAME(Filename) (! ISSLASH ((Filename)[0]))
+# define IS_FILE_NAME_WITH_DIR(Filename) (strchr ((Filename), '/') != NULL)
+#endif
+
+/* Deprecated macros. For backward compatibility with old users of the
+ 'filename' module. */
+#define IS_ABSOLUTE_PATH IS_ABSOLUTE_FILE_NAME
+#define IS_PATH_WITH_DIR IS_FILE_NAME_WITH_DIR
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FILENAME_H */
diff --git a/libsbutil/gnulib/gl-inline.h b/libsbutil/gnulib/gl-inline.h
index bb8598e..d752cc7 100644
--- a/libsbutil/gnulib/gl-inline.h
+++ b/libsbutil/gnulib/gl-inline.h
@@ -3,13 +3,14 @@
/* Please see the Gnulib manual for how to use these macros.
Suppress extern inline with HP-UX cc, as it appears to be broken; see
- <http://lists.gnu.org/archive/html/bug-texinfo/2013-02/msg00030.html>.
+ <https://lists.gnu.org/r/bug-texinfo/2013-02/msg00030.html>.
Suppress extern inline with Sun C in standards-conformance mode, as it
mishandles inline functions that call each other. E.g., for 'inline void f
(void) { } inline void g (void) { f (); }', c99 incorrectly complains
'reference to static identifier "f" in extern inline function'.
- This bug was observed with Sun C 5.12 SunOS_i386 2011/11/16.
+ This bug was observed with Oracle Developer Studio 12.6
+ (Sun C 5.15 SunOS_sparc 2017/05/30).
Suppress extern inline (with or without __attribute__ ((__gnu_inline__)))
on configurations that mistakenly use 'static inline' to implement
@@ -17,23 +18,35 @@
if isdigit is mistakenly implemented via a static inline function,
a program containing an extern inline function that calls isdigit
may not work since the C standard prohibits extern inline functions
- from calling static functions. This bug is known to occur on:
+ from calling static functions (ISO C 99 section 6.7.4.(3).
+ This bug is known to occur on:
OS X 10.8 and earlier; see:
- http://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html
+ https://lists.gnu.org/r/bug-gnulib/2012-12/msg00023.html
DragonFly; see
- http://muscles.dragonflybsd.org/bulk/bleeding-edge-potential/latest-per-pkg/ah-tty-0.3.12.log
+ http://muscles.dragonflybsd.org/bulk/clang-master-potential/20141111_102002/logs/ah-tty-0.3.12.log
FreeBSD; see:
- http://lists.gnu.org/archive/html/bug-gnulib/2014-07/msg00104.html
+ https://lists.gnu.org/r/bug-gnulib/2014-07/msg00104.html
OS X 10.9 has a macro __header_inline indicating the bug is fixed for C and
- for clang but remains for g++; see <http://trac.macports.org/ticket/41033>.
- Assume DragonFly and FreeBSD will be similar. */
+ for clang but remains for g++; see <https://trac.macports.org/ticket/41033>.
+ Assume DragonFly and FreeBSD will be similar.
+
+ GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
+ inline semantics, unless -fgnu89-inline is used. It defines a macro
+ __GNUC_STDC_INLINE__ to indicate this situation or a macro
+ __GNUC_GNU_INLINE__ to indicate the opposite situation.
+ GCC 4.2 with -std=c99 or -std=gnu99 implements the GNU C inline
+ semantics but warns, unless -fgnu89-inline is used:
+ warning: C99 inline functions are not supported; using GNU89
+ warning: to disable this warning use -fgnu89-inline or the gnu_inline function attribute
+ It defines a macro __GNUC_GNU_INLINE__ to indicate this situation.
+ */
#if (((defined __APPLE__ && defined __MACH__) \
|| defined __DragonFly__ || defined __FreeBSD__) \
- && (defined __header_inline \
+ && (defined HAVE___HEADER_INLINE \
? (defined __cplusplus && defined __GNUC_STDC_INLINE__ \
&& ! defined __clang__) \
: ((! defined _DONT_USE_CTYPE_INLINE_ \
@@ -43,15 +56,18 @@
# define _GL_EXTERN_INLINE_STDHEADER_BUG
#endif
#if ((__GNUC__ \
- ? defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ \
+ ? (defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ \
+ && !defined __PCC__) \
: (199901L <= __STDC_VERSION__ \
&& !defined __HP_cc \
+ && !defined __PGI \
&& !(defined __SUNPRO_C && __STDC__))) \
&& !defined _GL_EXTERN_INLINE_STDHEADER_BUG)
# define _GL_INLINE inline
# define _GL_EXTERN_INLINE extern inline
# define _GL_EXTERN_INLINE_IN_USE
#elif (2 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __STRICT_ANSI__ \
+ && !defined __PCC__ \
&& !defined _GL_EXTERN_INLINE_STDHEADER_BUG)
# if defined __GNUC_GNU_INLINE__ && __GNUC_GNU_INLINE__
/* __gnu_inline__ suppresses a GCC 4.2 diagnostic. */
@@ -62,8 +78,8 @@
# define _GL_EXTERN_INLINE extern
# define _GL_EXTERN_INLINE_IN_USE
#else
-# define _GL_INLINE static _GL_UNUSED
-# define _GL_EXTERN_INLINE static _GL_UNUSED
+# define _GL_INLINE _GL_UNUSED static
+# define _GL_EXTERN_INLINE _GL_UNUSED static
#endif
/* In GCC 4.6 (inclusive) to 5.1 (exclusive),
diff --git a/libsbutil/gnulib/glue.h b/libsbutil/gnulib/glue.h
index 083ab73..2e0602d 100644
--- a/libsbutil/gnulib/glue.h
+++ b/libsbutil/gnulib/glue.h
@@ -4,7 +4,70 @@
* Licensed under the GPL-2
*/
+#pragma once
+
+#define _GL_CONFIG_H_INCLUDED 1
+
+#if defined __GNUC__ && defined __GNUC_MINOR__ && !defined __clang__
+# define _GL_GNUC_PREREQ(major, minor) \
+ ((major) < __GNUC__ + ((minor) <= __GNUC_MINOR__))
+#elif defined __clang__
+ /* clang really only groks GNU C 4.2. */
+# define _GL_GNUC_PREREQ(major, minor) \
+ ((major) < 4 + ((minor) <= 2))
+#else
+# define _GL_GNUC_PREREQ(major, minor) 0
+#endif
+
+#ifndef _GL_ATTRIBUTE_DEALLOC
+# if _GL_GNUC_PREREQ (11, 0)
+# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i)))
+# else
+# define _GL_ATTRIBUTE_DEALLOC(f, i)
+# endif
+#endif
+
+#define _GL_ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args))
+#define _GL_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__))
#define _GL_ATTRIBUTE_CONST __attribute__ ((__const__))
+#define _GL_ATTRIBUTE_COLD __attribute__ ((__cold__))
+#define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (free, 1)
+#define _GL_ATTRIBUTE_DEPRECATED [[__deprecated__]]
+#define _GL_ATTRIBUTE_FALLTHROUGH [[__fallthrough__]]
+#define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+#define _GL_ATTRIBUTE_NODISCARD [[__nodiscard__]]
#define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
+#define _GL_ATTRIBUTE_RETURNS_NONNULL __attribute__ ((__returns_nonnull__))
#include "gl-inline.h"
+
+/* musl does not have rawmemchr */
+#if !HAVE_DECL_RAWMEMCHR
+void *rawmemchr(const void *s, int c);
+#endif
+
+/* gnulib's rawmemchr uses static_assert */
+#ifndef HAVE_RAWMEMCHR
+#include <assert.h>
+#endif
+
+/* C23 compat */
+#include <stdbool.h>
+#include <limits.h>
+#include <stdint.h>
+
+#define _GL_INTEGER_WIDTH(min, max) (((min) < 0) + _GL_COB128 (max))
+#define _GL_COB128(n) (_GL_COB64 ((n) >> 31 >> 31 >> 2) + _GL_COB64 (n))
+#define _GL_COB64(n) (_GL_COB32 ((n) >> 31 >> 1) + _GL_COB32 (n))
+#define _GL_COB32(n) (_GL_COB16 ((n) >> 16) + _GL_COB16 (n))
+#define _GL_COB16(n) (_GL_COB8 ((n) >> 8) + _GL_COB8 (n))
+#define _GL_COB8(n) (_GL_COB4 ((n) >> 4) + _GL_COB4 (n))
+#define _GL_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + !!((n) & 1))
+
+#ifndef UCHAR_WIDTH
+# define UCHAR_WIDTH _GL_INTEGER_WIDTH (0, UCHAR_MAX)
+#endif
+
+#ifndef UINTPTR_WIDTH
+# define UINTPTR_WIDTH _GL_INTEGER_WIDTH(0, UINTPTR_MAX)
+#endif
diff --git a/libsbutil/gnulib/hash-pjw.c b/libsbutil/gnulib/hash-pjw.c
index b2e0251..fbe8ef6 100644
--- a/libsbutil/gnulib/hash-pjw.c
+++ b/libsbutil/gnulib/hash-pjw.c
@@ -1,19 +1,19 @@
/* hash-pjw.c -- compute a hash value from a NUL-terminated string.
- Copyright (C) 2001, 2003, 2006, 2009-2015 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003, 2006, 2009-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
- (at your option) any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser 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/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -25,7 +25,7 @@
/* A hash function for NUL-terminated char* strings using
the method described by Bruno Haible.
- See http://www.haible.de/bruno/hashfunc.html. */
+ See https://www.haible.de/bruno/hashfunc.html. */
size_t
hash_pjw (const void *x, size_t tablesize)
diff --git a/libsbutil/gnulib/hash-pjw.h b/libsbutil/gnulib/hash-pjw.h
index f4b005c..1d9ffea 100644
--- a/libsbutil/gnulib/hash-pjw.h
+++ b/libsbutil/gnulib/hash-pjw.h
@@ -1,23 +1,38 @@
/* hash-pjw.h -- declaration for a simple hash function
- Copyright (C) 2001, 2003, 2009-2015 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003, 2009-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
- (at your option) any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser 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/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* This file uses _GL_ATTRIBUTE_PURE. */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
#include <stddef.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
/* Compute a hash code for a NUL-terminated string starting at X,
and return the hash code modulo TABLESIZE.
The result is platform dependent: it depends on the size of the 'size_t'
type and on the signedness of the 'char' type. */
extern size_t hash_pjw (void const *x, size_t tablesize) _GL_ATTRIBUTE_PURE;
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libsbutil/gnulib/hash-triple.c b/libsbutil/gnulib/hash-triple-simple.c
similarity index 71%
rename from libsbutil/gnulib/hash-triple.c
rename to libsbutil/gnulib/hash-triple-simple.c
index 06cfbdf..51d1332 100644
--- a/libsbutil/gnulib/hash-triple.c
+++ b/libsbutil/gnulib/hash-triple-simple.c
@@ -1,9 +1,9 @@
/* Hash functions for file-related triples: name, device, inode.
- Copyright (C) 2007, 2009-2015 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009-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,
@@ -12,12 +12,13 @@
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/>. */
/* written by Jim Meyering */
#include <config.h>
+/* Specification. */
#include "hash-triple.h"
#include <stdlib.h>
@@ -39,23 +40,13 @@ triple_hash (void const *x, size_t table_size)
return (tmp ^ p->st_ino) % table_size;
}
-/* Hash an F_triple, without considering the file name. */
-size_t
-triple_hash_no_name (void const *x, size_t table_size)
-{
- struct F_triple const *p = x;
-
- /* Ignoring the device number here should be fine. */
- return p->st_ino % table_size;
-}
-
/* Compare two F_triple structs. */
bool
triple_compare_ino_str (void const *x, void const *y)
{
struct F_triple const *a = x;
struct F_triple const *b = y;
- return (SAME_INODE (*a, *b) && STREQ (a->name, b->name)) ? true : false;
+ return PSAME_INODE (a, b) && STREQ (a->name, b->name);
}
/* Free an F_triple. */
diff --git a/libsbutil/gnulib/hash-triple.h b/libsbutil/gnulib/hash-triple.h
index 0658d81..63819ae 100644
--- a/libsbutil/gnulib/hash-triple.h
+++ b/libsbutil/gnulib/hash-triple.h
@@ -1,9 +1,36 @@
+/* Hash functions for file-related (name, device, inode) triples.
+ Copyright (C) 2007-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
+ (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 <https://www.gnu.org/licenses/>. */
+
+/* Written by Jim Meyering, 2007. */
+
#ifndef HASH_TRIPLE_H
#define HASH_TRIPLE_H
+/* This file uses _GL_ATTRIBUTE_PURE. */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
#include <sys/types.h>
#include <sys/stat.h>
-#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* Describe a just-created or just-renamed destination file. */
struct F_triple
@@ -13,12 +40,21 @@ struct F_triple
dev_t st_dev;
};
+/* Defined in module 'hash-triple-simple'. */
+
extern size_t triple_hash (void const *x, size_t table_size) _GL_ATTRIBUTE_PURE;
-extern size_t triple_hash_no_name (void const *x, size_t table_size)
- _GL_ATTRIBUTE_PURE;
-extern bool triple_compare (void const *x, void const *y);
extern bool triple_compare_ino_str (void const *x, void const *y)
_GL_ATTRIBUTE_PURE;
extern void triple_free (void *x);
+/* Defined in module 'hash-triple'. */
+extern size_t triple_hash_no_name (void const *x, size_t table_size)
+ _GL_ATTRIBUTE_PURE;
+extern bool triple_compare (void const *x, void const *y);
+
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/libsbutil/gnulib/hash.c b/libsbutil/gnulib/hash.c
index 4f27d5c..e06a235 100644
--- a/libsbutil/gnulib/hash.c
+++ b/libsbutil/gnulib/hash.c
@@ -1,21 +1,21 @@
/* hash - hashing table processing.
- Copyright (C) 1998-2004, 2006-2007, 2009-2015 Free Software Foundation, Inc.
+ Copyright (C) 1998-2004, 2006-2007, 2009-2025 Free Software Foundation, Inc.
Written by Jim Meyering, 1992.
- 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser 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/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* A generic hash table package. */
@@ -29,6 +29,7 @@
#include "bitrotate.h"
#include "xalloc-oversized.h"
+#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -138,38 +139,24 @@ static const Hash_tuning default_tuning =
/* Information and lookup. */
-/* The following few functions provide information about the overall hash
- table organization: the number of entries, number of buckets and maximum
- length of buckets. */
-
-/* Return the number of buckets in the hash table. The table size, the total
- number of buckets (used plus unused), or the maximum number of slots, are
- the same quantity. */
-
size_t
hash_get_n_buckets (const Hash_table *table)
{
return table->n_buckets;
}
-/* Return the number of slots in use (non-empty buckets). */
-
size_t
hash_get_n_buckets_used (const Hash_table *table)
{
return table->n_buckets_used;
}
-/* Return the number of active entries. */
-
size_t
hash_get_n_entries (const Hash_table *table)
{
return table->n_entries;
}
-/* Return the length of the longest chain (bucket). */
-
size_t
hash_get_max_bucket_length (const Hash_table *table)
{
@@ -194,9 +181,6 @@ hash_get_max_bucket_length (const Hash_table *table)
return max_bucket_length;
}
-/* Do a mild validation of a hash table, by traversing it and checking two
- statistics. */
-
bool
hash_table_ok (const Hash_table *table)
{
@@ -254,9 +238,6 @@ safe_hasher (const Hash_table *table, const void *key)
return table->bucket + n;
}
-/* If ENTRY matches an entry already in the hash table, return the
- entry from the table. Otherwise, return NULL. */
-
void *
hash_lookup (const Hash_table *table, const void *entry)
{
@@ -275,15 +256,6 @@ hash_lookup (const Hash_table *table, const void *entry)
/* Walking. */
-/* The functions in this page traverse the hash table and process the
- contained entries. For the traversal to work properly, the hash table
- should not be resized nor modified while any particular entry is being
- processed. In particular, entries should not be added, and an entry
- may be removed only if there is no shrink threshold and the entry being
- removed has already been passed to hash_get_next. */
-
-/* Return the first data in the table, or NULL if the table is empty. */
-
void *
hash_get_first (const Hash_table *table)
{
@@ -299,10 +271,6 @@ hash_get_first (const Hash_table *table)
return bucket->data;
}
-/* Return the user data for the entry following ENTRY, where ENTRY has been
- returned by a previous call to either 'hash_get_first' or 'hash_get_next'.
- Return NULL if there are no more entries. */
-
void *
hash_get_next (const Hash_table *table, const void *entry)
{
@@ -328,10 +296,6 @@ hash_get_next (const Hash_table *table, const void *entry)
return NULL;
}
-/* Fill BUFFER with pointers to active user entries in the hash table, then
- return the number of pointers copied. Do not copy more than BUFFER_SIZE
- pointers. */
-
size_t
hash_get_entries (const Hash_table *table, void **buffer,
size_t buffer_size)
@@ -356,14 +320,6 @@ hash_get_entries (const Hash_table *table, void **buffer,
return counter;
}
-/* Call a PROCESSOR function for each entry of a hash table, and return the
- number of entries for which the processor function returned success. A
- pointer to some PROCESSOR_DATA which will be made available to each call to
- the processor function. The PROCESSOR accepts two arguments: the first is
- the user entry being walked into, the second is the value of PROCESSOR_DATA
- as received. The walking continue for as long as the PROCESSOR function
- returns nonzero. When it returns zero, the walking is interrupted. */
-
size_t
hash_do_for_each (const Hash_table *table, Hash_processor processor,
void *processor_data)
@@ -390,9 +346,6 @@ hash_do_for_each (const Hash_table *table, Hash_processor processor,
/* Allocation and clean-up. */
-/* Return a hash index for a NUL-terminated STRING between 0 and N_BUCKETS-1.
- This is a convenience routine for constructing other hashing functions. */
-
#if USE_DIFF_HASH
/* About hashings, Paul Eggert writes to me (FP), on 1994-01-01: "Please see
@@ -546,49 +499,19 @@ compute_bucket_size (size_t candidate, const Hash_tuning *tuning)
if (!tuning->is_n_buckets)
{
float new_candidate = candidate / tuning->growth_threshold;
- if (SIZE_MAX <= new_candidate)
- return 0;
+ if ((float) SIZE_MAX <= new_candidate)
+ goto nomem;
candidate = new_candidate;
}
candidate = next_prime (candidate);
if (xalloc_oversized (candidate, sizeof (struct hash_entry *)))
- return 0;
+ goto nomem;
return candidate;
-}
-/* Allocate and return a new hash table, or NULL upon failure. The initial
- number of buckets is automatically selected so as to _guarantee_ that you
- may insert at least CANDIDATE different user entries before any growth of
- the hash table size occurs. So, if have a reasonably tight a-priori upper
- bound on the number of entries you intend to insert in the hash table, you
- may save some table memory and insertion time, by specifying it here. If
- the IS_N_BUCKETS field of the TUNING structure is true, the CANDIDATE
- argument has its meaning changed to the wanted number of buckets.
-
- TUNING points to a structure of user-supplied values, in case some fine
- tuning is wanted over the default behavior of the hasher. If TUNING is
- NULL, the default tuning parameters are used instead. If TUNING is
- provided but the values requested are out of bounds or might cause
- rounding errors, return NULL.
-
- The user-supplied HASHER function, when not NULL, accepts two
- arguments ENTRY and TABLE_SIZE. It computes, by hashing ENTRY contents, a
- slot number for that entry which should be in the range 0..TABLE_SIZE-1.
- This slot number is then returned.
-
- The user-supplied COMPARATOR function, when not NULL, accepts two
- arguments pointing to user data, it then returns true for a pair of entries
- that compare equal, or false otherwise. This function is internally called
- on entries which are already known to hash to the same bucket index,
- but which are distinct pointers.
-
- The user-supplied DATA_FREER function, when not NULL, may be later called
- with the user data as an argument, just before the entry containing the
- data gets freed. This happens from within 'hash_free' or 'hash_clear'.
- You should specify this function only if you want these functions to free
- all of your 'data' data. This is typically the case when your data is
- simply an auxiliary struct that you have malloc'd to aggregate several
- values. */
+ nomem:
+ errno = ENOMEM;
+ return 0;
+}
Hash_table *
hash_initialize (size_t candidate, const Hash_tuning *tuning,
@@ -616,6 +539,7 @@ hash_initialize (size_t candidate, const Hash_tuning *tuning,
if the user provides invalid tuning options, we silently revert to
using the defaults, and ignore further request to change the tuning
options. */
+ errno = EINVAL;
goto fail;
}
@@ -645,10 +569,6 @@ hash_initialize (size_t candidate, const Hash_tuning *tuning,
return NULL;
}
-/* Make all buckets empty, placing any chained entries on the free list.
- Apply the user-specified function data_freer (if any) to the datas of any
- affected entries. */
-
void
hash_clear (Hash_table *table)
{
@@ -687,17 +607,13 @@ hash_clear (Hash_table *table)
table->n_entries = 0;
}
-/* Reclaim all storage associated with a hash table. If a data_freer
- function has been supplied by the user when the hash table was created,
- this function applies it to the data of each entry before freeing that
- entry. */
-
void
hash_free (Hash_table *table)
{
struct hash_entry *bucket;
struct hash_entry *cursor;
struct hash_entry *next;
+ int err = errno;
/* Call the user data_freer function. */
if (table->data_freer && table->n_entries)
@@ -740,6 +656,8 @@ hash_free (Hash_table *table)
/* Free the remainder of the hash table structure. */
free (table->bucket);
free (table);
+
+ errno = err;
}
/* Insertion and deletion. */
@@ -853,8 +771,8 @@ hash_find_entry (Hash_table *table, const void *entry,
/* Internal helper, to move entries from SRC to DST. Both tables must
share the same free entry list. If SAFE, only move overflow
entries, saving bucket heads for later, so that no allocations will
- occur. Return false if the free entry list is exhausted and an
- allocation fails. */
+ occur. Return false (setting errno) if the free entry list is
+ exhausted and an allocation fails. */
static bool
transfer_entries (Hash_table *dst, Hash_table *src, bool safe)
@@ -931,14 +849,6 @@ transfer_entries (Hash_table *dst, Hash_table *src, bool safe)
return true;
}
-/* For an already existing hash table, change the number of buckets through
- specifying CANDIDATE. The contents of the hash table are preserved. The
- new number of buckets is automatically selected so as to _guarantee_ that
- the table may receive at least CANDIDATE different user entries, including
- those already in the table, before any other growth of the hash table size
- occurs. If TUNING->IS_N_BUCKETS is true, then CANDIDATE specifies the
- exact number of buckets desired. Return true iff the rehash succeeded. */
-
bool
hash_rehash (Hash_table *table, size_t candidate)
{
@@ -1009,31 +919,17 @@ hash_rehash (Hash_table *table, size_t candidate)
passes. Two passes give worse cache performance and takes
longer, but at this point, we're already out of memory, so slow
and safe is better than failure. */
+ int err = errno;
table->free_entry_list = new_table->free_entry_list;
if (! (transfer_entries (table, new_table, true)
&& transfer_entries (table, new_table, false)))
abort ();
/* table->n_entries already holds its value. */
free (new_table->bucket);
+ errno = err;
return false;
}
-/* Insert ENTRY into hash TABLE if there is not already a matching entry.
-
- Return -1 upon memory allocation failure.
- Return 1 if insertion succeeded.
- Return 0 if there is already a matching entry in the table,
- and in that case, if MATCHED_ENT is non-NULL, set *MATCHED_ENT
- to that entry.
-
- This interface is easier to use than hash_insert when you must
- distinguish between the latter two cases. More importantly,
- hash_insert is unusable for some types of ENTRY values. When using
- hash_insert, the only way to distinguish those cases is to compare
- the return value and ENTRY. That works only when you can have two
- different ENTRY values that point to data that compares "equal". Thus,
- when the ENTRY value is a simple scalar, you must use
- hash_insert_if_absent. ENTRY must not be NULL. */
int
hash_insert_if_absent (Hash_table *table, void const *entry,
void const **matched_ent)
@@ -1076,8 +972,11 @@ hash_insert_if_absent (Hash_table *table, void const *entry,
: (table->n_buckets * tuning->growth_factor
* tuning->growth_threshold));
- if (SIZE_MAX <= candidate)
- return -1;
+ if ((float) SIZE_MAX <= candidate)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
/* If the rehash fails, arrange to return NULL. */
if (!hash_rehash (table, candidate))
@@ -1116,12 +1015,6 @@ hash_insert_if_absent (Hash_table *table, void const *entry,
return 1;
}
-/* If ENTRY matches an entry already in the hash table, return the pointer
- to the entry from the table. Otherwise, insert ENTRY and return ENTRY.
- Return NULL if the storage required for insertion cannot be allocated.
- This implementation does not support duplicate entries or insertion of
- NULL. */
-
void *
hash_insert (Hash_table *table, void const *entry)
{
@@ -1132,12 +1025,8 @@ hash_insert (Hash_table *table, void const *entry)
: (void *) (err == 0 ? matched_ent : entry));
}
-/* If ENTRY is already in the table, remove it and return the just-deleted
- data (the user may want to deallocate its storage). If ENTRY is not in the
- table, don't modify the table and return NULL. */
-
void *
-hash_delete (Hash_table *table, const void *entry)
+hash_remove (Hash_table *table, const void *entry)
{
void *data;
struct hash_entry *bucket;
@@ -1196,6 +1085,12 @@ hash_delete (Hash_table *table, const void *entry)
return data;
}
+void *
+hash_delete (Hash_table *table, const void *entry)
+{
+ return hash_remove (table, entry);
+}
+
/* Testing. */
#if TESTING
diff --git a/libsbutil/gnulib/hash.h b/libsbutil/gnulib/hash.h
index 1e90c31..397b421 100644
--- a/libsbutil/gnulib/hash.h
+++ b/libsbutil/gnulib/hash.h
@@ -1,20 +1,20 @@
/* hash - hashing table processing.
- Copyright (C) 1998-1999, 2001, 2003, 2009-2015 Free Software Foundation,
+ Copyright (C) 1998-1999, 2001, 2003, 2009-2025 Free Software Foundation,
Inc.
Written by Jim Meyering <meyering@ascend.com>, 1998.
- 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser 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/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* A generic hash table package. */
@@ -24,32 +24,19 @@
#ifndef HASH_H_
# define HASH_H_
+/* This file uses _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_DEPRECATED,
+ _GL_ATTRIBUTE_MALLOC, _GL_ATTRIBUTE_NODISCARD, _GL_ATTRIBUTE_PURE,
+ _GL_ATTRIBUTE_RETURNS_NONNULL. */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
# include <stdio.h>
-# include <stdbool.h>
-
-/* The __attribute__ feature is available in gcc versions 2.5 and later.
- The warn_unused_result attribute appeared first in gcc-3.4.0. */
-# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-# define _GL_ATTRIBUTE_WUR __attribute__ ((__warn_unused_result__))
-# else
-# define _GL_ATTRIBUTE_WUR /* empty */
-# endif
-# ifndef _GL_ATTRIBUTE_DEPRECATED
-/* The __attribute__((__deprecated__)) feature
- is available in gcc versions 3.1 and newer. */
-# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 1)
-# define _GL_ATTRIBUTE_DEPRECATED /* empty */
-# else
-# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__))
-# endif
+# ifdef __cplusplus
+extern "C" {
# endif
-typedef size_t (*Hash_hasher) (const void *, size_t);
-typedef bool (*Hash_comparator) (const void *, const void *);
-typedef void (*Hash_data_freer) (void *);
-typedef bool (*Hash_processor) (void *, void *);
-
struct hash_tuning
{
/* This structure is mainly used for 'hash_initialize', see the block
@@ -68,36 +55,219 @@ struct hash_table;
typedef struct hash_table Hash_table;
-/* Information and lookup. */
-size_t hash_get_n_buckets (const Hash_table *) _GL_ATTRIBUTE_PURE;
-size_t hash_get_n_buckets_used (const Hash_table *) _GL_ATTRIBUTE_PURE;
-size_t hash_get_n_entries (const Hash_table *) _GL_ATTRIBUTE_PURE;
-size_t hash_get_max_bucket_length (const Hash_table *) _GL_ATTRIBUTE_PURE;
-bool hash_table_ok (const Hash_table *) _GL_ATTRIBUTE_PURE;
-void hash_print_statistics (const Hash_table *, FILE *);
-void *hash_lookup (const Hash_table *, const void *);
-
-/* Walking. */
-void *hash_get_first (const Hash_table *) _GL_ATTRIBUTE_PURE;
-void *hash_get_next (const Hash_table *, const void *);
-size_t hash_get_entries (const Hash_table *, void **, size_t);
-size_t hash_do_for_each (const Hash_table *, Hash_processor, void *);
-
-/* Allocation and clean-up. */
-size_t hash_string (const char *, size_t) _GL_ATTRIBUTE_PURE;
-void hash_reset_tuning (Hash_tuning *);
-Hash_table *hash_initialize (size_t, const Hash_tuning *,
- Hash_hasher, Hash_comparator,
- Hash_data_freer) _GL_ATTRIBUTE_WUR;
-void hash_clear (Hash_table *);
-void hash_free (Hash_table *);
-
-/* Insertion and deletion. */
-bool hash_rehash (Hash_table *, size_t) _GL_ATTRIBUTE_WUR;
-void *hash_insert (Hash_table *, const void *) _GL_ATTRIBUTE_WUR;
-
-int hash_insert_if_absent (Hash_table *table, const void *entry,
- const void **matched_ent);
-void *hash_delete (Hash_table *, const void *);
+/*
+ * Information and lookup.
+ */
+
+/* The following few functions provide information about the overall hash
+ table organization: the number of entries, number of buckets and maximum
+ length of buckets. */
+
+/* Return the number of buckets in the hash table. The table size, the total
+ number of buckets (used plus unused), or the maximum number of slots, are
+ the same quantity. */
+extern size_t hash_get_n_buckets (const Hash_table *table)
+ _GL_ATTRIBUTE_PURE;
+
+/* Return the number of slots in use (non-empty buckets). */
+extern size_t hash_get_n_buckets_used (const Hash_table *table)
+ _GL_ATTRIBUTE_PURE;
+
+/* Return the number of active entries. */
+extern size_t hash_get_n_entries (const Hash_table *table)
+ _GL_ATTRIBUTE_PURE;
+
+/* Return the length of the longest chain (bucket). */
+extern size_t hash_get_max_bucket_length (const Hash_table *table)
+ _GL_ATTRIBUTE_PURE;
+
+/* Do a mild validation of a hash table, by traversing it and checking two
+ statistics. */
+extern bool hash_table_ok (const Hash_table *table)
+ _GL_ATTRIBUTE_PURE;
+
+extern void hash_print_statistics (const Hash_table *table, FILE *stream);
+
+/* If ENTRY matches an entry already in the hash table, return the
+ entry from the table. Otherwise, return NULL. */
+extern void *hash_lookup (const Hash_table *table, const void *entry);
+
+/*
+ * Walking.
+ */
+
+/* The functions in this page traverse the hash table and process the
+ contained entries. For the traversal to work properly, the hash table
+ should not be resized nor modified while any particular entry is being
+ processed. In particular, entries should not be added, and an entry
+ may be removed only if there is no shrink threshold and the entry being
+ removed has already been passed to hash_get_next. */
+
+/* Return the first data in the table, or NULL if the table is empty. */
+extern void *hash_get_first (const Hash_table *table)
+ _GL_ATTRIBUTE_PURE;
+
+/* Return the user data for the entry following ENTRY, where ENTRY has been
+ returned by a previous call to either 'hash_get_first' or 'hash_get_next'.
+ Return NULL if there are no more entries. */
+extern void *hash_get_next (const Hash_table *table, const void *entry);
+
+/* Fill BUFFER with pointers to active user entries in the hash table, then
+ return the number of pointers copied. Do not copy more than BUFFER_SIZE
+ pointers. */
+extern size_t hash_get_entries (const Hash_table *table, void **buffer,
+ size_t buffer_size);
+
+typedef bool (*Hash_processor) (void *entry, void *processor_data);
+
+/* Call a PROCESSOR function for each entry of a hash table, and return the
+ number of entries for which the processor function returned success. A
+ pointer to some PROCESSOR_DATA which will be made available to each call to
+ the processor function. The PROCESSOR accepts two arguments: the first is
+ the user entry being walked into, the second is the value of PROCESSOR_DATA
+ as received. The walking continue for as long as the PROCESSOR function
+ returns nonzero. When it returns zero, the walking is interrupted. */
+extern size_t hash_do_for_each (const Hash_table *table,
+ Hash_processor processor, void *processor_data);
+
+/*
+ * Allocation and clean-up.
+ */
+
+/* Return a hash index for a NUL-terminated STRING between 0 and N_BUCKETS-1.
+ This is a convenience routine for constructing other hashing functions. */
+extern size_t hash_string (const char *string, size_t n_buckets)
+ _GL_ATTRIBUTE_PURE;
+
+extern void hash_reset_tuning (Hash_tuning *tuning);
+
+typedef size_t (*Hash_hasher) (const void *entry, size_t table_size);
+typedef bool (*Hash_comparator) (const void *entry1, const void *entry2);
+typedef void (*Hash_data_freer) (void *entry);
+
+/* Reclaim all storage associated with a hash table. If a data_freer
+ function has been supplied by the user when the hash table was created,
+ this function applies it to the data of each entry before freeing that
+ entry. This function preserves errno, like 'free'. */
+extern void hash_free (Hash_table *table);
+
+/* Allocate and return a new hash table, or NULL upon failure. The initial
+ number of buckets is automatically selected so as to _guarantee_ that you
+ may insert at least CANDIDATE different user entries before any growth of
+ the hash table size occurs. So, if have a reasonably tight a-priori upper
+ bound on the number of entries you intend to insert in the hash table, you
+ may save some table memory and insertion time, by specifying it here. If
+ the IS_N_BUCKETS field of the TUNING structure is true, the CANDIDATE
+ argument has its meaning changed to the wanted number of buckets.
+
+ TUNING points to a structure of user-supplied values, in case some fine
+ tuning is wanted over the default behavior of the hasher. If TUNING is
+ NULL, the default tuning parameters are used instead. If TUNING is
+ provided but the values requested are out of bounds or might cause
+ rounding errors, return NULL.
+
+ The user-supplied HASHER function, when not NULL, accepts two
+ arguments ENTRY and TABLE_SIZE. It computes, by hashing ENTRY contents, a
+ slot number for that entry which should be in the range 0..TABLE_SIZE-1.
+ This slot number is then returned.
+
+ The user-supplied COMPARATOR function, when not NULL, accepts two
+ arguments pointing to user data, it then returns true for a pair of entries
+ that compare equal, or false otherwise. This function is internally called
+ on entries which are already known to hash to the same bucket index,
+ but which are distinct pointers.
+
+ The user-supplied DATA_FREER function, when not NULL, may be later called
+ with the user data as an argument, just before the entry containing the
+ data gets freed. This happens from within 'hash_free' or 'hash_clear'.
+ You should specify this function only if you want these functions to free
+ all of your 'data' data. This is typically the case when your data is
+ simply an auxiliary struct that you have malloc'd to aggregate several
+ values.
+
+ Set errno on failure; otherwise errno is unspecified. */
+_GL_ATTRIBUTE_NODISCARD
+extern Hash_table *hash_initialize (size_t candidate,
+ const Hash_tuning *tuning,
+ Hash_hasher hasher,
+ Hash_comparator comparator,
+ Hash_data_freer data_freer)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (hash_free, 1);
+
+/* Like hash_initialize, but invokes xalloc_die instead of returning NULL. */
+/* This function is defined by module 'xhash'. */
+_GL_ATTRIBUTE_NODISCARD
+extern Hash_table *hash_xinitialize (size_t candidate,
+ const Hash_tuning *tuning,
+ Hash_hasher hasher,
+ Hash_comparator comparator,
+ Hash_data_freer data_freer)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (hash_free, 1)
+ _GL_ATTRIBUTE_RETURNS_NONNULL;
+
+/* Make all buckets empty, placing any chained entries on the free list.
+ Apply the user-specified function data_freer (if any) to the data of any
+ affected entries. */
+extern void hash_clear (Hash_table *table);
+
+/*
+ * Insertion and deletion.
+ */
+
+/* For an already existing hash table, change the number of buckets through
+ specifying CANDIDATE. The contents of the hash table are preserved. The
+ new number of buckets is automatically selected so as to _guarantee_ that
+ the table may receive at least CANDIDATE different user entries, including
+ those already in the table, before any other growth of the hash table size
+ occurs. If TUNING->IS_N_BUCKETS is true, then CANDIDATE specifies the
+ exact number of buckets desired. Return true iff the rehash succeeded,
+ false (setting errno) otherwise. */
+_GL_ATTRIBUTE_NODISCARD
+extern bool hash_rehash (Hash_table *table, size_t candidate);
+
+/* If ENTRY matches an entry already in the hash table, return the pointer
+ to the entry from the table. Otherwise, insert ENTRY and return ENTRY.
+ Return NULL (setting errno) if the storage required for insertion
+ cannot be allocated. This implementation does not support
+ duplicate entries or insertion of NULL. */
+_GL_ATTRIBUTE_NODISCARD
+extern void *hash_insert (Hash_table *table, const void *entry);
+
+/* Same as hash_insert, but invokes xalloc_die instead of returning NULL. */
+/* This function is defined by module 'xhash'. */
+extern void *hash_xinsert (Hash_table *table, const void *entry);
+
+/* Insert ENTRY into hash TABLE if there is not already a matching entry.
+
+ Return -1 (setting errno) upon memory allocation failure.
+ Return 1 if insertion succeeded.
+ Return 0 if there is already a matching entry in the table,
+ and in that case, if MATCHED_ENT is non-NULL, set *MATCHED_ENT
+ to that entry.
+
+ This interface is easier to use than hash_insert when you must
+ distinguish between the latter two cases. More importantly,
+ hash_insert is unusable for some types of ENTRY values. When using
+ hash_insert, the only way to distinguish those cases is to compare
+ the return value and ENTRY. That works only when you can have two
+ different ENTRY values that point to data that compares "equal". Thus,
+ when the ENTRY value is a simple scalar, you must use
+ hash_insert_if_absent. ENTRY must not be NULL. */
+extern int hash_insert_if_absent (Hash_table *table, const void *entry,
+ const void **matched_ent);
+
+/* If ENTRY is already in the table, remove it and return the just-deleted
+ data (the user may want to deallocate its storage). If ENTRY is not in the
+ table, don't modify the table and return NULL. */
+extern void *hash_remove (Hash_table *table, const void *entry);
+
+/* Same as hash_remove. This interface is deprecated.
+ FIXME: Remove in 2022. */
+_GL_ATTRIBUTE_DEPRECATED
+extern void *hash_delete (Hash_table *table, const void *entry);
+
+# ifdef __cplusplus
+}
+# endif
#endif
diff --git a/libsbutil/gnulib/idx.h b/libsbutil/gnulib/idx.h
new file mode 100644
index 0000000..639b6cf
--- /dev/null
+++ b/libsbutil/gnulib/idx.h
@@ -0,0 +1,144 @@
+/* A type for indices and sizes.
+ Copyright (C) 2020-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _IDX_H
+#define _IDX_H
+
+/* Get ptrdiff_t. */
+#include <stddef.h>
+
+/* Get PTRDIFF_MAX. */
+#include <stdint.h>
+
+/* The type 'idx_t' holds an (array) index or an (object) size.
+ Its implementation promotes to a signed integer type,
+ which can hold the values
+ 0..2^63-1 (on 64-bit platforms) or
+ 0..2^31-1 (on 32-bit platforms).
+
+ Why a signed integer type?
+
+ * Security: Signed types can be checked for overflow via
+ '-fsanitize=undefined', but unsigned types cannot.
+
+ * Comparisons without surprises: ISO C99 § 6.3.1.8 specifies a few
+ surprising results for comparisons, such as
+
+ (int) -3 < (unsigned long) 7 => false
+ (int) -3 < (unsigned int) 7 => false
+ and on 32-bit machines:
+ (long) -3 < (unsigned int) 7 => false
+
+ This is surprising because the natural comparison order is by
+ value in the realm of infinite-precision signed integers (ℤ).
+
+ The best way to get rid of such surprises is to use signed types
+ for numerical integer values, and use unsigned types only for
+ bit masks and enums.
+
+ Why not use 'size_t' directly?
+
+ * Because 'size_t' is an unsigned type, and a signed type is better.
+ See above.
+
+ Why not use 'ssize_t'?
+
+ * 'ptrdiff_t' is more portable; it is standardized by ISO C
+ whereas 'ssize_t' is standardized only by POSIX.
+
+ * 'ssize_t' is not required to be as wide as 'size_t', and some
+ now-obsolete POSIX platforms had 'size_t' wider than 'ssize_t'.
+
+ * Conversely, some now-obsolete platforms had 'ptrdiff_t' wider
+ than 'size_t', which can be a win and conforms to POSIX.
+
+ Won't this cause a problem with objects larger than PTRDIFF_MAX?
+
+ * Typical modern or large platforms do not allocate such objects,
+ so this is not much of a problem in practice; for example, you
+ can safely write 'idx_t len = strlen (s);'. To port to older
+ small platforms where allocations larger than PTRDIFF_MAX could
+ in theory be a problem, you can use Gnulib's ialloc module, or
+ functions like ximalloc in Gnulib's xalloc module.
+
+ Why not use 'ptrdiff_t' directly?
+
+ * Maintainability: When reading and modifying code, it helps to know that
+ a certain variable cannot have negative values. For example, when you
+ have a loop
+
+ int n = ...;
+ for (int i = 0; i < n; i++) ...
+
+ or
+
+ ptrdiff_t n = ...;
+ for (ptrdiff_t i = 0; i < n; i++) ...
+
+ you have to ask yourself "what if n < 0?". Whereas in
+
+ idx_t n = ...;
+ for (idx_t i = 0; i < n; i++) ...
+
+ you know that this case cannot happen.
+
+ Similarly, when a programmer writes
+
+ idx_t = ptr2 - ptr1;
+
+ there is an implied assertion that ptr1 and ptr2 point into the same
+ object and that ptr1 <= ptr2.
+
+ * Being future-proof: In the future, range types (integers which are
+ constrained to a certain range of values) may be added to C compilers
+ or to the C standard. Several programming languages (Ada, Haskell,
+ Common Lisp, Pascal) already have range types. Such range types may
+ help producing good code and good warnings. The type 'idx_t' could
+ then be typedef'ed to a range type that is signed after promotion. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* In the future, idx_t could be typedef'ed to a signed range type.
+ The clang "extended integer types", supported in Clang 11 or newer
+ <https://clang.llvm.org/docs/LanguageExtensions.html#extended-integer-types>,
+ are a special case of range types. However, these types don't support binary
+ operators with plain integer types (e.g. expressions such as x > 1).
+ Therefore, they don't behave like signed types (and not like unsigned types
+ either). So, we cannot use them here. */
+
+/* Use the signed type 'ptrdiff_t'. */
+/* Note: ISO C does not mandate that 'size_t' and 'ptrdiff_t' have the same
+ size, but it is so on all platforms we have seen since 1990. */
+typedef ptrdiff_t idx_t;
+
+/* IDX_MAX is the maximum value of an idx_t. */
+#define IDX_MAX PTRDIFF_MAX
+
+/* So far no need has been found for an IDX_WIDTH macro.
+ Perhaps there should be another macro IDX_VALUE_BITS that does not
+ count the sign bit and is therefore one less than PTRDIFF_WIDTH. */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _IDX_H */
diff --git a/libsbutil/gnulib/intprops-internal.h b/libsbutil/gnulib/intprops-internal.h
new file mode 100644
index 0000000..62de3c8
--- /dev/null
+++ b/libsbutil/gnulib/intprops-internal.h
@@ -0,0 +1,400 @@
+/* intprops-internal.h -- properties of integer types not visible to users
+
+ Copyright (C) 2001-2025 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#ifndef _GL_INTPROPS_INTERNAL_H
+#define _GL_INTPROPS_INTERNAL_H
+
+#include <limits.h>
+
+/* Pacify GCC 13.2 in some calls to _GL_EXPR_SIGNED. */
+#if 4 < __GNUC__ + (3 <= __GNUC_MINOR__) && !defined __clang__
+# pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
+
+/* Return a value with the common real type of E and V and the value of V.
+ Do not evaluate E. */
+#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))
+
+/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
+ <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00406.html>. */
+#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))
+
+/* The extra casts in the following macros work around compiler bugs,
+ e.g., in Cray C 5.0.3.0. */
+
+/* True if the real type T is signed. */
+#define _GL_TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* Return 1 if the real expression E, after promotion, has a
+ signed or floating type. Do not evaluate E. */
+#define _GL_EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
+
+
+/* Minimum and maximum values for integer types and expressions. */
+
+/* The width in bits of the integer type or expression T.
+ Do not evaluate T. T must not be a bit-field expression.
+ Padding bits are not supported; this is checked at compile-time below. */
+#define _GL_TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)
+
+/* The maximum and minimum values for the type of the expression E,
+ after integer promotion. E is not evaluated. */
+#define _GL_INT_MINIMUM(e) \
+ (_GL_EXPR_SIGNED (e) \
+ ? ~ _GL_SIGNED_INT_MAXIMUM (e) \
+ : _GL_INT_CONVERT (e, 0))
+#define _GL_INT_MAXIMUM(e) \
+ (_GL_EXPR_SIGNED (e) \
+ ? _GL_SIGNED_INT_MAXIMUM (e) \
+ : _GL_INT_NEGATE_CONVERT (e, 1))
+#define _GL_SIGNED_INT_MAXIMUM(e) \
+ (((_GL_INT_CONVERT (e, 1) << (_GL_TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1)
+
+/* Work around OpenVMS incompatibility with C99. */
+#if !defined LLONG_MAX && defined __INT64_MAX
+# define LLONG_MAX __INT64_MAX
+# define LLONG_MIN __INT64_MIN
+#endif
+
+/* This include file assumes that signed types are two's complement without
+ padding bits; the above macros have undefined behavior otherwise.
+ If this is a problem for you, please let us know how to fix it for your host.
+ This assumption is tested by the intprops-tests module. */
+
+/* Does the __typeof__ keyword work? This could be done by
+ 'configure', but for now it's easier to do it by hand. */
+#if ((defined __GNUC__ && 2 <= __GNUC__) \
+ || (defined __clang_major__ && 4 <= __clang_major__) \
+ || (defined __IBMC__ && 1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
+ || (defined __SUNPRO_C && 0x5110 <= __SUNPRO_C && !__STDC__) \
+ || (defined _MSC_VER && 1939 <= _MSC_VER))
+# define _GL_HAVE___TYPEOF__ 1
+#else
+# define _GL_HAVE___TYPEOF__ 0
+#endif
+
+/* Return 1 if the integer type or expression T might be signed. Return 0
+ if it is definitely unsigned. T must not be a bit-field expression.
+ This macro does not evaluate its argument, and expands to an
+ integer constant expression. */
+#if _GL_HAVE___TYPEOF__
+# define _GL_SIGNED_TYPE_OR_EXPR(t) _GL_TYPE_SIGNED (__typeof__ (t))
+#else
+# define _GL_SIGNED_TYPE_OR_EXPR(t) 1
+#endif
+
+/* Return 1 if - A would overflow in [MIN,MAX] arithmetic.
+ A should not have side effects, and A's type should be an
+ integer with minimum value MIN and maximum MAX. */
+#define _GL_INT_NEGATE_RANGE_OVERFLOW(a, min, max) \
+ ((min) < 0 ? (a) < - (max) : 0 < (a))
+
+/* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow
+ (A, B, P) work when P is non-null. */
+#ifdef __EDG__
+/* EDG-based compilers like nvc 22.1 cannot add 64-bit signed to unsigned
+ <https://bugs.gnu.org/53256>. */
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0
+#elif defined __has_builtin
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow)
+/* __builtin_{add,sub}_overflow exists but is not reliable in GCC 5.x and 6.x,
+ see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98269>. */
+#elif 7 <= __GNUC__
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW 1
+#else
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0
+#endif
+
+/* True if __builtin_mul_overflow (A, B, P) works when P is non-null. */
+#if defined __clang_major__ && __clang_major__ < 14
+/* Work around Clang bug <https://bugs.llvm.org/show_bug.cgi?id=16404>. */
+# define _GL_HAS_BUILTIN_MUL_OVERFLOW 0
+#else
+# define _GL_HAS_BUILTIN_MUL_OVERFLOW _GL_HAS_BUILTIN_ADD_OVERFLOW
+#endif
+
+/* True if __builtin_add_overflow_p (A, B, C) works, and similarly for
+ __builtin_sub_overflow_p and __builtin_mul_overflow_p. */
+#ifdef __EDG__
+/* In EDG-based compilers like ICC 2021.3 and earlier,
+ __builtin_add_overflow_p etc. are not treated as integral constant
+ expressions even when all arguments are. */
+# define _GL_HAS_BUILTIN_OVERFLOW_P 0
+#elif defined __has_builtin
+# define _GL_HAS_BUILTIN_OVERFLOW_P __has_builtin (__builtin_mul_overflow_p)
+#else
+# define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
+#endif
+
+#if (!defined _GL_STDCKDINT_H && 202311 <= __STDC_VERSION__ \
+ && ! (_GL_HAS_BUILTIN_ADD_OVERFLOW && _GL_HAS_BUILTIN_MUL_OVERFLOW))
+# include <stdckdint.h>
+#endif
+
+/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R.
+ Return 1 if the result overflows. Arguments should not have side
+ effects and A, B and *R can be of any integer type other than char,
+ bool, a bit-precise integer type, or an enumeration type. */
+#if _GL_HAS_BUILTIN_ADD_OVERFLOW
+# define _GL_INT_ADD_WRAPV(a, b, r) __builtin_add_overflow (a, b, r)
+# define _GL_INT_SUBTRACT_WRAPV(a, b, r) __builtin_sub_overflow (a, b, r)
+#elif defined ckd_add && defined ckd_sub && !defined _GL_STDCKDINT_H
+# define _GL_INT_ADD_WRAPV(a, b, r) ckd_add (r, + (a), + (b))
+# define _GL_INT_SUBTRACT_WRAPV(a, b, r) ckd_sub (r, + (a), + (b))
+#else
+# define _GL_INT_ADD_WRAPV(a, b, r) \
+ _GL_INT_OP_WRAPV (a, b, r, +, _GL_INT_ADD_RANGE_OVERFLOW)
+# define _GL_INT_SUBTRACT_WRAPV(a, b, r) \
+ _GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW)
+#endif
+#if _GL_HAS_BUILTIN_MUL_OVERFLOW
+# if ((9 < __GNUC__ + (3 <= __GNUC_MINOR__) \
+ || (__GNUC__ == 8 && 4 <= __GNUC_MINOR__)) \
+ && !defined __clang__ && !defined __EDG__)
+# define _GL_INT_MULTIPLY_WRAPV(a, b, r) __builtin_mul_overflow (a, b, r)
+# else
+ /* Work around GCC bug 91450. */
+# define _GL_INT_MULTIPLY_WRAPV(a, b, r) \
+ ((!_GL_SIGNED_TYPE_OR_EXPR (*(r)) && _GL_EXPR_SIGNED (a) && _GL_EXPR_SIGNED (b) \
+ && _GL_INT_MULTIPLY_RANGE_OVERFLOW (a, b, \
+ (__typeof__ (*(r))) 0, \
+ (__typeof__ (*(r))) -1)) \
+ ? ((void) __builtin_mul_overflow (a, b, r), 1) \
+ : __builtin_mul_overflow (a, b, r))
+# endif
+#elif defined ckd_mul && !defined _GL_STDCKDINT_H
+# define _GL_INT_MULTIPLY_WRAPV(a, b, r) ckd_mul (r, + (a), + (b))
+#else
+# define _GL_INT_MULTIPLY_WRAPV(a, b, r) \
+ _GL_INT_OP_WRAPV (a, b, r, *, _GL_INT_MULTIPLY_RANGE_OVERFLOW)
+#endif
+
+/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See:
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193
+ https://llvm.org/bugs/show_bug.cgi?id=25390
+ For now, assume GCC < 14 and all Clang versions generate bogus
+ warnings for _Generic. This matters only for compilers that
+ lack relevant builtins. */
+#if (__GNUC__ && __GNUC__ < 14) || defined __clang__
+# define _GL__GENERIC_BOGUS 1
+#else
+# define _GL__GENERIC_BOGUS 0
+#endif
+
+/* Store the low-order bits of A <op> B into *R, where OP specifies
+ the operation and OVERFLOW the overflow predicate. Return 1 if the
+ result overflows. Arguments should not have side effects,
+ and A, B and *R can be of any integer type other than char, bool, a
+ bit-precise integer type, or an enumeration type. */
+#if 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS
+# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \
+ (_Generic \
+ (*(r), \
+ signed char: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ signed char, SCHAR_MIN, SCHAR_MAX), \
+ unsigned char: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ unsigned char, 0, UCHAR_MAX), \
+ short int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ short int, SHRT_MIN, SHRT_MAX), \
+ unsigned short int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ unsigned short int, 0, USHRT_MAX), \
+ int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ int, INT_MIN, INT_MAX), \
+ unsigned int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ unsigned int, 0, UINT_MAX), \
+ long int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ long int, LONG_MIN, LONG_MAX), \
+ unsigned long int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ unsigned long int, 0, ULONG_MAX), \
+ long long int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+ long long int, LLONG_MIN, LLONG_MAX), \
+ unsigned long long int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+ unsigned long long int, 0, ULLONG_MAX)))
+#else
+/* Store the low-order bits of A <op> B into *R, where OP specifies
+ the operation and OVERFLOW the overflow predicate. If *R is
+ signed, its type is ST with bounds SMIN..SMAX; otherwise its type
+ is UT with bounds U..UMAX. ST and UT are narrower than int.
+ Return 1 if the result overflows. Arguments should not have side
+ effects, and A, B and *R can be of any integer type other than
+ char, bool, a bit-precise integer type, or an enumeration type. */
+# if _GL_HAVE___TYPEOF__
+# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \
+ (_GL_TYPE_SIGNED (__typeof__ (*(r))) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, st, smin, smax) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, ut, 0, umax))
+# else
+# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \
+ (overflow (a, b, smin, smax) \
+ ? (overflow (a, b, 0, umax) \
+ ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 1) \
+ : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) < 0) \
+ : (overflow (a, b, 0, umax) \
+ ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) >= 0 \
+ : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 0)))
+# endif
+
+# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \
+ (sizeof *(r) == sizeof (signed char) \
+ ? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \
+ signed char, SCHAR_MIN, SCHAR_MAX, \
+ unsigned char, UCHAR_MAX) \
+ : sizeof *(r) == sizeof (short int) \
+ ? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \
+ short int, SHRT_MIN, SHRT_MAX, \
+ unsigned short int, USHRT_MAX) \
+ : sizeof *(r) == sizeof (int) \
+ ? (_GL_EXPR_SIGNED (*(r)) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ int, INT_MIN, INT_MAX) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ unsigned int, 0, UINT_MAX)) \
+ : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow))
+# ifdef LLONG_MAX
+# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
+ (sizeof *(r) == sizeof (long int) \
+ ? (_GL_EXPR_SIGNED (*(r)) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ long int, LONG_MIN, LONG_MAX) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ unsigned long int, 0, ULONG_MAX)) \
+ : (_GL_EXPR_SIGNED (*(r)) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+ long long int, LLONG_MIN, LLONG_MAX) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+ unsigned long long int, 0, ULLONG_MAX)))
+# else
+# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
+ (_GL_EXPR_SIGNED (*(r)) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ long int, LONG_MIN, LONG_MAX) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ unsigned long int, 0, ULONG_MAX))
+# endif
+#endif
+
+/* Store the low-order bits of A <op> B into *R, where the operation
+ is given by OP. Use the unsigned type UT for calculation to avoid
+ overflow problems. *R's type is T, with extrema TMIN and TMAX.
+ T can be any signed integer type other than char, bool, a
+ bit-precise integer type, or an enumeration type.
+ Return 1 if the result overflows. */
+#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \
+ (overflow (a, b, tmin, tmax) \
+ ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \
+ : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0))
+
+/* Return 1 if the integer expressions A - B and -A would overflow,
+ respectively. Arguments should not have side effects,
+ and can be any signed integer type other than char, bool, a
+ bit-precise integer type, or an enumeration type.
+ These macros are tuned for their last input argument being a constant. */
+
+#if _GL_HAS_BUILTIN_OVERFLOW_P
+# define _GL_INT_NEGATE_OVERFLOW(a) \
+ __builtin_sub_overflow_p (0, a, (__typeof__ (- (a))) 0)
+#else
+# define _GL_INT_NEGATE_OVERFLOW(a) \
+ _GL_INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
+#endif
+
+/* Return the low-order bits of A <op> B, where the operation is given
+ by OP. Use the unsigned type UT for calculation to avoid undefined
+ behavior on signed integer overflow, and convert the result to type T.
+ UT is at least as wide as T and is no narrower than unsigned int,
+ T is two's complement, and there is no padding or trap representations.
+ Assume that converting UT to T yields the low-order bits, as is
+ done in all known two's-complement C compilers. E.g., see:
+ https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
+
+ According to the C standard, converting UT to T yields an
+ implementation-defined result or signal for values outside T's
+ range. However, code that works around this theoretical problem
+ runs afoul of a compiler bug in Oracle Studio 12.3 x86. See:
+ https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html
+ As the compiler bug is real, don't try to work around the
+ theoretical problem. */
+
+#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \
+ ((t) ((ut) (a) op (ut) (b)))
+
+/* Return true if the numeric values A + B, A - B, A * B fall outside
+ the range TMIN..TMAX. Arguments should not have side effects
+ and can be any integer type other than char, bool,
+ a bit-precise integer type, or an enumeration type.
+ TMIN should be signed and nonpositive.
+ TMAX should be positive, and should be signed unless TMIN is zero. */
+#define _GL_INT_ADD_RANGE_OVERFLOW(a, b, tmin, tmax) \
+ ((b) < 0 \
+ ? (((tmin) \
+ ? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (a, (tmin) - (b))) || (b) < (tmin)) \
+ && (a) < (tmin) - (b)) \
+ : (a) <= -1 - (b)) \
+ || ((_GL_EXPR_SIGNED (a) ? 0 <= (a) : (tmax) < (a)) && (tmax) < (a) + (b))) \
+ : (a) < 0 \
+ ? (((tmin) \
+ ? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (b, (tmin) - (a))) || (a) < (tmin)) \
+ && (b) < (tmin) - (a)) \
+ : (b) <= -1 - (a)) \
+ || ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (a, b)) || (tmax) < (b)) \
+ && (tmax) < (a) + (b))) \
+ : (tmax) < (b) || (tmax) - (b) < (a))
+#define _GL_INT_SUBTRACT_RANGE_OVERFLOW(a, b, tmin, tmax) \
+ (((a) < 0) == ((b) < 0) \
+ ? ((a) < (b) \
+ ? !(tmin) || -1 - (tmin) < (b) - (a) - 1 \
+ : (tmax) < (a) - (b)) \
+ : (a) < 0 \
+ ? ((!_GL_EXPR_SIGNED (_GL_INT_CONVERT ((a) - (tmin), b)) && (a) - (tmin) < 0) \
+ || (a) - (tmin) < (b)) \
+ : ((! (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
+ && _GL_EXPR_SIGNED (_GL_INT_CONVERT ((tmax) + (b), a))) \
+ && (tmax) <= -1 - (b)) \
+ || (tmax) + (b) < (a)))
+#define _GL_INT_MULTIPLY_RANGE_OVERFLOW(a, b, tmin, tmax) \
+ ((b) < 0 \
+ ? ((a) < 0 \
+ ? (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
+ ? (a) < (tmax) / (b) \
+ : ((_GL_INT_NEGATE_OVERFLOW (b) \
+ ? _GL_INT_CONVERT (b, tmax) >> (_GL_TYPE_WIDTH (+ (b)) - 1) \
+ : (tmax) / -(b)) \
+ <= -1 - (a))) \
+ : _GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \
+ ? (_GL_EXPR_SIGNED (a) \
+ ? 0 < (a) + (tmin) \
+ : 0 < (a) && -1 - (tmin) < (a) - 1) \
+ : (tmin) / (b) < (a)) \
+ : (b) == 0 \
+ ? 0 \
+ : ((a) < 0 \
+ ? (_GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (a, tmin)) && (a) == -1 \
+ ? (_GL_EXPR_SIGNED (b) ? 0 < (b) + (tmin) : -1 - (tmin) < (b) - 1) \
+ : (tmin) / (a) < (b)) \
+ : (tmax) / (b) < (a)))
+
+#endif /* _GL_INTPROPS_INTERNAL_H */
diff --git a/libsbutil/gnulib/intprops.h b/libsbutil/gnulib/intprops.h
new file mode 100644
index 0000000..92dfef2
--- /dev/null
+++ b/libsbutil/gnulib/intprops.h
@@ -0,0 +1,335 @@
+/* intprops.h -- properties of integer types
+
+ Copyright (C) 2001-2025 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#ifndef _GL_INTPROPS_H
+#define _GL_INTPROPS_H
+
+#include "intprops-internal.h"
+
+/* The extra casts in the following macros work around compiler bugs,
+ e.g., in Cray C 5.0.3.0. */
+
+/* True if the arithmetic type T is an integer type. bool counts as
+ an integer. */
+#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
+
+/* True if the real type T is signed. */
+#define TYPE_SIGNED(t) _GL_TYPE_SIGNED (t)
+
+/* Return 1 if the real expression E, after promotion, has a
+ signed or floating type. Do not evaluate E. */
+#define EXPR_SIGNED(e) _GL_EXPR_SIGNED (e)
+
+
+/* Minimum and maximum values for integer types and expressions. */
+
+/* The width in bits of the integer type or expression T.
+ Do not evaluate T. T must not be a bit-field expression.
+ Padding bits are not supported; this is checked at compile-time below. */
+#define TYPE_WIDTH(t) _GL_TYPE_WIDTH (t)
+
+/* The maximum and minimum values for the integer type T. */
+#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
+#define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
+ : ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1)))
+
+/* Bound on length of the string representing an unsigned integer
+ value representable in B bits. log10 (2.0) < 146/485. The
+ smallest value of B where this bound is not tight is 2621. */
+#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485)
+
+/* Bound on length of the string representing an integer type or expression T.
+ T must not be a bit-field expression.
+
+ Subtract 1 for the sign bit if T is signed, and then add 1 more for
+ a minus sign if needed.
+
+ Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 1 when its argument is
+ unsigned, this macro may overestimate the true bound by one byte when
+ applied to unsigned types of size 2, 4, 16, ... bytes. */
+#define INT_STRLEN_BOUND(t) \
+ (INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \
+ + _GL_SIGNED_TYPE_OR_EXPR (t))
+
+/* Bound on buffer size needed to represent an integer type or expression T,
+ including the terminating null. T must not be a bit-field expression. */
+#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
+
+
+/* Range overflow checks.
+
+ The INT_<op>_RANGE_OVERFLOW macros return 1 if the corresponding C
+ operators overflow arithmetically when given the same arguments.
+ These macros do not rely on undefined or implementation-defined behavior.
+ Although their implementations are simple and straightforward,
+ they are harder to use and may be less efficient than the
+ INT_<op>_WRAPV, INT_<op>_OK, and INT_<op>_OVERFLOW macros described below.
+
+ Example usage:
+
+ long int i = ...;
+ long int j = ...;
+ if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX))
+ printf ("multiply would overflow");
+ else
+ printf ("product is %ld", i * j);
+
+ Restrictions on *_RANGE_OVERFLOW macros:
+
+ These macros do not check for all possible numerical problems or
+ undefined or unspecified behavior: they do not check for division
+ by zero, for bad shift counts, or for shifting negative numbers.
+
+ These macros may evaluate their arguments zero or multiple times,
+ so the arguments should not have side effects. The arithmetic
+ arguments (including the MIN and MAX arguments) must be of the same
+ integer type after the usual arithmetic conversions, and the type
+ must have minimum value MIN and maximum MAX. Unsigned types should
+ use a zero MIN of the proper type.
+
+ Because all arguments are subject to integer promotions, these
+ macros typically do not work on types narrower than 'int'.
+
+ These macros are tuned for constant MIN and MAX. For commutative
+ operations such as A + B, they are also tuned for constant B. */
+
+/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic.
+ See above for restrictions. */
+#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \
+ ((b) < 0 \
+ ? (a) < (min) - (b) \
+ : (max) - (b) < (a))
+
+/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic.
+ See above for restrictions. */
+#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max) \
+ ((b) < 0 \
+ ? (max) + (b) < (a) \
+ : (a) < (min) + (b))
+
+/* Return 1 if - A would overflow in [MIN,MAX] arithmetic.
+ See above for restrictions. */
+#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \
+ _GL_INT_NEGATE_RANGE_OVERFLOW (a, min, max)
+
+/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic.
+ See above for restrictions. Avoid && and || as they tickle
+ bugs in Sun C 5.11 2010/08/13 and other compilers; see
+ <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00401.html>. */
+#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \
+ ((b) < 0 \
+ ? ((a) < 0 \
+ ? (a) < (max) / (b) \
+ : (b) == -1 \
+ ? 0 \
+ : (min) / (b) < (a)) \
+ : (b) == 0 \
+ ? 0 \
+ : ((a) < 0 \
+ ? (a) < (min) / (b) \
+ : (max) / (b) < (a)))
+
+/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic.
+ See above for restrictions. Do not check for division by zero. */
+#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max) \
+ ((min) < 0 && (b) == -1 && (a) < - (max))
+
+/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic.
+ See above for restrictions. Do not check for division by zero.
+ Mathematically, % should never overflow, but on x86-like hosts
+ INT_MIN % -1 traps, and the C standard permits this, so treat this
+ as an overflow too. */
+#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max) \
+ INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max)
+
+/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic.
+ See above for restrictions. Here, MIN and MAX are for A only, and B need
+ not be of the same type as the other arguments. The C standard says that
+ behavior is undefined for shifts unless 0 <= B < wordwidth, and that when
+ A is negative then A << B has undefined behavior and A >> B has
+ implementation-defined behavior, but do not check these other
+ restrictions. */
+#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \
+ ((a) < 0 \
+ ? (a) < (min) >> (b) \
+ : (max) >> (b) < (a))
+
+/* The _GL*_OVERFLOW macros have the same restrictions as the
+ *_RANGE_OVERFLOW macros, except that they do not assume that operands
+ (e.g., A and B) have the same type as MIN and MAX. Instead, they assume
+ that the result (e.g., A + B) has that type. */
+#if _GL_HAS_BUILTIN_OVERFLOW_P
+# define _GL_ADD_OVERFLOW(a, b, min, max) \
+ __builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0)
+# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \
+ __builtin_sub_overflow_p (a, b, (__typeof__ ((a) - (b))) 0)
+# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \
+ __builtin_mul_overflow_p (a, b, (__typeof__ ((a) * (b))) 0)
+#else
+# define _GL_ADD_OVERFLOW(a, b, min, max) \
+ ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \
+ : (a) < 0 ? (b) <= (a) + (b) \
+ : (b) < 0 ? (a) <= (a) + (b) \
+ : (a) + (b) < (b))
+# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \
+ ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \
+ : (a) < 0 ? 1 \
+ : (b) < 0 ? (a) - (b) <= (a) \
+ : (a) < (b))
+# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \
+ (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \
+ || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))
+#endif
+#define _GL_DIVIDE_OVERFLOW(a, b, min, max) \
+ ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \
+ : (a) < 0 ? (b) <= (a) + (b) - 1 \
+ : (b) < 0 && (a) + (b) <= (a))
+#define _GL_REMAINDER_OVERFLOW(a, b, min, max) \
+ ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \
+ : (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \
+ : (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max))
+
+/* Return a nonzero value if A is a mathematical multiple of B, where
+ A is unsigned, B is negative, and MAX is the maximum value of A's
+ type. A's type must be the same as (A % B)'s type. Normally (A %
+ -B == 0) suffices, but things get tricky if -B would overflow. */
+#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max) \
+ (((b) < -_GL_SIGNED_INT_MAXIMUM (b) \
+ ? (_GL_SIGNED_INT_MAXIMUM (b) == (max) \
+ ? (a) \
+ : (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1)) \
+ : (a) % - (b)) \
+ == 0)
+
+/* Check for integer overflow, and report low order bits of answer.
+
+ The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators
+ might not yield numerically correct answers due to arithmetic overflow.
+ The INT_<op>_WRAPV macros compute the low-order bits of the sum,
+ difference, and product of two C integers, and return 1 if these
+ low-order bits are not numerically correct.
+ These macros work correctly on all known practical hosts, and do not rely
+ on undefined behavior due to signed arithmetic overflow.
+
+ Example usage, assuming A and B are long int:
+
+ if (INT_MULTIPLY_OVERFLOW (a, b))
+ printf ("result would overflow\n");
+ else
+ printf ("result is %ld (no overflow)\n", a * b);
+
+ Example usage with WRAPV flavor:
+
+ long int result;
+ bool overflow = INT_MULTIPLY_WRAPV (a, b, &result);
+ printf ("result is %ld (%s)\n", result,
+ overflow ? "after overflow" : "no overflow");
+
+ Restrictions on these macros:
+
+ These macros do not check for all possible numerical problems or
+ undefined or unspecified behavior: they do not check for division
+ by zero, for bad shift counts, or for shifting negative numbers.
+
+ These macros may evaluate their arguments zero or multiple times, so the
+ arguments should not have side effects.
+
+ The WRAPV macros are not constant expressions. They support only
+ +, binary -, and *.
+
+ Because the WRAPV macros convert the result, they report overflow
+ in different circumstances than the OVERFLOW macros do. For
+ example, in the typical case with 16-bit 'short' and 32-bit 'int',
+ if A, B and *R are all of type 'short' then INT_ADD_OVERFLOW (A, B)
+ returns false because the addition cannot overflow after A and B
+ are converted to 'int', whereas INT_ADD_WRAPV (A, B, R) returns
+ true or false depending on whether the sum fits into 'short'.
+
+ These macros are tuned for their last input argument being a constant.
+
+ A, B, and *R should be integers; they need not be the same type,
+ and they need not be all signed or all unsigned.
+ However, none of the integer types should be bit-precise,
+ and *R's type should not be char, bool, or an enumeration type.
+
+ Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B,
+ A % B, and A << B would overflow, respectively. */
+
+#define INT_ADD_OVERFLOW(a, b) \
+ _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW)
+#define INT_SUBTRACT_OVERFLOW(a, b) \
+ _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW)
+#define INT_NEGATE_OVERFLOW(a) _GL_INT_NEGATE_OVERFLOW (a)
+#define INT_MULTIPLY_OVERFLOW(a, b) \
+ _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)
+#define INT_DIVIDE_OVERFLOW(a, b) \
+ _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW)
+#define INT_REMAINDER_OVERFLOW(a, b) \
+ _GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW)
+#define INT_LEFT_SHIFT_OVERFLOW(a, b) \
+ INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \
+ _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
+
+/* Return 1 if the expression A <op> B would overflow,
+ where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test,
+ assuming MIN and MAX are the minimum and maximum for the result type.
+ Arguments should be free of side effects. */
+#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \
+ op_result_overflow (a, b, \
+ _GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \
+ _GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b)))
+
+/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R.
+ Return 1 if the result overflows. See above for restrictions. */
+#define INT_ADD_WRAPV(a, b, r) _GL_INT_ADD_WRAPV (a, b, r)
+#define INT_SUBTRACT_WRAPV(a, b, r) _GL_INT_SUBTRACT_WRAPV (a, b, r)
+#define INT_MULTIPLY_WRAPV(a, b, r) _GL_INT_MULTIPLY_WRAPV (a, b, r)
+
+/* The following macros compute A + B, A - B, and A * B, respectively.
+ If no overflow occurs, they set *R to the result and return 1;
+ otherwise, they return 0 and may modify *R.
+
+ Example usage:
+
+ long int result;
+ if (INT_ADD_OK (a, b, &result))
+ printf ("result is %ld\n", result);
+ else
+ printf ("overflow\n");
+
+ A, B, and *R should be integers; they need not be the same type,
+ and they need not be all signed or all unsigned.
+ However, none of the integer types should be bit-precise,
+ and *R's type should not be char, bool, or an enumeration type.
+
+ These macros work correctly on all known practical hosts, and do not rely
+ on undefined behavior due to signed arithmetic overflow.
+
+ These macros are not constant expressions.
+
+ These macros may evaluate their arguments zero or multiple times, so the
+ arguments should not have side effects.
+
+ These macros are tuned for B being a constant. */
+
+#define INT_ADD_OK(a, b, r) (! INT_ADD_WRAPV (a, b, r))
+#define INT_SUBTRACT_OK(a, b, r) (! INT_SUBTRACT_WRAPV (a, b, r))
+#define INT_MULTIPLY_OK(a, b, r) (! INT_MULTIPLY_WRAPV (a, b, r))
+
+#endif /* _GL_INTPROPS_H */
diff --git a/libsbutil/gnulib/libc-config.h b/libsbutil/gnulib/libc-config.h
new file mode 100644
index 0000000..33da9cf
--- /dev/null
+++ b/libsbutil/gnulib/libc-config.h
@@ -0,0 +1,209 @@
+/* System definitions for code taken from the GNU C Library
+
+ Copyright 2017-2025 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+/* This is intended to be a good-enough substitute for glibc system
+ macros like those defined in <sys/cdefs.h>, so that Gnulib code
+ shared with glibc can do this as the first #include:
+
+ #ifndef _LIBC
+ # include <libc-config.h>
+ #endif
+
+ When compiled as part of glibc this is a no-op; when compiled as
+ part of Gnulib this includes Gnulib's <config.h> and defines macros
+ that glibc library code would normally assume.
+
+ Note: This header file MUST NOT be included by public header files
+ of Gnulib. */
+
+#include <config.h>
+
+/* On glibc this includes <features.h> and <sys/cdefs.h> and #defines
+ _FEATURES_H, __WORDSIZE, and __set_errno. On FreeBSD 11 and
+ DragonFlyBSD 5.9 it includes <sys/cdefs.h> which defines __nonnull.
+ Elsewhere it is harmless. */
+#include <errno.h>
+
+/* From glibc <errno.h>. */
+#ifndef __set_errno
+# define __set_errno(val) (errno = (val))
+#endif
+
+/* From glibc <features.h>. */
+
+#if defined __clang__
+ /* clang really only groks GNU C 4.2, regardless of its value of __GNUC__. */
+# undef __GNUC_PREREQ
+# define __GNUC_PREREQ(maj, min) ((maj) < 4 + ((min) <= 2))
+#endif
+#ifndef __GNUC_PREREQ
+# if defined __GNUC__ && defined __GNUC_MINOR__
+# define __GNUC_PREREQ(maj, min) ((maj) < __GNUC__ + ((min) <= __GNUC_MINOR__))
+# else
+# define __GNUC_PREREQ(maj, min) 0
+# endif
+#endif
+
+#ifndef __glibc_clang_prereq
+# if defined __clang_major__ && defined __clang_minor__
+# ifdef __apple_build_version__
+/* Apple for some reason renumbers __clang_major__ and __clang_minor__.
+ Gnulib code uses only __glibc_clang_prereq (3, 5); map it to
+ 6000000 <= __apple_build_version__. Support for other calls to
+ __glibc_clang_prereq can be added here as needed. */
+# define __glibc_clang_prereq(maj, min) \
+ ((maj) == 3 && (min) == 5 ? 6000000 <= __apple_build_version__ : 0)
+# else
+# define __glibc_clang_prereq(maj, min) \
+ ((maj) < __clang_major__ + ((min) <= __clang_minor__))
+# endif
+# else
+# define __glibc_clang_prereq(maj, min) 0
+# endif
+#endif
+
+#ifndef __attribute_nonnull__
+/* <sys/cdefs.h> either does not exist, or is too old for Gnulib.
+ Prepare to include <cdefs.h>, which is Gnulib's version of a
+ more-recent glibc <sys/cdefs.h>. */
+
+/* Define _FEATURES_H so that <cdefs.h> does not include <features.h>. */
+# ifndef _FEATURES_H
+# define _FEATURES_H 1
+# endif
+/* Define __GNULIB_CDEFS so that <cdefs.h> does not attempt to include
+ nonexistent files. */
+# define __GNULIB_CDEFS
+/* Undef the macros unconditionally defined by our copy of glibc
+ <sys/cdefs.h>, so that they do not clash with any system-defined
+ versions. */
+# undef _SYS_CDEFS_H
+# undef __ASMNAME
+# undef __ASMNAME2
+# undef __BEGIN_DECLS
+# undef __CONCAT
+# undef __END_DECLS
+# undef __HAVE_GENERIC_SELECTION
+# undef __LDBL_COMPAT
+# undef __LDBL_REDIR
+# undef __LDBL_REDIR1
+# undef __LDBL_REDIR1_DECL
+# undef __LDBL_REDIR1_NTH
+# undef __LDBL_REDIR2_DECL
+# undef __LDBL_REDIR_DECL
+# undef __LDBL_REDIR_NTH
+# undef __LEAF
+# undef __LEAF_ATTR
+# undef __NTH
+# undef __NTHNL
+# undef __REDIRECT
+# undef __REDIRECT_LDBL
+# undef __REDIRECT_NTH
+# undef __REDIRECT_NTHNL
+# undef __REDIRECT_NTH_LDBL
+# undef __STRING
+# undef __THROW
+# undef __THROWNL
+# undef __attr_access
+# undef __attr_access_none
+# undef __attr_dealloc
+# undef __attr_dealloc_free
+# undef __attribute__
+# undef __attribute_alloc_align__
+# undef __attribute_alloc_size__
+# undef __attribute_artificial__
+# undef __attribute_const__
+# undef __attribute_deprecated__
+# undef __attribute_deprecated_msg__
+# undef __attribute_format_arg__
+# undef __attribute_format_strfmon__
+# undef __attribute_malloc__
+# undef __attribute_maybe_unused__
+# undef __attribute_noinline__
+# undef __attribute_nonstring__
+# undef __attribute_pure__
+# undef __attribute_returns_twice__
+# undef __attribute_used__
+# undef __attribute_warn_unused_result__
+# undef __errordecl
+# undef __extension__
+# undef __extern_always_inline
+# undef __extern_inline
+# undef __flexarr
+# undef __fortified_attr_access
+# undef __fortify_function
+# undef __glibc_c99_flexarr_available
+# undef __glibc_has_attribute
+# undef __glibc_has_builtin
+# undef __glibc_has_extension
+# undef __glibc_likely
+# undef __glibc_macro_warning
+# undef __glibc_macro_warning1
+# undef __glibc_unlikely
+# undef __inline
+# undef __ptr_t
+# undef __restrict
+# undef __restrict_arr
+# undef __va_arg_pack
+# undef __va_arg_pack_len
+# undef __warnattr
+# undef __wur
+# ifndef __GNULIB_CDEFS
+# undef __bos
+# undef __bos0
+# undef __glibc_fortify
+# undef __glibc_fortify_n
+# undef __glibc_objsize
+# undef __glibc_objsize0
+# undef __glibc_safe_len_cond
+# undef __glibc_safe_or_unknown_len
+# undef __glibc_unsafe_len
+# undef __glibc_unsigned_or_positive
+# endif
+
+/* Include our copy of glibc <sys/cdefs.h>. */
+# include <cdefs.h>
+
+/* <cdefs.h> __inline is too pessimistic for non-GCC. */
+# undef __inline
+# ifndef HAVE___INLINE
+# if 199901 <= __STDC_VERSION__ || defined inline
+# define __inline inline
+# else
+# define __inline
+# endif
+# endif
+
+#endif /* defined __glibc_likely */
+
+
+/* A substitute for glibc <libc-symbols.h>, good enough for Gnulib. */
+#define attribute_hidden
+#define libc_hidden_proto(name)
+#define libc_hidden_def(name)
+#define libc_hidden_weak(name)
+#define libc_hidden_ver(local, name)
+#define strong_alias(name, aliasname)
+#define weak_alias(name, aliasname)
+
+/* A substitute for glibc <shlib-compat.h>, good enough for Gnulib. */
+#define SHLIB_COMPAT(lib, introduced, obsoleted) 0
+#define compat_symbol(lib, local, symbol, version) extern int dummy
+#define versioned_symbol(lib, local, symbol, version) extern int dummy
diff --git a/libsbutil/gnulib/malloc/scratch_buffer.gl.h b/libsbutil/gnulib/malloc/scratch_buffer.gl.h
new file mode 100644
index 0000000..2ea4060
--- /dev/null
+++ b/libsbutil/gnulib/malloc/scratch_buffer.gl.h
@@ -0,0 +1,133 @@
+/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2015-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _SCRATCH_BUFFER_H
+#define _SCRATCH_BUFFER_H
+
+/* Scratch buffers with a default stack allocation and fallback to
+ heap allocation. It is expected that this function is used in this
+ way:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ return -1;
+
+ scratch_buffer_free (&tmpbuf);
+ return 0;
+
+ The allocation functions (scratch_buffer_grow,
+ scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make
+ sure that the heap allocation, if any, is freed, so that the code
+ above does not have a memory leak. The buffer still remains in a
+ state that can be deallocated using scratch_buffer_free, so a loop
+ like this is valid as well:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ break;
+
+ scratch_buffer_free (&tmpbuf);
+
+ scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed
+ to grow the buffer by at least 512 bytes. This means that when
+ using the scratch buffer as a backing store for a non-character
+ array whose element size, in bytes, is 512 or smaller, the scratch
+ buffer only has to grow once to make room for at least one more
+ element.
+*/
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/* Scratch buffer. Must be initialized with scratch_buffer_init
+ before its use. */
+struct scratch_buffer {
+ void *data; /* Pointer to the beginning of the scratch area. */
+ size_t length; /* Allocated space at the data pointer, in bytes. */
+ union { max_align_t __align; char __c[1024]; } __space;
+};
+
+/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space
+ and BUFFER->length reflects the available space. */
+static inline void
+scratch_buffer_init (struct scratch_buffer *buffer)
+{
+ buffer->data = buffer->__space.__c;
+ buffer->length = sizeof (buffer->__space);
+}
+
+/* Deallocates *BUFFER (if it was heap-allocated). */
+static inline void
+scratch_buffer_free (struct scratch_buffer *buffer)
+{
+ if (buffer->data != buffer->__space.__c)
+ free (buffer->data);
+}
+
+/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT
+ preserved. Return true on success, false on allocation failure (in
+ which case the old buffer is freed). On success, the new buffer is
+ larger than the previous size. On failure, *BUFFER is deallocated,
+ but remains in a free-able state, and errno is set. */
+bool __libc_scratch_buffer_grow (struct scratch_buffer *buffer);
+
+/* Alias for __libc_scratch_buffer_grow. */
+static inline _GL_ATTRIBUTE_ALWAYS_INLINE bool
+scratch_buffer_grow (struct scratch_buffer *buffer)
+{
+ return _GL_LIKELY (__libc_scratch_buffer_grow (buffer));
+}
+
+/* Like __libc_scratch_buffer_grow, but preserve the old buffer
+ contents on success, as a prefix of the new buffer. */
+bool __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer);
+
+/* Alias for __libc_scratch_buffer_grow_preserve. */
+static inline _GL_ATTRIBUTE_ALWAYS_INLINE bool
+scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
+{
+ return _GL_LIKELY (__libc_scratch_buffer_grow_preserve (buffer));
+}
+
+/* Grow *BUFFER so that it can store at least NELEM elements of SIZE
+ bytes. The buffer contents are NOT preserved. Both NELEM and SIZE
+ can be zero. Return true on success, false on allocation failure
+ (in which case the old buffer is freed, but *BUFFER remains in a
+ free-able state, and errno is set). It is unspecified whether this
+ function can reduce the array size. */
+bool __libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size);
+
+/* Alias for __libc_scratch_set_array_size. */
+static inline _GL_ATTRIBUTE_ALWAYS_INLINE bool
+scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size)
+{
+ return _GL_LIKELY (__libc_scratch_buffer_set_array_size
+ (buffer, nelem, size));
+}
+
+#endif /* _SCRATCH_BUFFER_H */
diff --git a/libsbutil/gnulib/malloc/scratch_buffer_grow.c b/libsbutil/gnulib/malloc/scratch_buffer_grow.c
new file mode 100644
index 0000000..2cb5325
--- /dev/null
+++ b/libsbutil/gnulib/malloc/scratch_buffer_grow.c
@@ -0,0 +1,56 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2015-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <scratch_buffer.h>
+#include <errno.h>
+
+bool
+__libc_scratch_buffer_grow (struct scratch_buffer *buffer)
+{
+ void *new_ptr;
+ size_t new_length = buffer->length * 2;
+
+ /* Discard old buffer. */
+ scratch_buffer_free (buffer);
+
+ /* Check for overflow. */
+ if (__glibc_likely (new_length >= buffer->length))
+ new_ptr = malloc (new_length);
+ else
+ {
+ __set_errno (ENOMEM);
+ new_ptr = NULL;
+ }
+
+ if (__glibc_unlikely (new_ptr == NULL))
+ {
+ /* Buffer must remain valid to free. */
+ scratch_buffer_init (buffer);
+ return false;
+ }
+
+ /* Install new heap-based buffer. */
+ buffer->data = new_ptr;
+ buffer->length = new_length;
+ return true;
+}
+libc_hidden_def (__libc_scratch_buffer_grow)
diff --git a/libsbutil/gnulib/malloc/scratch_buffer_grow_preserve.c b/libsbutil/gnulib/malloc/scratch_buffer_grow_preserve.c
new file mode 100644
index 0000000..304635d
--- /dev/null
+++ b/libsbutil/gnulib/malloc/scratch_buffer_grow_preserve.c
@@ -0,0 +1,67 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2015-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <scratch_buffer.h>
+#include <errno.h>
+#include <string.h>
+
+bool
+__libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
+{
+ size_t new_length = 2 * buffer->length;
+ void *new_ptr;
+
+ if (buffer->data == buffer->__space.__c)
+ {
+ /* Move buffer to the heap. No overflow is possible because
+ buffer->length describes a small buffer on the stack. */
+ new_ptr = malloc (new_length);
+ if (new_ptr == NULL)
+ return false;
+ memcpy (new_ptr, buffer->__space.__c, buffer->length);
+ }
+ else
+ {
+ /* Buffer was already on the heap. Check for overflow. */
+ if (__glibc_likely (new_length >= buffer->length))
+ new_ptr = realloc (buffer->data, new_length);
+ else
+ {
+ __set_errno (ENOMEM);
+ new_ptr = NULL;
+ }
+
+ if (__glibc_unlikely (new_ptr == NULL))
+ {
+ /* Deallocate, but buffer must remain valid to free. */
+ free (buffer->data);
+ scratch_buffer_init (buffer);
+ return false;
+ }
+ }
+
+ /* Install new heap-based buffer. */
+ buffer->data = new_ptr;
+ buffer->length = new_length;
+ return true;
+}
+libc_hidden_def (__libc_scratch_buffer_grow_preserve)
diff --git a/libsbutil/gnulib/pathmax.h b/libsbutil/gnulib/pathmax.h
deleted file mode 100644
index 2a5af08..0000000
--- a/libsbutil/gnulib/pathmax.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Define PATH_MAX somehow. Requires sys/types.h.
- Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2015 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 2, 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/>. */
-
-#ifndef _PATHMAX_H
-# define _PATHMAX_H
-
-/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename,
- including the terminating NUL byte.
- <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html>
- PATH_MAX is not defined on systems which have no limit on filename length,
- such as GNU/Hurd.
-
- This file does *not* define PATH_MAX always. Programs that use this file
- can handle the GNU/Hurd case in several ways:
- - Either with a package-wide handling, or with a per-file handling,
- - Either through a
- #ifdef PATH_MAX
- or through a fallback like
- #ifndef PATH_MAX
- # define PATH_MAX 8192
- #endif
- or through a fallback like
- #ifndef PATH_MAX
- # define PATH_MAX pathconf ("/", _PC_PATH_MAX)
- #endif
- */
-
-# include <unistd.h>
-
-# include <limits.h>
-
-# ifndef _POSIX_PATH_MAX
-# define _POSIX_PATH_MAX 256
-# endif
-
-/* Don't include sys/param.h if it already has been. */
-# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
-# include <sys/param.h>
-# endif
-
-# if !defined PATH_MAX && defined MAXPATHLEN
-# define PATH_MAX MAXPATHLEN
-# endif
-
-# ifdef __hpux
-/* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename,
- *not* including the terminating NUL byte, and is set to 1023.
- Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is
- not defined at all any more. */
-# undef PATH_MAX
-# define PATH_MAX 1024
-# endif
-
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com,
- section "Maximum Path Length Limitation",
- <http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx#maxpath>
- explains that the maximum size of a filename, including the terminating
- NUL byte, is 260 = 3 + 256 + 1.
- This is the same value as
- - FILENAME_MAX in <stdio.h>,
- - _MAX_PATH in <stdlib.h>,
- - MAX_PATH in <windef.h>.
- Undefine the original value, because mingw's <limits.h> gets it wrong. */
-# undef PATH_MAX
-# define PATH_MAX 260
-# endif
-
-#endif /* _PATHMAX_H */
diff --git a/libsbutil/gnulib/rawmemchr.c b/libsbutil/gnulib/rawmemchr.c
new file mode 100644
index 0000000..afdd767
--- /dev/null
+++ b/libsbutil/gnulib/rawmemchr.c
@@ -0,0 +1,135 @@
+/* Searching in a string.
+ Copyright (C) 2008-2025 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+/* A function definition is needed only if HAVE_RAWMEMCHR is not defined. */
+#if !HAVE_RAWMEMCHR
+
+# include <limits.h>
+# include <stdint.h>
+
+
+/* Find the first occurrence of C in S. */
+void *
+rawmemchr (const void *s, int c_in)
+{
+# ifdef __CHERI_PURE_CAPABILITY__
+ /* Most architectures let you read an aligned word,
+ even if the unsigned char array at S ends in the middle of the word.
+ However CHERI does not, so call memchr
+ with the underlying object's remaining length.
+ This cannot return NULL if S points to a C_IN-terminated array.
+ Use builtins rather than including <cheri.h> which is less stable. */
+ return memchr (s, c_in, (__builtin_cheri_length_get (s)
+ - __builtin_cheri_offset_get (s)));
+# else
+
+ /* You can change this typedef to experiment with performance. */
+ typedef uintptr_t longword;
+ /* Verify that the longword type lacks padding bits. */
+ static_assert (UINTPTR_WIDTH == UCHAR_WIDTH * sizeof (uintptr_t));
+
+ const unsigned char *char_ptr;
+ unsigned char c = c_in;
+
+ /* Handle the first few bytes by reading one byte at a time.
+ Do this until CHAR_PTR is aligned on a natural longword boundary,
+ as using alignof (longword) might be slower. */
+ for (char_ptr = (const unsigned char *) s;
+ (uintptr_t) char_ptr % sizeof (longword) != 0;
+ ++char_ptr)
+ if (*char_ptr == c)
+ return (void *) char_ptr;
+
+ longword const *longword_ptr = s = char_ptr;
+
+ /* Compute auxiliary longword values:
+ repeated_one is a value which has a 1 in every byte.
+ repeated_c has c in every byte. */
+ longword repeated_one = (longword) -1 / UCHAR_MAX;
+ longword repeated_c = repeated_one * c;
+ longword repeated_hibit = repeated_one * (UCHAR_MAX / 2 + 1);
+
+ /* Instead of the traditional loop which tests each byte, we will
+ test a longword at a time. The tricky part is testing if any of
+ the bytes in the longword in question are equal to
+ c. We first use an xor with repeated_c. This reduces the task
+ to testing whether any of the bytes in longword1 is zero.
+
+ (The following comments assume 8-bit bytes, as POSIX requires;
+ the code's use of UCHAR_MAX should work even if bytes have more
+ than 8 bits.)
+
+ We compute tmp =
+ ((longword1 - repeated_one) & ~longword1) & (repeated_one * 0x80).
+ That is, we perform the following operations:
+ 1. Subtract repeated_one.
+ 2. & ~longword1.
+ 3. & a mask consisting of 0x80 in every byte.
+ Consider what happens in each byte:
+ - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+ and step 3 transforms it into 0x80. A carry can also be propagated
+ to more significant bytes.
+ - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+ position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
+ the byte ends in a single bit of value 0 and k bits of value 1.
+ After step 2, the result is just k bits of value 1: 2^k - 1. After
+ step 3, the result is 0. And no carry is produced.
+ So, if longword1 has only non-zero bytes, tmp is zero.
+ Whereas if longword1 has a zero byte, call j the position of the least
+ significant zero byte. Then the result has a zero at positions 0, ...,
+ j-1 and a 0x80 at position j. We cannot predict the result at the more
+ significant bytes (positions j+1..3), but it does not matter since we
+ already have a non-zero bit at position 8*j+7.
+
+ The test whether any byte in longword1 is zero is equivalent
+ to testing whether tmp is nonzero.
+
+ This test can read beyond the end of a string, depending on where
+ C_IN is encountered. However, this is considered safe since the
+ initialization phase ensured that the read will be aligned,
+ therefore, the read will not cross page boundaries and will not
+ cause a fault. */
+
+ while (1)
+ {
+ longword longword1 = *longword_ptr ^ repeated_c;
+
+ if ((((longword1 - repeated_one) & ~longword1) & repeated_hibit) != 0)
+ break;
+ longword_ptr++;
+ }
+
+ char_ptr = s = longword_ptr;
+
+ /* At this point, we know that one of the sizeof (longword) bytes
+ starting at char_ptr is == c. If we knew endianness, we
+ could determine the first such byte without any further memory
+ accesses, just by looking at the tmp result from the last loop
+ iteration. However, the following simple and portable code does
+ not attempt this potential optimization. */
+
+ while (*char_ptr != c)
+ char_ptr++;
+ return (void *) char_ptr;
+# endif
+}
+
+#endif
diff --git a/libsbutil/gnulib/same-inode.h b/libsbutil/gnulib/same-inode.h
index ecc3049..8ed3b3a 100644
--- a/libsbutil/gnulib/same-inode.h
+++ b/libsbutil/gnulib/same-inode.h
@@ -1,33 +1,95 @@
-/* Determine whether two stat buffers refer to the same file.
+/* Determine whether two stat buffers are known to refer to the same file.
- Copyright (C) 2006, 2009-2015 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-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
- (at your option) any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser 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/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef SAME_INODE_H
-# define SAME_INODE_H 1
-
-# ifdef __VMS
-# define SAME_INODE(a, b) \
- ((a).st_ino[0] == (b).st_ino[0] \
- && (a).st_ino[1] == (b).st_ino[1] \
- && (a).st_ino[2] == (b).st_ino[2] \
- && (a).st_dev == (b).st_dev)
+#define SAME_INODE_H 1
+
+/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE. */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
+#include <sys/stat.h>
+
+_GL_INLINE_HEADER_BEGIN
+#ifndef SAME_INODE_INLINE
+# define SAME_INODE_INLINE _GL_INLINE
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* True if A and B point to structs with st_dev and st_ino members
+ that are known to represent the same file.
+
+ Use | and ^ to shorten generated code, and to lessen the
+ probability of screwups if st_ino is an array. */
+
+#if defined __VMS && __CRTL_VER < 80200000
+# define PSAME_INODE(a, b) (! (((a)->st_dev ^ (b)->st_dev) \
+ | ((a)->st_ino[0] ^ (b)->st_ino[0]) \
+ | ((a)->st_ino[1] ^ (b)->st_ino[1]) \
+ | ((a)->st_ino[2] ^ (b)->st_ino[2])))
+#elif defined _WIN32 && ! defined __CYGWIN__
+ /* Native Windows. */
+# if _GL_WINDOWS_STAT_INODES
+ /* stat() and fstat() set st_dev and st_ino to 0 if information about
+ the inode is not available. */
+# if _GL_WINDOWS_STAT_INODES == 2
+# define PSAME_INODE(a, b) \
+ (! (! ((a)->st_dev | (a)->st_ino._gl_ino[0] | (a)->st_ino._gl_ino[1]) \
+ | ((a)->st_dev ^ (b)->st_dev) \
+ | ((a)->st_ino._gl_ino[0] ^ (b)->st_ino._gl_ino[0]) \
+ | ((a)->st_ino._gl_ino[1] ^ (b)->st_ino._gl_ino[1])))
+# else
+# define PSAME_INODE(a, b) (! (! ((a)->st_dev | (a)->st_ino) \
+ | ((a)->st_dev ^ (b)->st_dev) \
+ | ((a)->st_ino ^ (b)->st_ino)))
+# endif
# else
-# define SAME_INODE(a, b) \
- ((a).st_ino == (b).st_ino \
- && (a).st_dev == (b).st_dev)
+ /* stat() and fstat() set st_ino to 0 always. */
+# define PSAME_INODE(a, b) 0
# endif
+#else
+ /* POSIX. */
+# define PSAME_INODE(a, b) (! (((a)->st_dev ^ (b)->st_dev) \
+ | ((a)->st_ino ^ (b)->st_ino)))
+#endif
+
+/* True if struct objects A and B are known to represent the same file. */
+
+#define SAME_INODE(a, b) PSAME_INODE (&(a), &(b))
+
+/* True if *A and *B represent the same file. Unlike PSAME_INODE,
+ args are evaluated once and must point to struct stat. */
+
+SAME_INODE_INLINE bool
+psame_inode (struct stat const *a, struct stat const *b)
+{
+ return PSAME_INODE (a, b);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+_GL_INLINE_HEADER_END
#endif
diff --git a/libsbutil/gnulib/scratch_buffer.h b/libsbutil/gnulib/scratch_buffer.h
new file mode 100644
index 0000000..d8fb07b
--- /dev/null
+++ b/libsbutil/gnulib/scratch_buffer.h
@@ -0,0 +1,117 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2017-2025 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert, 2017. */
+
+#ifndef _GL_SCRATCH_BUFFER_H
+#define _GL_SCRATCH_BUFFER_H
+
+/* Scratch buffers with a default stack allocation and fallback to
+ heap allocation. It is expected that this function is used in this
+ way:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ return -1;
+
+ scratch_buffer_free (&tmpbuf);
+ return 0;
+
+ The allocation functions (scratch_buffer_grow,
+ scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make
+ sure that the heap allocation, if any, is freed, so that the code
+ above does not have a memory leak. The buffer still remains in a
+ state that can be deallocated using scratch_buffer_free, so a loop
+ like this is valid as well:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ break;
+
+ scratch_buffer_free (&tmpbuf);
+
+ scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed
+ to grow the buffer by at least 512 bytes. This means that when
+ using the scratch buffer as a backing store for a non-character
+ array whose element size, in bytes, is 512 or smaller, the scratch
+ buffer only has to grow once to make room for at least one more
+ element.
+*/
+
+/* Scratch buffer. Must be initialized with scratch_buffer_init
+ before its use. */
+struct scratch_buffer;
+
+/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space
+ and BUFFER->length reflects the available space. */
+#if 0
+extern void scratch_buffer_init (struct scratch_buffer *buffer);
+#endif
+
+/* Deallocates *BUFFER (if it was heap-allocated). */
+#if 0
+extern void scratch_buffer_free (struct scratch_buffer *buffer);
+#endif
+
+/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT
+ preserved. Return true on success, false on allocation failure (in
+ which case the old buffer is freed). On success, the new buffer is
+ larger than the previous size. On failure, *BUFFER is deallocated,
+ but remains in a free-able state, and errno is set. */
+#if 0
+extern bool scratch_buffer_grow (struct scratch_buffer *buffer);
+#endif
+
+/* Like scratch_buffer_grow, but preserve the old buffer
+ contents on success, as a prefix of the new buffer. */
+#if 0
+extern bool scratch_buffer_grow_preserve (struct scratch_buffer *buffer);
+#endif
+
+/* Grow *BUFFER so that it can store at least NELEM elements of SIZE
+ bytes. The buffer contents are NOT preserved. Both NELEM and SIZE
+ can be zero. Return true on success, false on allocation failure
+ (in which case the old buffer is freed, but *BUFFER remains in a
+ free-able state, and errno is set). It is unspecified whether this
+ function can reduce the array size. */
+#if 0
+extern bool scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size);
+#endif
+
+
+/* The implementation is imported from glibc. */
+
+/* Avoid possible conflicts with symbols exported by the GNU libc. */
+#define __libc_scratch_buffer_grow gl_scratch_buffer_grow
+#define __libc_scratch_buffer_grow_preserve gl_scratch_buffer_grow_preserve
+#define __libc_scratch_buffer_set_array_size gl_scratch_buffer_set_array_size
+
+#ifndef _GL_LIKELY
+/* Rely on __builtin_expect, as provided by the module 'builtin-expect'. */
+# define _GL_LIKELY(cond) __builtin_expect ((cond), 1)
+# define _GL_UNLIKELY(cond) __builtin_expect ((cond), 0)
+#endif
+
+#include <malloc/scratch_buffer.gl.h>
+
+#endif /* _GL_SCRATCH_BUFFER_H */
diff --git a/libsbutil/gnulib/xalloc-oversized.h b/libsbutil/gnulib/xalloc-oversized.h
index f0e9778..0f66bd0 100644
--- a/libsbutil/gnulib/xalloc-oversized.h
+++ b/libsbutil/gnulib/xalloc-oversized.h
@@ -1,38 +1,65 @@
/* xalloc-oversized.h -- memory allocation size checking
- Copyright (C) 1990-2000, 2003-2004, 2006-2015 Free Software Foundation, Inc.
+ Copyright (C) 1990-2000, 2003-2004, 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
- (at your option) any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser 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/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef XALLOC_OVERSIZED_H_
-# define XALLOC_OVERSIZED_H_
-
-# include <stddef.h>
-
-/* Return 1 if an array of N objects, each of size S, cannot exist due
- to size arithmetic overflow. S must be positive and N must be
- nonnegative. This is a macro, not a function, so that it
- works correctly even when SIZE_MAX < N.
-
- By gnulib convention, SIZE_MAX represents overflow in size
- calculations, so the conservative dividend to use here is
- SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
- However, malloc (SIZE_MAX) fails on all known hosts where
- sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
- exactly-SIZE_MAX allocations on such hosts; this avoids a test and
- branch when S is known to be 1. */
+#define XALLOC_OVERSIZED_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* True if N * S does not fit into both ptrdiff_t and size_t.
+ N and S should be nonnegative and free of side effects.
+ This expands to a constant expression if N and S are both constants.
+ By gnulib convention, SIZE_MAX represents overflow in size_t
+ calculations, so the conservative size_t-based dividend to use here
+ is SIZE_MAX - 1. */
+#define __xalloc_oversized(n, s) \
+ ((s) != 0 \
+ && (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) < (n))
+
+/* Return 1 if and only if an array of N objects, each of size S,
+ cannot exist reliably because its total size in bytes would exceed
+ MIN (PTRDIFF_MAX, SIZE_MAX - 1).
+
+ N and S should be nonnegative and free of side effects.
+
+ Warning: (xalloc_oversized (N, S) ? NULL : malloc (N * S)) can
+ misbehave if N and S are both narrower than ptrdiff_t and size_t,
+ and can be rewritten as (xalloc_oversized (N, S) ? NULL
+ : malloc (N * (size_t) S)).
+
+ This is a macro, not a function, so that it works even if an
+ argument exceeds MAX (PTRDIFF_MAX, SIZE_MAX). */
+#if 7 <= __GNUC__ && !defined __clang__ && PTRDIFF_MAX < SIZE_MAX
# define xalloc_oversized(n, s) \
- ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
+ __builtin_mul_overflow_p (n, s, (ptrdiff_t) 1)
+#elif 5 <= __GNUC__ && !defined __clang__ && !defined __ICC \
+ && PTRDIFF_MAX < SIZE_MAX
+# define xalloc_oversized(n, s) \
+ (__builtin_constant_p (n) && __builtin_constant_p (s) \
+ ? __xalloc_oversized (n, s) \
+ : __extension__ \
+ ({ ptrdiff_t __xalloc_count; \
+ __builtin_mul_overflow (n, s, &__xalloc_count); }))
+
+/* Other compilers use integer division; this may be slower but is
+ more portable. */
+#else
+# define xalloc_oversized(n, s) __xalloc_oversized (n, s)
+#endif
#endif /* !XALLOC_OVERSIZED_H_ */
diff --git a/libsbutil/gnulib/xalloc.h b/libsbutil/gnulib/xalloc.h
index 3077f27..be20647 100644
--- a/libsbutil/gnulib/xalloc.h
+++ b/libsbutil/gnulib/xalloc.h
@@ -1 +1,3 @@
-#include "sbutil.h"
+#include <sbutil.h>
+/* make canonicalize use unwrapped faccessat */
+#define faccessat sbio_faccessat
diff --git a/libsbutil/gnulib/xgetcwd.h b/libsbutil/gnulib/xgetcwd.h
deleted file mode 100644
index fbe0a7c..0000000
--- a/libsbutil/gnulib/xgetcwd.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* This is slightly wrong as libsbutil code is supposed to work both in
- * libsandbox and in sandbox, but egetcwd is only available in the former.
- * We'll worry about that if/when it becomes an issue for other programs.
- *
- * Copyright 1999-2015 Gentoo Foundation
- * Licensed under the GPL-2
- */
-
-extern char *egetcwd(char *buf, size_t size);
-
-static inline char *xgetcwd(void)
-{
- char *ret = egetcwd(NULL, 0);
- if (ret == NULL && errno == ENOMEM)
- xalloc_die();
- return ret;
-}
diff --git a/libsbutil/local.mk b/libsbutil/local.mk
index dc6937f..93e5518 100644
--- a/libsbutil/local.mk
+++ b/libsbutil/local.mk
@@ -4,7 +4,8 @@ noinst_LIBRARIES += %D%/libsbutil.a
$(AM_CPPFLAGS) \
$(SIXTY_FOUR_FLAGS) \
-I$(top_srcdir)/%D% \
- -I$(top_srcdir)/%D%/include
+ -I$(top_srcdir)/%D%/include \
+ -I$(top_srcdir)/%D%/gnulib
%C%_libsbutil_a_CFLAGS = -fPIC
%C%_libsbutil_a_SOURCES = \
%D%/sbutil.h \
@@ -40,26 +41,32 @@ noinst_LIBRARIES += %D%/libsbutil.a
%D%/src/config.c \
%D%/include/rcscripts/util/dynbuf.h \
%D%/src/dynbuf.c \
- %D%/gnulib/areadlink.h \
- %D%/gnulib/areadlink-with-size.c \
- %D%/gnulib/bitrotate.c \
- %D%/gnulib/bitrotate.h \
- %D%/gnulib/canonicalize.c \
- %D%/gnulib/canonicalize.h \
- %D%/gnulib/careadlinkat.h \
- %D%/gnulib/dosname.h \
- %D%/gnulib/file-set.c \
- %D%/gnulib/file-set.h \
- %D%/gnulib/gl-inline.h \
- %D%/gnulib/glue.h \
- %D%/gnulib/hash.c \
- %D%/gnulib/hash.h \
- %D%/gnulib/hash-pjw.c \
- %D%/gnulib/hash-pjw.h \
- %D%/gnulib/hash-triple.c \
- %D%/gnulib/hash-triple.h \
- %D%/gnulib/pathmax.h \
- %D%/gnulib/same-inode.h \
- %D%/gnulib/xalloc.h \
- %D%/gnulib/xalloc-oversized.h \
- %D%/gnulib/xgetcwd.h
+ %D%/gnulib/attribute.h \
+ %D%/gnulib/bitrotate.c \
+ %D%/gnulib/bitrotate.h \
+ %D%/gnulib/canonicalize.c \
+ %D%/gnulib/canonicalize.h \
+ %D%/gnulib/cdefs.h \
+ %D%/gnulib/file-set.c \
+ %D%/gnulib/file-set.h \
+ %D%/gnulib/filename.h \
+ %D%/gnulib/gl-inline.h \
+ %D%/gnulib/glue.h \
+ %D%/gnulib/hash-pjw.c \
+ %D%/gnulib/hash-pjw.h \
+ %D%/gnulib/hash-triple-simple.c \
+ %D%/gnulib/hash-triple.h \
+ %D%/gnulib/hash.c \
+ %D%/gnulib/hash.h \
+ %D%/gnulib/idx.h \
+ %D%/gnulib/intprops-internal.h \
+ %D%/gnulib/intprops.h \
+ %D%/gnulib/libc-config.h \
+ %D%/gnulib/malloc/scratch_buffer.gl.h \
+ %D%/gnulib/malloc/scratch_buffer_grow.c \
+ %D%/gnulib/malloc/scratch_buffer_grow_preserve.c \
+ %D%/gnulib/rawmemchr.c \
+ %D%/gnulib/same-inode.h \
+ %D%/gnulib/scratch_buffer.h \
+ %D%/gnulib/xalloc-oversized.h \
+ %D%/gnulib/xalloc.h
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2025-01-21 20:36 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-21 20:36 [gentoo-commits] proj/sandbox:master commit in: /, libsbutil/gnulib/malloc/, libsbutil/, libsbutil/gnulib/ Mike Gilbert
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox