#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
use std::os::raw::{c_char, c_int, c_void};
pub const UUID_SIZE: usize = 16;
pub const F_SET_EXT2: c_int = 2;
pub const F_SET_EXT3: c_int = 3;
pub const F_SET_EXT4: c_int = 4;
#[repr(C)]
pub struct ext4_bcache {
_opaque: [u8; 0],
}
#[repr(C)]
pub struct ext4_fs {
_opaque: [u8; 0],
}
#[repr(C)]
pub struct ext4_blockdev_iface {
pub open: Option<unsafe extern "C" fn(bdev: *mut ext4_blockdev) -> c_int>,
pub bread: Option<
unsafe extern "C" fn(
bdev: *mut ext4_blockdev,
buf: *mut c_void,
blk_id: u64,
blk_cnt: u32,
) -> c_int,
>,
pub bwrite: Option<
unsafe extern "C" fn(
bdev: *mut ext4_blockdev,
buf: *const c_void,
blk_id: u64,
blk_cnt: u32,
) -> c_int,
>,
pub close: Option<unsafe extern "C" fn(bdev: *mut ext4_blockdev) -> c_int>,
pub lock: Option<unsafe extern "C" fn(bdev: *mut ext4_blockdev) -> c_int>,
pub unlock: Option<unsafe extern "C" fn(bdev: *mut ext4_blockdev) -> c_int>,
pub ph_bsize: u32,
pub ph_bcnt: u64,
pub ph_bbuf: *mut u8,
pub ph_refctr: u32,
pub bread_ctr: u32,
pub bwrite_ctr: u32,
pub p_user: *mut c_void,
}
#[repr(C)]
pub struct ext4_blockdev {
pub bdif: *mut ext4_blockdev_iface,
pub part_offset: u64,
pub part_size: u64,
pub bc: *mut ext4_bcache,
pub lg_bsize: u32,
pub lg_bcnt: u64,
pub cache_write_back: u32,
pub fs: *mut ext4_fs,
pub journal: *mut c_void,
}
#[repr(C)]
pub struct ext4_mkfs_info {
pub len: u64,
pub block_size: u32,
pub blocks_per_group: u32,
pub inodes_per_group: u32,
pub inode_size: u32,
pub inodes: u32,
pub journal_blocks: u32,
pub feat_ro_compat: u32,
pub feat_compat: u32,
pub feat_incompat: u32,
pub bg_desc_reserve_blocks: u32,
pub dsc_size: u16,
pub uuid: [u8; UUID_SIZE],
pub journal: bool,
pub label: *const c_char,
}
extern "C" {
pub fn ext4_block_init(bdev: *mut ext4_blockdev) -> c_int;
pub fn ext4_block_fini(bdev: *mut ext4_blockdev) -> c_int;
pub fn ext4_block_bind_bcache(bdev: *mut ext4_blockdev, bc: *mut ext4_bcache) -> c_int;
pub fn ext4_bcache_init_dynamic(bc: *mut ext4_bcache, cnt: u32, itemsize: u32) -> c_int;
pub fn ext4_bcache_fini_dynamic(bc: *mut ext4_bcache) -> c_int;
pub fn ext4_mkfs_read_info(bdev: *mut ext4_blockdev, info: *mut ext4_mkfs_info) -> c_int;
pub fn ext4_mkfs(
fs: *mut ext4_fs,
bd: *mut ext4_blockdev,
info: *mut ext4_mkfs_info,
fs_type: c_int,
) -> c_int;
}
impl Default for ext4_blockdev_iface {
fn default() -> Self {
Self {
open: None,
bread: None,
bwrite: None,
close: None,
lock: None,
unlock: None,
ph_bsize: 0,
ph_bcnt: 0,
ph_bbuf: std::ptr::null_mut(),
ph_refctr: 0,
bread_ctr: 0,
bwrite_ctr: 0,
p_user: std::ptr::null_mut(),
}
}
}
impl Default for ext4_blockdev {
fn default() -> Self {
Self {
bdif: std::ptr::null_mut(),
part_offset: 0,
part_size: 0,
bc: std::ptr::null_mut(),
lg_bsize: 0,
lg_bcnt: 0,
cache_write_back: 0,
fs: std::ptr::null_mut(),
journal: std::ptr::null_mut(),
}
}
}
impl Default for ext4_mkfs_info {
fn default() -> Self {
Self {
len: 0,
block_size: 4096,
blocks_per_group: 0,
inodes_per_group: 0,
inode_size: 256,
inodes: 0,
journal_blocks: 0,
feat_ro_compat: 0,
feat_compat: 0,
feat_incompat: 0,
bg_desc_reserve_blocks: 0,
dsc_size: 0,
uuid: [0u8; UUID_SIZE],
journal: false,
label: std::ptr::null(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_struct_default_construction() {
let _iface = ext4_blockdev_iface::default();
let _bdev = ext4_blockdev::default();
let _info = ext4_mkfs_info::default();
}
#[test]
fn test_constants() {
assert_eq!(UUID_SIZE, 16);
assert_eq!(F_SET_EXT2, 2);
assert_eq!(F_SET_EXT3, 3);
assert_eq!(F_SET_EXT4, 4);
}
#[test]
fn test_blockdev_iface_default_values() {
let iface = ext4_blockdev_iface::default();
assert!(iface.open.is_none());
assert!(iface.bread.is_none());
assert!(iface.bwrite.is_none());
assert!(iface.close.is_none());
assert!(iface.lock.is_none());
assert!(iface.unlock.is_none());
assert_eq!(iface.ph_bsize, 0);
assert_eq!(iface.ph_bcnt, 0);
assert!(iface.ph_bbuf.is_null());
assert_eq!(iface.ph_refctr, 0);
assert_eq!(iface.bread_ctr, 0);
assert_eq!(iface.bwrite_ctr, 0);
assert!(iface.p_user.is_null());
}
#[test]
fn test_blockdev_default_values() {
let bdev = ext4_blockdev::default();
assert!(bdev.bdif.is_null());
assert_eq!(bdev.part_offset, 0);
assert_eq!(bdev.part_size, 0);
assert!(bdev.bc.is_null());
assert_eq!(bdev.lg_bsize, 0);
assert_eq!(bdev.lg_bcnt, 0);
assert_eq!(bdev.cache_write_back, 0);
assert!(bdev.fs.is_null());
assert!(bdev.journal.is_null());
}
#[test]
fn test_mkfs_info_default_values() {
let info = ext4_mkfs_info::default();
assert_eq!(info.len, 0);
assert_eq!(info.block_size, 4096);
assert_eq!(info.blocks_per_group, 0);
assert_eq!(info.inodes_per_group, 0);
assert_eq!(info.inode_size, 256);
assert_eq!(info.inodes, 0);
assert_eq!(info.journal_blocks, 0);
assert_eq!(info.feat_ro_compat, 0);
assert_eq!(info.feat_compat, 0);
assert_eq!(info.feat_incompat, 0);
assert_eq!(info.bg_desc_reserve_blocks, 0);
assert_eq!(info.dsc_size, 0);
assert_eq!(info.uuid, [0u8; UUID_SIZE]);
assert!(!info.journal);
assert!(info.label.is_null());
}
#[test]
fn test_blockdev_iface_custom_values() {
let mut buffer = vec![0u8; 512];
let mut iface = ext4_blockdev_iface::default();
iface.ph_bsize = 512;
iface.ph_bcnt = 1024;
iface.ph_bbuf = buffer.as_mut_ptr();
assert_eq!(iface.ph_bsize, 512);
assert_eq!(iface.ph_bcnt, 1024);
assert!(!iface.ph_bbuf.is_null());
}
#[test]
fn test_mkfs_info_custom_values() {
let mut info = ext4_mkfs_info::default();
info.len = 10 * 1024 * 1024; info.block_size = 1024;
info.inode_size = 128;
info.uuid = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
info.journal = true;
assert_eq!(info.len, 10 * 1024 * 1024);
assert_eq!(info.block_size, 1024);
assert_eq!(info.inode_size, 128);
assert_eq!(info.uuid[0], 1);
assert_eq!(info.uuid[15], 16);
assert!(info.journal);
}
}