You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
install: name the directory component that could not be created - #14772
create_dir_all_safe now returns the failing prefix along with its error, and the ancestor search walks up past files, symlink loops and unreadable directories instead of giving up with the whole path. A name that exists but can't be descended into reports EEXIST when it doesn't resolve and ENOTDIR when it resolves to a non-directory, which is what GNU prints. When the parent of the failing component can't be searched at all, that parent is named instead - the difference between r--/x, which GNU reports as r--, and r-x/x, which it reports as r-x/x. The message string gained a place for the errno.
install -d keeps creating directories path-based. I tried routing it through the same fd walk and it broke write-only directories: DirFd::open needs read permission, mkdir only needs write and execute, so install -d wx-dir/sub started failing where GNU succeeds. There's a regression test for that now. -D has had the same limitation since it moved to the fd walk, which is #14778; this PR does not change it.
Checked on Linux against GNU 9.12 built from source: -D messages match in 19 of 24 cases covering symlinks, dangling symlinks, plain files, symlink loops, unreadable, read-only and write-only parents, and doubled slashes. The five that differ also differ on main and are not changed here: trailing-slash targets (-D f regular/sub/, -D f dangling/sub/), an unreadable existing parent (-D f r--/f), and two -D -t cases covered by #14999. No GNU source was read.
Conflicts with #12715 in the two -d hunks. Whichever lands second resolves to with_umask(0, || create_dir_all_safe(&path_to_create, DEFAULT_MODE)) with show!(InstallError::CreateDirFailed(e.path, e.error)).
GNU test failed: tests/id/setgid. tests/id/setgid is passing on 'main'. Maybe you have to rebase?
Skipping an intermittent issue tests/date/resolution (passes in this run but fails in the 'main' branch)
The reason will be displayed to describe this comment to others. Learn more.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.
Report the failing path component for nested mkdir errors
src/uu/install/src/install.rs:517
install -d still passes the entire path_to_create as the error path, so a nested failure such as install -d dangling/sub (or regular/sub where regular is a file) will continue to report dangling/sub/regular/sub instead of the failing component. Keep the path-based mkdir behavior for write-only parents, but track the component that failed (or add a path-based helper that returns it) before constructing CreateDirFailed.
The reason will be displayed to describe this comment to others. Learn more.
It only decides which error gets printed. If the target is an existing non-directory, install stops with "Not a directory"; otherwise nothing is done with the result. If the path changes after the check, the directories are still created through create_dir_all_safe, which works through directory descriptors (mkdirat, openat with O_DIRECTORY) and refuses a file or dangling symlink at that name by itself. So a race can only change which message you get, to "cannot create directory". The check isn't new either: main already does the same exists()/is_dir() check on the -t target; this moves it after the trailing-slash trim.
The new blame branch is what implements the documented r--/x versus r-x/x distinction, but the added tests only cover a regular file, a dangling symlink, and the successful -d write-only case. Add an integration test for an unsearchable parent (and ideally the loop/read-only error cases described by the PR) so this error-path naming behavior cannot regress.
Remove GNU test path reference from PR description
tests/by-util/test_install.rs:2891
The PR description references the GNU test path tests/install/basic-1. Please remove that path reference and summarize the observed behavior instead; this repository must not include references to GNU source/test paths.
Rechecked against GNU 9.12 built from the release tarball (9.10 behaves the same): this branch matches GNU in 19 of 24 -D cases. The five that differ are trailing-slash targets (-D f regular/sub/, -D f dangling/sub/), an unreadable existing parent (-D f r--/f), and two -D -t cases that #14999 covers. None of them match on main either. I've corrected the description.
Correction: with the current #12715 this is one hunk in directory(), and with_umask must not be nested there, since install already runs under it. Keep #12715's DirBuilder with DEFAULT_MODE and take this PR's error: show!(InstallError::CreateDirFailed(failed_create_dir_prefix(&path_to_create), e)), keeping the #[cfg(unix)]/#[cfg(not(unix))] split for failed.
Nothing converts a CreateDirError into an io::Error, and doing so would
silently drop the path the type exists to carry. Also document why the
access(2) call in blame() is sound.
`install -d` creates its directories by path, so it still reported the
whole path when that failed, e.g. 'dangling/sub' where GNU names
'dangling'. Name the first component that is not an existing directory,
through the same blame logic create_dir_all_safe uses for -D.
The parent-versus-component choice in blame() had no test: cover a parent
that cannot be searched (named) against one that can (the component is
named), and a symlink loop in the leading directories, for -D and -d.
The reason will be displayed to describe this comment to others. Learn more.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
installnamed the whole leading-directory path instead of the component that failed, and with-Dgave no reason at all:create_dir_all_safenow returns the failing prefix along with its error, and the ancestor search walks up past files, symlink loops and unreadable directories instead of giving up with the whole path. A name that exists but can't be descended into reports EEXIST when it doesn't resolve and ENOTDIR when it resolves to a non-directory, which is what GNU prints. When the parent of the failing component can't be searched at all, that parent is named instead - the difference betweenr--/x, which GNU reports asr--, andr-x/x, which it reports asr-x/x. The message string gained a place for the errno.install -dkeeps creating directories path-based. I tried routing it through the same fd walk and it broke write-only directories:DirFd::openneeds read permission,mkdironly needs write and execute, soinstall -d wx-dir/substarted failing where GNU succeeds. There's a regression test for that now.-Dhas had the same limitation since it moved to the fd walk, which is #14778; this PR does not change it.Checked on Linux against GNU 9.12 built from source:
-Dmessages match in 19 of 24 cases covering symlinks, dangling symlinks, plain files, symlink loops, unreadable, read-only and write-only parents, and doubled slashes. The five that differ also differ on main and are not changed here: trailing-slash targets (-D f regular/sub/,-D f dangling/sub/), an unreadable existing parent (-D f r--/f), and two-D -tcases covered by #14999. No GNU source was read.Closes #14995