Skip to content
This repository has been archived by the owner on Feb 18, 2025. It is now read-only.

Commit

Permalink
Move implementations to shared dirs-sys crate
Browse files Browse the repository at this point in the history
  • Loading branch information
soc committed May 13, 2019
1 parent 7c53ecd commit dc83292
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 198 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Cargo.lock
/target
**/*.rs.bk
.idea
10 changes: 1 addition & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,4 @@ keywords = ["xdg", "basedir", "app_dirs", "path", "folder"]

[dependencies]
cfg-if = "0.1"

[target.'cfg(unix)'.dependencies]
libc = "0.2"

[target.'cfg(target_os = "redox")'.dependencies]
redox_users = "0.3.0"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["knownfolders", "objbase", "shlobj", "winbase", "winerror"] }
dirs-sys = ""
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,9 @@ The following commands will build this library on Linux, macOS and Windows:

```
cargo build --target=x86_64-unknown-linux-gnu
cargo build --target=x86_64-apple-darwin
cargo build --target=x86_64-pc-windows-gnu
cargo build --target=x86_64-apple-darwin
cargo build --target=x86_64-unknown-redox
```

## License
Expand Down
8 changes: 1 addition & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! - a tiny library with a minimal API (16 functions)
//! - that provides the platform-specific, user-accessible locations
//! - for finding and storing configuration, cache and other data
//! - on Linux, Windows (≥ Vista) and macOS.
//! - on Linux, Redox, Windows (≥ Vista) and macOS.
//!
//! The library provides the location of these directories by leveraging the mechanisms defined by
//!
Expand All @@ -18,19 +18,13 @@ extern crate cfg_if;

use std::path::PathBuf;

#[cfg(unix)]
mod unix;

cfg_if! {
if #[cfg(target_os = "windows")] {
mod win;
use win as sys;
} else if #[cfg(target_os = "macos")] {
mod mac;
use mac as sys;
} else if #[cfg(target_os = "redox")] {
mod redox;
use redox as sys;
} else if #[cfg(target_os = "wasi")] {
mod wasi;
use wasi as sys;
Expand Down
56 changes: 16 additions & 40 deletions src/lin.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,28 @@
extern crate dirs_sys;

use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use std::process::Command;

use unix;

pub fn home_dir() -> Option<PathBuf> { unix::home_dir() }
pub fn cache_dir() -> Option<PathBuf> { env::var_os("XDG_CACHE_HOME") .and_then(is_absolute_path).or_else(|| home_dir().map(|h| h.join(".cache"))) }
pub fn config_dir() -> Option<PathBuf> { env::var_os("XDG_CONFIG_HOME").and_then(is_absolute_path).or_else(|| home_dir().map(|h| h.join(".config"))) }
pub fn data_dir() -> Option<PathBuf> { env::var_os("XDG_DATA_HOME") .and_then(is_absolute_path).or_else(|| home_dir().map(|h| h.join(".local/share"))) }
pub fn home_dir() -> Option<PathBuf> { dirs_sys::home_dir() }
pub fn cache_dir() -> Option<PathBuf> { env::var_os("XDG_CACHE_HOME") .and_then(dirs_sys::is_absolute_path).or_else(|| home_dir().map(|h| h.join(".cache"))) }
pub fn config_dir() -> Option<PathBuf> { env::var_os("XDG_CONFIG_HOME").and_then(dirs_sys::is_absolute_path).or_else(|| home_dir().map(|h| h.join(".config"))) }
pub fn data_dir() -> Option<PathBuf> { env::var_os("XDG_DATA_HOME") .and_then(dirs_sys::is_absolute_path).or_else(|| home_dir().map(|h| h.join(".local/share"))) }
pub fn data_local_dir() -> Option<PathBuf> { data_dir().clone() }
pub fn runtime_dir() -> Option<PathBuf> { env::var_os("XDG_RUNTIME_DIR").and_then(is_absolute_path) }
pub fn runtime_dir() -> Option<PathBuf> { env::var_os("XDG_RUNTIME_DIR").and_then(dirs_sys::is_absolute_path) }
pub fn executable_dir() -> Option<PathBuf> {
env::var_os("XDG_BIN_HOME").and_then(is_absolute_path).or_else(|| {
env::var_os("XDG_BIN_HOME").and_then(dirs_sys::is_absolute_path).or_else(|| {
data_dir().map(|mut e| { e.pop(); e.push("bin"); e })
})
}
pub fn audio_dir() -> Option<PathBuf> { run_xdg_user_dir_command("MUSIC") }
pub fn desktop_dir() -> Option<PathBuf> { run_xdg_user_dir_command("DESKTOP") }
pub fn document_dir() -> Option<PathBuf> { run_xdg_user_dir_command("DOCUMENTS") }
pub fn download_dir() -> Option<PathBuf> { run_xdg_user_dir_command("DOWNLOAD") }
pub fn audio_dir() -> Option<PathBuf> { dirs_sys::user_dir("MUSIC") }
pub fn desktop_dir() -> Option<PathBuf> { dirs_sys::user_dir("DESKTOP") }
pub fn document_dir() -> Option<PathBuf> { dirs_sys::user_dir("DOCUMENTS") }
pub fn download_dir() -> Option<PathBuf> { dirs_sys::user_dir("DOWNLOAD") }
pub fn font_dir() -> Option<PathBuf> { data_dir().map(|d| d.join("fonts")) }
pub fn picture_dir() -> Option<PathBuf> { run_xdg_user_dir_command("PICTURES") }
pub fn public_dir() -> Option<PathBuf> { run_xdg_user_dir_command("PUBLICSHARE") }
pub fn template_dir() -> Option<PathBuf> { run_xdg_user_dir_command("TEMPLATES") }
pub fn video_dir() -> Option<PathBuf> { run_xdg_user_dir_command("VIDEOS") }

// we don't need to explicitly handle empty strings in the code above,
// because an empty string is not considered to be a absolute path here.
fn is_absolute_path(path: OsString) -> Option<PathBuf> {
let path = PathBuf::from(path);
if path.is_absolute() {
Some(path)
} else {
None
}
}

fn run_xdg_user_dir_command(arg: &str) -> Option<PathBuf> {
use std::os::unix::ffi::OsStringExt;
let mut out = match Command::new("xdg-user-dir").arg(arg).output() {
Ok(output) => output.stdout,
Err(_) => return None,
};
let out_len = out.len();
out.truncate(out_len - 1);
Some(PathBuf::from(OsString::from_vec(out)))
}
pub fn picture_dir() -> Option<PathBuf> { dirs_sys::user_dir("PICTURES") }
pub fn public_dir() -> Option<PathBuf> { dirs_sys::user_dir("PUBLICSHARE") }
pub fn template_dir() -> Option<PathBuf> { dirs_sys::user_dir("TEMPLATES") }
pub fn video_dir() -> Option<PathBuf> { dirs_sys::user_dir("VIDEOS") }

#[cfg(test)]
mod tests {
Expand Down
6 changes: 3 additions & 3 deletions src/mac.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::path::PathBuf;
extern crate dirs_sys;

use unix;
use std::path::PathBuf;

pub fn home_dir() -> Option<PathBuf> { unix::home_dir() }
pub fn home_dir() -> Option<PathBuf> { dirs_sys::home_dir() }
pub fn cache_dir() -> Option<PathBuf> { home_dir().map(|h| h.join("Library/Caches")) }
pub fn config_dir() -> Option<PathBuf> { home_dir().map(|h| h.join("Library/Preferences")) }
pub fn data_dir() -> Option<PathBuf> { home_dir().map(|h| h.join("Library/Application Support")) }
Expand Down
46 changes: 0 additions & 46 deletions src/redox.rs

This file was deleted.

52 changes: 0 additions & 52 deletions src/unix.rs

This file was deleted.

4 changes: 1 addition & 3 deletions src/wasi.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// TODO: flesh this out once actual WASI APIs for this are designed.
//
// For now here are just enough definitions to make things *compile*.
// Stub definitions to make things *compile*.

use std::path::PathBuf;

Expand Down
50 changes: 13 additions & 37 deletions src/win.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,20 @@
use std;
use std::path::PathBuf;
extern crate dirs_sys;

extern crate winapi;
use self::winapi::shared::winerror;
use self::winapi::um::knownfolders;
use self::winapi::um::combaseapi;
use self::winapi::um::shlobj;
use self::winapi::um::shtypes;
use self::winapi::um::winbase;
use self::winapi::um::winnt;
use std::path::PathBuf;

pub fn home_dir() -> Option<PathBuf> { known_folder(&knownfolders::FOLDERID_Profile) }
pub fn data_dir() -> Option<PathBuf> { known_folder(&knownfolders::FOLDERID_RoamingAppData) }
pub fn data_local_dir() -> Option<PathBuf> { known_folder(&knownfolders::FOLDERID_LocalAppData) }
pub fn home_dir() -> Option<PathBuf> { dirs_sys::known_folder_profile() }
pub fn data_dir() -> Option<PathBuf> { dirs_sys::known_folder_roaming_app_data() }
pub fn data_local_dir() -> Option<PathBuf> { dirs_sys::known_folder_local_app_data() }
pub fn cache_dir() -> Option<PathBuf> { data_local_dir() }
pub fn config_dir() -> Option<PathBuf> { data_dir() }
pub fn executable_dir() -> Option<PathBuf> { None }
pub fn runtime_dir() -> Option<PathBuf> { None }
pub fn audio_dir() -> Option<PathBuf> { known_folder(&knownfolders::FOLDERID_Music) }
pub fn desktop_dir() -> Option<PathBuf> { known_folder(&knownfolders::FOLDERID_Desktop) }
pub fn document_dir() -> Option<PathBuf> { known_folder(&knownfolders::FOLDERID_Documents) }
pub fn download_dir() -> Option<PathBuf> { known_folder(&knownfolders::FOLDERID_Downloads) }
pub fn audio_dir() -> Option<PathBuf> { dirs_sys::known_folder_music() }
pub fn desktop_dir() -> Option<PathBuf> { dirs_sys::known_folder_desktop() }
pub fn document_dir() -> Option<PathBuf> { dirs_sys::known_folder_documents() }
pub fn download_dir() -> Option<PathBuf> { dirs_sys::known_folder_downloads() }
pub fn font_dir() -> Option<PathBuf> { None }
pub fn picture_dir() -> Option<PathBuf> { known_folder(&knownfolders::FOLDERID_Pictures) }
pub fn public_dir() -> Option<PathBuf> { known_folder(&knownfolders::FOLDERID_Public) }
pub fn template_dir() -> Option<PathBuf> { known_folder(&knownfolders::FOLDERID_Templates) }
pub fn video_dir() -> Option<PathBuf> { known_folder(&knownfolders::FOLDERID_Videos) }

fn known_folder(folder_id: shtypes::REFKNOWNFOLDERID) -> Option<PathBuf> {
unsafe {
let mut path_ptr: winnt::PWSTR = std::ptr::null_mut();
let result = shlobj::SHGetKnownFolderPath(folder_id, 0, std::ptr::null_mut(), &mut path_ptr);
if result == winerror::S_OK {
let len = winbase::lstrlenW(path_ptr) as usize;
let path = std::slice::from_raw_parts(path_ptr, len);
let ostr: std::ffi::OsString = std::os::windows::ffi::OsStringExt::from_wide(path);
combaseapi::CoTaskMemFree(path_ptr as *mut winapi::ctypes::c_void);
Some(PathBuf::from(ostr))
} else {
None
}
}
}
pub fn picture_dir() -> Option<PathBuf> { dirs_sys::known_folder_pictures() }
pub fn public_dir() -> Option<PathBuf> { dirs_sys::known_folder_public()}
pub fn template_dir() -> Option<PathBuf> { dirs_sys::known_folder_templates() }
pub fn video_dir() -> Option<PathBuf> { dirs_sys::known_folder_videos() }

0 comments on commit dc83292

Please sign in to comment.