1 | use crate::ffi::CString; |
2 | use crate::path::SMALL_PATH_BUFFER_SIZE; |
3 | use crate::{backend, io, path}; |
4 | use alloc::vec::Vec; |
5 | #[cfg (not(target_os = "fuchsia" ))] |
6 | use backend::fd::AsFd; |
7 | |
8 | /// `chdir(path)`—Change the current working directory. |
9 | /// |
10 | /// # References |
11 | /// - [POSIX] |
12 | /// - [Linux] |
13 | /// |
14 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html |
15 | /// [Linux]: https://man7.org/linux/man-pages/man2/chdir.2.html |
16 | #[inline ] |
17 | pub fn chdir<P: path::Arg>(path: P) -> io::Result<()> { |
18 | path.into_with_c_str(backend::process::syscalls::chdir) |
19 | } |
20 | |
21 | /// `fchdir(fd)`—Change the current working directory. |
22 | /// |
23 | /// # References |
24 | /// - [POSIX] |
25 | /// - [Linux] |
26 | /// |
27 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html |
28 | /// [Linux]: https://man7.org/linux/man-pages/man2/fchdir.2.html |
29 | #[cfg (not(target_os = "fuchsia" ))] |
30 | #[inline ] |
31 | pub fn fchdir<Fd: AsFd>(fd: Fd) -> io::Result<()> { |
32 | backend::process::syscalls::fchdir(fd.as_fd()) |
33 | } |
34 | |
35 | /// `getcwd()`—Return the current working directory. |
36 | /// |
37 | /// If `reuse` is non-empty, reuse its buffer to store the result if possible. |
38 | /// |
39 | /// # References |
40 | /// - [POSIX] |
41 | /// - [Linux] |
42 | /// |
43 | /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html |
44 | /// [Linux]: https://man7.org/linux/man-pages/man3/getcwd.3.html |
45 | #[cfg (not(target_os = "wasi" ))] |
46 | #[inline ] |
47 | pub fn getcwd<B: Into<Vec<u8>>>(reuse: B) -> io::Result<CString> { |
48 | _getcwd(buffer:reuse.into()) |
49 | } |
50 | |
51 | fn _getcwd(mut buffer: Vec<u8>) -> io::Result<CString> { |
52 | // This code would benefit from having a better way to read into |
53 | // uninitialized memory, but that requires `unsafe`. |
54 | buffer.clear(); |
55 | buffer.reserve(SMALL_PATH_BUFFER_SIZE); |
56 | buffer.resize(new_len:buffer.capacity(), value:0_u8); |
57 | |
58 | loop { |
59 | match backend::process::syscalls::getcwd(&mut buffer) { |
60 | Err(io::Errno::RANGE) => { |
61 | buffer.reserve(additional:1); // use `Vec` reallocation strategy to grow capacity exponentially |
62 | buffer.resize(new_len:buffer.capacity(), value:0_u8); |
63 | } |
64 | Ok(_) => { |
65 | let len: usize = buffer.iter().position(|x: &u8| *x == b' \0' ).unwrap(); |
66 | buffer.resize(new_len:len, value:0_u8); |
67 | return Ok(CString::new(buffer).unwrap()); |
68 | } |
69 | Err(errno: Errno) => return Err(errno), |
70 | } |
71 | } |
72 | } |
73 | |