Compare commits

...

4 commits

Author SHA1 Message Date
CismonX
96c1835512
doc: minor cleanup for user and install manual 2025-07-14 20:43:18 +08:00
CismonX
602519db12
build: misc refactor
EX_DEP():
- Do not generate feature check code if `feat-names` is empty.
- Improve docs.

others:
- Reuse `$host_os` for system type check result.
2025-07-12 12:53:16 +08:00
CismonX
296b85cbe9
build: refactor feature variable exporting
- Remove EX_AMCOND() and EX_FEAT_EXPORT(), instead add flags to
  EX_FEAT() to check whether a feature should be exported.
- Only mark a feature to be exported with AM_CONDITIONAL() when
  it is checked within either */Makefile.am or tests/atlocal.in.
- Only add a feature to test/atlocal.in when it is checked by
  ATX_FEAT_*().
- Move feature "bookmarkfs-util" after features that may enable it,
  so that its enable status can be correctly displayed.
2025-07-12 12:52:28 +08:00
CismonX
300e3d889a
test: skip sandbox tests if not enabled 2025-07-11 23:44:21 +08:00
8 changed files with 89 additions and 116 deletions

View file

@ -17,9 +17,6 @@ Requirements
- GNU/Linux - GNU/Linux
- FreeBSD (with caveats) - FreeBSD (with caveats)
See the user manual for comments if you wish to port BookmarkFS to other
operating systems.
### Dependencies ### Dependencies
In addition to the OS kernel and a POSIX-compatible libc, In addition to the OS kernel and a POSIX-compatible libc,
@ -49,14 +46,11 @@ Requirements
* Autoconf Archive * Autoconf Archive
- `pkg-config` - `pkg-config`
- POSIX-compatible `make` - POSIX-compatible `make`
* One with `VPATH` support is recommended
- C99-capable C compiler - C99-capable C compiler
* GCC or Clang is recommended
Optionally: Optionally:
- GNU Texinfo - GNU Texinfo (for building the user manual)
* For building the user manual
Installation Installation
@ -74,27 +68,27 @@ Installation
$ ../configure --help $ ../configure --help
BookmarkFS has multiple components. By default, none will be built. BookmarkFS has multiple components. By default, none will be built.
Except for the utility library, each component can be enabled independently: To enable a component, specify the corresponding option:
- The BookmarkFS utility library: `--enable-bookmarkfs-util` - `--enable-bookmarkfs-util`: the BookmarkFS utility library
* Requires: libseccomp (Linux-only), xxHash * Requires: libseccomp (Linux-only), xxHash
* Automatically enabled if required by other components * Automatically enabled if required by other components
- The `mount.bookmarkfs` program: `--enable-bookmarkfs-mount` - `--enable-bookmarkfs-mount`: the `mount.bookmarkfs` program
* Requires: libfuse, bookmarkfs-util * Requires: libfuse, bookmarkfs-util
- The `fsck.bookmarkfs` program: `--enable-bookmarkfs-fsck` - `--enable-bookmarkfs-fsck`: the `fsck.bookmarkfs` program
* Requires: Readline, bookmarkfs-util * Requires: Readline, bookmarkfs-util
- The `mkfs.bookmarkfs` program: `--enable-bookmarkfs-mkfs` - `--enable-bookmarkfs-mkfs`: the `mkfs.bookmarkfs` program
- The `bookmarkctl` program: `--enable-bookmarkctl` - `--enable-bookmarkctl`: the `bookmarkctl` program
- The Firefox backend: `--enable-backend-firefox` - `--enable-backend-firefox`: backend for Firefox
* Requires: SQLite, Nettle, uriparser, bookmarkfs-util * Requires: SQLite, Nettle, uriparser, bookmarkfs-util
- The Chromium backend: `--enable-backend-chromium` - `--enable-backend-chromium`: backend for Chromium
* Requires: Jansson, Nettle, bookmarkfs-util * Requires: Jansson, Nettle, bookmarkfs-util
- The Tcl-based handler for `fsck.bookmarkfs`: `--enable-fsck-handler-tcl` - `--enable-fsck-handler-tcl`: Tcl-based handler for `fsck.bookmarkfs`
* Requires: Tcl * Requires: Tcl
For each of the required third-party libraries, if installed in a For each of the required third-party libraries, if installed in a
custom location, it should be specified with `--with-<foo>=<pkgconfdir>`, custom location, it should be specified with `--with-<lib>=<pkgconfdir>`,
where `<foo>` is the library name, and `<pkgconfdir>` is the directory where `<lib>` is the library name, and `<pkgconfdir>` is the directory
holding its pkg-config file. holding its pkg-config file.
Other options: Other options:
@ -103,7 +97,7 @@ Installation
* Build the utility library without sandboxing features * Build the utility library without sandboxing features
* No longer requires: libseccomp * No longer requires: libseccomp
- `--disable-sandbox-landlock` (Linux-only) - `--disable-sandbox-landlock` (Linux-only)
* Disable the [Landlock] feature in the sandbox implementation * Do not use [Landlock] for sandboxing
- `--disable-xxhash-inline` - `--disable-xxhash-inline`
* Do not use xxHash as a header-only library * Do not use xxHash as a header-only library
- `--disable-backend-firefox-write` - `--disable-backend-firefox-write`
@ -115,7 +109,7 @@ Installation
- `--enable-boookmarkfs-debug` - `--enable-boookmarkfs-debug`
* Add more run-time checks and logs for debugging * Add more run-time checks and logs for debugging
- `--disable-native-watcher` - `--disable-native-watcher`
* Build the file watcher without platform-specific API dependency * Do not use platform-specific features for the file watcher
- `--disable-interactive-fsck` - `--disable-interactive-fsck`
* Disable interactive features for `fsck.bookmarkfs` * Disable interactive features for `fsck.bookmarkfs`
* No longer requires: Readline * No longer requires: Readline
@ -141,7 +135,7 @@ Installation
$ make install-exec $ make install-exec
Install the development headers and the pkg-config file: Install headers, man pages and the pkg-config file:
$ make install-data $ make install-data

