Port Rust native library and runtime to FreeBSD

ober

a2c2b317c98f4459e4350ef64133d0b901940b55

diff --git a/jerboa-native-rs/Cargo.toml b/jerboa-native-rs/Cargo.toml
index 17241a4..8384adb 100644
--- a/jerboa-native-rs/Cargo.toml
+++ b/jerboa-native-rs/Cargo.toml
@@ -17,7 +17,6 @@ postgres = "0.19"
 x25519-dalek = { version = "2", features = ["static_secrets"] }
 hkdf = "0.12"
 sha2 = "0.10"
-inotify = { version = "0.11", default-features = false }
 rcgen = { version = "0.13", features = ["ring", "pem"] }
 time = "0.3"
 rustls = { version = "0.23", default-features = false, features = ["ring", "logging", "std", "tls12"] }
@@ -26,8 +25,11 @@ rustls-pemfile = "2"
 webpki-roots = "0.26"
 duckdb = { version = "1", features = ["bundled"], optional = true }
 
+[target.'cfg(target_os = "linux")'.dependencies]
+inotify = { version = "0.11", default-features = false }
+
 [features]
-default = ["duckdb"]
+default = []
 
 [profile.release]
 lto = true
diff --git a/jerboa-native-rs/src/integrity.rs b/jerboa-native-rs/src/integrity.rs
index 0a44cb3..9c5761a 100644
--- a/jerboa-native-rs/src/integrity.rs
+++ b/jerboa-native-rs/src/integrity.rs
@@ -3,6 +3,16 @@ use ring::{digest, signature};
 #[allow(deprecated)]
 use ring::constant_time;
 
+/// Portable path to the current executable.
+fn self_exe_path() -> &'static str {
+    #[cfg(target_os = "linux")]
+    { "/proc/self/exe" }
+    #[cfg(target_os = "freebsd")]
+    { "/proc/curproc/file" }
+    #[cfg(not(any(target_os = "linux", target_os = "freebsd")))]
+    { "/proc/self/exe" }
+}
+
 /// Read /proc/self/exe and compute its SHA-256 hash.
 /// output: buffer for the 32-byte hash
 /// output_len: must be >= 32
@@ -22,7 +32,7 @@ pub extern "C" fn jerboa_integrity_hash_self(
             return -1;
         }
 
-        let binary = match std::fs::read("/proc/self/exe") {
+        let binary = match std::fs::read(self_exe_path()) {
             Ok(b) => b,
             Err(e) => {
                 set_last_error(format!("cannot read /proc/self/exe: {}", e));
@@ -56,7 +66,7 @@ pub extern "C" fn jerboa_integrity_verify_hash(
             return -1;
         }
 
-        let binary = match std::fs::read("/proc/self/exe") {
+        let binary = match std::fs::read(self_exe_path()) {
             Ok(b) => b,
             Err(e) => {
                 set_last_error(format!("cannot read /proc/self/exe: {}", e));
@@ -105,7 +115,7 @@ pub extern "C" fn jerboa_integrity_sign_verify(
             return -1;
         }
 
-        let mut binary = match std::fs::read("/proc/self/exe") {
+        let mut binary = match std::fs::read(self_exe_path()) {
             Ok(b) => b,
             Err(e) => {
                 set_last_error(format!("cannot read /proc/self/exe: {}", e));
diff --git a/jerboa-native-rs/src/lib.rs b/jerboa-native-rs/src/lib.rs
index 3108588..bbd093e 100644
--- a/jerboa-native-rs/src/lib.rs
+++ b/jerboa-native-rs/src/lib.rs
@@ -6,15 +6,21 @@ mod regex_native;
 mod secure_mem;
 mod sqlite;
 mod postgres_native;
+#[cfg(target_os = "linux")]
 mod epoll;
+#[cfg(target_os = "linux")]
 mod inotify_native;
+#[cfg(target_os = "linux")]
 mod landlock;
 mod tls;
 mod x509;
+#[cfg(target_os = "linux")]
 mod antidebug;
+#[cfg(target_os = "linux")]
 mod seccomp;
 mod integrity;
 mod x25519;
+#[cfg(target_os = "linux")]
 mod process_ctl;
 #[cfg(feature = "duckdb")]
 mod duckdb_native;
diff --git a/jerboa-native-rs/src/secure_mem.rs b/jerboa-native-rs/src/secure_mem.rs
index 4a93b01..7fc9a99 100644
--- a/jerboa-native-rs/src/secure_mem.rs
+++ b/jerboa-native-rs/src/secure_mem.rs
@@ -36,10 +36,12 @@ pub extern "C" fn jerboa_secure_alloc(size: usize) -> *mut u8 {
         // Lock into RAM — never swapped to disk
         unsafe { libc::mlock(data as *const _, size); }
 
-        // Exclude from core dumps
+        // Exclude from core dumps (MADV_DONTDUMP is Linux-specific)
+        #[cfg(target_os = "linux")]
         unsafe { libc::madvise(data as *mut _, size, libc::MADV_DONTDUMP); }
 
-        // Don't inherit in child processes
+        // Don't inherit in child processes (MADV_DONTFORK is Linux-specific)
+        #[cfg(target_os = "linux")]
         unsafe { libc::madvise(data as *mut _, size, libc::MADV_DONTFORK); }
 
         data