Compare commits

...

3 commits

Author SHA1 Message Date
CismonX
ba9a23c295
backend_firefox: refactor db query utils
- `DO_QUERY()` macro:
  * Pass stmt idx as argument instead of pointer.
  * Remove the `BEFORE_QUERY` argument.
- Shorter names for stmt idx.
2025-06-16 11:22:53 +08:00
CismonX
31f4311419
backend_firefox: misc refactor
- `mozorigin_get()`, `mozplace_addref()`: pass struct as argument.
- `parse_mozurl_host()`: rename to `parse_mozurl`; add comments;
  store parse results to argument of type `struct mozorigin`.
- Rename objects of type `struct mozXXX` from `XXX_cols` to `mX`.
- ...
2025-06-15 17:45:52 +08:00
CismonX
6fc165ff65
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.
2025-06-14 11:43:03 +08:00
5 changed files with 301 additions and 372 deletions

View file

@ -166,19 +166,6 @@ Notes
In this case, the utility library will not be built from source, In this case, the utility library will not be built from source,
and other components will link to the specified library instead. 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 ### FreeBSD and GNU libiconv
NOTE: You may skip this section if _not_ building the Chromium backend. NOTE: You may skip this section if _not_ building the Chromium backend.

View file

@ -196,18 +196,7 @@ AS_VAR_IF([ac_have_largefile], [no], [
])) ]))
]) ])
m4_version_prereq([2.72], [ AX_COMPILE_CHECK_SIZEOF([time_t])
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([uintptr_t], [#include <stdint.h>]) AX_COMPILE_CHECK_SIZEOF([uintptr_t], [#include <stdint.h>])
# -- Output -- # -- Output --

View file

@ -58,17 +58,14 @@
#include "watcher.h" #include "watcher.h"
#include "xstd.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 ) #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 // See Chromium source code: /base/time/time.h
// (`base::Time::kTimeTToMicrosecondsOffset`) // (`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 #define BOOKMARKS_ROOT_ID 0
@ -387,7 +384,7 @@ build_tsnode (
ts = &now; 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; int64_t microsecs = secs * 1000000 + ts->tv_nsec / 1000;
char buf[32]; char buf[32];
@ -1461,12 +1458,17 @@ parse_ts (
} }
if (buf != NULL) { if (buf != NULL) {
time_t secs = microsecs / 1000000; int64_t secs = microsecs / 1000000 - EPOCH_DIFF;
if (unlikely(secs < EPOCH_DIFF)) { if (unlikely(secs < 0)) {
// Stay away from negative tv_sec // 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; buf->tv_nsec = (microsecs % 1000000) * 1000;
} }
return 0; return 0;

File diff suppressed because it is too large Load diff

View file

@ -31,13 +31,14 @@
#include <unistd.h> #include <unistd.h>
#include "check_util.h" #include "check_util.h"
#include "backend_util.h"
#include "frontend_util.h" #include "frontend_util.h"
#include "prng.h" #include "prng.h"
// Forward declaration start // Forward declaration start
static int compare_timespec (struct timespec, struct timespec); static int compare_timespec (struct timespec, struct timespec);
static int do_check_fs_times (int, int); 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 // Forward declaration end
static int static int
@ -113,9 +114,8 @@ do_check_fs_times (
ASSERT_NE(-1, compare_timespec(stat_buf.st_atim, now)); ASSERT_NE(-1, compare_timespec(stat_buf.st_atim, now));
for (int i = 0; i < rounds; ++i) { for (int i = 0; i < rounds; ++i) {
uint64_t bits = prng_rand(); usecs_to_timespec(&times[0], prng_rand());
usecs_to_timespec(&times[0], bits & 0xffffffff); usecs_to_timespec(&times[1], prng_rand());
usecs_to_timespec(&times[1], bits >> 32);
ASSERT_EQ(0, futimens(fd, times)); ASSERT_EQ(0, futimens(fd, times));
ASSERT_EQ(0, fstat(fd, &stat_buf)); ASSERT_EQ(0, fstat(fd, &stat_buf));
@ -142,9 +142,15 @@ do_check_fs_times (
static void static void
usecs_to_timespec ( usecs_to_timespec (
struct timespec *ts_buf, 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; ts_buf->tv_nsec = (usecs % 1000000) * 1000;
} }