diff options
-rw-r--r-- | src/unistd.rs | 38 | ||||
-rw-r--r-- | test/test_unistd.rs | 19 |
2 files changed, 55 insertions, 2 deletions
diff --git a/src/unistd.rs b/src/unistd.rs index 1b2175ea..2c4a92c3 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -6,9 +6,9 @@ use fcntl::FcntlArg::F_SETFD; use libc::{self, c_char, c_void, c_int, c_uint, size_t, pid_t, off_t, uid_t, gid_t, mode_t}; use std::mem; use std::ffi::{CString, CStr, OsString}; -use std::os::unix::ffi::OsStringExt; -use std::path::PathBuf; +use std::os::unix::ffi::{OsStringExt}; use std::os::unix::io::RawFd; +use std::path::{PathBuf}; use void::Void; use sys::stat::Mode; @@ -532,6 +532,40 @@ pub fn sleep(seconds: libc::c_uint) -> c_uint { unsafe { libc::sleep(seconds) } } +/// Creates a regular file which persists even after process termination +/// +/// * `template`: a path whose 6 rightmost characters must be X, e.g. /tmp/tmpfile_XXXXXX +/// * returns: tuple of file descriptor and filename +/// +/// Err is returned either if no temporary filename could be created or the template doesn't +/// end with XXXXXX +/// +/// # Example +/// +/// ```rust +/// use nix::unistd; +/// +/// let fd = match unistd::mkstemp("/tmp/tempfile_XXXXXX") { +/// Ok((fd, path)) => { +/// unistd::unlink(path.as_path()).unwrap(); // flag file to be deleted at app termination +/// fd +/// } +/// Err(e) => panic!("mkstemp failed: {}", e) +/// }; +/// // do something with fd +/// ``` +#[inline] +pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> { + let mut path = try!(template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()})); + let p = path.as_mut_ptr() as *mut _; + let fd = unsafe { libc::mkstemp(p) }; + let last = path.pop(); // drop the trailing nul + debug_assert!(last == Some(b'\0')); + let pathname = OsString::from_vec(path); + try!(Errno::result(fd)); + Ok((fd, PathBuf::from(pathname))) +} + #[cfg(any(target_os = "linux", target_os = "android"))] mod linux { use sys::syscall::{syscall, SYSPIVOTROOT}; diff --git a/test/test_unistd.rs b/test/test_unistd.rs index f7bbe0bf..856693f6 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -55,6 +55,25 @@ fn test_wait() { } } +#[test] +fn test_mkstemp() { + let result = mkstemp("/tmp/nix_tempfile.XXXXXX"); + match result { + Ok((fd, path)) => { + close(fd).unwrap(); + unlink(path.as_path()).unwrap(); + }, + Err(e) => panic!("mkstemp failed: {}", e) + } + + let result = mkstemp("/tmp/"); + match result { + Ok(_) => { + panic!("mkstemp succeeded even though it should fail (provided a directory)"); + }, + Err(_) => {} + } +} #[test] fn test_getpid() { |