View file

@ -23,11 +23,11 @@ LT_INIT([disable-static dlopen])
AC_CANONICAL_HOST AC_CANONICAL_HOST
AS_CASE(["${host_os}"], [linux*], [ AS_CASE(["${host_os}"], [linux*], [
AS_VAR_SET([host_os_is_linux], [yes]) AS_VAR_SET([host_os], [linux])
], [freebsd*], [ ], [freebsd*], [
AS_VAR_SET([host_os_is_freebsd], [yes]) AS_VAR_SET([host_os], [freebsd])
], [ ], [
AC_MSG_ERROR(m4_normalize([Unsupported platform "${host_os}".])) AC_MSG_ERROR([Unsupported platform "${host_os}".])
]) ])
# -- Checks for programs -- # -- Checks for programs --
@ -39,62 +39,63 @@ AC_PROG_MAKE_SET
# -- Checks for features -- # -- Checks for features --
EX_FEAT([bookmarkfs-util], [no], [the BookmarkFS utility library], , [1]) EX_FEAT([bookmarkctl], [NE], [the bookmarkctl program])
EX_FEAT([bookmarkctl], [no], [the bookmarkctl program], , [1]) EX_FEAT([bookmarkfs-fsck], [NE], [the fsck.bookmarkfs program], [
EX_FEAT([bookmarkfs-fsck], [no], [the fsck.bookmarkfs program], [
AS_VAR_SET([enable_bookmarkfs_util], [yes]) AS_VAR_SET([enable_bookmarkfs_util], [yes])
AS_VAR_SET([enable_interactive_fsck], [yes]) AS_VAR_SET([enable_interactive_fsck], [yes])
], [1])
EX_FEAT([bookmarkfs-mkfs], [no], [the mkfs.bookmarkfs program], , [1])
EX_FEAT([bookmarkfs-mount], [no], [the mount.bookmarkfs program], [
AS_VAR_SET([enable_bookmarkfs_util], [yes])
], [1])
EX_FEAT([sandbox], [yes], [sandboxing])
AS_VAR_IF([host_os_is_linux], [yes], [
EX_FEAT([sandbox-landlock], [yes], [Landlock features for sandboxing])
]) ])
EX_FEAT([xxhash-inline], [yes], [using xxhash as a header-only library]) EX_FEAT([bookmarkfs-mkfs], [NE], [the mkfs.bookmarkfs program])
EX_FEAT([bookmarkfs-debug], [no], [debugging features for BookmarkFS]) EX_FEAT([bookmarkfs-mount], [NE], [the mount.bookmarkfs program], [
AS_VAR_SET([enable_bookmarkfs_util], [yes])
])
EX_FEAT([backend-firefox], [no], [Firefox backend], [ EX_FEAT([sandbox], [YDE], [sandboxing])
AS_VAR_IF([host_os], [linux], [
EX_FEAT([sandbox-landlock], [YD], [using Landlock for sandboxing])
])
EX_FEAT([xxhash-inline], [YD], [using xxhash as a header-only library])
EX_FEAT([bookmarkfs-debug], [ND], [debugging features for BookmarkFS])
EX_FEAT([backend-firefox], [NE], [Firefox backend], [
AS_VAR_SET([enable_bookmarkfs_util], [yes]) AS_VAR_SET([enable_bookmarkfs_util], [yes])
AS_VAR_SET([enable_backend_firefox_write], [yes]) AS_VAR_SET([enable_backend_firefox_write], [yes])
], [1]) ])
EX_FEAT([backend-firefox-write], , [write support for the Firefox backend]) EX_FEAT([backend-firefox-write], [DE], [write support for the Firefox backend])
EX_FEAT([backend-chromium], [no], [Chromium backend], [ EX_FEAT([backend-chromium], [NE], [Chromium backend], [
AS_VAR_SET([enable_bookmarkfs_util], [yes]) AS_VAR_SET([enable_bookmarkfs_util], [yes])
AS_VAR_SET([enable_backend_chromium_write], [yes]) AS_VAR_SET([enable_backend_chromium_write], [yes])
], [1]) ])
EX_FEAT([backend-chromium-write], , [write support for the Chromium backend]) EX_FEAT([backend-chromium-write], [DE],
[write support for the Chromium backend])
EX_FEAT([native-watcher], [yes], [platform-specific file watcher]) EX_FEAT([native-watcher], [YD], [platform-specific file watcher])
EX_FEAT([interactive-fsck], , [interactive features for fsck.bookmarkfs]) EX_FEAT([interactive-fsck], [DE], [interactive features for fsck.bookmarkfs])
EX_FEAT([fsck-handler-tcl], [no], [Tcl-based fsck handler], , [1]) EX_FEAT([fsck-handler-tcl], [NE], [Tcl-based fsck handler])
EX_FEAT([bookmarkfs-util], [E], [the BookmarkFS utility library], [
EX_DEP([bookmarkfs_util], [>= 0.1], [BookmarkFS utility library], [
AS_VAR_SET([enable_bookmarkfs_util], [no])
])
])
# -- Checks for libraries -- # -- Checks for libraries --
AX_PTHREAD AX_PTHREAD
EX_DEP([bookmarkfs_util], [>= 0.1], [BookmarkFS utility library], [
AS_VAR_SET([enable_bookmarkfs_util], [no])
])
EX_DEP([fuse3], [>= 3.5], [fuse3 library], , [bookmarkfs-mount]) EX_DEP([fuse3], [>= 3.5], [fuse3 library], , [bookmarkfs-mount])
AS_VAR_IF([host_os_is_linux], [yes], [ AS_VAR_IF([host_os], [linux], [
EX_DEP([libseccomp], [>= 2.5], [libseccomp library], , [sandbox]) EX_DEP([libseccomp], [>= 2.5], [libseccomp library], , [sandbox])
]) ])
@ -118,12 +119,6 @@ EX_DEP([libxxhash], [>= 0.8], [xxHash library], [
]) ])
], [bookmarkfs-util]) ], [bookmarkfs-util])
EX_AMCOND([bookmarkfs-util], [bookmarkctl], [bookmarkfs-fsck],
[bookmarkfs-mkfs], [bookmarkfs-mount], [sandbox], [backend-firefox],
[backend-firefox-write], [backend-chromium], [backend-chromium-write],
[interactive-fsck], [fsck-handler-tcl])
EX_FEAT_EXPORT([bookmarkfs-debug], [sandbox-landlock], [native-watcher])
# -- Checks for compiler builtins and attributes -- # -- Checks for compiler builtins and attributes --
AX_GCC_BUILTIN([__builtin_ctz]) AX_GCC_BUILTIN([__builtin_ctz])

