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

uefi/fs: add path and pathbuf abstraction #771

Merged
merged 2 commits into from
May 6, 2023

Conversation

phip1611
Copy link
Contributor

@phip1611 phip1611 commented Apr 25, 2023

I finally had time to work on the promised (#472 / #747 ) path and pathbuf abstraction for the uefi::fs module.

Once this is merged and the other stuff in the tracking issue is solved, I think it would be a good time for a new release :)

Status

  • path and pathbuf abstraction that works as good as possible with CStr16 and CString16 and are close to the API of std::path
  • fix the open todo in code (just a small thingy)
  • use the new abstractions in the FileSystem abstraction
  • update the changelog

API Design

For simplicity, there are no . or .. components in a path allowed. However, if someone ever needs this, this can be part of a future MR. However, I don't see why one would ever want this. There is no present working directory in a UEFI environment..

Open Questions

Users will not be able to pass in str and String.. but they can do something like: fs::write(cstr16!("foo\\bar")) and I think this is sufficient and convenient enough. Do you agree?

Some other Remarks

The Cartesian product of all convenient trait implementations ({AsRef, Borrow, From} x {Path, PathBuf, CStr16, CString16, str, String}) is quite challenging. I decided that there is only a good interoperability between {Path, PathBuf} x {CStr16, CString16} and {str, String} x {CStr16, CString16}.

Checklist

  • Sensible git history (for example, squash "typo" or "fix" commits). See the Rewriting History guide for help.
  • Update the changelog (if necessary)

@phip1611
Copy link
Contributor Author

The whole fs module was much more work than I expected 😀 However, feel free to have a look and leave some remarks, @nicholasbishop.

@phip1611 phip1611 self-assigned this Apr 25, 2023
@phip1611 phip1611 force-pushed the fs branch 4 times, most recently from 005af84 to 82e4499 Compare May 2, 2023 20:14
@phip1611 phip1611 marked this pull request as ready for review May 2, 2023 20:22
@phip1611 phip1611 requested a review from nicholasbishop May 2, 2023 20:22
@@ -423,6 +423,12 @@ impl<StrType: AsRef<str> + ?Sized> EqStrUntilNul<StrType> for CStr16 {
}
}

impl AsRef<CStr16> for CStr16 {
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 thought that there is a default implementation for that by the core lib. Apparently, there is not.

Copy link
Member

@nicholasbishop nicholasbishop left a comment

Choose a reason for hiding this comment

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

Users will not be able to pass in str and String.. but they can do something like: fs::write(cstr16!("foo\bar")) and I think this is sufficient and convenient enough. Do you agree?

Yep I think that's fine

uefi/src/fs/path/mod.rs Outdated Show resolved Hide resolved
uefi/src/fs/path/mod.rs Show resolved Hide resolved
uefi/src/fs/path/pathbuf.rs Outdated Show resolved Hide resolved
/// Stringified version of [`SEPARATOR`].
pub const SEPARATOR_STR: &str = "\\";
/// [`SEPARATOR_STR`] but as useful UEFI type.
pub const SEPARATOR_CSTR16: &CStr16 = uefi_macros::cstr16!("\\");
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if the SEPARATOR_STR and SEPARATOR_CSTR16 constants are needed. (Commented elsewhere about converting a use of SEPARATOR_CSTR16 -> SEPARATOR_C16). I know std has https://doc.rust-lang.org/std/path/constant.MAIN_SEPARATOR_STR.html, but I can't think of why one would use that instead of the char one.

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 also do not have a strong opinion here. Probably we can drop them, yes

uefi/src/fs/path/pathbuf.rs Outdated Show resolved Hide resolved
uefi/src/fs/path/pathbuf.rs Outdated Show resolved Hide resolved
);
assert_eq!(
Path::new(cstr16!("\\a\\b")).parent(),
Some(PathBuf::from(cstr16!("a"))),
Copy link
Member

Choose a reason for hiding this comment

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

Is there a bug here? I would have expected \\a instead of just a.

Copy link
Contributor Author

@phip1611 phip1611 May 4, 2023

Choose a reason for hiding this comment

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

This is intended and is documented on the Components struct. I do not specifically handle the root component as a dedicated path component, as all paths are absolute, always (as reflected by the module documentation). We do not have a present working directory here. Because of this simplification, Components doesn't need to be an enum but can be a struct.

Hence, "\a\b" and "a\b" are both absolute paths starting at root, in my abstraction.

Copy link
Member

@nicholasbishop nicholasbishop May 4, 2023

Choose a reason for hiding this comment

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

Ah when reading the docs I missed this implication. The docs emphasize that in UEFI there's no CWD and no support for ./.., but to me that doesn't indicate relative paths aren't useful. For example:

fn get_boot_path(sub_path: &Path) -> PathBuf {
    let boot_path = Path::new(cstr16!(r"\efi\boot"));
    boot_path.join(sub_path);
}

get_boot_path(Path::new(cstr16!(r"somesubdir\somefile")));

There's no direct use of ./.. here, but relative paths are still needed. As you say in the PR description, this could be added later, which I think is fine. I do wonder though, if \a is the same as a, shouldn't Path have a custom eq impl so that the comparison reflects that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, yeah, I see. Currently, there is no .join() method on a Path/PathBuf.

A Custom PartialEq-impl sounds reasonable

uefi/src/fs/file_system.rs Show resolved Hide resolved
phip1611 added 2 commits May 6, 2023 09:08
Now, only remove_dir_all is missing. The reason for this is not technical.
Someone just needs to put a little more effort into it.
@phip1611
Copy link
Contributor Author

phip1611 commented May 6, 2023

Are we good to go now?

@phip1611 phip1611 mentioned this pull request May 6, 2023
2 tasks
Copy link
Member

@nicholasbishop nicholasbishop left a comment

Choose a reason for hiding this comment

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

Lgtm!

@nicholasbishop nicholasbishop merged commit 0044c73 into rust-osdev:main May 6, 2023
@phip1611 phip1611 deleted the fs branch May 6, 2023 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants