Skip to content

Commit

Permalink
mktemp: combine --tmpdir and subdirectory info
Browse files Browse the repository at this point in the history
Combine the directory given in `--tmpdir` with any subdirectory
structure appearing in the prefix of the template string. For example,

    $ mktemp --tmpdir=a b/cXXX
    a/b/cNqJ

Previously, this would have incorrectly exited with an error message.
  • Loading branch information
jfinkels committed May 27, 2022
1 parent 1d18eab commit 806d259
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 13 deletions.
21 changes: 20 additions & 1 deletion src/uu/mktemp/src/mktemp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,26 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
(template, tmp)
}
} else {
(template, PathBuf::from(tmpdir))
// In this case, the command was `mktemp --tmpdir=foo XXX`, so
// we need to parse out the parent directory and the filename
// from the argument `XXX`, since it may be include path
// separators.

// The template cannot be an absolute path. For example, `mktemp
// --tmpdir=a /XXX` is not allowed.
if path.is_absolute() {
return Err(MkTempError::InvalidTemplate(template.into()).into());
}

// `mktemp --tmpdir=a b/cXXX` becomes `a`, `b`, and `cXXX`.
// Then the `tmpdir` is `a/b` and `template` is `cXXX`.
let subdirectory = path.parent().unwrap_or_else(|| Path::new(""));
let tmpdir = PathBuf::from(tmpdir).join(subdirectory);
let template = match path.file_name() {
None => template,
Some(s) => s.to_str().unwrap(),
};
(template, tmpdir)
};

let make_dir = matches.is_present(OPT_DIRECTORY);
Expand Down
39 changes: 27 additions & 12 deletions tests/by-util/test_mktemp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ const TMPDIR: &str = "TMPDIR";
#[cfg(windows)]
const TMPDIR: &str = "TMP";

/// An assertion that uses [`matches_template`] and adds a helpful error message.
macro_rules! assert_matches_template {
($template:expr, $s:expr) => {{
assert!(
matches_template($template, $s),
"\"{}\" != \"{}\"",
$template,
$s
);
}};
}

#[test]
fn test_mktemp_mktemp() {
let scene = TestScenario::new(util_name!());
Expand Down Expand Up @@ -417,6 +429,21 @@ fn test_mktemp_directory_tmpdir() {
assert!(PathBuf::from(result.stdout_str().trim()).is_dir());
}

/// Test for combining `--tmpdir` and a template with a subdirectory.
#[test]
fn test_tmpdir_template_has_subdirectory() {
let (at, mut ucmd) = at_and_ucmd!();
at.mkdir("a");
#[cfg(not(windows))]
let (template, joined) = ("a/bXXXX", "./a/bXXXX");
#[cfg(windows)]
let (template, joined) = (r"a\bXXXX", r".\a\bXXXX");
let result = ucmd.args(&["--tmpdir=.", template]).succeeds();
let filename = result.no_stderr().stdout_str().trim_end();
assert_matches_template!(joined, filename);
assert!(at.file_exists(filename));
}

/// Test that an absolute path is disallowed when --tmpdir is provided.
#[test]
fn test_tmpdir_absolute_path() {
Expand Down Expand Up @@ -466,18 +493,6 @@ fn matches_template(template: &str, s: &str) -> bool {
true
}

/// An assertion that uses [`matches_template`] and adds a helpful error message.
macro_rules! assert_matches_template {
($template:expr, $s:expr) => {{
assert!(
matches_template($template, $s),
"\"{}\" != \"{}\"",
$template,
$s
);
}};
}

/// Test that the file is created in the directory given by the template.
#[test]
fn test_respect_template() {
Expand Down

0 comments on commit 806d259

Please sign in to comment.