Skip to content

Commit 71d7559

Browse files
committed
mkdir: do not change mode of directories that we have not created
1 parent b89a625 commit 71d7559

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

src/uu/mkdir/src/mkdir.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,10 @@ pub fn mkdir(path: &Path, recursive: bool, mode: u32, verbose: bool) -> UResult<
165165
let path_buf = dir_strip_dot_for_creation(path);
166166
let path = path_buf.as_path();
167167

168-
create_dir(path, recursive, verbose, false)?;
169-
chmod(path, mode)
168+
if create_dir(path, recursive, verbose, false)? {
169+
chmod(path, mode)?;
170+
}
171+
Ok(())
170172
}
171173

172174
#[cfg(any(unix, target_os = "redox"))]
@@ -186,22 +188,25 @@ fn chmod(_path: &Path, _mode: u32) -> UResult<()> {
186188
Ok(())
187189
}
188190

191+
// Return true if the directory at `path` has been created by this call.
189192
// `is_parent` argument is not used on windows
190193
#[allow(unused_variables)]
191-
fn create_dir(path: &Path, recursive: bool, verbose: bool, is_parent: bool) -> UResult<()> {
194+
fn create_dir(path: &Path, recursive: bool, verbose: bool, is_parent: bool) -> UResult<bool> {
192195
if path.exists() && !recursive {
193196
return Err(USimpleError::new(
194197
1,
195198
format!("{}: File exists", path.display()),
196199
));
197200
}
198201
if path == Path::new("") {
199-
return Ok(());
202+
return Ok(false);
200203
}
201204

202205
if recursive {
203206
match path.parent() {
204-
Some(p) => create_dir(p, recursive, verbose, true)?,
207+
Some(p) => {
208+
create_dir(p, recursive, verbose, true)?;
209+
}
205210
None => {
206211
USimpleError::new(1, "failed to create whole tree");
207212
}
@@ -222,9 +227,9 @@ fn create_dir(path: &Path, recursive: bool, verbose: bool, is_parent: bool) -> U
222227
// which is umask modified by 'u+wx'
223228
chmod(path, (!mode::get_umask() & 0o0777) | 0o0300)?;
224229
}
225-
Ok(())
230+
Ok(true)
226231
}
227-
Err(_) if path.is_dir() => Ok(()),
232+
Err(_) if path.is_dir() => Ok(false),
228233
Err(e) => Err(e.into()),
229234
}
230235
}

tests/by-util/test_mkdir.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,27 @@ fn test_mkdir_parent_mode_check_existing_parent() {
129129
);
130130
}
131131

132+
#[cfg(not(windows))]
133+
#[test]
134+
fn test_mkdir_parent_mode_skip_existing_last_component_chmod() {
135+
let (at, mut ucmd) = at_and_ucmd!();
136+
137+
at.mkdir("a");
138+
at.mkdir("a/b");
139+
at.set_mode("a/b", 0);
140+
141+
let default_umask: mode_t = 0o160;
142+
143+
ucmd.arg("-p")
144+
.arg("a/b")
145+
.umask(default_umask)
146+
.succeeds()
147+
.no_stderr()
148+
.no_stdout();
149+
150+
assert_eq!(at.metadata("a/b").permissions().mode() as mode_t, 0o40000);
151+
}
152+
132153
#[test]
133154
fn test_mkdir_dup_file() {
134155
let scene = TestScenario::new(util_name!());

0 commit comments

Comments
 (0)