@@ -400,12 +400,19 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
400400 let open_mode = file:: MODE_READ | file:: MODE_WRITE ;
401401 let file = uefi_fs:: FileProtocol :: from_path ( old, open_mode, 0 ) ?;
402402
403- // Delete if new already exists
404- if let Ok ( f) = uefi_fs:: FileProtocol :: from_path ( new, open_mode, 0 ) {
405- f. delete ( ) ?;
403+ // If tbe device prefix is same or both path are relative (in which case None will be
404+ // returned), then we can just use `set_file_name`.
405+ if super :: path:: device_prefix ( old. as_os_str ( ) ) == super :: path:: device_prefix ( new. as_os_str ( ) ) {
406+ // Delete if new already exists
407+ if let Ok ( f) = uefi_fs:: FileProtocol :: from_path ( new, open_mode, 0 ) {
408+ f. delete ( ) ?;
409+ }
410+ file. set_file_name ( new. as_os_str ( ) )
411+ } else {
412+ // Use simple copy if the new path is in a different device.
413+ copy ( old, new) ?;
414+ file. delete ( )
406415 }
407-
408- file. set_file_name ( new. as_os_str ( ) )
409416}
410417
411418pub fn set_perm ( p : & Path , perm : FilePermissions ) -> io:: Result < ( ) > {
@@ -475,9 +482,23 @@ pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
475482 unsupported ( )
476483}
477484
478- // FIXME: Find an efficient implementation
479- pub fn copy ( _from : & Path , _to : & Path ) -> io:: Result < u64 > {
480- unsupported ( )
485+ pub fn copy ( from : & Path , to : & Path ) -> io:: Result < u64 > {
486+ let from_file = uefi_fs:: FileProtocol :: from_path ( from, file:: MODE_READ , 0 ) ?;
487+ let to_file = uefi_fs:: FileProtocol :: from_path (
488+ to,
489+ file:: MODE_READ | file:: MODE_WRITE | file:: MODE_CREATE ,
490+ 0 ,
491+ ) ?;
492+ // Truncate destination file.
493+ to_file. set_file_size ( 0 ) ?;
494+
495+ let info = from_file. get_file_info ( ) ?;
496+ let file_size = unsafe { ( * info. as_ptr ( ) ) . file_size } ;
497+ let mut buffer = Vec :: < u8 > :: with_capacity ( file_size as usize ) ;
498+ let mut buffer_size = buffer. capacity ( ) ;
499+ from_file. read ( & mut buffer, & mut buffer_size) ?;
500+ unsafe { buffer. set_len ( buffer_size) } ;
501+ Ok ( to_file. write ( & buffer) ? as u64 )
481502}
482503
483504// Liberal Cascade Delete
0 commit comments