@@ -400,12 +400,19 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
400
400
let open_mode = file:: MODE_READ | file:: MODE_WRITE ;
401
401
let file = uefi_fs:: FileProtocol :: from_path ( old, open_mode, 0 ) ?;
402
402
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 ( )
406
415
}
407
-
408
- file. set_file_name ( new. as_os_str ( ) )
409
416
}
410
417
411
418
pub fn set_perm ( p : & Path , perm : FilePermissions ) -> io:: Result < ( ) > {
@@ -475,9 +482,23 @@ pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
475
482
unsupported ( )
476
483
}
477
484
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 )
481
502
}
482
503
483
504
// Liberal Cascade Delete
0 commit comments