use crate::fs::traverse::lfs_fs_traverse_;
use crate::types::{lfs_block_t, lfs_size_t, lfs_ssize_t};
pub fn lfs_stat_(
lfs: *mut super::lfs::Lfs,
path: *const u8,
info: *mut crate::lfs_info::LfsInfo,
) -> i32 {
use crate::dir::fetch::lfs_dir_getinfo;
use crate::dir::find::lfs_dir_find;
use crate::lfs_type::lfs_type::LFS_TYPE_DIR;
use crate::tag::{lfs_tag_id, lfs_tag_type3};
if lfs.is_null() || path.is_null() || info.is_null() {
return crate::error::LFS_ERR_INVAL;
}
unsafe {
let mut cwd = core::mem::zeroed::<crate::dir::LfsMdir>();
let mut path_ptr = path;
let tag = lfs_dir_find(lfs, &mut cwd, &mut path_ptr, core::ptr::null_mut());
if tag < 0 {
return tag;
}
let mut p = path_ptr;
#[cfg(feature = "loop_limits")]
const MAX_STAT_PATH_ITER: u32 = 1024;
#[cfg(feature = "loop_limits")]
let mut iter: u32 = 0;
while *p != 0 {
#[cfg(feature = "loop_limits")]
{
if iter >= MAX_STAT_PATH_ITER {
panic!(
"loop_limits: MAX_STAT_PATH_ITER ({}) exceeded",
MAX_STAT_PATH_ITER
);
}
iter += 1;
}
if *p == b'/' {
if u32::from(lfs_tag_type3(tag as u32)) != LFS_TYPE_DIR {
return crate::error::LFS_ERR_NOTDIR;
}
break;
}
p = p.add(1);
}
lfs_dir_getinfo(lfs, &cwd, lfs_tag_id(tag as u32), info)
}
}
pub fn lfs_fs_stat_(lfs: *mut super::lfs::Lfs, fsinfo: *mut crate::lfs_info::LfsFsinfo) -> i32 {
use crate::dir::fetch::lfs_dir_fetch;
use crate::dir::traverse::lfs_dir_get;
use crate::lfs_gstate::lfs_gstate_needssuperblock;
use crate::lfs_superblock::{lfs_superblock_fromle32, LfsSuperblock};
use crate::lfs_type::lfs_type::LFS_TYPE_INLINESTRUCT;
use crate::tag::lfs_mktag;
use crate::types::LFS_DISK_VERSION;
unsafe {
let lfs_ref = &*lfs;
let fsinfo = &mut *fsinfo;
if !lfs_gstate_needssuperblock(&lfs_ref.gstate) {
fsinfo.disk_version = LFS_DISK_VERSION;
} else {
let mut dir = crate::dir::LfsMdir {
pair: [0, 0],
rev: 0,
off: 0,
etag: 0,
count: 0,
erased: false,
split: false,
tail: [0, 0],
};
let err = lfs_dir_fetch(lfs, &mut dir, &lfs_ref.root);
if err != 0 {
return crate::lfs_pass_err!(err);
}
let mut superblock = core::mem::zeroed::<LfsSuperblock>();
let tag = lfs_dir_get(
lfs,
&dir as *const _,
lfs_mktag(0x7ff, 0x3ff, 0),
lfs_mktag(
LFS_TYPE_INLINESTRUCT,
0,
core::mem::size_of::<LfsSuperblock>() as u32,
),
&mut superblock as *mut _ as *mut core::ffi::c_void,
);
if tag < 0 {
return tag;
}
lfs_superblock_fromle32(&mut superblock);
fsinfo.disk_version = superblock.version;
}
fsinfo.block_size = (*lfs_ref.cfg).block_size;
fsinfo.block_count = lfs_ref.block_count;
fsinfo.name_max = lfs_ref.name_max;
fsinfo.file_max = lfs_ref.file_max;
fsinfo.attr_max = lfs_ref.attr_max;
}
0
}
pub unsafe extern "C" fn lfs_fs_size_count(p: *mut core::ffi::c_void, _block: lfs_block_t) -> i32 {
if p.is_null() {
return 0;
}
let size = p as *mut lfs_size_t;
unsafe { *size = (*size).saturating_add(1) };
0
}
pub fn lfs_fs_size_(lfs: *mut super::lfs::Lfs) -> lfs_ssize_t {
let mut size: lfs_size_t = 0;
let err = lfs_fs_traverse_(
lfs,
Some(lfs_fs_size_count),
&mut size as *mut _ as *mut core::ffi::c_void,
false,
);
if err != 0 {
return crate::lfs_pass_err!(err);
}
size as lfs_ssize_t
}