use crate::common::{single_mount, write_compressible_data};
use btrfs_uapi::{
defrag,
filesystem::sync,
send_receive::encoded_read,
subvolume::{SubvolumeFlags, subvolume_create, subvolume_flags_set},
};
use std::{ffi::CStr, fs::File, os::unix::io::AsFd};
#[test]
#[ignore = "requires elevated privileges"]
fn encoded_read_uncompressed() {
let (_td, mnt) = single_mount();
let name = CStr::from_bytes_with_nul(b"snap-uncompressed\0").unwrap();
subvolume_create(mnt.fd(), name, &[]).expect("subvolume_create failed");
let subvol_path = mnt.path().join("snap-uncompressed");
let file_path = subvol_path.join("data.bin");
std::fs::write(&file_path, &vec![42u8; 4096]).unwrap();
sync(mnt.fd()).unwrap();
let subvol_dir = File::open(&subvol_path).unwrap();
subvolume_flags_set(subvol_dir.as_fd(), SubvolumeFlags::RDONLY)
.expect("set readonly failed");
let file = File::open(&file_path).unwrap();
let mut buf = vec![0u8; 128 * 1024];
let result = encoded_read(file.as_fd(), &mut buf, 0, 4096);
match result {
Ok(r) => {
assert!(r.bytes_read > 0, "should read some data");
assert_eq!(
r.compression, 0,
"uncompressed data should have compression=0"
);
}
Err(nix::errno::Errno::ENOTTY) => {
eprintln!("encoded_read not supported on this kernel, skipping");
}
Err(e) => panic!("encoded_read failed unexpectedly: {e}"),
}
}
#[test]
#[ignore = "requires elevated privileges"]
fn encoded_read_compressed() {
let (_td, mnt) = single_mount();
let name = CStr::from_bytes_with_nul(b"snap-compressed\0").unwrap();
subvolume_create(mnt.fd(), name, &[]).expect("subvolume_create failed");
let subvol_path = mnt.path().join("snap-compressed");
write_compressible_data(&subvol_path, "zeros.bin", 128 * 1024);
sync(mnt.fd()).unwrap();
let file = File::options()
.read(true)
.write(true)
.open(subvol_path.join("zeros.bin"))
.unwrap();
let _ = defrag::defrag_range(
file.as_fd(),
&defrag::DefragRangeArgs::new().compress(defrag::CompressSpec {
compress_type: defrag::CompressType::Zstd,
level: None,
}),
);
drop(file);
sync(mnt.fd()).unwrap();
let subvol_dir = File::open(&subvol_path).unwrap();
subvolume_flags_set(subvol_dir.as_fd(), SubvolumeFlags::RDONLY)
.expect("set readonly failed");
let file = File::open(subvol_path.join("zeros.bin")).unwrap();
let mut buf = vec![0u8; 128 * 1024];
let result = encoded_read(file.as_fd(), &mut buf, 0, 128 * 1024);
match result {
Ok(r) => {
assert!(r.bytes_read > 0, "should read some data");
assert!(
r.compression > 0,
"compressible data after defrag should be stored compressed, got compression={}",
r.compression,
);
assert!(
r.unencoded_len >= r.unencoded_file_len,
"unencoded_len ({}) should be >= unencoded_file_len ({})",
r.unencoded_len,
r.unencoded_file_len,
);
}
Err(nix::errno::Errno::ENOTTY) => {
eprintln!("encoded_read not supported on this kernel, skipping");
}
Err(e) => panic!("encoded_read failed unexpectedly: {e}"),
}
}