diff --git a/freebsd/src/lib.rs b/freebsd/src/lib.rs index 7a9ffff..6cff7e9 100644 --- a/freebsd/src/lib.rs +++ b/freebsd/src/lib.rs @@ -489,3 +489,30 @@ impl FreeBSDCommandExt for std::process::Command { self } } + +pub fn copy_file_range(source_fd: i32, s_offset: i64, dest_fd: i32, d_offset: i64, max_len: usize) -> nix::Result { + unsafe { + let mut source_offset = s_offset; + let mut dest_offset = d_offset; + let mut remaining_len = max_len; + let mut copied_len = 0usize; + loop { + match nix::libc::copy_file_range(source_fd, &mut source_offset, dest_fd, &mut dest_offset, remaining_len, 0) { + 0 => { + break Ok(copied_len) + }, + -1 => { + break Err(nix::Error::last()) + }, + m => { + assert!(m.is_positive()); + let n = m as usize; + assert!(n <= remaining_len); + remaining_len -= n; + copied_len += n; + } + } + } + } +} + diff --git a/xcd/src/ipc.rs b/xcd/src/ipc.rs index bb9a735..0b2b668 100644 --- a/xcd/src/ipc.rs +++ b/xcd/src/ipc.rs @@ -885,15 +885,9 @@ async fn fd_import( info!("import: content_type is {content_type}"); - unsafe { - freebsd::nix::libc::copy_file_range( - source_fd, - std::ptr::null_mut(), - dest_fd, - std::ptr::null_mut(), - file_len, - 0, - ); + if let Err(error) = freebsd::copy_file_range(source_fd, 0, dest_fd, 0, file_len) { + error!(error=error.to_string(), "copy_file_range failed"); + return ipc_err(EIO, "failed to copyin archive") } info!("copy_file_range done"); @@ -922,8 +916,8 @@ async fn fd_import( let diff_id = OciDigest::new_unchecked(output_lines[0].trim()); let archive_digest = OciDigest::new_unchecked(output_lines[1].trim()); - info!("diff_id: {diff_id}"); - info!("archive_digest: {archive_digest}"); + info!(diff_id=diff_id.as_str(), "diff_id"); + info!(archive_digest=archive_digest.as_str(), "archive_digest"); let path = { let mut path = config.layers_dir.to_path_buf();