@@ -102,19 +102,16 @@ pub fn read(fd: FileDescriptor, buffer: &mut [u8]) -> Result<usize, SyscallError
102102}
103103
104104#[ 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
117113 }
114+ _ => fs:: root_dir ( ) . clone ( ) ,
118115 } ;
119116
120117 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>
129126 lookup_mode = LookupMode :: Create ;
130127 }
131128
132- let inode = fs:: lookup_path_with ( dir , path, lookup_mode, true ) ?;
129+ let inode = fs:: lookup_path_with ( at , path, lookup_mode, true ) ?;
133130
134131 if flags. contains ( OpenFlags :: O_DIRECTORY ) && !inode. inode ( ) . metadata ( ) ?. is_directory ( ) {
135132 return Err ( SyscallError :: ENOTDIR ) ;
@@ -139,9 +136,7 @@ pub fn open(fd: usize, path: &Path, mode: usize) -> Result<usize, SyscallError>
139136 inode. inode ( ) . truncate ( 0 ) ?;
140137 }
141138
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) ?)
145140}
146141
147142#[ syscall]
@@ -183,15 +178,29 @@ pub fn close(fd: FileDescriptor) -> Result<usize, SyscallError> {
183178}
184179
185180#[ 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+ } ;
188192
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 ( ) {
191200 return Err ( SyscallError :: ENOTDIR ) ;
192201 }
193202
194- scheduler :: get_scheduler ( ) . current_task ( ) . set_cwd ( inode ) ;
203+ current_thread . set_cwd ( ent ) ;
195204 Ok ( 0 )
196205}
197206
0 commit comments