1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 03:57:44 +00:00

mktemp: make temp dir

This commit is contained in:
Knight 2016-06-18 17:41:47 +08:00
parent d52869ef26
commit c6897da7f0
2 changed files with 67 additions and 7 deletions

View file

@ -26,6 +26,8 @@ use std::iter;
use rand::Rng;
use tempfile::NamedTempFileOptions;
mod tempdir;
static NAME: &'static str = "mktemp";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
static DEFAULT_TEMPLATE: &'static str = "tmp.XXXXXXXXXX";
@ -173,7 +175,18 @@ pub fn dry_exec(mut tmpdir: PathBuf, prefix: &str, rand: usize, suffix: &str) ->
fn exec(tmpdir: PathBuf, prefix: &str, rand: usize, suffix: &str, make_dir: bool) -> i32 {
// TODO: respect make_dir option
if make_dir {
crash!(1, "Directory option is not supported yet. Sorry.");
match tempdir::new_in(&tmpdir, prefix, rand, suffix) {
Ok(ref f) => {
println!("{}", f);
return 0;
}
Err(e) => {
if !quiet {
show_info!("{}", e);
}
return 1;
}
}
}
let tmpfile = NamedTempFileOptions::new()
@ -184,13 +197,17 @@ fn exec(tmpdir: PathBuf, prefix: &str, rand: usize, suffix: &str, make_dir: bool
let tmpfile = match tmpfile {
Ok(f) => f,
Err(_) => crash!(1, "failed to create tempfile")
Err(e) => {
if !quiet {
show_info!("failed to create tempfile: {}", e);
}
return 1;
}
};
let tmpname = tmpfile
.path()
.to_string_lossy()
.to_string();
let tmpname = tmpfile.path()
.to_string_lossy()
.to_string();
println!("{}", tmpname);

43
src/mktemp/tempdir.rs Normal file
View file

@ -0,0 +1,43 @@
// Mainly taken from crate `tempdir`
extern crate rand;
use rand::{Rng, thread_rng};
use std::io::Result as IOResult;
use std::io::{Error, ErrorKind};
use std::path::Path;
// How many times should we (re)try finding an unused random name? It should be
// enough that an attacker will run out of luck before we run out of patience.
const NUM_RETRIES: u32 = 1 << 31;
#[cfg(unix)]
fn create_dir<P: AsRef<Path>>(path: P) -> IOResult<()> {
use std::fs::DirBuilder;
use std::os::unix::fs::DirBuilderExt;
DirBuilder::new().mode(0o700).create(path)
}
#[cfg(windows)]
fn create_dir<P: AsRef<Path>>(path: P) -> IOResult<()> {
::std::fs::create_dir(path)
}
pub fn new_in<P: AsRef<Path>>(tmpdir: P, prefix: &str, rand: usize, suffix: &str) -> IOResult<String> {
let mut rng = thread_rng();
for _ in 0..NUM_RETRIES {
let rand_chars: String = rng.gen_ascii_chars().take(rand).collect();
let leaf = format!("{}{}{}", prefix, rand_chars, suffix);
let path = tmpdir.as_ref().join(&leaf);
match create_dir(&path) {
Ok(_) => return Ok(path.to_string_lossy().into_owned()),
Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {}
Err(e) => return Err(e),
}
}
Err(Error::new(ErrorKind::AlreadyExists,
"too many temporary directories already exist"))
}