]> git.proxmox.com Git - proxmox-backup.git/blame - src/tape/file_formats/multi_volume_reader.rs
update to first proxmox crate split
[proxmox-backup.git] / src / tape / file_formats / multi_volume_reader.rs
CommitLineData
983e929e
DM
1use std::io::{Read};
2
3use anyhow::{bail, Error};
4
6ef1b649 5use proxmox_io::ReadExt;
983e929e 6
048b43af 7use pbs_tape::{TapeRead, MediaContentHeader};
983e929e
DM
8
9/// Read multi volume data streams written by `MultiVolumeWriter`
10///
11/// Note: We do not use this feature currently.
12pub struct MultiVolumeReader<'a> {
13 reader: Option<Box<dyn TapeRead + 'a>>,
14 next_reader_fn: Box<dyn 'a + FnMut() -> Result<Box<dyn TapeRead +'a>, Error>>,
15 complete: bool,
16 header: MediaContentHeader,
17}
18
19impl <'a> MultiVolumeReader<'a> {
20
21 /// Creates a new instance
22 pub fn new(
23 reader: Box<dyn TapeRead +'a>,
24 header: MediaContentHeader,
25 next_reader_fn: Box<dyn 'a + FnMut() -> Result<Box<dyn TapeRead +'a>, Error>>,
26 ) -> Result<Self, Error> {
27
28 if header.part_number != 0 {
29 bail!("MultiVolumeReader::new - got wrong header part_number ({} != 0)",
30 header.part_number);
31 }
32
33 Ok(Self {
34 reader: Some(reader),
35 next_reader_fn,
36 complete: false,
37 header,
38 })
39 }
40}
41
42impl <'a> Read for MultiVolumeReader<'a> {
43
44 fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
45 if self.complete {
46 return Ok(0);
47 }
48
49 if self.reader.is_none() {
50 let mut reader = (self.next_reader_fn)()
51 .map_err(|err| proxmox::io_format_err!("multi-volume next failed: {}", err))?;
52
6ef1b649 53 proxmox_lang::try_block!({
983e929e
DM
54 let part_header: MediaContentHeader = unsafe { reader.read_le_value()? };
55 self.reader = Some(reader);
56
57 if part_header.uuid != self.header.uuid {
58 proxmox::io_bail!("got wrong part uuid");
59 }
60 if part_header.content_magic!= self.header.content_magic {
61 proxmox::io_bail!("got wrong part content magic");
62 }
63
64 let expect_part_number = self.header.part_number + 1;
65
66 if part_header.part_number != expect_part_number {
67 proxmox::io_bail!("got wrong part number ({} != {})",
68 part_header.part_number, expect_part_number);
69 }
70
71 self.header.part_number = expect_part_number;
72
73 Ok(())
74 }).map_err(|err| {
75 proxmox::io_format_err!("multi-volume read content header failed: {}", err)
76 })?;
77 }
78
79 match self.reader {
80 None => unreachable!(),
81 Some(ref mut reader) => {
82 match reader.read(buf) {
83 Ok(0) => {
84 if reader.is_incomplete()? {
85 self.reader = None;
86 self.read(buf)
87 } else {
88 self.reader = None;
89 self.complete = true;
90 Ok(0)
91 }
92 }
93 Ok(n) => Ok(n),
94 Err(err) => Err(err)
95 }
96 }
97 }
98 }
99}