1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
#![warn(missing_docs)] //! This crate can parse and read qcow2 virtual disks, as used by qemu and other emulators. //! //! [Qcow2](https://en.wikipedia.org/wiki/Qcow) is a flexible format for disk images, that only //! allocates space as needed. It has many other interesting features. //! //! The following featuers are supported by this crate: //! //! * Reading blocks of virtual disk data. //! * Reading data that is not aligned to block boundaries. //! * Parsing and validation of the header. //! * Reporting the names of any unsupported features, using the "feature name table" extension. //! * Basic caching of guest data locations, so nearby reads will be fast. //! //! These features are not yet supported, but should be easy to add: //! //! * Listing and reading snapshots. //! * Reading version 2, currently only version 3 is supported. //! * Reading compressed data. //! * Backing file support, so you can chain qcow2 files together. //! * Reporting information about images. //! //! These features are harder, or less interesting to me. Patches welcome! //! //! * Reading encrypted qcow2 files. //! * Writing virtual disk data. //! * Repairing the disk if refcounts are out of date. //! * Compacting the virtual disk so it takes less space. //! * Maintaining a "dirty bitmap" to make backups faster. //! * Creating new qcow2 images. //! * Creating new snapshots. //! * Checking qcow2 images for inconsistencies. //! * Merging images into their backing file. //! * Resizing images. //! //! The repository for this crate is at https://github.com/vasi/qcow2-rs extern crate byteorder; extern crate lru_cache; extern crate positioned_io; mod error; mod extension; mod feature; mod header; mod int; mod read; pub use error::Error; pub use read::Reader; use std::fmt::{self, Debug, Formatter}; use std::result; use std::sync::Mutex; use byteorder::BigEndian; use lru_cache::LruCache; use positioned_io::{ReadAt, ByteIo}; const L2_CACHE_SIZE: usize = 32; /// A qcow2 image. /// /// # Examples /// /// ```no_run /// extern crate positioned_io; /// extern crate qcow2; /// /// # use std::fs::File; /// use positioned_io::ReadAt; /// use qcow2::Qcow2; /// /// # fn foo() -> qcow2::Result<()> { /// /// // Open a file. /// let file = try!(File::open("image.qcow2")); /// let qcow = try!(Qcow2::open(file)); /// /// // Read some data. /// let reader = try!(qcow.reader()); /// let mut buf = vec![0, 4096]; /// try!(reader.read_exact_at(5 * 1024 * 1024, &mut buf)); /// /// # Ok(()) } fn main() { foo().unwrap(); } /// ``` pub struct Qcow2<I> where I: ReadAt { header: header::Header, io: ByteIo<I, BigEndian>, l2_cache: Mutex<LruCache<u64, u64>>, } /// The result type for operations on qcow2 images. pub type Result<T> = std::result::Result<T, Error>; impl<I> Qcow2<I> where I: ReadAt { /// Open a source of data as a qcow2 image. /// /// Usually the data source `io` will be a file. pub fn open(io: I) -> Result<Self> { let io: ByteIo<_, BigEndian> = ByteIo::new(io); let mut q = Qcow2 { header: Default::default(), io: io, l2_cache: Mutex::new(LruCache::new(L2_CACHE_SIZE)), }; try!(q.header.read(&mut q.io)); Ok(q) } /// Get the size of each block of this qcow2 image. pub fn cluster_size(&self) -> u64 { self.header.cluster_size() } /// Get the size of the virtual image. /// /// This is likely to differ from the size of the qcow2 file itself, since the file can grow. pub fn guest_size(&self) -> u64 { self.header.guest_size() } } impl<I> Debug for Qcow2<I> where I: ReadAt { fn fmt(&self, f: &mut Formatter) -> result::Result<(), fmt::Error> { f.debug_struct("Qcow2") .field("header", &self.header) .finish() } }