View file

@ -3354,8 +3354,8 @@ Handler-specific options:
Path to the Tcl script file. Path to the Tcl script file.
This option is mandatory. This option is mandatory.
The script is evaluated once after interpreter initialization. The script is evaluated after interpreter initialization.
The evaluation result will be used as the command name for later executions. Later executions use the evaluation result as command name.
The following variables are set before script evaluation: The following variables are set before script evaluation:
@ -4217,7 +4217,6 @@ For example:
@itemize @bullet{} @itemize @bullet{}
@item access local files other than the bookmark storage @item access local files other than the bookmark storage
@item establish socket connections @item establish socket connections
@item execute other files
@end itemize @end itemize
This mechanism reduces the attack surface for exploit, This mechanism reduces the attack surface for exploit,

View file

@ -8,24 +8,29 @@ dnl This file is offered as-is, without any warranty.
dnl dnl
dnl dnl
dnl EX_FEAT(feature, [default-value], description, [action-if-enabled], dnl EX_FEAT(feat-name, flags, feat-desc, [action-if-enabled])
dnl [no-ac-define])
dnl dnl
dnl Provide an option to enable or disable a feature. dnl Provide an option to enable or disable a feature.
dnl dnl
dnl flags:
dnl - N: Disable this feature by default
dnl - Y: Enable this feature by default
dnl - D: When enabled, define a macro for this feature in config.h
dnl - E: When enabled, export this feature with AM_CONDITIONAL()
dnl
AC_DEFUN([EX_FEAT], [ AC_DEFUN([EX_FEAT], [
m4_pushdef([arg_action_], m4_if([$2], [no], [enable], [disable])) m4_pushdef([op_], m4_if(m4_index([$2], [N]), [-1], [disable], [enable]))
m4_pushdef([feat_name_], m4_translit([$1], [-], [_])) m4_pushdef([feat_name_], m4_translit([$1], [-], [_]))
AC_MSG_CHECKING(m4_normalize([if $3 is enabled])) AC_MSG_CHECKING(m4_normalize([if $3 is enabled]))
AC_ARG_ENABLE([$1], m4_normalize([ AC_ARG_ENABLE([$1], [AS_HELP_STRING([--]op_[-$1], op_ [$3])], , [
AS_HELP_STRING([--]arg_action_[-$1], arg_action_ [$3]) m4_if(m4_index([$2], [Y]), [-1], , [
]), , m4_ifnblank([$2], [ AS_VAR_SET([enable_]feat_name_, [yes])
AS_VAR_SET([enable_]feat_name_, [$2]) ])
])) ])
AS_VAR_IF([enable_]feat_name_, [yes], [ AS_VAR_IF([enable_]feat_name_, [yes], [
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
$4 $4
m4_ifblank([$5], [ m4_if(m4_index([$2], [D]), [-1], , [
AC_DEFINE(m4_if(m4_substr(feat_name_, 0, 10), [bookmarkfs], , AC_DEFINE(m4_if(m4_substr(feat_name_, 0, 10), [bookmarkfs], ,
[BOOKMARKFS_])[]m4_toupper(feat_name_), [BOOKMARKFS_])[]m4_toupper(feat_name_),
[1], [Define to 1 if $3 is enabled.]) [1], [Define to 1 if $3 is enabled.])
@ -33,39 +38,45 @@ AC_DEFUN([EX_FEAT], [
], [ ], [
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
]) ])
m4_if(m4_index([$2], [E]), [-1], , [
AM_CONDITIONAL(m4_translit(feat_name_, [a-z], [A-Z]),
[test x$enable_]feat_name_[ != xno])
])
AS_VAR_SET([desc_]feat_name_, ["$3"]) AS_VAR_SET([desc_]feat_name_, ["$3"])
m4_popdef([arg_action_]) m4_popdef([op_])
m4_popdef([feat_name_]) m4_popdef([feat_name_])
]) ])
dnl dnl
dnl EX_DEP(pkg-name, version, pkg-desc, [action-if-found], dnl EX_DEP(pkg-name, version, pkg-desc, [action-if-found], [feat-names]...)
dnl [required-by-features]...)
dnl dnl
dnl Check whether a package exists with `pkg-config`, dnl Check whether a package exists with `pkg-config`,
dnl and provide an option to specify the package's custom install location. dnl and provide an option to specify the package's custom install location.
dnl dnl
dnl If at least one feature specified in `feat-names` is enabled,
dnl automatically enable checking the package, and fail if not found.
dnl
AC_DEFUN([EX_DEP], [ AC_DEFUN([EX_DEP], [
AC_ARG_WITH([$1], m4_normalize([ AC_ARG_WITH([$1], m4_normalize([
AS_HELP_STRING([--with-m4_translit([$1], [_], [-])[[=PKGCONFIGDIR]]], AS_HELP_STRING([--with-m4_translit([$1], [_], [-])[[=PKGCONFIGDIR]]],
[pkg-config search path for $3]) [pkg-config search path for $3])
]), , [ ]), , [
AS_VAR_SET([with_$1], [no]) AS_VAR_SET([with_$1], [no])
m4_foreach([feat_name_], [m4_shiftn(4, $@)], [ m4_ifnblank([$5], m4_foreach([feat_name_], [m4_shiftn(4, $@)], [
AS_VAR_IF([enable_]m4_translit(feat_name_, [-], [_]), [yes], [ AS_VAR_IF([enable_]m4_translit(feat_name_, [-], [_]), [yes], [
AS_VAR_SET([with_$1], [yes]) AS_VAR_SET([with_$1], [yes])
]) ])
]) ]))
]) ])
AS_VAR_IF([with_$1], [no], [ AS_VAR_IF([with_$1], [no], [
m4_foreach([feat_name_], [m4_shiftn(4, $@)], [ m4_ifnblank([$5], m4_foreach([feat_name_], [m4_shiftn(4, $@)], [
AS_VAR_IF([enable_]m4_translit(feat_name_, [-], [_]), [yes], [ AS_VAR_IF([enable_]m4_translit(feat_name_, [-], [_]), [yes], [
AC_MSG_ERROR(m4_normalize([ AC_MSG_ERROR(m4_normalize([
Bad option '[--without-]feat_name_'. The $3 is mandatory Bad option '[--without-]feat_name_'. The $3 is mandatory
for AS_VAR_GET([desc_]m4_translit(feat_name_, [-], [_])). for AS_VAR_GET([desc_]m4_translit(feat_name_, [-], [_])).
])) ]))
]) ])
]) ]))
], [ ], [
AS_VAR_SET([old_pkg_config_path_], ["${PKG_CONFIG_PATH}"]) AS_VAR_SET([old_pkg_config_path_], ["${PKG_CONFIG_PATH}"])
AS_VAR_IF([with_$1], [yes], , [ AS_VAR_IF([with_$1], [yes], , [
@ -76,34 +87,3 @@ AC_DEFUN([EX_DEP], [
AS_VAR_SET([PKG_CONFIG_PATH], ["${old_pkg_config_path_}"]) AS_VAR_SET([PKG_CONFIG_PATH], ["${old_pkg_config_path_}"])
]) ])
]) ])
dnl
dnl EX_AMCOND([features]...)
dnl
dnl Export feature flags to Makefile templates.
dnl
AC_DEFUN([EX_AMCOND], [
m4_foreach([feat_name_], [$@], [
AM_CONDITIONAL(m4_translit(feat_name_, [-a-z], [_A-Z]),
[test x$enable_]m4_translit(feat_name_, [-], [_])[ != xno])
])
])
dnl
dnl EX_FEAT_EXPORT([features]...)
dnl
dnl Export feature flags to Autoconf output variables,
dnl similar to the ones set by AM_CONTITIONAL() (`xxx_TRUE` only).
dnl
AC_DEFUN([EX_FEAT_EXPORT], [
m4_foreach([feat_name_], [$@], [
m4_pushdef([out_var_], m4_translit(feat_name_, [-a-z], [_A-Z])[_TRUE])
AS_VAR_IF([enable_]m4_translit(feat_name_, [-], [_]), [yes], [
AC_SUBST(out_var_, [''])
], [
AC_SUBST(out_var_, ['#'])
])
AM_SUBST_NOTMAKE(out_var_)
m4_popdef([out_var_])
])
])

View file

@ -22,8 +22,12 @@ if BOOKMARKFS_UTIL
check_util_lib_CPPFLAGS = -I$(top_srcdir)/src check_util_lib_CPPFLAGS = -I$(top_srcdir)/src
check_util_lib_LDADD = $(top_builddir)/src/libbookmarkfs_util.la check_util_lib_LDADD = $(top_builddir)/src/libbookmarkfs_util.la
check_util_lib_SOURCES = check_lib.c check_watcher.c check_sandbox.c \ check_util_lib_SOURCES = check_lib.c check_watcher.c \
check_hashmap.c check_util.c check_hashmap.c check_util.c
if SANDBOX
check_util_lib_SOURCES += check_sandbox.c
endif # SANDBOX
endif # BOOKMARKFS_UTIL endif # BOOKMARKFS_UTIL
if BOOKMARKFS_MOUNT if BOOKMARKFS_MOUNT

View file

@ -17,12 +17,9 @@ buildsrcdir="$top_builddir/src"
@BOOKMARKFS_MKFS_TRUE@ feat_bookmarkfs_mkfs=y @BOOKMARKFS_MKFS_TRUE@ feat_bookmarkfs_mkfs=y
@BOOKMARKFS_MOUNT_TRUE@ feat_bookmarkfs_mount=y @BOOKMARKFS_MOUNT_TRUE@ feat_bookmarkfs_mount=y
@SANDBOX_TRUE@ feat_sandbox=y @SANDBOX_TRUE@ feat_sandbox=y
@SANDBOX_LANDLOCK_TRUE@ feat_sandbox_landlock=y
@BOOKMARKFS_DEBUG_TRUE@ feat_bookmarkfs_debug=y
@BACKEND_FIREFOX_TRUE@ feat_backend_firefox=y @BACKEND_FIREFOX_TRUE@ feat_backend_firefox=y
@BACKEND_FIREFOX_WRITE_TRUE@ feat_backend_firefox_write=y @BACKEND_FIREFOX_WRITE_TRUE@ feat_backend_firefox_write=y
@BACKEND_CHROMIUM_TRUE@ feat_backend_chromium=y @BACKEND_CHROMIUM_TRUE@ feat_backend_chromium=y
@BACKEND_CHROMIUM_WRITE_TRUE@ feat_backend_chromium_write=y @BACKEND_CHROMIUM_WRITE_TRUE@ feat_backend_chromium_write=y
@INTERACTIVE_FSCK_TRUE@ feat_interactive_fsck=y @INTERACTIVE_FSCK_TRUE@ feat_interactive_fsck=y
@NATIVE_WATCHER_TRUE@ feat_native_watcher=y
@FSCK_HANDLER_TCL_TRUE@ feat_fsck_handler_tcl=y @FSCK_HANDLER_TCL_TRUE@ feat_fsck_handler_tcl=y

View file

@ -59,8 +59,10 @@ dispatch_subcmds (
status = subcmd_prng(argc, argv); status = subcmd_prng(argc, argv);
} else if (0 == strcmp("watcher", cmd)) { } else if (0 == strcmp("watcher", cmd)) {
status = check_watcher(argc, argv); status = check_watcher(argc, argv);
#ifdef BOOKMARKFS_SANDBOX
} else if (0 == strcmp("sandbox", cmd)) { } else if (0 == strcmp("sandbox", cmd)) {
status = check_sandbox(argc, argv); status = check_sandbox(argc, argv);
#endif
} else if (0 == strcmp("hashmap", cmd)) { } else if (0 == strcmp("hashmap", cmd)) {
status = check_hashmap(argc, argv); status = check_hashmap(argc, argv);
} else { } else {

View file

@ -11,6 +11,8 @@ AT_SETUP([util lib: sandbox])
AT_KEYWORDS([lib sandbox]) AT_KEYWORDS([lib sandbox])
ATX_CHECK_LIB([ ATX_CHECK_LIB([
ATX_FEAT_PREREQ([sandbox])
tmpdir=./$(ath_fn_rand_u64_hex).tmp.d tmpdir=./$(ath_fn_rand_u64_hex).tmp.d
mkdir $tmpdir mkdir $tmpdir