use crate::{Error, Result, error};
use std::mem::MaybeUninit;
use std::ffi::CStr;
use std::path::Path;
use pathstr::PathStr;
use mackrow::*;
#[cfg(feature = "magic")]
pub(crate) fn mime<P>(path: P) -> Result<String>
where P: AsRef<Path>
{
use crate::err;
use magic::{Cookie, cookie::Flags};
let cookie = Cookie::open(Flags::MIME_TYPE).map_err(|e| err!(e))?;
let db = Default::default();
let cookie = cookie.load(&db).map_err(|e| err!(e))?;
Ok(cookie.file(path.as_ref()).map_err(|e| err!(e))?)
}
#[cfg(feature = "magic")]
pub(crate) fn encoding<P>(path: P) -> Result<String>
where P: AsRef<Path>
{
use crate::err;
use magic::{Cookie, cookie::Flags};
let cookie = Cookie::open(Flags::MIME_ENCODING).map_err(|e| err!(e))?;
let db = Default::default();
let cookie = cookie.load(&db).map_err(|e| err!(e))?;
Ok(cookie.file(path.as_ref()).map_err(|e| err!(e))?)
}
pub(crate) fn readlink<P>(path: P) -> Result<PathStr>
where P: AsRef<Path>
{
let path = PathStr::from(path.as_ref());
let cpath = path.cstring()?;
let sz: usize;
let sc = unsafe { libc::pathconf(cpath.as_ptr(), libc::_PC_PATH_MAX) };
sz = tern!(sc <= 0 ? 4096 : sc as usize);
let mut buffer = Vec::with_capacity(sz);
let rc = unsafe { libc::readlink(cpath.as_ptr(), buffer.as_mut_ptr(), buffer.capacity()) };
if rc == -1
{
error!("readlink: {}", errno::errno())
}
let cs = unsafe { CStr::from_ptr(buffer.as_ptr()) };
let mut r = match cs.to_str()
{
Ok(s) => s.to_string(),
_ => cs.to_string_lossy().into_owned()
};
r.truncate(rc as usize);
Ok(PathStr::from(r))
}
pub(crate) fn realpath<P>(path: P) -> Result<PathStr>
where P: AsRef<Path>
{
let path = PathStr::from(path.as_ref());
let cpath = path.cstring()?;
let sz: usize;
let sc = unsafe { libc::pathconf(cpath.as_ptr(), libc::_PC_PATH_MAX) };
sz = tern!(sc <= 0 ? 4096 : sc as usize);
let mut buffer = Vec::with_capacity(sz);
let res = unsafe { libc::realpath(cpath.as_ptr(), buffer.as_mut_ptr()) };
if res.is_null()
{
error!("realpath: {}", errno::errno())
}
let cs = unsafe { CStr::from_ptr(buffer.as_ptr()) };
Ok(PathStr::from(match cs.to_str()
{
Ok(s) => s.to_string(),
_ => cs.to_string_lossy().into_owned()
}))
}
pub(crate) fn groupname_from_id(id: libc::gid_t) -> Result<String>
{
let sz: usize;
let sc = unsafe { libc::sysconf(libc::_SC_GETGR_R_SIZE_MAX) };
sz = tern!(sc <= 0 ? 2048 : sc as usize);
let mut gr = MaybeUninit::<libc::group>::uninit();
let mut buffer = Vec::with_capacity(sz);
let mut np = std::ptr::null_mut();
let rc = unsafe
{
libc::getgrgid_r(id, gr.as_mut_ptr(), buffer.as_mut_ptr(), buffer.capacity(), &mut np)
};
if rc != 0
{
return Err(Error::io(std::io::Error::last_os_error()))
}
if np.is_null()
{
error!("groupname_from_id: np returned null")
}
let gr = unsafe { gr.assume_init() };
unsafe
{
let cs = CStr::from_ptr(gr.gr_name);
if let Ok(s) = cs.to_str()
{
Ok(s.to_string())
}
else
{
Ok(cs.to_string_lossy().into_owned())
}
}
}
pub(crate) fn username_from_id(id: libc::uid_t) -> Result<String>
{
let sz: usize;
let sc = unsafe { libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) };
sz = tern!(sc <= 0 ? 2048 : sc as usize);
let mut pw = MaybeUninit::<libc::passwd>::uninit();
let mut buffer = Vec::with_capacity(sz);
let mut np = std::ptr::null_mut();
let rc = unsafe
{
libc::getpwuid_r(id, pw.as_mut_ptr(), buffer.as_mut_ptr(), buffer.capacity(), &mut np)
};
if rc != 0
{
return Err(Error::io(std::io::Error::last_os_error()))
}
if np.is_null()
{
error!("username_from_id: np returned null")
}
let pw = unsafe { pw.assume_init() };
unsafe
{
let cs = CStr::from_ptr(pw.pw_name);
if let Ok(s) = cs.to_str()
{
Ok(s.to_string())
}
else
{
Ok(cs.to_string_lossy().into_owned())
}
}
}