11use crate :: ffi:: { OsStr , OsString } ;
2- use crate :: fmt;
32use crate :: hash:: Hash ;
43use crate :: io:: { self , BorrowedCursor , IoSlice , IoSliceMut , SeekFrom } ;
54use crate :: io:: { Read , Seek , Write } ;
65use crate :: path:: { Path , PathBuf } ;
76use crate :: sys:: resources:: { DirIterResource , FileDesc , FileResource } ;
87use crate :: sys:: time:: SystemTime ;
98use crate :: sys:: { unsupported, unsupported_err} ;
9+ use crate :: sys_common:: ignore_notfound;
10+ use crate :: { fmt, fs} ;
1011use safa_api:: errors:: ErrorStatus ;
1112use safa_api:: raw;
1213use safa_api:: raw:: io:: FSObjectType ;
@@ -365,6 +366,8 @@ pub fn unlink(p: &Path) -> io::Result<()> {
365366
366367pub fn rename ( old : & Path , new : & Path ) -> io:: Result < ( ) > {
367368 let old_str = path_to_str ! ( old) ;
369+ let new_str = path_to_str ! ( new) ;
370+
368371 let old_attrs = syscalls:: fs:: getdirentry ( old_str) ?;
369372 // TODO: implement native rename syscall
370373 match old_attrs. attrs . kind {
@@ -374,13 +377,25 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
374377 Ok ( ( ) )
375378 }
376379 FSObjectType :: Directory => {
380+ // create the new directory if it doesn't exist
381+ if let Err ( e) = syscalls:: fs:: createdir ( new_str)
382+ && e != ErrorStatus :: AlreadyExists
383+ {
384+ return Err ( e. into ( ) ) ;
385+ }
386+
377387 for entry in crate :: fs:: read_dir ( old) ? {
378388 let entry = entry?;
379- let old_path = entry. path ( ) ;
389+ let entry_name = entry. file_name ( ) ;
390+ // special cases for '.' and '..' to avoid infinite recursion
391+ if entry_name. as_encoded_bytes ( ) == b"." || entry_name. as_encoded_bytes ( ) == b".." {
392+ continue ;
393+ }
394+
395+ let old_entry_path = entry. path ( ) ;
380396
381- let new_path = new. join ( entry. file_name ( ) ) ;
382- rename ( & old_path, & new_path) ?;
383- syscalls:: fs:: remove_path ( path_to_str ! ( old_path) ) ?;
397+ let new_entry_path = new. join ( entry_name) ;
398+ rename ( & old_entry_path, & new_entry_path) ?;
384399 }
385400
386401 syscalls:: fs:: remove_path ( old_str) ?;
@@ -405,7 +420,31 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
405420}
406421
407422pub fn remove_dir_all ( path : & Path ) -> io:: Result < ( ) > {
408- super :: common:: remove_dir_all ( path)
423+ for child in crate :: fs:: read_dir ( path) ? {
424+ let result: io:: Result < ( ) > = try {
425+ let child = child?;
426+ let name = child. file_name ( ) ;
427+ // special cases for '.' and '..' to avoid infinite recursion
428+ if name. as_encoded_bytes ( ) == b"." || name. as_encoded_bytes ( ) == b".." {
429+ continue ;
430+ }
431+
432+ let path = child. path ( ) ;
433+
434+ if child. file_type ( ) ?. is_dir ( ) {
435+ remove_dir_all ( & path) ?;
436+ } else {
437+ fs:: remove_file ( & path) ?;
438+ }
439+ } ;
440+ // ignore internal NotFound errors to prevent race conditions
441+ if let Err ( err) = & result
442+ && err. kind ( ) != io:: ErrorKind :: NotFound
443+ {
444+ return result;
445+ }
446+ }
447+ ignore_notfound ( fs:: remove_dir ( path) )
409448}
410449
411450pub fn exists ( path : & Path ) -> io:: Result < bool > {
@@ -446,5 +485,14 @@ pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
446485}
447486
448487pub fn copy ( from : & Path , to : & Path ) -> io:: Result < u64 > {
449- super :: common:: copy ( from, to)
488+ let mut reader = fs:: File :: open ( from) ?;
489+ let metadata = reader. metadata ( ) ?;
490+
491+ if !metadata. is_file ( ) {
492+ return Err ( ErrorStatus :: NotAFile . into ( ) ) ;
493+ }
494+
495+ let mut writer = fs:: File :: create ( to) ?;
496+ let ret = io:: copy ( & mut reader, & mut writer) ?;
497+ Ok ( ret)
450498}
0 commit comments