summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/unistd.rs38
-rw-r--r--test/test_unistd.rs19
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() {