Write the header to `file`.
(&self, file: &mut F)
| 450 | |
| 451 | /// Write the header to `file`. |
| 452 | pub fn write_to<F: Write + Seek>(&self, file: &mut F) -> Result<()> { |
| 453 | // Writes the next u32 to the file. |
| 454 | fn write_u32_be<F: Write>(f: &mut F, value: u32) -> Result<()> { |
| 455 | u32::write_be(f, value).map_err(Error::WritingHeader) |
| 456 | } |
| 457 | |
| 458 | // Writes the next u64 to the file. |
| 459 | fn write_u64_be<F: Write>(f: &mut F, value: u64) -> Result<()> { |
| 460 | u64::write_be(f, value).map_err(Error::WritingHeader) |
| 461 | } |
| 462 | |
| 463 | write_u32_be(file, self.magic)?; |
| 464 | write_u32_be(file, self.version)?; |
| 465 | write_u64_be(file, self.backing_file_offset)?; |
| 466 | write_u32_be(file, self.backing_file_size)?; |
| 467 | write_u32_be(file, self.cluster_bits)?; |
| 468 | write_u64_be(file, self.size)?; |
| 469 | write_u32_be(file, self.crypt_method)?; |
| 470 | write_u32_be(file, self.l1_size)?; |
| 471 | write_u64_be(file, self.l1_table_offset)?; |
| 472 | write_u64_be(file, self.refcount_table_offset)?; |
| 473 | write_u32_be(file, self.refcount_table_clusters)?; |
| 474 | write_u32_be(file, self.nb_snapshots)?; |
| 475 | write_u64_be(file, self.snapshots_offset)?; |
| 476 | |
| 477 | if self.version == 3 { |
| 478 | write_u64_be(file, self.incompatible_features)?; |
| 479 | write_u64_be(file, self.compatible_features)?; |
| 480 | write_u64_be(file, self.autoclear_features)?; |
| 481 | write_u32_be(file, self.refcount_order)?; |
| 482 | write_u32_be(file, self.header_size)?; |
| 483 | |
| 484 | if self.header_size > V3_BARE_HEADER_SIZE { |
| 485 | write_u64_be(file, 0)?; // no compression |
| 486 | } |
| 487 | |
| 488 | write_u32_be(file, 0)?; // header extension type: end of header extension area |
| 489 | write_u32_be(file, 0)?; // length of header extension data: 0 |
| 490 | } |
| 491 | |
| 492 | if let Some(backing_file_path) = self.backing_file.as_ref().map(|bf| &bf.path) { |
| 493 | if self.backing_file_offset > 0 { |
| 494 | file.seek(SeekFrom::Start(self.backing_file_offset)) |
| 495 | .map_err(Error::WritingHeader)?; |
| 496 | } |
| 497 | write!(file, "{backing_file_path}").map_err(Error::WritingHeader)?; |
| 498 | } |
| 499 | |
| 500 | // Set the file length by seeking and writing a zero to the last byte. This avoids needing |
| 501 | // a `File` instead of anything that implements seek as the `file` argument. |
| 502 | // Zeros out the l1 and refcount table clusters. |
| 503 | let cluster_size = 0x01u64 << self.cluster_bits; |
| 504 | let refcount_blocks_size = u64::from(self.refcount_table_clusters) * cluster_size; |
| 505 | file.seek(SeekFrom::Start( |
| 506 | self.refcount_table_offset + refcount_blocks_size - 2, |
| 507 | )) |
| 508 | .map_err(Error::WritingHeader)?; |
| 509 | file.write(&[0u8]).map_err(Error::WritingHeader)?; |