#![cfg(unix)]
use std::{
env::temp_dir,
ffi::{CString, OsString},
io,
os::unix::prelude::{OsStrExt, OsStringExt},
path::{Path, PathBuf},
};
pub fn mkdtemp(template: CString) -> Result<CString, (io::Error, CString)> {
let template_raw = template.into_raw();
unsafe {
let result = libc::mkdtemp(template_raw);
let template = CString::from_raw(template_raw);
if result.is_null() {
Err((io::Error::last_os_error(), template))
} else {
Ok(template)
}
}
}
pub fn mkdtemp_in_temp_dir<P: AsRef<Path>>(prefix: P) -> io::Result<PathBuf> {
let mut template = temp_dir();
template.push(prefix);
let mut template = template.into_os_string();
template.push("XXXXXX");
let template = CString::new(template.as_bytes())?;
mkdtemp(template)
.map_err(|(io_error, _)| io_error)
.map(|modified_template| OsString::from_vec(modified_template.into()).into())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mkdtemp_fail_if_template_doesnt_end_with_x() {
let template = CString::new("/tmp/foo").unwrap();
let (io_error, template) = mkdtemp(template).unwrap_err();
assert_eq!(template, CString::new("/tmp/foo").unwrap());
assert_eq!(io_error.kind(), io::ErrorKind::InvalidInput)
}
#[test]
fn mkdtemp_in_temp_dir_fail_if_path_contains_a_nul_byte() {
assert!(mkdtemp_in_temp_dir("foo\0bar").is_err())
}
}