commit - efaf222244a17c530f5e2150244957d925fbb58a
commit + aa3d42441d6a7314454191888aeac21682cf2cfe
blob - 5f8e39bd2ff40baa5509001d77ceec8213ab29de
blob + 8d7b53e85df424cc4a01c912451f7ed46fecdb6f
--- compat.h
+++ compat.h
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <time.h>
#ifdef __OpenBSD__
#include <unistd.h> /* pledge, unveil */
#endif
/*
+ * timingsafe_bcmp - constant-time memory comparison.
+ * Available in OpenBSD and macOS; provide a shim elsewhere.
+ */
+#if !defined(__OpenBSD__) && !defined(__APPLE__)
+static inline int
+timingsafe_bcmp(const void *b1, const void *b2, size_t n)
+{
+ const unsigned char *p1 = b1, *p2 = b2;
+ int ret = 0;
+
+ for (; n > 0; n--)
+ ret |= *p1++ ^ *p2++;
+ return (ret != 0);
+}
+#endif
+
+/*
+ * arc4random_buf - high-quality random bytes.
+ * Available in OpenBSD and macOS; provide a shim for other platforms.
+ * For development/testing, reading from /dev/urandom is sufficient.
+ */
+#if !defined(__OpenBSD__) && !defined(__APPLE__)
+#include <fcntl.h>
+#include <unistd.h>
+static inline void
+arc4random_buf(void *buf, size_t n)
+{
+ int fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1)
+ abort();
+ if (read(fd, buf, n) != (ssize_t)n)
+ abort();
+ close(fd);
+}
+#endif
+
+/*
+ * timegm - inverse of gmtime.
+ * Non-standard but available on many systems; provide a shim for POSIX.
+ */
+#if !defined(__OpenBSD__) && !defined(__APPLE__) && !defined(__GLIBC__)
+static inline time_t
+timegm(struct tm *tm)
+{
+ time_t ret;
+ char *tz;
+
+ tz = getenv("TZ");
+ if (tz != NULL)
+ tz = strdup(tz);
+ setenv("TZ", "", 1);
+ tzset();
+ ret = mktime(tm);
+ if (tz != NULL) {
+ setenv("TZ", tz, 1);
+ free(tz);
+ } else {
+ unsetenv("TZ");
+ }
+ tzset();
+ return ret;
+}
+#endif
+
+/*
* reallocarray - safe realloc with overflow checking.
* Available in OpenBSD and glibc >= 2.26; provide a shim elsewhere
* (including macOS/Apple libc which does not provide it).