1 use std
::ffi
::OsString
;
2 use std
::path
::PathBuf
;
4 // we don't need to explicitly handle empty strings in the code above,
5 // because an empty string is not considered to be a absolute path here.
6 pub fn is_absolute_path(path
: OsString
) -> Option
<PathBuf
> {
7 let path
= PathBuf
::from(path
);
8 if path
.is_absolute() {
15 #[cfg(all(unix, not(target_os = "redox")))]
18 #[cfg(all(unix, not(target_os = "redox")))]
19 mod target_unix_not_redox
{
22 use std
::ffi
::{CStr, OsString}
;
24 use std
::os
::unix
::ffi
::OsStringExt
;
25 use std
::path
::PathBuf
;
30 // https://github.com/rust-lang/rust/blob/master/src/libstd/sys/unix/os.rs#L498
31 pub fn home_dir() -> Option
<PathBuf
> {
32 return env
::var_os("HOME")
33 .and_then(|h
| if h
.is_empty() { None }
else { Some(h) }
)
34 .or_else(|| unsafe { fallback() }
)
37 #[cfg(any(target_os = "android", target_os = "ios", target_os = "emscripten"))]
38 unsafe fn fallback() -> Option
<OsString
> {
41 #[cfg(not(any(target_os = "android", target_os = "ios", target_os = "emscripten")))]
42 unsafe fn fallback() -> Option
<OsString
> {
43 let amt
= match libc
::sysconf(libc
::_SC_GETPW_R_SIZE_MAX
) {
44 n
if n
< 0 => 512 as usize,
47 let mut buf
= Vec
::with_capacity(amt
);
48 let mut passwd
: libc
::passwd
= mem
::zeroed();
49 let mut result
= ptr
::null_mut();
50 match libc
::getpwuid_r(
57 0 if !result
.is_null() => {
58 let ptr
= passwd
.pw_dir
as *const _
;
59 let bytes
= CStr
::from_ptr(ptr
).to_bytes();
63 Some(OsStringExt
::from_vec(bytes
.to_vec()))
73 #[cfg(all(unix, not(target_os = "redox")))]
74 pub use self::target_unix_not_redox
::home_dir
;
76 #[cfg(target_os = "redox")]
77 extern crate redox_users
;
79 #[cfg(target_os = "redox")]
82 use std
::path
::PathBuf
;
84 use super::redox_users
::{All, AllUsers, Config}
;
86 pub fn home_dir() -> Option
<PathBuf
> {
87 let current_uid
= redox_users
::get_uid().ok()?
;
88 let users
= AllUsers
::basic(Config
::default()).ok()?
;
89 let user
= users
.get_by_id(current_uid
)?
;
91 Some(PathBuf
::from(user
.home
.clone()))
96 #[cfg(target_os = "redox")]
97 pub use self::target_redox
::home_dir
;
99 #[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
102 #[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
103 mod target_unix_not_mac
{
105 use std
::collections
::HashMap
;
107 use std
::path
::{Path, PathBuf}
;
109 use super::{home_dir, is_absolute_path}
;
110 use super::xdg_user_dirs
;
112 fn user_dir_file(home_dir
: &Path
) -> PathBuf
{
113 env
::var_os("XDG_CONFIG_HOME").and_then(is_absolute_path
).unwrap_or_else(|| home_dir
.join(".config")).join("user-dirs.dirs")
116 // this could be optimized further to not create a map and instead retrieve the requested path only
117 pub fn user_dir(user_dir_name
: &str) -> Option
<PathBuf
> {
118 if let Some(home_dir
) = home_dir() {
119 xdg_user_dirs
::single(&home_dir
, &user_dir_file(&home_dir
), user_dir_name
).remove(user_dir_name
)
125 pub fn user_dirs(home_dir_path
: &Path
) -> HashMap
<String
, PathBuf
> {
126 xdg_user_dirs
::all(home_dir_path
, &user_dir_file(home_dir_path
))
131 #[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
132 pub use self::target_unix_not_mac
::{user_dir, user_dirs}
;
134 #[cfg(target_os = "windows")]
137 #[cfg(target_os = "windows")]
140 use std
::ffi
::OsString
;
141 use std
::os
::windows
::ffi
::OsStringExt
;
142 use std
::path
::PathBuf
;
147 use super::winapi
::shared
::winerror
;
148 use super::winapi
::um
::{combaseapi, knownfolders, shlobj, shtypes, winbase, winnt}
;
150 pub fn known_folder(folder_id
: shtypes
::REFKNOWNFOLDERID
) -> Option
<PathBuf
> {
152 let mut path_ptr
: winnt
::PWSTR
= ptr
::null_mut();
153 let result
= shlobj
::SHGetKnownFolderPath(folder_id
, 0, ptr
::null_mut(), &mut path_ptr
);
154 if result
== winerror
::S_OK
{
155 let len
= winbase
::lstrlenW(path_ptr
) as usize;
156 let path
= slice
::from_raw_parts(path_ptr
, len
);
157 let ostr
: OsString
= OsStringExt
::from_wide(path
);
158 combaseapi
::CoTaskMemFree(path_ptr
as *mut winapi
::ctypes
::c_void
);
159 Some(PathBuf
::from(ostr
))
161 combaseapi
::CoTaskMemFree(path_ptr
as *mut winapi
::ctypes
::c_void
);
167 pub fn known_folder_profile() -> Option
<PathBuf
> {
168 known_folder(&knownfolders
::FOLDERID_Profile
)
171 pub fn known_folder_roaming_app_data() -> Option
<PathBuf
> {
172 known_folder(&knownfolders
::FOLDERID_RoamingAppData
)
175 pub fn known_folder_local_app_data() -> Option
<PathBuf
> {
176 known_folder(&knownfolders
::FOLDERID_LocalAppData
)
179 pub fn known_folder_music() -> Option
<PathBuf
> {
180 known_folder(&knownfolders
::FOLDERID_Music
)
183 pub fn known_folder_desktop() -> Option
<PathBuf
> {
184 known_folder(&knownfolders
::FOLDERID_Desktop
)
187 pub fn known_folder_documents() -> Option
<PathBuf
> {
188 known_folder(&knownfolders
::FOLDERID_Documents
)
191 pub fn known_folder_downloads() -> Option
<PathBuf
> {
192 known_folder(&knownfolders
::FOLDERID_Downloads
)
195 pub fn known_folder_pictures() -> Option
<PathBuf
> {
196 known_folder(&knownfolders
::FOLDERID_Pictures
)
199 pub fn known_folder_public() -> Option
<PathBuf
> {
200 known_folder(&knownfolders
::FOLDERID_Public
)
202 pub fn known_folder_templates() -> Option
<PathBuf
> {
203 known_folder(&knownfolders
::FOLDERID_Templates
)
205 pub fn known_folder_videos() -> Option
<PathBuf
> {
206 known_folder(&knownfolders
::FOLDERID_Videos
)
211 #[cfg(target_os = "windows")]
212 pub use self::target_windows
::{
213 known_folder
, known_folder_profile
, known_folder_roaming_app_data
, known_folder_local_app_data
,
214 known_folder_music
, known_folder_desktop
, known_folder_documents
, known_folder_downloads
,
215 known_folder_pictures
, known_folder_public
, known_folder_templates
, known_folder_videos