Skip to content

Add xdg_basedir API#157518

Open
CAD97 wants to merge 1 commit into
rust-lang:mainfrom
CAD97:xdg_basedir
Open

Add xdg_basedir API#157518
CAD97 wants to merge 1 commit into
rust-lang:mainfrom
CAD97:xdg_basedir

Conversation

@CAD97
Copy link
Copy Markdown
Contributor

@CAD97 CAD97 commented Jun 6, 2026

Implements an API providing easy access to the XDG Base Directories.

XdgDirsIter isn't as performant as it could be due to needing to shift things forward, but this was the simplest thing I could come up with that wasn't just entirely reimplementing split_paths with owned input.

I chose to defer runtime_dir (XDG_RUNTIME_DIR) since the lack of a specified default (but specified expectation for applications to determine an alternative option somehow) makes the correct usage (and thus ideal API) less obvious.

@rustbot rustbot added O-unix Operating system: Unix-like S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jun 6, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Jun 6, 2026

r? @aapoalas

rustbot has assigned @aapoalas.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @ChrisDenton, libs
  • @ChrisDenton, libs expanded to 11 candidates
  • Random selection from LawnGnome, Mark-Simulacrum, aapoalas, clarfonthey, jhpratt

@CAD97 CAD97 mentioned this pull request Jun 6, 2026
5 tasks
@CAD97
Copy link
Copy Markdown
Contributor Author

CAD97 commented Jun 6, 2026

cc @BurntSushi (+1 on ACP)

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@Kobzol
Copy link
Copy Markdown
Member

Kobzol commented Jun 6, 2026

Might be interesting to @rami3l.

@rami3l
Copy link
Copy Markdown
Member

rami3l commented Jun 6, 2026

@Kobzol Thanks for the ping!

Our current plan with @Cloud0310 regarding rust-lang/rustup#247 is slightly more complicated than this because it involves handling both old and new home definitions shared by rustup and cargo. That said, having std APIs for the XDG paths will definitely make this easier.

Copy link
Copy Markdown
Contributor

@aapoalas aapoalas left a comment

Choose a reason for hiding this comment

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

Looks good to me - I had a bunch of comments here and there but nothing that I'd consider blocking.

Let me know your thoughts on the comments and one we've handled them one way or another (made changes or decided to ignore) then we can put this on the train.

View changes since this review

@@ -0,0 +1,166 @@
//! XDG (X Desktop Group) related functionality for Unix platforms.
//!
//! The [XDG Base Directory Specification][basedir] defines where user-specific
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion: I'd reorder this:

Suggested change
//! The [XDG Base Directory Specification][basedir] defines where user-specific
//! The [XDG Base Directory Specification][basedir] defines a set of base directories, relative to which user-specific files should be looked for.

//!
//! Directories returned by this module are not guaranteed to exist yet. If the
//! directory does not exist, an application should attempt to create it with
//! [permissions mode][super::fs::PermissionsExt::from_mode] `0o700`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thought: Not the responsibility of this module at all, but this smells like the start of a TOCTOU bug story.

use crate::path::{Path, PathBuf};

fn xdg_home_dir() -> PathBuf {
// Note: home_dir can return `Some("")` in some cases. We assume that in
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion: Maybe mention the getpwuid_r function by name for the "in some cases" - I assume that's the main / only case referred to here?

}
}

fn xdg_dir(env: &str, fallback_home_subdir: impl AsRef<Path>) -> PathBuf {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nitpick: Only ever called with fallback_home_subdir: &'static str - could just monomorphise this in code to save that little bit of compile time.

/// An application `appid` would typically be expected to write its state data to
/// `{state_home_dir}/{appid}/**/*`.
///
/// Common kinds of state data include actions history (such as logs, history,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

praise: Big fan of explaining the purpose a little <3

xdg_dir("XDG_STATE_HOME", ".local/state")
}

/// A base directory relative to which user-specific non-essential caches should be written.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nitpick: Why the rewording from the XDG specification's "non-essential (cached) data" to "non-essential caches"?

pub struct XdgDirsIter(Option<OsString>);

impl XdgDirsIter {
fn new(env: &str, default: impl AsRef<OsStr>) -> Self {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nitpick: Here too the default is always &'static str - could just monomorphise manually.


fn next(&mut self) -> Option<Self::Item> {
let dirs = self.0.take()?;
let next = split_paths(&dirs).next()?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thought: So we're effectively reproducing a split_paths iterator by using split_paths itself combined with manual byte shifting.

This... definitely isn't that great. It's a little sad that we perform PathBuf copies "ahead of time" per item but that kind of goes with not having lending iterators. Draining the OsString one set of bytes at a time though... that's really sad indeed.

I don't think it's necessarily something that should block this PR, but this really could maybe use a little more thinking / polish. Like, maybe we should store the current position in the XdgDirsIter and slice &dirs before calling split_paths to avoid the draining? We'd need an unsafe for the slicing, but its safety condition is exactly the same one we have in the loop right now, and we wouldn't need any other unsafe beyond that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

O-unix Operating system: Unix-like S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants