Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholasbishop committed Jul 22, 2023
1 parent 10978ae commit 36d3e1f
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 2 deletions.
21 changes: 21 additions & 0 deletions uefi-test-runner/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,26 @@ pub fn test(sfs: ScopedProtocol<SimpleFileSystem>) -> Result<(), fs::Error> {
// file should not be available after remove all
assert!(!fs.try_exists(cstr16!("foo_dir\\1"))?);

test_copy(&mut fs)?;

Ok(())
}

fn test_copy(fs: &mut FileSystem) -> Result<(), fs::Error> {
// Test copying when the destination exists but the source does not. Verify
// that the destination is not deleted or altered in this case.
fs.write(cstr16!("file1"), "data1")?;
assert_eq!(
fs.copy(cstr16!("src"), cstr16!("file1")),
Err(fs::Error::Io(IoError {
path: PathBuf::from(cstr16!("src")),
context: IoErrorContext::OpenError,
uefi_error: uefi::Error::new(Status::NOT_FOUND, ()),
}))
);
assert_eq!(fs.read(cstr16!("file1"))?, b"data1");

// TODO

Ok(())
}
87 changes: 85 additions & 2 deletions uefi/src/fs/file_system/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,91 @@ impl<'a> FileSystem<'a> {
src_path: impl AsRef<Path>,
dest_path: impl AsRef<Path>,
) -> FileSystemResult<()> {
let read = self.read(src_path)?;
self.write(dest_path, read)
let src_path = src_path.as_ref();
let dest_path = dest_path.as_ref();

// Open the source file for reading.
let mut src = self
.open(src_path, UefiFileMode::Read, false)?
.into_regular_file()
.ok_or(Error::Io(IoError {
path: src_path.to_path_buf(),
context: IoErrorContext::NotAFile,
uefi_error: Status::INVALID_PARAMETER.into(),
}))?;

// Get the source file's size in bytes.
let src_size = {
let src_info = src.get_boxed_info::<UefiFileInfo>().map_err(|err| {
Error::Io(IoError {
path: src_path.to_path_buf(),
context: IoErrorContext::Metadata,
uefi_error: err,
})
})?;
src_info.file_size()
};

// Try to delete the destination file in case it already exists. Allow
// this to fail, since it might not exist.
let _ = self.remove_file(dest_path);

// Create and open the destination file.
let mut dest = self
.open(dest_path, UefiFileMode::CreateReadWrite, false)?
.into_regular_file()
.ok_or(Error::Io(IoError {
path: dest_path.to_path_buf(),
context: IoErrorContext::OpenError,
uefi_error: Status::INVALID_PARAMETER.into(),
}))?;

// 1 MiB copy buffer.
let mut chunk = vec![0; 1024 * 1024];

// Read chunks from the source file and write to the destination file.
let mut remaining_size = src_size;
while remaining_size > 0 {
// Read one chunk.
let num_bytes_read = src.read(&mut chunk).map_err(|err| {
Error::Io(IoError {
path: src_path.to_path_buf(),
context: IoErrorContext::ReadFailure,
uefi_error: err.to_err_without_payload(),
})
})?;

// If the read returned no bytes, but `remaining_size > 0`, return
// an error.
if num_bytes_read == 0 {
return Err(Error::Io(IoError {
path: src_path.to_path_buf(),
context: IoErrorContext::ReadFailure,
uefi_error: Status::ABORTED.into(),
}));
}

// Copy the bytes read out to the destination file.
dest.write(&chunk[..num_bytes_read]).map_err(|err| {
Error::Io(IoError {
path: dest_path.to_path_buf(),
context: IoErrorContext::WriteFailure,
uefi_error: err.to_err_without_payload(),
})
})?;

remaining_size -= u64::try_from(num_bytes_read).unwrap();
}

dest.flush().map_err(|err| {
Error::Io(IoError {
path: dest_path.to_path_buf(),
context: IoErrorContext::FlushFailure,
uefi_error: err,
})
})?;

Ok(())
}

/// Creates a new, empty directory at the provided path
Expand Down

0 comments on commit 36d3e1f

Please sign in to comment.