zipfuse: supports zip on block device
Add a test case to ensure that zipfuse works with a block device whose
content is backed by a zip file. Fortunately, zip-rs already supports
reading a zip file from a block device: it locates the end of central
directory record by reverse-scanning a file from the end.
Bug: 186377508
Test: cargo test (android test missing because we don't have the
loopdevice crate for Android, which is fine)
Change-Id: I8fbbfd18a2a0df2a550e3f679ba74ba603b59efd
diff --git a/zipfuse/.cargo/config.toml b/zipfuse/.cargo/config.toml
index b87b13a..2fc1783 100644
--- a/zipfuse/.cargo/config.toml
+++ b/zipfuse/.cargo/config.toml
@@ -1,4 +1,3 @@
-# Mounting requires root privilege. The fuse library in crosvm doesn't support
-# fusermount yet.
+# losetup requires root privilege.
[target.x86_64-unknown-linux-gnu]
-runner = 'unshare -mUr'
+runner = 'sudo -E'
diff --git a/zipfuse/Cargo.toml b/zipfuse/Cargo.toml
index 220d352..c8f2f3a 100644
--- a/zipfuse/Cargo.toml
+++ b/zipfuse/Cargo.toml
@@ -12,3 +12,7 @@
zip = "0.5"
tempfile = "3.2"
nix = "0.20"
+
+[dev-dependencies]
+loopdev = "0.2"
+scopeguard = "1.1"
diff --git a/zipfuse/src/main.rs b/zipfuse/src/main.rs
index 21f7f9c..12c891c 100644
--- a/zipfuse/src/main.rs
+++ b/zipfuse/src/main.rs
@@ -633,14 +633,8 @@
);
}
- #[test]
- fn supports_deflate() {
- let test_dir = tempfile::TempDir::new().unwrap();
- let zip_path = test_dir.path().join("test.zip");
- let mut zip_file = File::create(&zip_path).unwrap();
- zip_file.write_all(include_bytes!("../testdata/test.zip")).unwrap();
-
- let mnt_path = test_dir.path().join("mnt");
+ fn run_fuse_and_check_test_zip(test_dir: &Path, zip_path: &Path) {
+ let mnt_path = test_dir.join("mnt");
assert!(fs::create_dir(&mnt_path).is_ok());
start_fuse(&zip_path, &mnt_path);
@@ -654,4 +648,44 @@
check_file(&mnt_path, "dir/file2", include_bytes!("../testdata/dir/file2"));
assert!(nix::mount::umount2(&mnt_path, nix::mount::MntFlags::empty()).is_ok());
}
+
+ #[test]
+ fn supports_deflate() {
+ let test_dir = tempfile::TempDir::new().unwrap();
+ let zip_path = test_dir.path().join("test.zip");
+ let mut zip_file = File::create(&zip_path).unwrap();
+ zip_file.write_all(include_bytes!("../testdata/test.zip")).unwrap();
+
+ run_fuse_and_check_test_zip(&test_dir.path(), &zip_path);
+ }
+
+ #[cfg(not(target_os = "android"))] // Android doesn't have the loopdev crate
+ #[test]
+ fn supports_zip_on_block_device() {
+ // Write test.zip to the test directory
+ let test_dir = tempfile::TempDir::new().unwrap();
+ let zip_path = test_dir.path().join("test.zip");
+ let mut zip_file = File::create(&zip_path).unwrap();
+ let data = include_bytes!("../testdata/test.zip");
+ zip_file.write_all(data).unwrap();
+
+ // Pad 0 to test.zip so that its size is multiple of 4096.
+ const BLOCK_SIZE: usize = 4096;
+ let size = (data.len() + BLOCK_SIZE) & !BLOCK_SIZE;
+ let pad_size = size - data.len();
+ assert!(pad_size != 0);
+ let pad = vec![0; pad_size];
+ zip_file.write_all(pad.as_slice()).unwrap();
+ drop(zip_file);
+
+ // Attach test.zip to a loop device
+ let lc = loopdev::LoopControl::open().unwrap();
+ let ld = scopeguard::guard(lc.next_free().unwrap(), |ld| {
+ ld.detach().unwrap();
+ });
+ ld.attach_file(&zip_path).unwrap();
+
+ // Start zipfuse over to the loop device (not the zip file)
+ run_fuse_and_check_test_zip(&test_dir.path(), &ld.path().unwrap());
+ }
}