libbsd_sys/lib.rs
1//! Raw FFI bindings to libbsd.
2//!
3//! This crate provides `extern "C"` declarations for the functions and types
4//! exported by [libbsd](https://libbsd.freedesktop.org/), a library that
5//! provides commonly-used BSD functions on GNU/Linux systems.
6//!
7//! # Platform support
8//!
9//! On **macOS**, **FreeBSD**, **OpenBSD**, and **NetBSD**,
10//! most of these functions are already part of the system C library, so no
11//! additional library is needed.
12//!
13//! On **Linux**, the crate uses `pkg-config` at build time to locate libbsd.
14//! On Debian/Ubuntu, install the development headers with:
15//!
16//! ```sh
17//! apt install libbsd-dev
18//! ```
19//!
20//! On **Windows** and other unsupported platforms, this crate is empty.
21//!
22//! # Conditional compilation
23//!
24//! Functions that only exist in libbsd (not on any BSD natively) are gated
25//! behind `#[cfg(target_os = "linux")]`. Functions available on the BSDs but
26//! not macOS are gated behind `#[cfg(not(target_os = "macos"))]`.
27//!
28//! The `strnvis` and `strnunvis` functions have different parameter orders
29//! depending on whether the platform follows the NetBSD convention (macOS,
30//! NetBSD, OpenBSD) or the FreeBSD convention (FreeBSD, Linux/libbsd).
31
32#![no_std]
33#![allow(non_camel_case_types)]
34
35#[cfg(not(target_os = "windows"))]
36mod imp;
37#[cfg(not(target_os = "windows"))]
38pub use imp::*;
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn smoke_arc4random() {
46 unsafe {
47 let _ = arc4random();
48 }
49 }
50
51 #[test]
52 fn smoke_strlcpy() {
53 let src = b"hello\0";
54 let mut dst = [0u8; 16];
55 unsafe {
56 let n = strlcpy(
57 dst.as_mut_ptr().cast(),
58 src.as_ptr().cast(),
59 dst.len() as size_t,
60 );
61 assert_eq!(n, 5);
62 assert_eq!(&dst[..6], b"hello\0");
63 }
64 }
65
66 #[test]
67 #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd"))]
68 fn smoke_humanize_number() {
69 let mut buf = [0u8; 16];
70 unsafe {
71 let ret = humanize_number(
72 buf.as_mut_ptr().cast(),
73 buf.len() as size_t,
74 1024 * 1024,
75 b"\0".as_ptr().cast(),
76 HN_AUTOSCALE,
77 HN_DECIMAL | HN_NOSPACE | HN_B,
78 );
79 assert!(ret >= 0);
80 }
81 }
82
83 #[test]
84 fn smoke_arc4random_uniform() {
85 unsafe {
86 let val = arc4random_uniform(100);
87 assert!(val < 100);
88 }
89 }
90
91 #[test]
92 fn smoke_strtonum() {
93 let s = b"42\0";
94 let mut errstr: *const core::ffi::c_char = core::ptr::null();
95 unsafe {
96 let val = strtonum(s.as_ptr().cast(), 0, 100, &mut errstr);
97 assert_eq!(val, 42);
98 assert!(errstr.is_null());
99 }
100 }
101
102 #[test]
103 fn smoke_getprogname() {
104 unsafe {
105 let name = getprogname();
106 assert!(!name.is_null());
107 }
108 }
109
110 #[test]
111 fn smoke_vis_str() {
112 let src = b"hello\tworld\0";
113 let mut dst = [0u8; 64];
114 unsafe {
115 let ret = strvis(dst.as_mut_ptr().cast(), src.as_ptr().cast(), VIS_TAB);
116 assert!(ret > 0);
117 }
118 }
119}