use super::*;
pub fn stat_impl_default<F: VectorBackend + ?Sized>(
backend: &mut F,
path: &Path,
) -> VfResult<VfAttrs> {
let mut a = VfAttrs {
file: FileOperand::from_os_path(path),
masks: AttrMask::stat(),
..VfAttrs::default()
};
backend.vgetattrs_impl(std::slice::from_mut(&mut a))?;
Ok(a)
}
pub fn lstat_impl_default<F: VectorBackend + ?Sized>(
backend: &mut F,
path: &Path,
) -> VfResult<VfAttrs> {
let mut a = VfAttrs {
file: FileOperand::from_os_path(path),
masks: AttrMask::stat(),
..VfAttrs::default()
};
backend.vgetattrs_nofollow_impl(std::slice::from_mut(&mut a))?;
Ok(a)
}
pub fn fstat_impl_default<F: VectorBackend + ?Sized>(
backend: &mut F,
tcf: &FileOperand,
) -> VfResult<VfAttrs> {
let mut a = VfAttrs {
file: tcf.clone(),
masks: AttrMask::stat(),
..VfAttrs::default()
};
backend.vgetattrs_impl(std::slice::from_mut(&mut a))?;
Ok(a)
}
pub fn exists_impl_default<F: VectorBackend + ?Sized>(
backend: &mut F,
path: &Path,
) -> VfResult<bool> {
match backend.lstat_impl(path) {
Ok(_) => Ok(true),
Err(e) if e.raw_code() == ERR_NOENT => Ok(false),
Err(e) => Err(e),
}
}
pub fn file_type_impl_default<F: VectorBackend + ?Sized>(
backend: &mut F,
path: &Path,
) -> VfResult<VfType> {
Ok(backend.lstat_impl(path)?.ftype)
}
pub fn native_metadata_impl_default<F: VectorBackend + ?Sized>(
backend: &mut F,
target: Target<'_, FileOperand>,
options: vfsi_core::api::AttrsOptions,
) -> VfResult<VfAttrs> {
let file = match target {
Target::Path(path) => FileOperand::from_os_path(path),
Target::File(file) => file.clone(),
};
let path = match target {
Target::Path(path) => Some(path),
Target::File(file) => file.path(),
};
let mut attrs = VfAttrs {
file,
masks: options.fields(),
..VfAttrs::default()
};
let result = if options.follow_final_symlink() {
backend.vgetattrs_impl(std::slice::from_mut(&mut attrs))
} else {
backend.vgetattrs_nofollow_impl(std::slice::from_mut(&mut attrs))
};
result.map_err(|error| match path {
Some(path) => error.with_context("metadata", path),
None => error,
})?;
Ok(attrs)
}
pub fn native_metadata_path_impl_default<F: VectorBackend + ?Sized>(
backend: &mut F,
path: &std::path::Path,
follow: bool,
) -> VfResult<Attrs> {
native_metadata_impl_default(
backend,
Target::Path(path),
vfsi_core::api::AttrsOptions::new()
.with_fields(metadata_mask())
.with_follow_final_symlink(follow),
)
.map(vfsi_core::metadata_from_attrs)
}
pub fn native_set_metadata_path_impl_default<F: VectorBackend + ?Sized>(
backend: &mut F,
op: &SetAttrsOp<&std::path::Path>,
) -> VfResult<()> {
let path = *op.target();
backend
.set_attributes_impl(&op.with_target(Target::Path(path)))
.map_err(|error| error.with_context("set_metadata", path))
}
fn setattrs_to_legacy(op: &SetAttrsOp<Target<'_, FileOperand>>) -> VfResult<VfAttrs> {
let [accessed, modified] = vfsi_core::internal::validate_setattrs(op)?;
let mut attrs = VfAttrs {
file: match op.target() {
Target::Path(path) => FileOperand::from_os_path(path),
Target::File(file) => (*file).clone(),
},
..VfAttrs::default()
};
if let Some(permissions) = op.requested_permissions() {
attrs.masks |= AttrMask::MODE;
attrs.mode = permissions.mode();
}
if let Some(uid) = op.requested_uid() {
attrs.masks |= AttrMask::UID;
attrs.uid = uid;
}
if let Some(gid) = op.requested_gid() {
attrs.masks |= AttrMask::GID;
attrs.gid = gid;
}
if let Some(size) = op.requested_len() {
attrs.masks |= AttrMask::SIZE;
attrs.size = size;
}
if let Some(time) = accessed {
(attrs.atime_sec, attrs.atime_nsec) = time;
attrs.masks |= AttrMask::ATIME;
}
if let Some(time) = modified {
(attrs.mtime_sec, attrs.mtime_nsec) = time;
attrs.masks |= AttrMask::MTIME;
}
Ok(attrs)
}
pub fn vsetattrs_typed_default<F: VectorBackend + ?Sized>(
backend: &mut F,
updates: &[SetAttrsOp<Target<'_, FileOperand>>],
) -> VfResult<()> {
let attrs = updates
.iter()
.enumerate()
.map(|(index, op)| {
setattrs_to_legacy(op).map_err(|error| {
let error = error.with_index(index);
let path = match op.target() {
Target::Path(path) => Some(*path),
Target::File(file) => file.path(),
};
match path {
Some(path) => error.with_context("vsetattrs", path),
None => error,
}
})
})
.collect::<VfResult<Vec<_>>>()?;
let mut start = 0;
while start < updates.len() {
let follow = updates[start].follow_final_symlink();
let count = updates[start..]
.iter()
.take_while(|op| op.follow_final_symlink() == follow)
.count();
let result = if follow {
backend.vsetattrs_raw_impl(&attrs[start..start + count])
} else {
backend.vsetattrs_raw_nofollow_impl(&attrs[start..start + count])
};
result.map_err(|error| match error.index() {
Some(index) if index < count => error.with_index(start + index),
Some(_) => VfError::transport(None, "setattrs backend returned an invalid error index"),
None => error,
})?;
start += count;
}
Ok(())
}