Skip to content

Commit 1222f52

Browse files
committed
Auto merge of #428 - philippkeller:mkstemp, r=fiveop
Add Mkstemp (fixed for rust 1.2) I fixed @antifuchs addition of `mkstmp` in #365 by making it compile in Rust 1.2 and adding documentation. A few remarks: - made it working with Rust 1.2 which needed `to_bytes_with_nul()`. I think the implementation is memory safe but would like to have a pair of eyes checking that - replaced Path by PathBuf so it's more in line with getcwd - I didn't move it into another module. If this still the consensus then I would like to do that but in a separate PR (probably moving all stdio methods out) - it's true that unistd doesn't need mkstmp since there is the crate tempdir and tempfile, but I'd love to see this here for completeness
2 parents 1b4656f + b47120d commit 1222f52

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

src/unistd.rs

+36-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use fcntl::FcntlArg::F_SETFD;
66
use libc::{self, c_char, c_void, c_int, c_uint, size_t, pid_t, off_t, uid_t, gid_t, mode_t};
77
use std::mem;
88
use std::ffi::{CString, CStr, OsString};
9-
use std::os::unix::ffi::OsStringExt;
10-
use std::path::PathBuf;
9+
use std::os::unix::ffi::{OsStringExt};
1110
use std::os::unix::io::RawFd;
11+
use std::path::{PathBuf};
1212
use void::Void;
1313
use sys::stat::Mode;
1414

@@ -532,6 +532,40 @@ pub fn sleep(seconds: libc::c_uint) -> c_uint {
532532
unsafe { libc::sleep(seconds) }
533533
}
534534

535+
/// Creates a regular file which persists even after process termination
536+
///
537+
/// * `template`: a path whose 6 rightmost characters must be X, e.g. /tmp/tmpfile_XXXXXX
538+
/// * returns: tuple of file descriptor and filename
539+
///
540+
/// Err is returned either if no temporary filename could be created or the template doesn't
541+
/// end with XXXXXX
542+
///
543+
/// # Example
544+
///
545+
/// ```rust
546+
/// use nix::unistd;
547+
///
548+
/// let fd = match unistd::mkstemp("/tmp/tempfile_XXXXXX") {
549+
/// Ok((fd, path)) => {
550+
/// unistd::unlink(path.as_path()).unwrap(); // flag file to be deleted at app termination
551+
/// fd
552+
/// }
553+
/// Err(e) => panic!("mkstemp failed: {}", e)
554+
/// };
555+
/// // do something with fd
556+
/// ```
557+
#[inline]
558+
pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
559+
let mut path = try!(template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()}));
560+
let p = path.as_mut_ptr() as *mut _;
561+
let fd = unsafe { libc::mkstemp(p) };
562+
let last = path.pop(); // drop the trailing nul
563+
debug_assert!(last == Some(b'\0'));
564+
let pathname = OsString::from_vec(path);
565+
try!(Errno::result(fd));
566+
Ok((fd, PathBuf::from(pathname)))
567+
}
568+
535569
#[cfg(any(target_os = "linux", target_os = "android"))]
536570
mod linux {
537571
use sys::syscall::{syscall, SYSPIVOTROOT};

test/test_unistd.rs

+19
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,25 @@ fn test_wait() {
5555
}
5656
}
5757

58+
#[test]
59+
fn test_mkstemp() {
60+
let result = mkstemp("/tmp/nix_tempfile.XXXXXX");
61+
match result {
62+
Ok((fd, path)) => {
63+
close(fd).unwrap();
64+
unlink(path.as_path()).unwrap();
65+
},
66+
Err(e) => panic!("mkstemp failed: {}", e)
67+
}
68+
69+
let result = mkstemp("/tmp/");
70+
match result {
71+
Ok(_) => {
72+
panic!("mkstemp succeeded even though it should fail (provided a directory)");
73+
},
74+
Err(_) => {}
75+
}
76+
}
5877

5978
#[test]
6079
fn test_getpid() {

0 commit comments

Comments
 (0)