openvmm_helpers/snapshot/
publish.rs1use super::SnapshotManifest;
7use anyhow::Context;
8use std::path::Path;
9
10pub fn write_snapshot(
17 dir: &Path,
18 manifest: &SnapshotManifest,
19 saved_state_bytes: &[u8],
20 memory_file_path: &Path,
21) -> anyhow::Result<()> {
22 fs_err::create_dir_all(dir)?;
23
24 let manifest_bytes = mesh::payload::encode(manifest.clone());
26 fs_err::write(dir.join("manifest.bin"), &manifest_bytes)?;
27
28 fs_err::write(dir.join("state.bin"), saved_state_bytes)?;
30
31 let memory_bin_path = dir.join("memory.bin");
33 let canonical_source = fs_err::canonicalize(memory_file_path)?;
34
35 let needs_link = if memory_bin_path.exists() {
38 let canonical_target = fs_err::canonicalize(&memory_bin_path)?;
39 if canonical_source == canonical_target {
40 false
41 } else {
42 fs_err::remove_file(&memory_bin_path)?;
45 true
46 }
47 } else {
48 true
49 };
50
51 if needs_link {
52 if let Err(err) = std::fs::hard_link(&canonical_source, &memory_bin_path) {
53 if err.kind() == std::io::ErrorKind::CrossesDevices {
54 anyhow::bail!(
55 "memory backing file ({}) must be on the same filesystem as the snapshot \
56 directory ({}); consider placing the backing file inside the snapshot \
57 directory",
58 memory_file_path.display(),
59 dir.display(),
60 );
61 }
62 return Err(err).with_context(|| {
63 format!(
64 "failed to hard-link {} -> {}",
65 canonical_source.display(),
66 memory_bin_path.display()
67 )
68 });
69 }
70 }
71
72 Ok(())
73}