1 | #[cfg (not(target_os = "fuchsia" ))] |
2 | use crate::backend::fd::AsFd; |
3 | #[cfg (feature = "fs" )] |
4 | use crate::path; |
5 | #[cfg (any(feature = "fs" , not(target_os = "fuchsia" )))] |
6 | use crate::{backend, io}; |
7 | #[cfg (all(feature = "alloc" , feature = "fs" ))] |
8 | use { |
9 | crate::ffi::{CStr, CString}, |
10 | crate::path::SMALL_PATH_BUFFER_SIZE, |
11 | alloc::vec::Vec, |
12 | }; |
13 | |
14 | /// `chdir(path)`—Change the current working directory. |
15 | /// |
16 | /// # References |
17 | /// - [POSIX] |
18 | /// - [Linux] |
19 | /// |
20 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html |
21 | /// [Linux]: https://man7.org/linux/man-pages/man2/chdir.2.html |
22 | #[inline ] |
23 | #[cfg (feature = "fs" )] |
24 | #[cfg_attr (doc_cfg, doc(cfg(feature = "fs" )))] |
25 | pub fn chdir<P: path::Arg>(path: P) -> io::Result<()> { |
26 | path.into_with_c_str(backend::process::syscalls::chdir) |
27 | } |
28 | |
29 | /// `fchdir(fd)`—Change the current working directory. |
30 | /// |
31 | /// # References |
32 | /// - [POSIX] |
33 | /// - [Linux] |
34 | /// |
35 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html |
36 | /// [Linux]: https://man7.org/linux/man-pages/man2/fchdir.2.html |
37 | #[cfg (not(target_os = "fuchsia" ))] |
38 | #[inline ] |
39 | pub fn fchdir<Fd: AsFd>(fd: Fd) -> io::Result<()> { |
40 | backend::process::syscalls::fchdir(fd.as_fd()) |
41 | } |
42 | |
43 | /// `getCWD`—Return the current working directory. |
44 | /// |
45 | /// If `reuse` already has available capacity, reuse it if possible. |
46 | /// |
47 | /// # References |
48 | /// - [POSIX] |
49 | /// - [Linux] |
50 | /// |
51 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html |
52 | /// [Linux]: https://man7.org/linux/man-pages/man3/getcwd.3.html |
53 | #[cfg (all(feature = "alloc" , feature = "fs" ))] |
54 | #[cfg (not(target_os = "wasi" ))] |
55 | #[cfg_attr (doc_cfg, doc(cfg(feature = "fs" )))] |
56 | #[inline ] |
57 | pub fn getcwd<B: Into<Vec<u8>>>(reuse: B) -> io::Result<CString> { |
58 | _getcwd(buffer:reuse.into()) |
59 | } |
60 | |
61 | #[cfg (all(feature = "alloc" , feature = "fs" ))] |
62 | #[allow (unsafe_code)] |
63 | fn _getcwd(mut buffer: Vec<u8>) -> io::Result<CString> { |
64 | buffer.clear(); |
65 | buffer.reserve(SMALL_PATH_BUFFER_SIZE); |
66 | |
67 | loop { |
68 | match backend::process::syscalls::getcwd(buffer.spare_capacity_mut()) { |
69 | Err(io::Errno::RANGE) => { |
70 | // Use `Vec` reallocation strategy to grow capacity |
71 | // exponentially. |
72 | buffer.reserve(buffer.capacity() + 1); |
73 | } |
74 | Ok(_) => { |
75 | // SAFETY: |
76 | // - "These functions return a null-terminated string" |
77 | // - [POSIX definition 3.375: String]: "A contiguous sequence |
78 | // of bytes terminated by and including the first null byte." |
79 | // |
80 | // Thus, there will be a single NUL byte at the end of the |
81 | // string. |
82 | // |
83 | // [POSIX definition 3.375: String]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_375 |
84 | unsafe { |
85 | buffer.set_len( |
86 | CStr::from_ptr(buffer.as_ptr().cast()) |
87 | .to_bytes_with_nul() |
88 | .len(), |
89 | ); |
90 | |
91 | return Ok(CString::from_vec_with_nul_unchecked(buffer)); |
92 | } |
93 | } |
94 | Err(errno) => return Err(errno), |
95 | } |
96 | } |
97 | } |
98 | |