Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unistd/dir: fix resolve_path behavior on trailing slashes #346

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jmaksymowicz
Copy link
Contributor

@jmaksymowicz jmaksymowicz commented Feb 16, 2024

Description

Currently, any part of the system that uses the resolve_path function (including stat, lstat, realpath and many others) don't consider the trailing slashes at the end of the path. For directories this is correct behavior, but if the last component of a path is not a directory, then the function should return with error and set errno to ENOTDIR.

The change currently breaks CI, as one of the tests for psh checks that trailing slashes for files are ignored.

Motivation and Context

Closes phoenix-rtos/phoenix-rtos-project#682 and brings API more in line with Open Group specification

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

This change may break existing software (including psh scripts) if it depends on the current trailing slash behavior. This may be difficult to detect if a path is generated automatically.

How Has This Been Tested?

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing linter checks and tests passed.
  • My changes generate no new compilation warnings for any of the targets.

Special treatment

  • This PR needs additional PRs to work (list the PRs, preferably in merge-order).
  • I will merge this PR by myself when appropriate.

Copy link

github-actions bot commented Feb 16, 2024

Unit Test Results

7 155 tests  ±0   6 440 ✅  - 8   38m 7s ⏱️ + 3m 57s
  397 suites ±0     707 💤 ±0 
    1 files   ±0       8 ❌ +8 

For more details on these failures, see this check.

Results for commit a3a6f07. ± Comparison against base commit 8e7daf8.

♻️ This comment has been updated with latest results.

unistd/dir.c Outdated
@@ -229,6 +231,12 @@ static int _resolve_abspath(char *path, char *result, int resolve_last_symlink,
}
}

if ((is_leaf != 0) && (resolve_last_symlink == 0)) {
/* TODO: in this case it's more efficient to check if file exists
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • a little bit misleading comment, you probably meant "instead of"? (as _readlink_abs would fail fast if lookup fails; still we do need getMode to check if it's a dir or not?) IMHO not worth a comment as the proposed solution is invalid (it's not a hot path, let's not dwell on it)
  • not sure if the issue is solved completely, what would happen in case of /symlink/to/file/ (when resolve_last_symlink == 0, eg. lstat). Is this handled correctly by callers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Checking if path exists and is a directory before call to _readlink_abs may be slightly more efficient in the case when (is_leaf != 0) && (resolve_last_symlink == 0) and the symlink exists. With this code the symlink's contents will be read even though it's not necessary. It's probably not a big performance concern.
  2. You're right, when doing lstat on /path/to/symlink/, if symlink exists and is a symlink then the call will succeed despite the trailing slash. I think in this case we need to check if (ends_with_slash != 0) and exit with errno == -ENOTDIR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Checking if path exists and is a directory before call to _readlink_abs may be slightly more efficient in the case when (is_leaf != 0) && (resolve_last_symlink == 0) and the symlink exists. With this code the symlink's contents will be read even though it's not necessary. It's probably not a big performance concern.

still, this should be instead of, not before as in the mentioned case you don't want to call _readlink_abs at all (if we really want to improve performance). I think it's not worth the additional code complexity (not a hot path), so IMHO TODO should be removed

Regarding (2) -> maybe add a test for this particular "corner case" to avoid regressions in the future (this code is hard enough to understand with all special cases ;))

unistd/dir.c Outdated
return SET_ERRNO(-EINVAL);
if (!S_ISLNK(msg.o.attr.val)) {
SET_ERRNO(-EINVAL);
return S_ISDIR(msg.o.attr.val) ? -EISDIR : -1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugly API (returning side info as an error). It's our internal function, maybe add explicit output param (it would increase the readability of the caller code)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a good idea, I'll change the API a bit to do this more elegantly.

unistd/dir.c Show resolved Hide resolved
@nalajcie
Copy link
Member

Please also copy the problem description from PR to the commit message body (or write something similar there to leave a trail)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants