@@ -102,19 +102,16 @@ pub fn read(fd: FileDescriptor, buffer: &mut [u8]) -> Result<usize, SyscallError
102
102
}
103
103
104
104
#[ syscall]
105
- pub fn open ( fd : usize , path : & Path , mode : usize ) -> Result < usize , SyscallError > {
106
- let dir = match fd as isize {
107
- 0 => {
108
- if !path. is_absolute ( ) {
109
- scheduler:: get_scheduler ( ) . current_task ( ) . cwd_dirent ( )
110
- } else {
111
- crate :: fs:: root_dir ( ) . clone ( )
112
- }
113
- }
114
-
115
- _ => {
116
- todo ! ( )
105
+ pub fn open ( fd : usize , path : & Path , _flags : usize , mode : usize ) -> Result < usize , SyscallError > {
106
+ let current_thread = scheduler:: current_thread ( ) ;
107
+ let at = match fd as isize {
108
+ AT_FDCWD if !path. is_absolute ( ) => current_thread. cwd_dirent ( ) ,
109
+ _ if !path. is_absolute ( ) => {
110
+ let ent = FileDescriptor :: from_usize ( fd) . handle ( ) ?. inode . clone ( ) ;
111
+ assert ! ( ent. inode( ) . metadata( ) ?. is_directory( ) ) ;
112
+ ent
117
113
}
114
+ _ => fs:: root_dir ( ) . clone ( ) ,
118
115
} ;
119
116
120
117
let mut flags = OpenFlags :: from_bits ( mode) . ok_or ( SyscallError :: EINVAL ) ?;
@@ -129,7 +126,7 @@ pub fn open(fd: usize, path: &Path, mode: usize) -> Result<usize, SyscallError>
129
126
lookup_mode = LookupMode :: Create ;
130
127
}
131
128
132
- let inode = fs:: lookup_path_with ( dir , path, lookup_mode, true ) ?;
129
+ let inode = fs:: lookup_path_with ( at , path, lookup_mode, true ) ?;
133
130
134
131
if flags. contains ( OpenFlags :: O_DIRECTORY ) && !inode. inode ( ) . metadata ( ) ?. is_directory ( ) {
135
132
return Err ( SyscallError :: ENOTDIR ) ;
@@ -139,9 +136,7 @@ pub fn open(fd: usize, path: &Path, mode: usize) -> Result<usize, SyscallError>
139
136
inode. inode ( ) . truncate ( 0 ) ?;
140
137
}
141
138
142
- Ok ( scheduler:: current_thread ( )
143
- . file_table
144
- . open_file ( inode. clone ( ) , flags) ?)
139
+ Ok ( current_thread. file_table . open_file ( inode. clone ( ) , flags) ?)
145
140
}
146
141
147
142
#[ syscall]
@@ -183,15 +178,29 @@ pub fn close(fd: FileDescriptor) -> Result<usize, SyscallError> {
183
178
}
184
179
185
180
#[ syscall]
186
- pub fn chdir ( path : & str ) -> Result < usize , SyscallError > {
187
- let inode = fs:: lookup_path ( Path :: new ( path) ) ?;
181
+ pub fn chdir ( fd : usize , path : & Path ) -> Result < usize , SyscallError > {
182
+ let current_thread = scheduler:: current_thread ( ) ;
183
+ let at = match fd as isize {
184
+ AT_FDCWD if !path. is_absolute ( ) => current_thread. cwd_dirent ( ) ,
185
+ _ if !path. is_absolute ( ) => {
186
+ let ent = FileDescriptor :: from_usize ( fd) . handle ( ) ?. inode . clone ( ) ;
187
+ assert ! ( ent. inode( ) . metadata( ) ?. is_directory( ) ) ;
188
+ ent
189
+ }
190
+ _ => fs:: root_dir ( ) . clone ( ) ,
191
+ } ;
188
192
189
- if !inode. inode ( ) . metadata ( ) ?. is_directory ( ) {
190
- // A component of path is not a directory.
193
+ if path. is_empty ( ) {
194
+ current_thread. set_cwd ( at) ;
195
+ return Ok ( 0 ) ;
196
+ }
197
+
198
+ let ent = fs:: lookup_path_with ( at, path, LookupMode :: None , true ) ?;
199
+ if !ent. inode ( ) . metadata ( ) ?. is_directory ( ) {
191
200
return Err ( SyscallError :: ENOTDIR ) ;
192
201
}
193
202
194
- scheduler :: get_scheduler ( ) . current_task ( ) . set_cwd ( inode ) ;
203
+ current_thread . set_cwd ( ent ) ;
195
204
Ok ( 0 )
196
205
}
197
206
0 commit comments