1
+ use user_std:: SyscallError ;
2
+
1
3
use crate :: error:: Error as StdError ;
2
4
use crate :: ffi:: { OsStr , OsString } ;
3
5
use crate :: fmt;
4
6
use crate :: io;
5
7
use crate :: marker:: PhantomData ;
8
+ use crate :: os:: amjad_os:: prelude:: OsStringExt ;
6
9
use crate :: path:: { self , PathBuf } ;
10
+ use crate :: sys:: amjad_os:: syscall_to_io_error;
11
+ use crate :: sys:: common:: small_c_string:: run_path_with_cstr;
7
12
8
13
// This function is needed by the panic runtime. The symbol is named in
9
14
// pre-link args for the target specification, so keep that in sync.
@@ -29,11 +34,35 @@ pub fn error_string(_errno: i32) -> String {
29
34
}
30
35
31
36
pub fn getcwd ( ) -> io:: Result < PathBuf > {
32
- todo ! ( "getcwd" )
37
+ let mut buf = Vec :: with_capacity ( 512 ) ;
38
+ loop {
39
+ unsafe {
40
+ // Safety: the size is equal to the capacity, I'm setting the length so we can access the slice
41
+ // its safe to use since the data will be overwritten by getcwd
42
+ buf. set_len ( buf. capacity ( ) ) ;
43
+ match user_std:: io:: syscall_get_cwd ( & mut buf) {
44
+ Ok ( len) => {
45
+ // Safety: forcing the length back to the safe space
46
+ buf. set_len ( len) ;
47
+ buf. shrink_to_fit ( ) ;
48
+ return Ok ( PathBuf :: from ( OsString :: from_vec ( buf) ) ) ;
49
+ }
50
+ Err ( SyscallError :: BufferTooSmall ) => {
51
+ // Trigger the internal buffer resizing logic of `Vec` by requiring
52
+ // more space than the current capacity.
53
+ // at this stage we have already set the length to the capacity
54
+ buf. reserve ( 1 ) ;
55
+ }
56
+ Err ( e) => return Err ( syscall_to_io_error ( e) ) ,
57
+ }
58
+ }
59
+ }
33
60
}
34
61
35
- pub fn chdir ( _: & path:: Path ) -> io:: Result < ( ) > {
36
- todo ! ( "chdir" )
62
+ pub fn chdir ( p : & path:: Path ) -> io:: Result < ( ) > {
63
+ run_path_with_cstr ( p, |p| unsafe {
64
+ user_std:: io:: syscall_chdir ( p) . map_err ( syscall_to_io_error)
65
+ } )
37
66
}
38
67
39
68
pub struct SplitPaths < ' a > ( !, PhantomData < & ' a ( ) > ) ;
@@ -74,7 +103,19 @@ impl StdError for JoinPathsError {
74
103
}
75
104
76
105
pub fn current_exe ( ) -> io:: Result < PathBuf > {
77
- todo ! ( "current_exe" )
106
+ use crate :: env;
107
+ use crate :: io:: ErrorKind ;
108
+
109
+ let exe_path = env:: args ( ) . next ( ) . ok_or ( io:: const_io_error!(
110
+ ErrorKind :: Uncategorized ,
111
+ "an executable path was not found because no arguments were provided through argv"
112
+ ) ) ?;
113
+ let path = PathBuf :: from ( exe_path) ;
114
+
115
+ // Prepend the current working directory to the path if it's not absolute.
116
+ // TODO: `is_absolute` is broken for non-unix since it relies on `cfgs` which I don't want to modify,
117
+ // I'm opening a PR to fix that, then this will be changed to `is_absolute` but doesn't change much anyway
118
+ if !path. has_root ( ) { getcwd ( ) . map ( |cwd| cwd. join ( path) ) } else { Ok ( path) }
78
119
}
79
120
80
121
pub struct Env ( !) ;
0 commit comments