]>
Commit | Line | Data |
---|---|---|
6522a427 | 1 | use fastrand; |
e1599b0c | 2 | use std::ffi::{OsStr, OsString}; |
83c7162d | 3 | use std::path::{Path, PathBuf}; |
6522a427 | 4 | use std::{io, iter::repeat_with}; |
83c7162d | 5 | |
e1599b0c | 6 | use crate::error::IoResultExt; |
0731742a | 7 | |
e1599b0c XL |
8 | fn tmpname(prefix: &OsStr, suffix: &OsStr, rand_len: usize) -> OsString { |
9 | let mut buf = OsString::with_capacity(prefix.len() + suffix.len() + rand_len); | |
10 | buf.push(prefix); | |
6522a427 EL |
11 | let mut char_buf = [0u8; 4]; |
12 | for c in repeat_with(fastrand::alphanumeric).take(rand_len) { | |
13 | buf.push(c.encode_utf8(&mut char_buf)); | |
83c7162d | 14 | } |
e1599b0c XL |
15 | buf.push(suffix); |
16 | buf | |
83c7162d XL |
17 | } |
18 | ||
19 | pub fn create_helper<F, R>( | |
20 | base: &Path, | |
e1599b0c XL |
21 | prefix: &OsStr, |
22 | suffix: &OsStr, | |
83c7162d XL |
23 | random_len: usize, |
24 | f: F, | |
25 | ) -> io::Result<R> | |
26 | where | |
27 | F: Fn(PathBuf) -> io::Result<R>, | |
28 | { | |
cdc7bbd5 XL |
29 | let num_retries = if random_len != 0 { |
30 | crate::NUM_RETRIES | |
31 | } else { | |
32 | 1 | |
33 | }; | |
0731742a XL |
34 | |
35 | for _ in 0..num_retries { | |
83c7162d XL |
36 | let path = base.join(tmpname(prefix, suffix, random_len)); |
37 | return match f(path) { | |
38 | Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => continue, | |
39 | res => res, | |
40 | }; | |
41 | } | |
42 | ||
43 | Err(io::Error::new( | |
e1599b0c XL |
44 | io::ErrorKind::AlreadyExists, |
45 | "too many temporary files exist", | |
46 | )) | |
47 | .with_err_path(|| base) | |
83c7162d | 48 | } |