Skip to main content

pavao_sys/
lib.rs

1#![warn(missing_docs)]
2
3//! Raw Rust bindings to Samba's `libsmbclient` library.
4//!
5//! This crate mirrors the native C types and functions. Most callers should use the safe
6//! [`pavao`](https://docs.rs/pavao) crate instead.
7//!
8//! # Safety
9//!
10//! The bindings do not validate pointers, lifetimes, buffer lengths, context state, or native
11//! return values. Callers must uphold the corresponding `libsmbclient` C API contracts.
12//! `libsmbclient` also shares process-wide parameter state, so separate contexts are not sufficient
13//! for thread safety. Callers must serialize all raw native activity with one process-wide lock.
14//! These bindings do not coordinate with Pavão's safe-wrapper lock; raw calls must never race a
15//! Pavão operation or any other raw `libsmbclient` call.
16//!
17//! # Callback contracts
18//!
19//! Unless an alias says otherwise, callbacks require a live, initialized context; every file or
20//! directory handle must be live and belong to that context; C strings must be NUL-terminated and
21//! readable for the call; and buffers must be valid for the supplied size. File and directory
22//! operation callbacks generally return `-1` or null with `errno` set on failure. Server-cache
23//! callbacks instead return one on failure and do not promise an `errno` value. Callback
24//! implementations must not unwind across the C ABI boundary.
25//!
26//! Directory-entry pointers are borrowed from `libsmbclient`. They may be invalidated by the next
27//! read on the same directory or when the directory is closed, so callers must copy needed data.
28//!
29//! # Feature flags
30//!
31//! | name       | description                                         | default |
32//! |------------|-----------------------------------------------------|---------|
33//! | `abi-0-6`  | Require libsmbclient ABI 0.6 or newer.             |         |
34//! | `abi-0-8`  | Require libsmbclient ABI 0.8 or newer.             |         |
35//! | `vendored` | Build the bundled Samba source instead of using the system library. |         |
36//!
37
38#![doc(html_playground_url = "https://play.rust-lang.org")]
39#![doc(
40    html_favicon_url = "https://raw.githubusercontent.com/veeso/pavao/main/docs/images/pavao.png"
41)]
42#![doc(html_logo_url = "https://raw.githubusercontent.com/veeso/pavao/main/docs/images/pavao.png")]
43#![allow(non_camel_case_types)]
44#![allow(clippy::upper_case_acronyms)]
45use std::{clone, default, mem, option};
46
47use libc::{
48    c_char, c_int, c_uint, c_ushort, c_void, mode_t, off_t, size_t, ssize_t, stat, statvfs, time_t,
49    timespec, timeval,
50};
51
52#[repr(C)]
53/// A directory entry returned by `libsmbclient`.
54pub struct smbc_dirent {
55    /// Native entry type discriminator.
56    ///
57    /// Values 1 through 9 represent workgroups, servers, file shares, printer shares,
58    /// communications shares, IPC shares, directories, files, and links, respectively.
59    pub smbc_type: c_uint,
60    /// Total size of this directory-entry structure in bytes.
61    pub dirlen: c_uint,
62    /// Length of `comment` in bytes, excluding its terminating NUL byte.
63    pub commentlen: c_uint,
64    /// Pointer to the NUL-terminated entry comment.
65    pub comment: *mut c_char,
66    /// Length of `name` in bytes, excluding its terminating NUL byte.
67    pub namelen: c_uint,
68    /// Flexible trailing storage containing the NUL-terminated entry name.
69    pub name: [c_char; 1usize],
70}
71#[repr(C)]
72#[derive(Copy)]
73/// Extended directory-entry metadata returned by `libsmbclient`.
74pub struct libsmb_file_info {
75    /// File size in bytes.
76    pub size: u64,
77    /// DOS attribute bitmask.
78    pub attrs: c_ushort,
79    /// Owning user identifier.
80    pub uid: c_uint,
81    /// Owning group identifier.
82    pub gid: c_uint,
83    /// Creation time, or zero when unsupported by the server.
84    pub btime_ts: timespec,
85    /// Last content-modification time.
86    pub mtime_ts: timespec,
87    /// Last access time.
88    pub atime_ts: timespec,
89    /// Last metadata-change time.
90    pub ctime_ts: timespec,
91    /// Pointer to the NUL-terminated entry name.
92    pub name: *mut c_char,
93    /// Pointer to the NUL-terminated DOS-compatible short name.
94    pub short_name: *mut c_char,
95}
96
97impl clone::Clone for libsmb_file_info {
98    fn clone(&self) -> Self {
99        *self
100    }
101}
102
103impl default::Default for libsmb_file_info {
104    fn default() -> Self {
105        unsafe { mem::zeroed() }
106    }
107}
108
109/// Native value for the `open_share_mode` option.
110pub type smbc_share_mode = c_uint;
111
112/// Native value for the SMB transport encryption policy.
113pub type smbc_smb_encrypt_level = c_int;
114
115/// Native Boolean represented as a C integer.
116pub type smbc_bool = c_int;
117
118/// Bitmask describing filesystem capabilities reported by `libsmbclient`.
119pub type smbc_vfs_feature = c_uint;
120
121/// Directory-entry type for an SMB workgroup.
122pub const SMBC_WORKGROUP: c_uint = 1;
123/// Directory-entry type for an SMB server.
124pub const SMBC_SERVER: c_uint = 2;
125/// Directory-entry type for an SMB file share.
126pub const SMBC_FILE_SHARE: c_uint = 3;
127/// Directory-entry type for an SMB printer share.
128pub const SMBC_PRINTER_SHARE: c_uint = 4;
129/// Directory-entry type for an SMB communications share.
130pub const SMBC_COMMS_SHARE: c_uint = 5;
131/// Directory-entry type for an SMB IPC share.
132pub const SMBC_IPC_SHARE: c_uint = 6;
133/// Directory-entry type for an SMB directory.
134pub const SMBC_DIR: c_uint = 7;
135/// Directory-entry type for an SMB file.
136pub const SMBC_FILE: c_uint = 8;
137/// Directory-entry type for an SMB symbolic link.
138pub const SMBC_LINK: c_uint = 9;
139/// Smallest file descriptor returned by `libsmbclient`.
140pub const SMBC_BASE_FD: c_int = 10_000;
141
142/// Share mode that denies DOS compatibility access.
143pub const SMBC_SHAREMODE_DENY_DOS: smbc_share_mode = 0;
144/// Share mode that denies all access sharing.
145pub const SMBC_SHAREMODE_DENY_ALL: smbc_share_mode = 1;
146/// Share mode that denies write sharing.
147pub const SMBC_SHAREMODE_DENY_WRITE: smbc_share_mode = 2;
148/// Share mode that denies read sharing.
149pub const SMBC_SHAREMODE_DENY_READ: smbc_share_mode = 3;
150/// Share mode that allows all sharing.
151pub const SMBC_SHAREMODE_DENY_NONE: smbc_share_mode = 4;
152/// Share mode that denies file-control-block sharing.
153pub const SMBC_SHAREMODE_DENY_FCB: smbc_share_mode = 7;
154
155/// Default SMB encryption policy.
156pub const SMBC_ENCRYPTLEVEL_DEFAULT: smbc_smb_encrypt_level = -1;
157/// SMB encryption is disabled.
158pub const SMBC_ENCRYPTLEVEL_NONE: smbc_smb_encrypt_level = 0;
159/// SMB encryption is requested when available.
160pub const SMBC_ENCRYPTLEVEL_REQUEST: smbc_smb_encrypt_level = 1;
161/// SMB encryption is required.
162pub const SMBC_ENCRYPTLEVEL_REQUIRE: smbc_smb_encrypt_level = 2;
163
164/// Extended-attribute flag that requires a new attribute.
165pub const SMBC_XATTR_FLAG_CREATE: c_int = 0x1;
166/// Extended-attribute flag that requires an existing attribute.
167pub const SMBC_XATTR_FLAG_REPLACE: c_int = 0x2;
168
169/// DOS attribute bit for read-only files.
170pub const SMBC_DOS_MODE_READONLY: c_int = 0x01;
171/// DOS attribute bit for hidden files.
172pub const SMBC_DOS_MODE_HIDDEN: c_int = 0x02;
173/// DOS attribute bit for system files.
174pub const SMBC_DOS_MODE_SYSTEM: c_int = 0x04;
175/// DOS attribute bit for volume identifiers.
176pub const SMBC_DOS_MODE_VOLUME_ID: c_int = 0x08;
177/// DOS attribute bit for directories.
178pub const SMBC_DOS_MODE_DIRECTORY: c_int = 0x10;
179/// DOS attribute bit for archived files.
180pub const SMBC_DOS_MODE_ARCHIVE: c_int = 0x20;
181
182/// VFS feature indicating a read-only filesystem.
183pub const SMBC_VFS_FEATURE_RDONLY: smbc_vfs_feature = 1 << 0;
184/// VFS feature indicating DFS support.
185pub const SMBC_VFS_FEATURE_DFS: smbc_vfs_feature = 1 << 28;
186/// VFS feature indicating case-insensitive path handling.
187pub const SMBC_VFS_FEATURE_CASE_INSENSITIVE: smbc_vfs_feature = 1 << 29;
188/// VFS feature indicating the absence of Unix CIFS extensions.
189pub const SMBC_VFS_FEATURE_NO_UNIXCIFS: smbc_vfs_feature = 1 << 30;
190
191/// Notification filter for file-name changes.
192pub const SMBC_NOTIFY_CHANGE_FILE_NAME: c_uint = 0x001;
193/// Notification filter for directory-name changes.
194pub const SMBC_NOTIFY_CHANGE_DIR_NAME: c_uint = 0x002;
195/// Notification filter for attribute changes.
196pub const SMBC_NOTIFY_CHANGE_ATTRIBUTES: c_uint = 0x004;
197/// Notification filter for size changes.
198pub const SMBC_NOTIFY_CHANGE_SIZE: c_uint = 0x008;
199/// Notification filter for last-write changes.
200pub const SMBC_NOTIFY_CHANGE_LAST_WRITE: c_uint = 0x010;
201/// Notification filter for last-access changes.
202pub const SMBC_NOTIFY_CHANGE_LAST_ACCESS: c_uint = 0x020;
203/// Notification filter for creation-time changes.
204pub const SMBC_NOTIFY_CHANGE_CREATION: c_uint = 0x040;
205/// Notification filter for extended-attribute changes.
206pub const SMBC_NOTIFY_CHANGE_EA: c_uint = 0x080;
207/// Notification filter for security changes.
208pub const SMBC_NOTIFY_CHANGE_SECURITY: c_uint = 0x100;
209/// Notification filter for stream-name changes.
210pub const SMBC_NOTIFY_CHANGE_STREAM_NAME: c_uint = 0x200;
211/// Notification filter for stream-size changes.
212pub const SMBC_NOTIFY_CHANGE_STREAM_SIZE: c_uint = 0x400;
213/// Notification filter for stream-write changes.
214pub const SMBC_NOTIFY_CHANGE_STREAM_WRITE: c_uint = 0x800;
215
216/// Notification action for an added entry.
217pub const SMBC_NOTIFY_ACTION_ADDED: c_uint = 1;
218/// Notification action for a removed entry.
219pub const SMBC_NOTIFY_ACTION_REMOVED: c_uint = 2;
220/// Notification action for a modified entry.
221pub const SMBC_NOTIFY_ACTION_MODIFIED: c_uint = 3;
222/// Notification action for an old entry name.
223pub const SMBC_NOTIFY_ACTION_OLD_NAME: c_uint = 4;
224/// Notification action for a new entry name.
225pub const SMBC_NOTIFY_ACTION_NEW_NAME: c_uint = 5;
226/// Notification action for an added stream.
227pub const SMBC_NOTIFY_ACTION_ADDED_STREAM: c_uint = 6;
228/// Notification action for a removed stream.
229pub const SMBC_NOTIFY_ACTION_REMOVED_STREAM: c_uint = 7;
230/// Notification action for a modified stream.
231pub const SMBC_NOTIFY_ACTION_MODIFIED_STREAM: c_uint = 8;
232
233#[repr(C)]
234#[derive(Copy)]
235/// Information about a queued SMB print job.
236pub struct print_job_info {
237    /// Numeric print-job identifier.
238    pub id: c_ushort,
239    /// Print priority, where lower values indicate higher priority.
240    pub priority: c_ushort,
241    /// Print-job size in bytes.
242    pub size: size_t,
243    /// NUL-terminated name of the user that owns the job.
244    pub user: [c_char; 128usize],
245    /// NUL-terminated job name, empty for an anonymous printer file.
246    pub name: [c_char; 128usize],
247    /// Time at which the job was spooled.
248    pub t: time_t,
249}
250
251impl clone::Clone for print_job_info {
252    fn clone(&self) -> Self {
253        *self
254    }
255}
256
257impl default::Default for print_job_info {
258    fn default() -> Self {
259        unsafe { mem::zeroed() }
260    }
261}
262
263/// Opaque native SMB server handle.
264pub enum _SMBCSRV {}
265/// Native SMB server handle.
266pub type SMBCSRV = _SMBCSRV;
267/// Opaque native SMB file or directory handle.
268pub enum _SMBCFILE {}
269/// Native SMB file or directory handle.
270pub type SMBCFILE = _SMBCFILE;
271/// Opaque native SMB client context.
272pub enum _SMBCCTX {}
273/// Native `libsmbclient` context.
274pub type SMBCCTX = _SMBCCTX;
275
276/// Optional callback that supplies authentication strings.
277///
278/// `srv` and `shr` are borrowed NUL-terminated strings. The callback must write NUL-terminated
279/// workgroup, username, and password values without exceeding `wglen`, `unlen`, and `pwlen`.
280pub type smbc_get_auth_data_fn = option::Option<
281    extern "C" fn(
282        srv: *const c_char,
283        shr: *const c_char,
284        wg: *mut c_char,
285        wglen: c_int,
286        un: *mut c_char,
287        unlen: c_int,
288        pw: *mut c_char,
289        pwlen: c_int,
290    ),
291>;
292/// Optional context-aware callback that supplies authentication strings.
293///
294/// `c` must be live, `srv` and `shr` are borrowed NUL-terminated strings, and each output buffer
295/// must receive a NUL-terminated value without exceeding its corresponding length.
296pub type smbc_get_auth_data_with_context_fn = Option<
297    extern "C" fn(
298        c: *mut SMBCCTX,
299        srv: *const c_char,
300        shr: *const c_char,
301        wg: *mut c_char,
302        wglen: c_int,
303        un: *mut c_char,
304        unlen: c_int,
305        pw: *mut c_char,
306        pwlen: c_int,
307    ),
308>;
309/// Optional callback that receives native `libsmbclient` diagnostics.
310pub type smbc_debug_callback_fn =
311    option::Option<extern "C" fn(private_ptr: *mut c_void, level: c_int, message: *const c_char)>;
312/// Optional callback invoked for each print job in a queue.
313///
314/// `i` is borrowed for the callback invocation and must not be retained or freed.
315pub type smbc_list_print_job_fn = option::Option<extern "C" fn(i: *mut print_job_info)>;
316/// Optional callback that checks whether a cached server is still available.
317///
318/// `srv` must be a live server handle associated with `c`. Returns zero on success or one on
319/// failure.
320pub type smbc_check_server_fn =
321    option::Option<extern "C" fn(c: *mut SMBCCTX, srv: *mut SMBCSRV) -> c_int>;
322/// Optional callback that removes an unused cached server.
323///
324/// `srv` must be a live server handle associated with `c`. Returns zero on success or one on
325/// failure.
326pub type smbc_remove_unused_server_fn =
327    option::Option<extern "C" fn(c: *mut SMBCCTX, srv: *mut SMBCSRV) -> c_int>;
328/// Optional callback that inserts a server into the connection cache.
329///
330/// `srv` must be live, and all name pointers must reference NUL-terminated strings for the call.
331/// Returns zero on success or one on failure.
332pub type smbc_add_cached_srv_fn = option::Option<
333    extern "C" fn(
334        c: *mut SMBCCTX,
335        srv: *mut SMBCSRV,
336        server: *const c_char,
337        share: *const c_char,
338        workgroup: *const c_char,
339        username: *const c_char,
340    ) -> c_int,
341>;
342/// Optional callback that looks up a server in the connection cache.
343///
344/// All name pointers must reference NUL-terminated strings for the call. A non-null result is a
345/// borrowed cache entry owned by `c`; null indicates no match or failure.
346pub type smbc_get_cached_srv_fn = option::Option<
347    extern "C" fn(
348        c: *mut SMBCCTX,
349        server: *const c_char,
350        share: *const c_char,
351        workgroup: *const c_char,
352        username: *const c_char,
353    ) -> *mut SMBCSRV,
354>;
355/// Optional callback that removes a server from the connection cache.
356///
357/// `srv` must be a live server handle associated with `c`. Returns zero on success or one on
358/// failure.
359pub type smbc_remove_cached_srv_fn =
360    option::Option<extern "C" fn(c: *mut SMBCCTX, srv: *mut SMBCSRV) -> c_int>;
361/// Optional callback that purges the connection cache.
362///
363/// Returns zero on success or one when cached servers remain in use.
364pub type smbc_purge_cached_fn = option::Option<extern "C" fn(c: *mut SMBCCTX) -> c_int>;
365
366/// Optional callback that opens a remote file.
367///
368/// `fname` must be a NUL-terminated SMB URL and `flags` must be valid native open flags. Returns a
369/// live file handle owned by `c`, or null with `errno` set on failure.
370pub type smbc_open_fn = option::Option<
371    extern "C" fn(
372        c: *mut SMBCCTX,
373        fname: *const c_char,
374        flags: c_int,
375        mode: mode_t,
376    ) -> *mut SMBCFILE,
377>;
378/// Optional callback that creates a remote file.
379///
380/// `path` must be a NUL-terminated SMB URL. Returns a live file handle owned by `c`, or null with
381/// `errno` set on failure.
382pub type smbc_creat_fn = option::Option<
383    extern "C" fn(c: *mut SMBCCTX, path: *const c_char, mode: mode_t) -> *mut SMBCFILE,
384>;
385/// Optional callback that reads bytes from an open remote file.
386///
387/// `file` must be live and belong to `c`; `buf` must be writable for `count` bytes. Returns the
388/// number of bytes read, zero at end of file, or `-1` with `errno` set on failure.
389pub type smbc_read_fn = option::Option<
390    extern "C" fn(c: *mut SMBCCTX, file: *mut SMBCFILE, buf: *mut c_void, count: size_t) -> ssize_t,
391>;
392/// Optional callback that writes bytes to an open remote file.
393///
394/// `file` must be live and belong to `c`; `buf` must be readable for `count` bytes. Returns the
395/// number of bytes written, or `-1` with `errno` set on failure.
396pub type smbc_write_fn = option::Option<
397    extern "C" fn(
398        c: *mut SMBCCTX,
399        file: *mut SMBCFILE,
400        buf: *const c_void,
401        count: size_t,
402    ) -> ssize_t,
403>;
404/// Callback invoked while `libsmbclient` splices data between two open files.
405pub type smbc_splice_callback_fn =
406    option::Option<extern "C" fn(n: off_t, priv_: *mut c_void) -> c_int>;
407/// Optional callback that splices data between two open remote files.
408pub type smbc_splice_fn = option::Option<
409    extern "C" fn(
410        c: *mut SMBCCTX,
411        srcfile: *mut SMBCFILE,
412        dstfile: *mut SMBCFILE,
413        count: off_t,
414        splice_cb: smbc_splice_callback_fn,
415        priv_: *mut c_void,
416    ) -> off_t,
417>;
418/// Optional callback that removes a remote file.
419///
420/// `fname` must be a NUL-terminated SMB URL. Returns zero on success or `-1` with `errno` set.
421pub type smbc_unlink_fn =
422    option::Option<extern "C" fn(c: *mut SMBCCTX, fname: *const c_char) -> c_int>;
423/// Optional callback that renames or moves a remote entry.
424///
425/// Both contexts must be live and both name pointers must be NUL-terminated SMB URLs. Returns zero
426/// on success or `-1` with `errno` set on failure.
427pub type smbc_rename_fn = option::Option<
428    extern "C" fn(
429        ocontext: *mut SMBCCTX,
430        oname: *const c_char,
431        ncontext: *mut SMBCCTX,
432        nname: *const c_char,
433    ) -> c_int,
434>;
435/// Optional callback that changes an open file's offset.
436///
437/// `file` must be live and belong to `c`; `whence` must be a valid `SEEK_*` value. Returns the new
438/// offset or `-1` with `errno` set on failure.
439pub type smbc_lseek_fn = option::Option<
440    extern "C" fn(c: *mut SMBCCTX, file: *mut SMBCFILE, offset: off_t, whence: c_int) -> off_t,
441>;
442/// Optional callback that reads metadata for a remote path.
443///
444/// `fname` must be a NUL-terminated SMB URL and `st` must be writable for one `stat`. Returns zero
445/// on success or `-1` with `errno` set on failure.
446pub type smbc_stat_fn =
447    option::Option<extern "C" fn(c: *mut SMBCCTX, fname: *const c_char, st: *mut stat) -> c_int>;
448/// Optional callback that reads filesystem statistics for a remote path.
449///
450/// `fname` must be a NUL-terminated SMB URL and `st` must be writable for one `statvfs`. Returns
451/// zero on success or `-1` with `errno` set on failure.
452pub type smbc_statvfs_fn =
453    option::Option<extern "C" fn(c: *mut SMBCCTX, fname: *const c_char, st: *mut statvfs) -> c_int>;
454/// Optional callback that reads filesystem statistics from an open file handle.
455pub type smbc_fstatvfs_fn =
456    option::Option<extern "C" fn(c: *mut SMBCCTX, file: *mut SMBCFILE, st: *mut statvfs) -> c_int>;
457/// Optional callback that changes the length of an open remote file.
458pub type smbc_ftruncate_fn =
459    option::Option<extern "C" fn(c: *mut SMBCCTX, file: *mut SMBCFILE, size: off_t) -> c_int>;
460/// Optional callback that reads metadata from an open file handle.
461///
462/// `file` must be live and belong to `c`; `st` must be writable for one `stat`. Returns zero on
463/// success or `-1` with `errno` set on failure.
464pub type smbc_fstat_fn =
465    option::Option<extern "C" fn(c: *mut SMBCCTX, file: *mut SMBCFILE, st: *mut stat) -> c_int>;
466/// Optional callback that closes an open file handle.
467///
468/// `file` must be live and belong to `c`. A successful zero return invalidates the handle; `-1`
469/// indicates failure with `errno` set.
470pub type smbc_close_fn =
471    option::Option<extern "C" fn(c: *mut SMBCCTX, file: *mut SMBCFILE) -> c_int>;
472/// Optional callback that opens a remote directory.
473///
474/// `fname` must be a NUL-terminated SMB URL. Returns a live directory handle owned by `c`, or null
475/// with `errno` set on failure.
476pub type smbc_opendir_fn =
477    option::Option<extern "C" fn(c: *mut SMBCCTX, fname: *const c_char) -> *mut SMBCFILE>;
478/// Optional callback that closes an open directory handle.
479///
480/// `dir` must be live and belong to `c`. A successful zero return invalidates the handle; `-1`
481/// indicates failure with `errno` set.
482pub type smbc_closedir_fn =
483    option::Option<extern "C" fn(c: *mut SMBCCTX, dir: *mut SMBCFILE) -> c_int>;
484/// Optional callback that reads the next directory entry.
485///
486/// `dir` must be live and belong to `c`. The returned entry is borrowed until the next read or
487/// directory close. Null means end-of-directory or failure; inspect `errno` to distinguish them.
488pub type smbc_readdir_fn =
489    option::Option<extern "C" fn(c: *mut SMBCCTX, dir: *mut SMBCFILE) -> *mut smbc_dirent>;
490/// Optional callback that reads the next directory entry with metadata.
491///
492/// `dir` must be live and belong to `c`. The returned metadata is read-only and borrowed until the
493/// next read or directory close. Null means end-of-directory or failure.
494pub type smbc_readdirplus_fn =
495    option::Option<extern "C" fn(c: *mut SMBCCTX, dir: *mut SMBCFILE) -> *mut libsmb_file_info>;
496/// Optional callback that reads the next directory entry and metadata into `st`.
497#[cfg(feature = "abi-0-6")]
498pub type smbc_readdirplus2_fn = option::Option<
499    extern "C" fn(c: *mut SMBCCTX, dir: *mut SMBCFILE, st: *mut stat) -> *const libsmb_file_info,
500>;
501/// Optional callback that reads multiple directory entries into a buffer.
502///
503/// `dir` must be live and `dirp` must be writable for `count` bytes. Returns bytes written, zero at
504/// end-of-directory, or `-1` with `errno` set on failure.
505pub type smbc_getdents_fn = option::Option<
506    extern "C" fn(
507        c: *mut SMBCCTX,
508        dir: *mut SMBCFILE,
509        dirp: *mut smbc_dirent,
510        count: c_int,
511    ) -> c_int,
512>;
513/// Optional callback that creates a remote directory.
514///
515/// `fname` must be a NUL-terminated SMB URL. Returns zero on success or `-1` with `errno` set.
516pub type smbc_mkdir_fn =
517    option::Option<extern "C" fn(c: *mut SMBCCTX, fname: *const c_char, mode: mode_t) -> c_int>;
518/// Optional callback that removes a remote directory.
519///
520/// `fname` must be a NUL-terminated SMB URL. Returns zero on success or `-1` with `errno` set.
521pub type smbc_rmdir_fn =
522    option::Option<extern "C" fn(c: *mut SMBCCTX, fname: *const c_char) -> c_int>;
523/// Optional callback that returns the current directory-stream offset.
524///
525/// `dir` must be live and belong to `c`. Returns the current offset or `-1` with `errno` set.
526pub type smbc_telldir_fn =
527    option::Option<extern "C" fn(c: *mut SMBCCTX, dir: *mut SMBCFILE) -> off_t>;
528/// Optional callback that changes a directory-stream offset.
529///
530/// `dir` must be live and belong to `c`, and `offset` must come from the same stream. Returns zero
531/// on success or `-1` with `errno` set on failure.
532pub type smbc_lseekdir_fn =
533    option::Option<extern "C" fn(c: *mut SMBCCTX, dir: *mut SMBCFILE, offset: off_t) -> c_int>;
534/// Optional callback that reads metadata from an open directory handle.
535///
536/// `dir` must be live and belong to `c`; `st` must be writable for one `stat`. Returns zero on
537/// success or `-1` with `errno` set on failure.
538pub type smbc_fstatdir_fn =
539    option::Option<extern "C" fn(c: *mut SMBCCTX, dir: *mut SMBCFILE, st: *mut stat) -> c_int>;
540/// A single directory notification action reported by `libsmbclient`.
541#[repr(C)]
542pub struct smbc_notify_callback_action {
543    /// Notification action discriminator.
544    pub action: u32,
545    /// NUL-terminated path associated with the action.
546    pub filename: *const c_char,
547}
548/// Callback invoked with directory notification actions.
549pub type smbc_notify_callback_fn = option::Option<
550    extern "C" fn(
551        actions: *const smbc_notify_callback_action,
552        num_actions: size_t,
553        private_data: *mut c_void,
554    ) -> c_int,
555>;
556/// Optional callback that watches a directory for changes.
557pub type smbc_notify_fn = option::Option<
558    extern "C" fn(
559        c: *mut SMBCCTX,
560        dir: *mut SMBCFILE,
561        recursive: smbc_bool,
562        completion_filter: u32,
563        callback_timeout_ms: c_uint,
564        cb: smbc_notify_callback_fn,
565        private_data: *mut c_void,
566    ) -> c_int,
567>;
568/// Optional callback that changes a remote entry's POSIX mode.
569///
570/// `fname` must be a NUL-terminated SMB URL. Returns zero on success or `-1` with `errno` set.
571pub type smbc_chmod_fn =
572    option::Option<extern "C" fn(c: *mut SMBCCTX, fname: *const c_char, mode: mode_t) -> c_int>;
573/// Optional callback that changes a remote entry's access and modification times.
574///
575/// `fname` must be a NUL-terminated SMB URL and `tbuf` must reference two valid `timeval` values.
576/// Returns zero on success or `-1` with `errno` set on failure.
577pub type smbc_utimes_fn = option::Option<
578    extern "C" fn(c: *mut SMBCCTX, fname: *const c_char, tbuf: *mut timeval) -> c_int,
579>;
580/// Optional callback that writes a remote entry's extended attribute.
581///
582/// `fname` and `name` must be NUL-terminated; `value` must be readable for `size` bytes. Returns
583/// zero on success or `-1` with `errno` set on failure.
584pub type smbc_setxattr_fn = option::Option<
585    extern "C" fn(
586        context: *mut SMBCCTX,
587        fname: *const c_char,
588        name: *const c_char,
589        value: *const c_void,
590        size: size_t,
591        flags: c_int,
592    ) -> c_int,
593>;
594/// Optional callback that reads a remote entry's extended attribute.
595///
596/// `fname` and `name` must be NUL-terminated. When `size` is nonzero, `value` must reference a
597/// writable buffer of that size; a zero size queries the required length. Returns the value size
598/// or `-1` with `errno` set on failure.
599pub type smbc_getxattr_fn = option::Option<
600    extern "C" fn(
601        context: *mut SMBCCTX,
602        fname: *const c_char,
603        name: *const c_char,
604        value: *const c_void,
605        size: size_t,
606    ) -> c_int,
607>;
608/// Optional callback that removes a remote entry's extended attribute.
609///
610/// `fname` and `name` must be NUL-terminated. Returns zero on success or `-1` with `errno` set.
611pub type smbc_removexattr_fn = option::Option<
612    extern "C" fn(context: *mut SMBCCTX, fname: *const c_char, name: *const c_char) -> c_int,
613>;
614/// Optional callback that lists a remote entry's extended attributes.
615///
616/// `fname` must be NUL-terminated. When `size` is nonzero, `list` must be writable for that many
617/// bytes; a zero size queries the required length. Returns the list size or `-1` on failure.
618pub type smbc_listxattr_fn = option::Option<
619    extern "C" fn(
620        context: *mut SMBCCTX,
621        fname: *const c_char,
622        list: *mut c_char,
623        size: size_t,
624    ) -> c_int,
625>;
626/// Optional callback that submits a remote file to a print queue.
627///
628/// Both contexts must be live and both string pointers must be NUL-terminated SMB URLs. Returns
629/// zero on success or `-1` with `errno` set on failure.
630pub type smbc_print_file_fn = option::Option<
631    extern "C" fn(
632        c_file: *mut SMBCCTX,
633        fname: *const c_char,
634        c_print: *mut SMBCCTX,
635        printq: *const c_char,
636    ) -> c_int,
637>;
638/// Optional callback that opens a new print job.
639///
640/// `fname` must be a NUL-terminated print-queue URL. Returns a live print handle owned by `c`, or
641/// null with `errno` set on failure.
642pub type smbc_open_print_job_fn =
643    option::Option<extern "C" fn(c: *mut SMBCCTX, fname: *const c_char) -> *mut SMBCFILE>;
644/// Optional callback that enumerates jobs in a print queue.
645///
646/// `fname` must be a NUL-terminated queue URL and `_fn` must remain callable throughout the
647/// operation. Returns zero on success or `-1` with `errno` set on failure.
648pub type smbc_list_print_jobs_fn = option::Option<
649    extern "C" fn(c: *mut SMBCCTX, fname: *const c_char, _fn: smbc_list_print_job_fn) -> c_int,
650>;
651/// Optional callback that removes a job from a print queue.
652///
653/// `fname` must be a NUL-terminated queue URL. Returns zero on success or `-1` with `errno` set.
654pub type smbc_unlink_print_job_fn =
655    option::Option<extern "C" fn(c: *mut SMBCCTX, fname: *const c_char, id: c_int) -> c_int>;
656
657#[link(name = "smbclient")]
658unsafe extern "C" {
659    /// Returns the native debug verbosity configured for `c`.
660    ///
661    /// # Safety
662    ///
663    /// `c` must be a valid native context pointer.
664    pub fn smbc_getDebug(c: *mut SMBCCTX) -> c_int;
665    /// Sets the native debug verbosity for `c`.
666    ///
667    /// # Safety
668    ///
669    /// `c` must be a valid native context pointer.
670    pub fn smbc_setDebug(c: *mut SMBCCTX, debug: c_int);
671    /// Sets the global `libsmbclient` configuration file used by `c`.
672    ///
673    /// Returns zero on success or `-1` when the file cannot be loaded.
674    ///
675    /// # Safety
676    ///
677    /// `c` must be a valid native context pointer, and `file` must point to a valid
678    /// NUL-terminated path.
679    pub fn smbc_setConfiguration(c: *mut SMBCCTX, file: *const c_char) -> c_int;
680    /// Installs the callback used for native diagnostic messages.
681    ///
682    /// The callback is process-global despite being selected through `c`.
683    ///
684    /// # Safety
685    ///
686    /// `c` must be a valid native context pointer. If `callback` is `Some`, its function and
687    /// `private_ptr` must remain valid whenever `libsmbclient` invokes it, and the callback must
688    /// not unwind across the C ABI boundary.
689    pub fn smbc_setLogCallback(
690        c: *mut SMBCCTX,
691        private_ptr: *mut c_void,
692        callback: smbc_debug_callback_fn,
693    );
694    /// Returns the NetBIOS name configured for `c`.
695    ///
696    /// # Safety
697    ///
698    /// `c` must be valid. The returned pointer must not be modified or freed and is invalidated by
699    /// changing the name or destroying `c`.
700    pub fn smbc_getNetbiosName(c: *mut SMBCCTX) -> *const c_char;
701    /// Sets the NetBIOS name configured for `c`.
702    ///
703    /// # Safety
704    ///
705    /// `c` must be valid and `netbios_name` must point to a valid NUL-terminated string.
706    pub fn smbc_setNetbiosName(c: *mut SMBCCTX, netbios_name: *const c_char);
707    /// Returns the workgroup configured for `c`.
708    ///
709    /// # Safety
710    ///
711    /// `c` must be valid. The returned pointer must not be modified or freed and is invalidated by
712    /// changing the workgroup or destroying `c`.
713    pub fn smbc_getWorkgroup(c: *mut SMBCCTX) -> *const c_char;
714    /// Sets the workgroup configured for `c`.
715    ///
716    /// # Safety
717    ///
718    /// `c` must be valid and `workgroup` must point to a valid NUL-terminated string.
719    pub fn smbc_setWorkgroup(c: *mut SMBCCTX, workgroup: *const c_char);
720    /// Returns the username configured for `c`.
721    ///
722    /// # Safety
723    ///
724    /// `c` must be valid. The returned pointer must not be modified or freed and is invalidated by
725    /// changing the username or destroying `c`.
726    pub fn smbc_getUser(c: *mut SMBCCTX) -> *const c_char;
727    /// Sets the username configured for `c`.
728    ///
729    /// # Safety
730    ///
731    /// `c` must be valid and `user` must point to a valid NUL-terminated string.
732    pub fn smbc_setUser(c: *mut SMBCCTX, user: *const c_char);
733    /// Returns the timeout configured for `c` in milliseconds.
734    ///
735    /// # Safety
736    ///
737    /// `c` must be a valid native context pointer.
738    pub fn smbc_getTimeout(c: *mut SMBCCTX) -> c_int;
739    /// Sets the timeout for `c` in milliseconds.
740    ///
741    /// # Safety
742    ///
743    /// `c` must be a valid native context pointer.
744    pub fn smbc_setTimeout(c: *mut SMBCCTX, timeout: c_int);
745    /// Returns the TCP port configured for `c`, or zero for the native default.
746    ///
747    /// # Safety
748    ///
749    /// `c` must be a valid native context pointer.
750    pub fn smbc_getPort(c: *mut SMBCCTX) -> u16;
751    /// Sets the TCP port used by `c`, where zero selects the native default.
752    ///
753    /// # Safety
754    ///
755    /// `c` must be a valid native context pointer.
756    pub fn smbc_setPort(c: *mut SMBCCTX, port: u16);
757    /// Returns whether full SMB time attribute names are enabled for `c`.
758    ///
759    /// # Safety
760    ///
761    /// `c` must be a valid native context pointer.
762    pub fn smbc_getOptionFullTimeNames(c: *mut SMBCCTX) -> smbc_bool;
763    /// Enables or disables full SMB time attribute names for `c`.
764    ///
765    /// # Safety
766    ///
767    /// `c` must be a valid native context pointer.
768    pub fn smbc_setOptionFullTimeNames(c: *mut SMBCCTX, b: smbc_bool);
769    /// Returns the user data pointer stored in `c`.
770    ///
771    /// # Safety
772    ///
773    /// `c` must be a valid native context pointer.
774    pub fn smbc_getOptionUserData(c: *mut SMBCCTX) -> *mut c_void;
775    /// Stores an opaque user data pointer in `c`.
776    ///
777    /// # Safety
778    ///
779    /// `c` must be a valid native context pointer. The caller must ensure the pointed-to data
780    /// remains valid for any native code that retrieves or uses it.
781    pub fn smbc_setOptionUserData(c: *mut SMBCCTX, user_data: *mut c_void);
782    /// Returns whether the password configured for `c` is an NT hash.
783    ///
784    /// # Safety
785    ///
786    /// `c` must be a valid native context pointer.
787    pub fn smbc_getOptionUseNTHash(c: *mut SMBCCTX) -> smbc_bool;
788    /// Marks the password configured for `c` as an NT hash when enabled.
789    ///
790    /// # Safety
791    ///
792    /// `c` must be a valid native context pointer.
793    pub fn smbc_setOptionUseNTHash(c: *mut SMBCCTX, b: smbc_bool);
794    /// Returns whether native debug output is written to standard error for `c`.
795    ///
796    /// # Safety
797    ///
798    /// `c` must be a valid native context pointer.
799    pub fn smbc_getOptionDebugToStderr(c: *mut SMBCCTX) -> smbc_bool;
800    /// Controls whether native debug output is written to standard error.
801    ///
802    /// # Safety
803    ///
804    /// `c` must be a valid, uninitialized native context pointer.
805    pub fn smbc_setOptionDebugToStderr(c: *mut SMBCCTX, b: smbc_bool);
806    /// Returns the file-open sharing mode configured for `c`.
807    ///
808    /// # Safety
809    ///
810    /// `c` must be a valid native context pointer.
811    pub fn smbc_getOptionOpenShareMode(c: *mut SMBCCTX) -> smbc_share_mode;
812    /// Sets the file-open sharing mode for `c`.
813    ///
814    /// # Safety
815    ///
816    /// `c` must be a valid, uninitialized context and `share_mode` must be supported.
817    pub fn smbc_setOptionOpenShareMode(c: *mut SMBCCTX, share_mode: smbc_share_mode);
818    /// Returns the SMB encryption policy configured for `c`.
819    ///
820    /// # Safety
821    ///
822    /// `c` must be a valid native context pointer.
823    pub fn smbc_getOptionSmbEncryptionLevel(c: *mut SMBCCTX) -> smbc_smb_encrypt_level;
824    /// Sets the SMB encryption policy for `c`.
825    ///
826    /// # Safety
827    ///
828    /// `c` must be a valid, uninitialized context and `level` must be supported.
829    pub fn smbc_setOptionSmbEncryptionLevel(c: *mut SMBCCTX, level: smbc_smb_encrypt_level);
830    /// Returns whether path matching is case-sensitive for `c`.
831    ///
832    /// # Safety
833    ///
834    /// `c` must be a valid native context pointer.
835    pub fn smbc_getOptionCaseSensitive(c: *mut SMBCCTX) -> smbc_bool;
836    /// Controls case-sensitive path matching for `c`.
837    ///
838    /// # Safety
839    ///
840    /// `c` must be a valid, uninitialized native context pointer.
841    pub fn smbc_setOptionCaseSensitive(c: *mut SMBCCTX, b: smbc_bool);
842    /// Returns the maximum local master browser query count configured for `c`.
843    ///
844    /// # Safety
845    ///
846    /// `c` must be a valid native context pointer.
847    pub fn smbc_getOptionBrowseMaxLmbCount(c: *mut SMBCCTX) -> c_int;
848    /// Sets the maximum local master browser query count for `c`.
849    ///
850    /// # Safety
851    ///
852    /// `c` must be a valid, uninitialized native context pointer.
853    pub fn smbc_setOptionBrowseMaxLmbCount(c: *mut SMBCCTX, count: c_int);
854    /// Returns whether URL encoding is enabled for directory-entry names in `c`.
855    ///
856    /// # Safety
857    ///
858    /// `c` must be a valid native context pointer.
859    pub fn smbc_getOptionUrlEncodeReaddirEntries(c: *mut SMBCCTX) -> smbc_bool;
860    /// Controls URL encoding of directory-entry names for `c`.
861    ///
862    /// # Safety
863    ///
864    /// `c` must be a valid, uninitialized native context pointer.
865    pub fn smbc_setOptionUrlEncodeReaddirEntries(c: *mut SMBCCTX, b: smbc_bool);
866    /// Returns whether each server connection is restricted to one share.
867    ///
868    /// # Safety
869    ///
870    /// `c` must be a valid native context pointer.
871    pub fn smbc_getOptionOneSharePerServer(c: *mut SMBCCTX) -> smbc_bool;
872    /// Restricts each server connection to one share when enabled.
873    ///
874    /// # Safety
875    ///
876    /// `c` must be a valid, uninitialized native context pointer.
877    pub fn smbc_setOptionOneSharePerServer(c: *mut SMBCCTX, b: smbc_bool);
878    /// Returns whether Kerberos authentication is enabled for `c`.
879    ///
880    /// # Safety
881    ///
882    /// `c` must be a valid native context pointer.
883    pub fn smbc_getOptionUseKerberos(c: *mut SMBCCTX) -> smbc_bool;
884    /// Controls whether Kerberos authentication is attempted for `c`.
885    ///
886    /// # Safety
887    ///
888    /// `c` must be a valid, uninitialized native context pointer.
889    pub fn smbc_setOptionUseKerberos(c: *mut SMBCCTX, b: smbc_bool);
890    /// Returns whether authentication falls back after Kerberos fails.
891    ///
892    /// # Safety
893    ///
894    /// `c` must be a valid native context pointer.
895    pub fn smbc_getOptionFallbackAfterKerberos(c: *mut SMBCCTX) -> smbc_bool;
896    /// Controls fallback after Kerberos authentication fails.
897    ///
898    /// # Safety
899    ///
900    /// `c` must be a valid, uninitialized native context pointer.
901    pub fn smbc_setOptionFallbackAfterKerberos(c: *mut SMBCCTX, b: smbc_bool);
902    /// Returns whether automatic anonymous authentication is disabled.
903    ///
904    /// # Safety
905    ///
906    /// `c` must be a valid native context pointer.
907    pub fn smbc_getOptionNoAutoAnonymousLogin(c: *mut SMBCCTX) -> smbc_bool;
908    /// Prevents automatic anonymous authentication when enabled.
909    ///
910    /// # Safety
911    ///
912    /// `c` must be a valid, uninitialized native context pointer.
913    pub fn smbc_setOptionNoAutoAnonymousLogin(c: *mut SMBCCTX, b: smbc_bool);
914    /// Returns whether Kerberos uses the credential cache.
915    ///
916    /// # Safety
917    ///
918    /// `c` must be a valid native context pointer.
919    pub fn smbc_getOptionUseCCache(c: *mut SMBCCTX) -> smbc_bool;
920    /// Controls whether Kerberos uses the credential cache.
921    ///
922    /// # Safety
923    ///
924    /// `c` must be a valid, uninitialized native context pointer.
925    pub fn smbc_setOptionUseCCache(c: *mut SMBCCTX, b: smbc_bool);
926    /// Returns whether POSIX extensions are enabled for `c`.
927    ///
928    /// Available when the `abi-0-8` feature is enabled.
929    ///
930    /// # Safety
931    ///
932    /// `c` must be a valid native context pointer.
933    #[cfg(feature = "abi-0-8")]
934    pub fn smbc_getOptionPosixExtensions(c: *mut SMBCCTX) -> smbc_bool;
935    /// Enables or disables POSIX extensions for `c`.
936    ///
937    /// Available when the `abi-0-8` feature is enabled.
938    ///
939    /// # Safety
940    ///
941    /// `c` must be a valid, uninitialized native context pointer.
942    #[cfg(feature = "abi-0-8")]
943    pub fn smbc_setOptionPosixExtensions(c: *mut SMBCCTX, b: smbc_bool);
944    /// Sets the minimum and maximum SMB dialects offered during protocol negotiation.
945    ///
946    /// Each protocol name must be a NUL-terminated Samba dialect string such as `NT1`,
947    /// `SMB2_02`, or `SMB3_11`. A null pointer keeps the corresponding `smb.conf` value.
948    /// Returns a non-zero value on success and `0` when a protocol name is not recognized.
949    ///
950    /// Available since Samba 4.10 (libsmbclient ABI 0.5). The call takes effect only when it
951    /// is issued before [`smbc_init_context`].
952    ///
953    /// # Safety
954    ///
955    /// `c` must be a valid, uninitialized [`SMBCCTX`]. Each non-null protocol pointer must point
956    /// to a NUL-terminated, valid Samba dialect string. This call must be issued before
957    /// [`smbc_init_context`].
958    pub fn smbc_setOptionProtocols(
959        c: *mut SMBCCTX,
960        min_protocol: *const c_char,
961        max_protocol: *const c_char,
962    ) -> smbc_bool;
963    /// Installs the context-aware authentication callback for `c`.
964    ///
965    /// # Safety
966    ///
967    /// `c` must be valid and uninitialized. The callback must uphold the native callback contract.
968    pub fn smbc_setFunctionAuthDataWithContext(
969        c: *mut SMBCCTX,
970        _fn: smbc_get_auth_data_with_context_fn,
971    );
972    /// Returns the file-open callback installed in `c`.
973    ///
974    /// # Safety
975    ///
976    /// `c` must be a valid, initialized native context pointer.
977    pub fn smbc_getFunctionOpen(c: *mut SMBCCTX) -> smbc_open_fn;
978    /// Returns the file-creation callback installed in `c`.
979    ///
980    /// # Safety
981    ///
982    /// `c` must be a valid, initialized native context pointer.
983    pub fn smbc_getFunctionCreat(c: *mut SMBCCTX) -> smbc_creat_fn;
984    /// Returns the file-read callback installed in `c`.
985    ///
986    /// # Safety
987    ///
988    /// `c` must be a valid, initialized native context pointer.
989    pub fn smbc_getFunctionRead(c: *mut SMBCCTX) -> smbc_read_fn;
990    /// Returns the file-write callback installed in `c`.
991    ///
992    /// # Safety
993    ///
994    /// `c` must be a valid, initialized native context pointer.
995    pub fn smbc_getFunctionWrite(c: *mut SMBCCTX) -> smbc_write_fn;
996    /// Returns the file-splicing callback installed in `c`.
997    ///
998    /// # Safety
999    ///
1000    /// `c` must be a valid, initialized native context pointer.
1001    pub fn smbc_getFunctionSplice(c: *mut SMBCCTX) -> smbc_splice_fn;
1002    /// Returns the file-removal callback installed in `c`.
1003    ///
1004    /// # Safety
1005    ///
1006    /// `c` must be a valid, initialized native context pointer.
1007    pub fn smbc_getFunctionUnlink(c: *mut SMBCCTX) -> smbc_unlink_fn;
1008    /// Returns the entry-rename callback installed in `c`.
1009    ///
1010    /// # Safety
1011    ///
1012    /// `c` must be a valid, initialized native context pointer.
1013    pub fn smbc_getFunctionRename(c: *mut SMBCCTX) -> smbc_rename_fn;
1014    /// Returns the file-seek callback installed in `c`.
1015    ///
1016    /// # Safety
1017    ///
1018    /// `c` must be a valid, initialized native context pointer.
1019    pub fn smbc_getFunctionLseek(c: *mut SMBCCTX) -> smbc_lseek_fn;
1020    /// Returns the path-metadata callback installed in `c`.
1021    ///
1022    /// # Safety
1023    ///
1024    /// `c` must be a valid, initialized native context pointer.
1025    pub fn smbc_getFunctionStat(c: *mut SMBCCTX) -> smbc_stat_fn;
1026    /// Returns the open-file metadata callback installed in `c`.
1027    ///
1028    /// # Safety
1029    ///
1030    /// `c` must be a valid, initialized native context pointer.
1031    pub fn smbc_getFunctionFstat(c: *mut SMBCCTX) -> smbc_fstat_fn;
1032    /// Returns the file-truncation callback installed in `c`.
1033    ///
1034    /// # Safety
1035    ///
1036    /// `c` must be a valid, initialized native context pointer.
1037    pub fn smbc_getFunctionFtruncate(c: *mut SMBCCTX) -> smbc_ftruncate_fn;
1038    /// Returns the filesystem-statistics callback installed in `c`.
1039    ///
1040    /// # Safety
1041    ///
1042    /// `c` must be a valid, initialized native context pointer.
1043    pub fn smbc_getFunctionStatVFS(c: *mut SMBCCTX) -> smbc_statvfs_fn;
1044    /// Returns the open-file filesystem-statistics callback installed in `c`.
1045    ///
1046    /// # Safety
1047    ///
1048    /// `c` must be a valid, initialized native context pointer.
1049    pub fn smbc_getFunctionFstatVFS(c: *mut SMBCCTX) -> smbc_fstatvfs_fn;
1050    /// Returns the file-close callback installed in `c`.
1051    ///
1052    /// # Safety
1053    ///
1054    /// `c` must be a valid, initialized native context pointer.
1055    pub fn smbc_getFunctionClose(c: *mut SMBCCTX) -> smbc_close_fn;
1056    /// Returns the directory-open callback installed in `c`.
1057    ///
1058    /// # Safety
1059    ///
1060    /// `c` must be a valid, initialized native context pointer.
1061    pub fn smbc_getFunctionOpendir(c: *mut SMBCCTX) -> smbc_opendir_fn;
1062    /// Returns the directory-close callback installed in `c`.
1063    ///
1064    /// # Safety
1065    ///
1066    /// `c` must be a valid, initialized native context pointer.
1067    pub fn smbc_getFunctionClosedir(c: *mut SMBCCTX) -> smbc_closedir_fn;
1068    /// Returns the directory-read callback installed in `c`.
1069    ///
1070    /// # Safety
1071    ///
1072    /// `c` must be a valid, initialized native context pointer.
1073    pub fn smbc_getFunctionReaddir(c: *mut SMBCCTX) -> smbc_readdir_fn;
1074    /// Returns the extended directory-read callback installed in `c`.
1075    ///
1076    /// # Safety
1077    ///
1078    /// `c` must be a valid, initialized native context pointer.
1079    pub fn smbc_getFunctionReaddirPlus(c: *mut SMBCCTX) -> smbc_readdirplus_fn;
1080    /// Returns the extended directory-read callback that also accepts a `stat` buffer.
1081    ///
1082    /// Available when the `abi-0-6` feature is enabled.
1083    ///
1084    /// # Safety
1085    ///
1086    /// `c` must be a valid, initialized native context pointer.
1087    #[cfg(feature = "abi-0-6")]
1088    pub fn smbc_getFunctionReaddirPlus2(c: *mut SMBCCTX) -> smbc_readdirplus2_fn;
1089    /// Returns the multiple-directory-entry callback installed in `c`.
1090    ///
1091    /// # Safety
1092    ///
1093    /// `c` must be a valid, initialized native context pointer.
1094    pub fn smbc_getFunctionGetdents(c: *mut SMBCCTX) -> smbc_getdents_fn;
1095    /// Returns the directory-creation callback installed in `c`.
1096    ///
1097    /// # Safety
1098    ///
1099    /// `c` must be a valid, initialized native context pointer.
1100    pub fn smbc_getFunctionMkdir(c: *mut SMBCCTX) -> smbc_mkdir_fn;
1101    /// Returns the directory-removal callback installed in `c`.
1102    ///
1103    /// # Safety
1104    ///
1105    /// `c` must be a valid, initialized native context pointer.
1106    pub fn smbc_getFunctionRmdir(c: *mut SMBCCTX) -> smbc_rmdir_fn;
1107    /// Returns the directory-position callback installed in `c`.
1108    ///
1109    /// # Safety
1110    ///
1111    /// `c` must be a valid, initialized native context pointer.
1112    pub fn smbc_getFunctionTelldir(c: *mut SMBCCTX) -> smbc_telldir_fn;
1113    /// Returns the directory-seek callback installed in `c`.
1114    ///
1115    /// # Safety
1116    ///
1117    /// `c` must be a valid, initialized native context pointer.
1118    pub fn smbc_getFunctionLseekdir(c: *mut SMBCCTX) -> smbc_lseekdir_fn;
1119    /// Returns the directory-metadata callback installed in `c`.
1120    ///
1121    /// # Safety
1122    ///
1123    /// `c` must be a valid, initialized native context pointer.
1124    pub fn smbc_getFunctionFstatdir(c: *mut SMBCCTX) -> smbc_fstatdir_fn;
1125    /// Returns the directory-notification callback installed in `c`.
1126    ///
1127    /// # Safety
1128    ///
1129    /// `c` must be a valid, initialized native context pointer.
1130    pub fn smbc_getFunctionNotify(c: *mut SMBCCTX) -> smbc_notify_fn;
1131    /// Returns the mode-change callback installed in `c`.
1132    ///
1133    /// # Safety
1134    ///
1135    /// `c` must be a valid, initialized native context pointer.
1136    pub fn smbc_getFunctionChmod(c: *mut SMBCCTX) -> smbc_chmod_fn;
1137    /// Returns the timestamp-update callback installed in `c`.
1138    ///
1139    /// # Safety
1140    ///
1141    /// `c` must be a valid, initialized native context pointer.
1142    pub fn smbc_getFunctionUtimes(c: *mut SMBCCTX) -> smbc_utimes_fn;
1143    /// Returns the extended-attribute write callback installed in `c`.
1144    ///
1145    /// # Safety
1146    ///
1147    /// `c` must be a valid, initialized native context pointer.
1148    pub fn smbc_getFunctionSetxattr(c: *mut SMBCCTX) -> smbc_setxattr_fn;
1149    /// Returns the extended-attribute read callback installed in `c`.
1150    ///
1151    /// # Safety
1152    ///
1153    /// `c` must be a valid, initialized native context pointer.
1154    pub fn smbc_getFunctionGetxattr(c: *mut SMBCCTX) -> smbc_getxattr_fn;
1155    /// Returns the extended-attribute removal callback installed in `c`.
1156    ///
1157    /// # Safety
1158    ///
1159    /// `c` must be a valid, initialized native context pointer.
1160    pub fn smbc_getFunctionRemovexattr(c: *mut SMBCCTX) -> smbc_removexattr_fn;
1161    /// Returns the extended-attribute listing callback installed in `c`.
1162    ///
1163    /// # Safety
1164    ///
1165    /// `c` must be a valid, initialized native context pointer.
1166    pub fn smbc_getFunctionListxattr(c: *mut SMBCCTX) -> smbc_listxattr_fn;
1167    /// Returns the file-printing callback installed in `c`.
1168    ///
1169    /// # Safety
1170    ///
1171    /// `c` must be a valid, initialized native context pointer.
1172    pub fn smbc_getFunctionPrintFile(c: *mut SMBCCTX) -> smbc_print_file_fn;
1173    /// Returns the print-job opening callback installed in `c`.
1174    ///
1175    /// # Safety
1176    ///
1177    /// `c` must be a valid, initialized native context pointer.
1178    pub fn smbc_getFunctionOpenPrintJob(c: *mut SMBCCTX) -> smbc_open_print_job_fn;
1179    /// Returns the print-job listing callback installed in `c`.
1180    ///
1181    /// # Safety
1182    ///
1183    /// `c` must be a valid, initialized native context pointer.
1184    pub fn smbc_getFunctionListPrintJobs(c: *mut SMBCCTX) -> smbc_list_print_jobs_fn;
1185    /// Returns the print-job removal callback installed in `c`.
1186    ///
1187    /// # Safety
1188    ///
1189    /// `c` must be a valid, initialized native context pointer.
1190    pub fn smbc_getFunctionUnlinkPrintJob(c: *mut SMBCCTX) -> smbc_unlink_print_job_fn;
1191    /// Allocates a new, uninitialized native SMB context.
1192    ///
1193    /// Returns null and sets `errno` to `ENOMEM` when allocation fails.
1194    ///
1195    /// # Safety
1196    ///
1197    /// A non-null pointer must be passed to [`smbc_init_context`] before use and eventually passed
1198    /// exactly once to [`smbc_free_context`].
1199    pub fn smbc_new_context() -> *mut SMBCCTX;
1200    /// Attempts to free `context` and optionally shuts down its connections.
1201    ///
1202    /// Returns zero on success. Returns one and sets `errno` to `EBUSY` if resources remain in use
1203    /// when `shutdown_ctx` is zero, or to `EBADF` if `context` is null.
1204    ///
1205    /// # Safety
1206    ///
1207    /// `context` must be a live pointer allocated by [`smbc_new_context`] and not previously freed.
1208    /// It remains owned by the caller when this function returns one.
1209    pub fn smbc_free_context(context: *mut SMBCCTX, shutdown_ctx: c_int) -> c_int;
1210    /// Sets fallback credentials used by `libsmbclient` for DFS referrals.
1211    ///
1212    /// # Safety
1213    ///
1214    /// `c` must be a valid native context pointer. Each non-null credential pointer must refer to
1215    /// a valid NUL-terminated string for the duration of the call.
1216    pub fn smbc_set_credentials_with_fallback(
1217        c: *mut SMBCCTX,
1218        workgroup: *const c_char,
1219        user: *const c_char,
1220        password: *const c_char,
1221    );
1222    /// Initializes a newly allocated native SMB context.
1223    ///
1224    /// Returns `context` on success. Returns null and sets `errno` to `EBADF`, `ENOMEM`, or `ENOENT`
1225    /// for a null context, allocation failure, or an unreadable Samba configuration, respectively.
1226    ///
1227    /// # Safety
1228    ///
1229    /// `context` must be a live, uninitialized pointer returned by [`smbc_new_context`]. On failure,
1230    /// the caller still owns it and must pass it to [`smbc_free_context`].
1231    pub fn smbc_init_context(context: *mut SMBCCTX) -> *mut SMBCCTX;
1232    /// Returns the linked `libsmbclient` version string.
1233    ///
1234    /// # Safety
1235    ///
1236    /// The returned pointer is borrowed static storage and must not be modified or freed.
1237    pub fn smbc_version() -> *const c_char;
1238}
1239
1240#[cfg(test)]
1241mod tests {
1242    use std::sync::atomic::{AtomicBool, Ordering};
1243
1244    use libc::{c_char, c_int, c_void};
1245    use serial_test::serial;
1246
1247    use super::*;
1248
1249    fn with_context(test: impl FnOnce(*mut SMBCCTX)) {
1250        unsafe {
1251            let context = smbc_new_context();
1252            assert!(!context.is_null());
1253            test(context);
1254            assert_eq!(smbc_free_context(context, 1), 0);
1255        }
1256    }
1257
1258    extern "C" fn record_log(private_ptr: *mut c_void, _level: c_int, _message: *const c_char) {
1259        unsafe { (&*private_ptr.cast::<AtomicBool>()).store(true, Ordering::SeqCst) };
1260    }
1261
1262    #[test]
1263    #[serial]
1264    fn treats_smbc_context_as_opaque() {
1265        with_context(|context| assert!(!context.is_null()));
1266    }
1267
1268    #[test]
1269    fn uses_fixed_width_file_info_size() {
1270        let info = libsmb_file_info {
1271            size: u64::MAX,
1272            ..Default::default()
1273        };
1274        assert_eq!(info.size, u64::MAX);
1275        assert_eq!(std::mem::size_of_val(&info.size), 8);
1276    }
1277
1278    #[test]
1279    fn uses_signed_encryption_level() {
1280        let level: smbc_smb_encrypt_level = -1;
1281        assert_eq!(level, -1);
1282    }
1283
1284    #[test]
1285    fn uses_const_context_string_pointers() {
1286        let _: unsafe extern "C" fn(*mut SMBCCTX) -> *const c_char = smbc_getNetbiosName;
1287        let _: unsafe extern "C" fn(*mut SMBCCTX, *const c_char) = smbc_setNetbiosName;
1288        let _: unsafe extern "C" fn(*mut SMBCCTX) -> *const c_char = smbc_getWorkgroup;
1289        let _: unsafe extern "C" fn(*mut SMBCCTX, *const c_char) = smbc_setWorkgroup;
1290        let _: unsafe extern "C" fn(*mut SMBCCTX) -> *const c_char = smbc_getUser;
1291        let _: unsafe extern "C" fn(*mut SMBCCTX, *const c_char) = smbc_setUser;
1292    }
1293
1294    #[test]
1295    fn exposes_directory_entry_constants() {
1296        assert_eq!(SMBC_WORKGROUP, 1);
1297        assert_eq!(SMBC_SERVER, 2);
1298        assert_eq!(SMBC_FILE_SHARE, 3);
1299        assert_eq!(SMBC_PRINTER_SHARE, 4);
1300        assert_eq!(SMBC_COMMS_SHARE, 5);
1301        assert_eq!(SMBC_IPC_SHARE, 6);
1302        assert_eq!(SMBC_DIR, 7);
1303        assert_eq!(SMBC_FILE, 8);
1304        assert_eq!(SMBC_LINK, 9);
1305        assert_eq!(SMBC_BASE_FD, 10000);
1306    }
1307
1308    #[test]
1309    fn exposes_share_and_encryption_constants() {
1310        assert_eq!(SMBC_SHAREMODE_DENY_DOS, 0);
1311        assert_eq!(SMBC_SHAREMODE_DENY_ALL, 1);
1312        assert_eq!(SMBC_SHAREMODE_DENY_WRITE, 2);
1313        assert_eq!(SMBC_SHAREMODE_DENY_READ, 3);
1314        assert_eq!(SMBC_SHAREMODE_DENY_NONE, 4);
1315        assert_eq!(SMBC_SHAREMODE_DENY_FCB, 7);
1316        assert_eq!(SMBC_ENCRYPTLEVEL_DEFAULT, -1);
1317        assert_eq!(SMBC_ENCRYPTLEVEL_NONE, 0);
1318        assert_eq!(SMBC_ENCRYPTLEVEL_REQUEST, 1);
1319        assert_eq!(SMBC_ENCRYPTLEVEL_REQUIRE, 2);
1320    }
1321
1322    #[test]
1323    fn exposes_extended_attribute_constants() {
1324        assert_eq!(SMBC_XATTR_FLAG_CREATE, 0x1);
1325        assert_eq!(SMBC_XATTR_FLAG_REPLACE, 0x2);
1326        assert_eq!(SMBC_DOS_MODE_READONLY, 0x01);
1327        assert_eq!(SMBC_DOS_MODE_HIDDEN, 0x02);
1328        assert_eq!(SMBC_DOS_MODE_SYSTEM, 0x04);
1329        assert_eq!(SMBC_DOS_MODE_VOLUME_ID, 0x08);
1330        assert_eq!(SMBC_DOS_MODE_DIRECTORY, 0x10);
1331        assert_eq!(SMBC_DOS_MODE_ARCHIVE, 0x20);
1332    }
1333
1334    #[test]
1335    fn exposes_vfs_feature_constants() {
1336        assert_eq!(SMBC_VFS_FEATURE_RDONLY, 1 << 0);
1337        assert_eq!(SMBC_VFS_FEATURE_DFS, 1 << 28);
1338        assert_eq!(SMBC_VFS_FEATURE_CASE_INSENSITIVE, 1 << 29);
1339        assert_eq!(SMBC_VFS_FEATURE_NO_UNIXCIFS, 1 << 30);
1340    }
1341
1342    #[test]
1343    fn exposes_notification_constants() {
1344        assert_eq!(SMBC_NOTIFY_CHANGE_FILE_NAME, 0x001);
1345        assert_eq!(SMBC_NOTIFY_CHANGE_DIR_NAME, 0x002);
1346        assert_eq!(SMBC_NOTIFY_CHANGE_ATTRIBUTES, 0x004);
1347        assert_eq!(SMBC_NOTIFY_CHANGE_SIZE, 0x008);
1348        assert_eq!(SMBC_NOTIFY_CHANGE_LAST_WRITE, 0x010);
1349        assert_eq!(SMBC_NOTIFY_CHANGE_LAST_ACCESS, 0x020);
1350        assert_eq!(SMBC_NOTIFY_CHANGE_CREATION, 0x040);
1351        assert_eq!(SMBC_NOTIFY_CHANGE_EA, 0x080);
1352        assert_eq!(SMBC_NOTIFY_CHANGE_SECURITY, 0x100);
1353        assert_eq!(SMBC_NOTIFY_CHANGE_STREAM_NAME, 0x200);
1354        assert_eq!(SMBC_NOTIFY_CHANGE_STREAM_SIZE, 0x400);
1355        assert_eq!(SMBC_NOTIFY_CHANGE_STREAM_WRITE, 0x800);
1356        assert_eq!(SMBC_NOTIFY_ACTION_ADDED, 1);
1357        assert_eq!(SMBC_NOTIFY_ACTION_REMOVED, 2);
1358        assert_eq!(SMBC_NOTIFY_ACTION_MODIFIED, 3);
1359        assert_eq!(SMBC_NOTIFY_ACTION_OLD_NAME, 4);
1360        assert_eq!(SMBC_NOTIFY_ACTION_NEW_NAME, 5);
1361        assert_eq!(SMBC_NOTIFY_ACTION_ADDED_STREAM, 6);
1362        assert_eq!(SMBC_NOTIFY_ACTION_REMOVED_STREAM, 7);
1363        assert_eq!(SMBC_NOTIFY_ACTION_MODIFIED_STREAM, 8);
1364    }
1365
1366    #[test]
1367    #[serial]
1368    fn gets_debug_level() {
1369        with_context(|context| unsafe {
1370            smbc_setDebug(context, 7);
1371            assert_eq!(smbc_getDebug(context), 7);
1372        });
1373    }
1374
1375    #[test]
1376    #[serial]
1377    fn rejects_missing_configuration() {
1378        with_context(|context| unsafe {
1379            assert_eq!(
1380                smbc_setConfiguration(context, c"/definitely/missing/pavao.conf".as_ptr()),
1381                -1
1382            );
1383        });
1384    }
1385
1386    #[test]
1387    #[serial]
1388    fn sets_log_callback() {
1389        with_context(|context| unsafe {
1390            let called = AtomicBool::new(false);
1391            let private_ptr = std::ptr::from_ref(&called).cast_mut().cast::<c_void>();
1392            smbc_setDebug(context, 1);
1393            smbc_setLogCallback(context, private_ptr, Some(record_log));
1394            assert_eq!(
1395                smbc_setConfiguration(context, c"/definitely/missing/pavao.conf".as_ptr()),
1396                -1
1397            );
1398            smbc_setLogCallback(context, std::ptr::null_mut(), None);
1399            assert!(called.load(Ordering::SeqCst));
1400        });
1401    }
1402
1403    #[test]
1404    #[serial]
1405    fn gets_default_port() {
1406        with_context(|context| unsafe {
1407            assert_eq!(smbc_getPort(context), 0);
1408        });
1409    }
1410
1411    #[test]
1412    #[serial]
1413    fn sets_port() {
1414        with_context(|context| unsafe {
1415            smbc_setPort(context, 445);
1416            assert_eq!(smbc_getPort(context), 445);
1417        });
1418    }
1419
1420    #[test]
1421    #[serial]
1422    fn gets_full_time_names_option() {
1423        with_context(|context| unsafe {
1424            assert_eq!(smbc_getOptionFullTimeNames(context), 0);
1425        });
1426    }
1427
1428    #[test]
1429    #[serial]
1430    fn sets_full_time_names_option() {
1431        with_context(|context| unsafe {
1432            smbc_setOptionFullTimeNames(context, 1);
1433            assert_eq!(smbc_getOptionFullTimeNames(context), 1);
1434        });
1435    }
1436
1437    #[test]
1438    #[serial]
1439    fn gets_empty_user_data() {
1440        with_context(|context| unsafe {
1441            assert!(smbc_getOptionUserData(context).is_null());
1442        });
1443    }
1444
1445    #[test]
1446    #[serial]
1447    fn sets_user_data() {
1448        with_context(|context| unsafe {
1449            let mut value = 42;
1450            let user_data = std::ptr::from_mut(&mut value).cast::<c_void>();
1451            smbc_setOptionUserData(context, user_data);
1452            assert_eq!(smbc_getOptionUserData(context), user_data);
1453            smbc_setOptionUserData(context, std::ptr::null_mut());
1454        });
1455    }
1456
1457    #[test]
1458    #[serial]
1459    fn gets_nt_hash_option() {
1460        with_context(|context| unsafe {
1461            assert_eq!(smbc_getOptionUseNTHash(context), 0);
1462        });
1463    }
1464
1465    #[test]
1466    #[serial]
1467    fn sets_nt_hash_option() {
1468        with_context(|context| unsafe {
1469            smbc_setOptionUseNTHash(context, 1);
1470            assert_eq!(smbc_getOptionUseNTHash(context), 1);
1471        });
1472    }
1473
1474    #[test]
1475    #[serial]
1476    fn sets_fallback_credentials() {
1477        with_context(|context| unsafe {
1478            smbc_setUser(context, c"user".as_ptr());
1479            smbc_set_credentials_with_fallback(
1480                context,
1481                c"WORKGROUP".as_ptr(),
1482                c"user".as_ptr(),
1483                c"password".as_ptr(),
1484            );
1485            assert_eq!(std::ffi::CStr::from_ptr(smbc_getUser(context)), c"user");
1486        });
1487    }
1488
1489    #[test]
1490    #[serial]
1491    fn gets_debug_to_stderr_option() {
1492        with_context(|context| unsafe {
1493            smbc_setOptionDebugToStderr(context, 1);
1494            assert_eq!(smbc_getOptionDebugToStderr(context), 1);
1495        });
1496    }
1497
1498    #[test]
1499    #[serial]
1500    fn gets_open_share_mode_option() {
1501        with_context(|context| unsafe {
1502            smbc_setOptionOpenShareMode(context, SMBC_SHAREMODE_DENY_ALL);
1503            assert_eq!(
1504                smbc_getOptionOpenShareMode(context),
1505                SMBC_SHAREMODE_DENY_ALL
1506            );
1507        });
1508    }
1509
1510    #[test]
1511    #[serial]
1512    fn gets_encryption_level_option() {
1513        with_context(|context| unsafe {
1514            smbc_setOptionSmbEncryptionLevel(context, SMBC_ENCRYPTLEVEL_REQUIRE);
1515            assert_eq!(
1516                smbc_getOptionSmbEncryptionLevel(context),
1517                SMBC_ENCRYPTLEVEL_REQUIRE
1518            );
1519        });
1520    }
1521
1522    #[test]
1523    #[serial]
1524    fn gets_case_sensitive_option() {
1525        with_context(|context| unsafe {
1526            smbc_setOptionCaseSensitive(context, 1);
1527            assert_eq!(smbc_getOptionCaseSensitive(context), 1);
1528        });
1529    }
1530
1531    #[test]
1532    #[serial]
1533    fn gets_browse_max_lmb_count_option() {
1534        with_context(|context| unsafe {
1535            smbc_setOptionBrowseMaxLmbCount(context, 9);
1536            assert_eq!(smbc_getOptionBrowseMaxLmbCount(context), 9);
1537        });
1538    }
1539
1540    #[test]
1541    #[serial]
1542    fn gets_url_encode_readdir_option() {
1543        with_context(|context| unsafe {
1544            smbc_setOptionUrlEncodeReaddirEntries(context, 1);
1545            assert_eq!(smbc_getOptionUrlEncodeReaddirEntries(context), 1);
1546        });
1547    }
1548
1549    #[test]
1550    #[serial]
1551    fn gets_one_share_per_server_option() {
1552        with_context(|context| unsafe {
1553            smbc_setOptionOneSharePerServer(context, 1);
1554            assert_eq!(smbc_getOptionOneSharePerServer(context), 1);
1555        });
1556    }
1557
1558    #[test]
1559    #[serial]
1560    fn gets_use_kerberos_option() {
1561        with_context(|context| unsafe {
1562            smbc_setOptionUseKerberos(context, 1);
1563            assert_eq!(smbc_getOptionUseKerberos(context), 1);
1564        });
1565    }
1566
1567    #[test]
1568    #[serial]
1569    fn gets_kerberos_fallback_option() {
1570        with_context(|context| unsafe {
1571            smbc_setOptionFallbackAfterKerberos(context, 1);
1572            assert_eq!(smbc_getOptionFallbackAfterKerberos(context), 1);
1573        });
1574    }
1575
1576    #[test]
1577    #[serial]
1578    fn gets_no_auto_anonymous_option() {
1579        with_context(|context| unsafe {
1580            smbc_setOptionNoAutoAnonymousLogin(context, 1);
1581            assert_eq!(smbc_getOptionNoAutoAnonymousLogin(context), 1);
1582        });
1583    }
1584
1585    #[test]
1586    #[serial]
1587    fn gets_use_ccache_option() {
1588        with_context(|context| unsafe {
1589            smbc_setOptionUseCCache(context, 1);
1590            assert_eq!(smbc_getOptionUseCCache(context), 1);
1591        });
1592    }
1593
1594    #[test]
1595    #[serial]
1596    fn binds_smbc_get_function_creat() {
1597        with_context(|context| unsafe {
1598            assert!(smbc_getFunctionCreat(context).is_some());
1599        });
1600    }
1601
1602    #[test]
1603    #[serial]
1604    fn binds_smbc_get_function_splice() {
1605        with_context(|context| unsafe {
1606            assert!(smbc_getFunctionSplice(context).is_some());
1607        });
1608    }
1609
1610    #[test]
1611    #[serial]
1612    fn binds_smbc_get_function_fstat() {
1613        with_context(|context| unsafe {
1614            assert!(smbc_getFunctionFstat(context).is_some());
1615        });
1616    }
1617
1618    #[test]
1619    #[serial]
1620    fn binds_smbc_get_function_fstatvfs() {
1621        with_context(|context| unsafe {
1622            assert!(smbc_getFunctionFstatVFS(context).is_some());
1623        });
1624    }
1625
1626    #[test]
1627    #[serial]
1628    fn binds_smbc_get_function_ftruncate() {
1629        with_context(|context| unsafe {
1630            assert!(smbc_getFunctionFtruncate(context).is_some());
1631        });
1632    }
1633
1634    #[test]
1635    #[serial]
1636    fn binds_smbc_get_function_getdents() {
1637        with_context(|context| unsafe {
1638            assert!(smbc_getFunctionGetdents(context).is_some());
1639        });
1640    }
1641
1642    #[test]
1643    #[serial]
1644    fn binds_smbc_get_function_telldir() {
1645        with_context(|context| unsafe {
1646            assert!(smbc_getFunctionTelldir(context).is_some());
1647        });
1648    }
1649
1650    #[test]
1651    #[serial]
1652    fn binds_smbc_get_function_lseekdir() {
1653        with_context(|context| unsafe {
1654            assert!(smbc_getFunctionLseekdir(context).is_some());
1655        });
1656    }
1657
1658    #[test]
1659    #[serial]
1660    fn binds_smbc_get_function_fstatdir() {
1661        with_context(|context| unsafe {
1662            assert!(smbc_getFunctionFstatdir(context).is_some());
1663        });
1664    }
1665
1666    #[test]
1667    #[serial]
1668    fn binds_smbc_get_function_notify() {
1669        with_context(|context| unsafe {
1670            assert!(smbc_getFunctionNotify(context).is_some());
1671        });
1672    }
1673
1674    #[cfg(feature = "abi-0-6")]
1675    #[test]
1676    #[serial]
1677    fn binds_smbc_get_function_readdir_plus_2() {
1678        with_context(|context| unsafe {
1679            assert!(smbc_getFunctionReaddirPlus2(context).is_some());
1680        });
1681    }
1682
1683    #[test]
1684    #[serial]
1685    fn binds_smbc_get_function_utimes() {
1686        with_context(|context| unsafe {
1687            assert!(smbc_getFunctionUtimes(context).is_some());
1688        });
1689    }
1690
1691    #[test]
1692    #[serial]
1693    fn binds_smbc_get_function_setxattr() {
1694        with_context(|context| unsafe {
1695            assert!(smbc_getFunctionSetxattr(context).is_some());
1696        });
1697    }
1698
1699    #[test]
1700    #[serial]
1701    fn binds_smbc_get_function_getxattr() {
1702        with_context(|context| unsafe {
1703            assert!(smbc_getFunctionGetxattr(context).is_some());
1704        });
1705    }
1706
1707    #[test]
1708    #[serial]
1709    fn binds_smbc_get_function_removexattr() {
1710        with_context(|context| unsafe {
1711            assert!(smbc_getFunctionRemovexattr(context).is_some());
1712        });
1713    }
1714
1715    #[test]
1716    #[serial]
1717    fn binds_smbc_get_function_listxattr() {
1718        with_context(|context| unsafe {
1719            assert!(smbc_getFunctionListxattr(context).is_some());
1720        });
1721    }
1722
1723    #[test]
1724    #[serial]
1725    fn binds_smbc_get_function_open_print_job() {
1726        with_context(|context| unsafe {
1727            assert!(smbc_getFunctionOpenPrintJob(context).is_some());
1728        });
1729    }
1730
1731    #[test]
1732    #[serial]
1733    fn binds_smbc_get_function_list_print_jobs() {
1734        with_context(|context| unsafe {
1735            assert!(smbc_getFunctionListPrintJobs(context).is_some());
1736        });
1737    }
1738
1739    #[test]
1740    #[serial]
1741    fn binds_smbc_get_function_unlink_print_job() {
1742        with_context(|context| unsafe {
1743            assert!(smbc_getFunctionUnlinkPrintJob(context).is_some());
1744        });
1745    }
1746
1747    #[cfg(feature = "abi-0-8")]
1748    #[test]
1749    #[serial]
1750    fn gets_posix_extensions_option() {
1751        with_context(|context| unsafe {
1752            let value = smbc_getOptionPosixExtensions(context);
1753            assert!(value == 0 || value == 1);
1754        });
1755    }
1756
1757    #[cfg(feature = "abi-0-8")]
1758    #[test]
1759    #[serial]
1760    fn sets_posix_extensions_option() {
1761        with_context(|context| unsafe {
1762            smbc_setOptionPosixExtensions(context, 1);
1763            assert_eq!(smbc_getOptionPosixExtensions(context), 1);
1764        });
1765    }
1766}