pub trait OnDiskFileDescriptor: FileDescriptor
{
#[inline(always)]
fn underlying_file_system_metadata(&self) -> io::Result<FileSystemMetadata>
{
let mut statvfs: statvfs = unsafe_uninitialized();
let result = unsafe { fstatvfs(self.as_raw_fd(), &mut statvfs) };
if likely!(result == 0)
{
Ok(FileSystemMetadata(statvfs))
}
else if likely!(result == -1)
{
Err(io::Error::last_os_error())
}
else
{
unreachable_code(format_args!("Unexpected result {} from fstatvfs()", result))
}
}
#[doc(hidden)]
const FSLABEL_MAX: usize = 256;
#[inline(always)]
fn get_file_system_label(&self) -> io::Result<CString>
{
const FS_IOC_GETFSLABEL: i32 = 2164298801u32 as i32;
let mut buffer = Vec::with_capacity(Self::FSLABEL_MAX);
let result = unsafe { ioctl(self.as_raw_fd(), FS_IOC_GETFSLABEL, buffer.as_mut_ptr()) };
if likely!(result == 0)
{
Ok(CString::from_fixed_length_buffer_ascii_nul_terminated(buffer))
}
else if likely!(result == -1)
{
Err(io::Error::last_os_error())
}
else
{
unreachable_code(format_args!("Unexpected result {} from ioctl()", result))
}
}
#[inline(always)]
fn set_file_system_label(&self, label: &CStr) -> io::Result<()>
{
const FS_IOC_SETFSLABEL: i32 = 1090556978;
let result = unsafe { ioctl(self.as_raw_fd(), FS_IOC_SETFSLABEL, label.as_ptr()) };
if likely!(result == 0)
{
Ok(())
}
else if likely!(result == -1)
{
Err(io::Error::last_os_error())
}
else
{
unreachable_code(format_args!("Unexpected result {} from ioctl()", result))
}
}
#[inline(always)]
fn get_inode_generation_number(&self) -> io::Result<InodeGenerationNumber>
{
let mut inode_generation_number = unsafe_uninitialized();
let result = unsafe { ioctl (self.as_raw_fd(), FS_IOC_GETVERSION, &mut inode_generation_number) };
if likely!(result == 0)
{
Ok(InodeGenerationNumber::from_i32(inode_generation_number))
}
else if likely!(result == -1)
{
Err(io::Error::last_os_error())
}
else
{
unreachable_code(format_args!("ioctl() returned unexpected result {}", result))
}
}
#[inline(always)]
fn set_inode_generation_number(&self, inode_generation_number: InodeGenerationNumber) -> io::Result<()>
{
let inode_generation_number: i32 = inode_generation_number.into();
let result = unsafe { ioctl (self.as_raw_fd(), FS_IOC_SETVERSION, &inode_generation_number) };
if likely!(result == 0)
{
Ok(())
}
else if likely!(result == -1)
{
Err(io::Error::last_os_error())
}
else
{
unreachable_code(format_args!("ioctl() returned unexpected result {}", result))
}
}
#[inline(always)]
fn get_inode_flags(&self) -> io::Result<InodeFlags>
{
let mut attributes = unsafe_uninitialized();
let result = unsafe { ioctl (self.as_raw_fd(), FS_IOC_GETFLAGS, &mut attributes) };
if likely!(result == 0)
{
Ok(InodeFlags::from_bits(attributes).unwrap())
}
else if likely!(result == -1)
{
Err(io::Error::last_os_error())
}
else
{
unreachable_code(format_args!("ioctl() returned unexpected result {}", result))
}
}
#[inline(always)]
fn set_inode_flags(&self, inode_flags: InodeFlags) -> io::Result<()>
{
let attributes = inode_flags.bits();
let result = unsafe { ioctl (self.as_raw_fd(), FS_IOC_SETFLAGS, &attributes) };
if likely!(result == 0)
{
Ok(())
}
else if likely!(result == -1)
{
Err(io::Error::last_os_error())
}
else
{
unreachable_code(format_args!("ioctl() returned unexpected result {}", result))
}
}
#[inline(always)]
fn get_extended_attribute(&self, extended_attribute_name: ExtendedAttributeName) -> io::Result<Option<Vec<u8>>>
{
let SixtyFourKb = 64 * 1024;
let mut value = Vec::with_capacity(SixtyFourKb);
let result = unsafe { fgetxattr(self.as_raw_fd(), extended_attribute_name.as_ptr(), value.as_mut_ptr() as *mut c_void, SixtyFourKb) };
if likely!(result >= 0)
{
unsafe { value.set_len(result as usize) };
value.shrink_to_fit();
Ok(Some(value))
}
else if likely!(result == 0)
{
match errno().0
{
ENODATA => Ok(None),
_ => Err(io::Error::last_os_error()),
}
}
else
{
unreachable_code(format_args!("fgetxattr() returned unexpected result {}", result))
}
}
#[inline(always)]
fn set_extended_attribute(&self, extended_attribute_name: ExtendedAttributeName, value: &[u8]) -> io::Result<()>
{
self.set_extended_attribute_internal(extended_attribute_name, value, 0).map(|_| ())
}
#[inline(always)]
fn create_extended_attribute(&self, extended_attribute_name: ExtendedAttributeName, value: &[u8]) -> io::Result<bool>
{
self.set_extended_attribute_internal(extended_attribute_name, value, XATTR_CREATE)
}
#[inline(always)]
fn replace_extended_attribute(&self, extended_attribute_name: ExtendedAttributeName, value: &[u8]) -> io::Result<bool>
{
self.set_extended_attribute_internal(extended_attribute_name, value, XATTR_REPLACE)
}
#[doc(hidden)]
#[inline(always)]
fn set_extended_attribute_internal(&self, extended_attribute_name: ExtendedAttributeName, value: &[u8], flags: i32) -> io::Result<bool>
{
let result = unsafe { fsetxattr(self.as_raw_fd(), extended_attribute_name.as_ptr(), value.as_ptr() as *const c_void, value.len(), flags) };
if likely!(result == 0)
{
Ok(true)
}
else if likely!(result == -1)
{
match errno().0
{
ENODATA if flags == XATTR_REPLACE =>
{
Ok(false)
},
EEXIST if flags == XATTR_CREATE =>
{
Ok(false)
},
_ => Err(io::Error::last_os_error()),
}
}
else
{
unreachable_code(format_args!("fremovexattr() returned unexpected result {}", result))
}
}
#[inline(always)]
fn remove_extended_attribute(&self, extended_attribute_name: ExtendedAttributeName) -> io::Result<bool>
{
let result = unsafe { fremovexattr(self.as_raw_fd(), extended_attribute_name.as_ptr()) };
if likely!(result == 0)
{
Ok(true)
}
else if likely!(result == -1)
{
match errno().0
{
ENODATA => Ok(false),
_ => Err(io::Error::last_os_error()),
}
}
else
{
unreachable_code(format_args!("fremovexattr() returned unexpected result {}", result))
}
}
#[inline(always)]
fn list_extended_attributes(&self) -> io::Result<ExtendedAttributeNames>
{
const SixtyFourKb: usize = 64 * 1024;
let mut buffer = Vec::with_capacity(SixtyFourKb);
let result = unsafe { flistxattr(self.as_raw_fd(), buffer.as_mut_ptr() as *mut c_char, SixtyFourKb) };
if likely!(result >= 0)
{
unsafe { buffer.set_len(result as usize) };
buffer.shrink_to_fit();
Ok(ExtendedAttributeNames::new(buffer))
}
else if likely!(result == -1)
{
Err(io::Error::last_os_error())
}
else
{
unreachable_code(format_args!("flistxattr() returned unexpected result {}", result))
}
}
}