mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
mktemp: make temp dir
This commit is contained in:
parent
d52869ef26
commit
c6897da7f0
2 changed files with 67 additions and 7 deletions
|
@ -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
43
src/mktemp/tempdir.rs
Normal 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"))
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue