mirror of
https://git.sr.ht/~cismonx/bookmarkfs
synced 2025-07-17 14:48:50 +00:00
all: properly handle time_t
on 32-bit platforms
Do not force 64-bit `time_t` on 32-bit platforms, since libfuse does not do so. Linking shared objects with incompatible types breaks ABI, resulting in undefined behavior. Instead, add run-time checks to make sure that timestamps do not overflow. If they do, set to `INT32_MAX`. Also tidy up build scripts, tests, and the installation guide.
This commit is contained in:
parent
f1451d206e
commit
6fc165ff65
5 changed files with 36 additions and 47 deletions
13
INSTALL.md
13
INSTALL.md
|
@ -166,19 +166,6 @@ Notes
|
|||
In this case, the utility library will not be built from source,
|
||||
and other components will link to the specified library instead.
|
||||
|
||||
### Targeting 32-bit Platforms
|
||||
|
||||
BookmarkFS requires 64-bit `off_t` and `time_t`, which may not be supported
|
||||
on 32-bit platforms (e.g., i386 FreeBSD does not support 64-bit `time_t`).
|
||||
|
||||
If using Autoconf 2.72 or later, the configuration script automatically
|
||||
performs checks and defines necessary macros, and fails if unsupported.
|
||||
With legacy Autoconf, only `off_t` is checked.
|
||||
|
||||
To manually configure 64-bit `time_t`, add preprocessor flags
|
||||
`-D_TIME_BITS=64` (or something equivalent, depending on the toolchain).
|
||||
If unsupported, `make` will fail.
|
||||
|
||||
### FreeBSD and GNU libiconv
|
||||
|
||||
NOTE: You may skip this section if _not_ building the Chromium backend.
|
||||
|
|
13
configure.ac
13
configure.ac
|
@ -196,18 +196,7 @@ AS_VAR_IF([ac_have_largefile], [no], [
|
|||
]))
|
||||
])
|
||||
|
||||
m4_version_prereq([2.72], [
|
||||
AC_SYS_YEAR2038
|
||||
AS_VAR_IF([ac_have_year2038], [no], [
|
||||
AC_MSG_ERROR(m4_normalize([
|
||||
64-bit time_t is unsupported on this platform.
|
||||
]))
|
||||
])
|
||||
], [
|
||||
dnl fallback to compile-time check...
|
||||
AX_COMPILE_CHECK_SIZEOF([time_t])
|
||||
])
|
||||
|
||||
AX_COMPILE_CHECK_SIZEOF([time_t])
|
||||
AX_COMPILE_CHECK_SIZEOF([uintptr_t], [#include <stdint.h>])
|
||||
|
||||
# -- Output --
|
||||
|
|
|
@ -58,17 +58,14 @@
|
|||
#include "watcher.h"
|
||||
#include "xstd.h"
|
||||
|
||||
#if defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T != 8)
|
||||
# error "64-bit time_t is required"
|
||||
#endif
|
||||
|
||||
#define BACKEND_FILENAME_GUID ( 1u << 16 )
|
||||
|
||||
// Chromium uses Windows FILETIME epoch instead of Unix epoch.
|
||||
// Chromium uses Windows FILETIME epoch, which is
|
||||
// `((1970 - 1601) * 365 + 89) * 24 * 3600` seconds before the Unix epoch.
|
||||
//
|
||||
// See Chromium source code: /base/time/time.h
|
||||
// (`base::Time::kTimeTToMicrosecondsOffset`)
|
||||
#define EPOCH_DIFF ( (time_t)((1970 - 1601) * 365 + 89) * 24 * 3600 )
|
||||
#define EPOCH_DIFF INT64_C(11644473600)
|
||||
|
||||
#define BOOKMARKS_ROOT_ID 0
|
||||
|
||||
|
@ -387,7 +384,7 @@ build_tsnode (
|
|||
ts = &now;
|
||||
}
|
||||
|
||||
time_t secs = ts->tv_sec + EPOCH_DIFF;
|
||||
int64_t secs = ts->tv_sec + EPOCH_DIFF;
|
||||
int64_t microsecs = secs * 1000000 + ts->tv_nsec / 1000;
|
||||
|
||||
char buf[32];
|
||||
|
@ -1461,12 +1458,17 @@ parse_ts (
|
|||
}
|
||||
|
||||
if (buf != NULL) {
|
||||
time_t secs = microsecs / 1000000;
|
||||
if (unlikely(secs < EPOCH_DIFF)) {
|
||||
int64_t secs = microsecs / 1000000 - EPOCH_DIFF;
|
||||
if (unlikely(secs < 0)) {
|
||||
// Stay away from negative tv_sec
|
||||
secs = EPOCH_DIFF;
|
||||
secs = 0;
|
||||
}
|
||||
buf->tv_sec = secs - EPOCH_DIFF;
|
||||
#if defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T < 8)
|
||||
else if (secs > INT32_MAX) {
|
||||
secs = INT32_MAX;
|
||||
}
|
||||
#endif
|
||||
buf->tv_sec = secs;
|
||||
buf->tv_nsec = (microsecs % 1000000) * 1000;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -2135,7 +2135,7 @@ static int64_t
|
|||
timespec_to_usecs (
|
||||
struct timespec const *ts
|
||||
) {
|
||||
return ts->tv_sec * 1000000 + ts->tv_nsec / 1000;
|
||||
return (int64_t)ts->tv_sec * 1000000 + ts->tv_nsec / 1000;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2778,11 +2778,16 @@ usecs_to_timespec (
|
|||
struct timespec *ts_buf,
|
||||
int64_t microsecs
|
||||
) {
|
||||
if (unlikely(microsecs < 0)) {
|
||||
microsecs = 0;
|
||||
int64_t secs = microsecs / 1000000;
|
||||
if (unlikely(secs < 0)) {
|
||||
secs = 0;
|
||||
}
|
||||
|
||||
ts_buf->tv_sec = microsecs / 1000000;
|
||||
#if defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T < 8)
|
||||
else if (secs > INT32_MAX) {
|
||||
secs = INT32_MAX;
|
||||
}
|
||||
#endif
|
||||
ts_buf->tv_sec = secs;
|
||||
ts_buf->tv_nsec = (microsecs % 1000000) * 1000;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,13 +31,14 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "check_util.h"
|
||||
#include "backend_util.h"
|
||||
#include "frontend_util.h"
|
||||
#include "prng.h"
|
||||
|
||||
// Forward declaration start
|
||||
static int compare_timespec (struct timespec, struct timespec);
|
||||
static int do_check_fs_times (int, int);
|
||||
static void usecs_to_timespec (struct timespec *, uint32_t);
|
||||
static void usecs_to_timespec (struct timespec *, uint64_t);
|
||||
// Forward declaration end
|
||||
|
||||
static int
|
||||
|
@ -113,9 +114,8 @@ do_check_fs_times (
|
|||
ASSERT_NE(-1, compare_timespec(stat_buf.st_atim, now));
|
||||
|
||||
for (int i = 0; i < rounds; ++i) {
|
||||
uint64_t bits = prng_rand();
|
||||
usecs_to_timespec(×[0], bits & 0xffffffff);
|
||||
usecs_to_timespec(×[1], bits >> 32);
|
||||
usecs_to_timespec(×[0], prng_rand());
|
||||
usecs_to_timespec(×[1], prng_rand());
|
||||
|
||||
ASSERT_EQ(0, futimens(fd, times));
|
||||
ASSERT_EQ(0, fstat(fd, &stat_buf));
|
||||
|
@ -142,9 +142,15 @@ do_check_fs_times (
|
|||
static void
|
||||
usecs_to_timespec (
|
||||
struct timespec *ts_buf,
|
||||
uint32_t usecs
|
||||
uint64_t usecs
|
||||
) {
|
||||
ts_buf->tv_sec = usecs / 1000000;
|
||||
int64_t secs = usecs / 1000000;
|
||||
#if defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T < 8)
|
||||
secs %= (int64_t)INT32_MAX + 1;
|
||||
#else
|
||||
secs %= TIMESPEC_SEC_MAX + 1;
|
||||
#endif
|
||||
ts_buf->tv_sec = secs;
|
||||
ts_buf->tv_nsec = (usecs % 1000000) * 1000;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue