magic_sys/
lib.rs

1//! # Features
2//!
3//! ## Build features
4//! - `pkg-config` (_enabled by default_) — Enable build using [`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) with the [`pkg-config` crate](https://docs.rs/pkg-config)  
5//!   Check the [crate README for `pkg-config` configuration details](https://crates.io/crates/magic#pkg-config)
6//! - `vcpkg` (_enabled by default_) — Enable build using [`vcpkg`](https://vcpkg.io/) with the [`vcpkg` crate](https://docs.rs/vcpkg)  
7//!   Check the [crate README for `vcpkg` configuration details](https://crates.io/crates/magic#vcpkg)
8//!
9//! ## `libmagic` API features
10//! - `v5-40` — Enable [`libmagic` v5.40 API](#libmagic-v540)
11//!
12//!
13//! # `libmagic` changelog
14//!
15//! The following is a subset of `libmagic` changes that are relevant for this `magic-sys` crate.
16//!
17//! `magic-sys` implements `libmagic` API v5.38 ..= v5.40.  
18//! `magic-sys` requires `libmagic` v5.39 or any newer version to build.  
19//!
20//! ## `libmagic` v5.38
21//!
22//! API baseline.  
23//!
24//! ## `libmagic` v5.39
25//!
26//! No API changes.  
27//! Add `libmagic.pc` to build (statically) with `pkg-config`.  
28//!
29//! ## `libmagic` v5.40
30//!
31//! Add [`MAGIC_PARAM_ENCODING_MAX`].  
32//!
33// not yet implemented
34// ## `libmagic` v5.41
35//
36// No API changes.
37//
38// ## `libmagic` v5.42
39//
40// No API changes.
41//
42// ## `libmagic` v5.43
43//
44// No API changes.
45//
46// ## `libmagic` v5.44
47//
48// Add [`MAGIC_NO_COMPRESS_FORK`].
49//
50// ## `libmagic` v5.45
51//
52// Add [`MAGIC_NO_CHECK_SIMH`].
53// Add [`MAGIC_PARAM_ELF_SHSIZE_MAX`].
54//
55// ## `libmagic` v5.46
56//
57// No API changes.
58//
59
60#![cfg_attr(docsrs, feature(doc_cfg))]
61#![cfg_attr(docsrs, feature(doc_cfg_hide))]
62#![cfg_attr(docsrs, doc(cfg_hide(docsrs)))]
63// Technically this crate doesn't need Rust `std`
64// but you'll still have to get the `libmagic` C library working for your target
65#![cfg_attr(not(test), no_std)]
66
67use core::ffi::c_void;
68use core::ffi::{c_char, c_int};
69use usize as size_t; // core::ffi::c_size_t is unstable, but "is currently always usize"
70
71// `libmagic` API as in "magic.h"
72
73#[allow(non_camel_case_types)]
74// https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
75#[repr(C)]
76pub struct magic_set {
77    _data: [u8; 0],
78    _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
79}
80
81#[allow(non_camel_case_types)]
82pub type magic_t = *mut magic_set;
83
84pub const MAGIC_NONE: c_int = 0x000_0000;
85pub const MAGIC_DEBUG: c_int = 0x000_0001;
86pub const MAGIC_SYMLINK: c_int = 0x000_0002;
87pub const MAGIC_COMPRESS: c_int = 0x000_0004;
88pub const MAGIC_DEVICES: c_int = 0x000_0008;
89pub const MAGIC_MIME_TYPE: c_int = 0x000_0010;
90pub const MAGIC_CONTINUE: c_int = 0x000_0020;
91pub const MAGIC_CHECK: c_int = 0x000_0040;
92pub const MAGIC_PRESERVE_ATIME: c_int = 0x000_0080;
93pub const MAGIC_RAW: c_int = 0x000_0100;
94pub const MAGIC_ERROR: c_int = 0x000_0200;
95pub const MAGIC_MIME_ENCODING: c_int = 0x000_0400;
96pub const MAGIC_MIME: c_int = MAGIC_MIME_TYPE | MAGIC_MIME_ENCODING;
97pub const MAGIC_APPLE: c_int = 0x00_0800;
98pub const MAGIC_EXTENSION: c_int = 0x100_0000;
99pub const MAGIC_COMPRESS_TRANSP: c_int = 0x200_0000;
100pub const MAGIC_NODESC: c_int = MAGIC_EXTENSION | MAGIC_MIME | MAGIC_APPLE;
101
102pub const MAGIC_NO_CHECK_COMPRESS: c_int = 0x000_1000;
103pub const MAGIC_NO_CHECK_TAR: c_int = 0x000_2000;
104pub const MAGIC_NO_CHECK_SOFT: c_int = 0x000_4000;
105pub const MAGIC_NO_CHECK_APPTYPE: c_int = 0x000_8000;
106pub const MAGIC_NO_CHECK_ELF: c_int = 0x001_0000;
107pub const MAGIC_NO_CHECK_TEXT: c_int = 0x002_0000;
108pub const MAGIC_NO_CHECK_CDF: c_int = 0x004_0000;
109pub const MAGIC_NO_CHECK_CSV: c_int = 0x008_0000;
110pub const MAGIC_NO_CHECK_TOKENS: c_int = 0x010_0000;
111pub const MAGIC_NO_CHECK_ENCODING: c_int = 0x020_0000;
112pub const MAGIC_NO_CHECK_JSON: c_int = 0x040_0000;
113
114pub const MAGIC_NO_CHECK_BUILTIN: c_int = MAGIC_NO_CHECK_COMPRESS |
115MAGIC_NO_CHECK_TAR      |
116// MAGIC_NO_CHECK_SOFT  |
117MAGIC_NO_CHECK_APPTYPE  |
118MAGIC_NO_CHECK_ELF      |
119MAGIC_NO_CHECK_TEXT     |
120MAGIC_NO_CHECK_CSV      |
121MAGIC_NO_CHECK_CDF      |
122MAGIC_NO_CHECK_TOKENS   |
123MAGIC_NO_CHECK_ENCODING |
124MAGIC_NO_CHECK_JSON;
125
126#[deprecated]
127pub const MAGIC_NO_CHECK_ASCII: c_int = MAGIC_NO_CHECK_TEXT;
128
129#[deprecated]
130pub const MAGIC_NO_CHECK_FORTRAN: c_int = 0x00_0000;
131#[deprecated]
132pub const MAGIC_NO_CHECK_TROFF: c_int = 0x00_0000;
133
134// TODO: MAGIC_VERSION string
135
136// TODO: MAGIC_SNPRINTB bytes
137
138pub const MAGIC_PARAM_INDIR_MAX: c_int = 0;
139pub const MAGIC_PARAM_NAME_MAX: c_int = 1;
140pub const MAGIC_PARAM_ELF_PHNUM_MAX: c_int = 2;
141pub const MAGIC_PARAM_ELF_SHNUM_MAX: c_int = 3;
142pub const MAGIC_PARAM_ELF_NOTES_MAX: c_int = 4;
143pub const MAGIC_PARAM_REGEX_MAX: c_int = 5;
144pub const MAGIC_PARAM_BYTES_MAX: c_int = 6;
145#[cfg_attr(docsrs, doc(cfg(feature = "v5-40")))]
146#[cfg(feature = "v5-40")]
147pub const MAGIC_PARAM_ENCODING_MAX: c_int = 7;
148
149// NOTE: the following are from `file.h`, but part of `magic.h` API
150pub const FILE_LOAD: c_int = 0;
151pub const FILE_CHECK: c_int = 1;
152pub const FILE_COMPILE: c_int = 2;
153pub const FILE_LIST: c_int = 3;
154
155extern "C" {
156    pub fn magic_open(flags: c_int) -> magic_t;
157    pub fn magic_close(cookie: magic_t);
158
159    pub fn magic_getpath(magicfile: *const c_char, action: c_int) -> *const c_char;
160    pub fn magic_file(cookie: magic_t, filename: *const c_char) -> *const c_char;
161    pub fn magic_descriptor(cookie: magic_t, fd: c_int) -> *const c_char;
162    pub fn magic_buffer(cookie: magic_t, buffer: *const c_void, length: size_t) -> *const c_char;
163
164    pub fn magic_error(cookie: magic_t) -> *const c_char;
165    pub fn magic_getflags(cookie: magic_t) -> c_int;
166    #[must_use]
167    pub fn magic_setflags(cookie: magic_t, flags: c_int) -> c_int;
168
169    pub fn magic_version() -> c_int;
170    #[must_use]
171    pub fn magic_load(cookie: magic_t, filename: *const c_char) -> c_int;
172    #[must_use]
173    pub fn magic_load_buffers(
174        cookie: magic_t,
175        buffers: *mut *mut c_void,
176        sizes: *mut size_t,
177        nbuffers: size_t,
178    ) -> c_int;
179
180    #[must_use]
181    pub fn magic_compile(cookie: magic_t, filename: *const c_char) -> c_int;
182    #[must_use]
183    pub fn magic_check(cookie: magic_t, filename: *const c_char) -> c_int;
184    #[must_use]
185    pub fn magic_list(cookie: magic_t, filename: *const c_char) -> c_int;
186    pub fn magic_errno(cookie: magic_t) -> c_int;
187
188    #[must_use]
189    pub fn magic_setparam(cookie: magic_t, param: c_int, value: *const c_void) -> c_int;
190    #[must_use]
191    pub fn magic_getparam(cookie: magic_t, param: c_int, value: *mut c_void) -> c_int;
192}
193
194#[cfg(test)]
195mod tests {
196    use super::*;
197
198    // Those tests are mostly just sanity checks to see if linkage works,
199    // they are NOT testing `libmagic` API/implementation
200
201    #[test]
202    fn test_magic_open() {
203        unsafe {
204            magic_open(MAGIC_NONE);
205        }
206    }
207
208    #[test]
209    fn test_magic_close() {
210        unsafe {
211            magic_close(std::ptr::null_mut());
212        }
213    }
214
215    #[test]
216    fn test_magic_getpath() {
217        unsafe {
218            magic_getpath(std::ptr::null(), FILE_CHECK);
219        }
220    }
221
222    #[test]
223    fn test_magic_file() {
224        unsafe {
225            magic_file(std::ptr::null_mut(), std::ptr::null());
226        }
227    }
228
229    #[test]
230    fn test_magic_descriptor() {
231        unsafe {
232            magic_descriptor(std::ptr::null_mut(), -1);
233        }
234    }
235
236    #[test]
237    fn test_magic_buffer() {
238        unsafe {
239            magic_buffer(std::ptr::null_mut(), std::ptr::null(), 0);
240        }
241    }
242
243    #[test]
244    fn test_magic_error() {
245        unsafe {
246            magic_error(std::ptr::null_mut());
247        }
248    }
249
250    #[test]
251    fn test_magic_getflags() {
252        unsafe {
253            magic_getflags(std::ptr::null_mut());
254        }
255    }
256
257    #[test]
258    fn test_magic_setflags() {
259        unsafe {
260            let _ = magic_setflags(std::ptr::null_mut(), MAGIC_NONE);
261        }
262    }
263
264    #[test]
265    fn test_magic_version() {
266        unsafe {
267            magic_version();
268        }
269    }
270
271    #[test]
272    fn test_magic_load() {
273        unsafe {
274            let _ = magic_load(std::ptr::null_mut(), std::ptr::null());
275        }
276    }
277
278    #[test]
279    fn test_magic_load_buffers() {
280        unsafe {
281            let _ = magic_load_buffers(
282                std::ptr::null_mut(),
283                std::ptr::null_mut(),
284                std::ptr::null_mut(),
285                0,
286            );
287        }
288    }
289
290    #[test]
291    fn test_magic_compile() {
292        unsafe {
293            let _ = magic_compile(std::ptr::null_mut(), std::ptr::null());
294        }
295    }
296
297    #[test]
298    fn test_magic_check() {
299        unsafe {
300            let _ = magic_check(std::ptr::null_mut(), std::ptr::null());
301        }
302    }
303
304    #[test]
305    fn test_magic_list() {
306        unsafe {
307            let _ = magic_list(std::ptr::null_mut(), std::ptr::null());
308        }
309    }
310
311    #[test]
312    fn test_magic_errno() {
313        unsafe {
314            magic_errno(std::ptr::null_mut());
315        }
316    }
317
318    #[test]
319    fn test_magic_setparam() {
320        unsafe {
321            let _ = magic_setparam(
322                std::ptr::null_mut(),
323                MAGIC_PARAM_INDIR_MAX,
324                std::ptr::null(),
325            );
326        }
327    }
328
329    #[test]
330    fn test_magic_getparam() {
331        unsafe {
332            let _ = magic_getparam(
333                std::ptr::null_mut(),
334                MAGIC_PARAM_INDIR_MAX,
335                std::ptr::null_mut(),
336            );
337        }
338    }
339}