summary refs log tree commit diff
path: root/qcow/src/qcow.rs
diff options
context:
space:
mode:
Diffstat (limited to 'qcow/src/qcow.rs')
-rw-r--r--qcow/src/qcow.rs136
1 files changed, 1 insertions, 135 deletions
diff --git a/qcow/src/qcow.rs b/qcow/src/qcow.rs
index 57e42fc..3153df1 100644
--- a/qcow/src/qcow.rs
+++ b/qcow/src/qcow.rs
@@ -46,7 +46,6 @@ pub enum Error {
     NoRefcountClusters,
     NotEnoughSpaceForRefcounts,
     OpeningFile(io::Error),
-    ReadingData(io::Error),
     ReadingHeader(io::Error),
     ReadingPointers(io::Error),
     ReadingRefCountBlock(refcount::Error),
@@ -55,14 +54,12 @@ pub enum Error {
     RefcountTableOffEnd,
     RefcountTableTooLarge,
     SeekingFile(io::Error),
-    SettingFileSize(io::Error),
     SettingRefcountRefcount(io::Error),
     SizeTooSmallForNumberOfClusters,
     TooManyL1Entries(u64),
     TooManyRefcounts(u64),
     UnsupportedRefcountOrder,
     UnsupportedVersion(u32),
-    WritingData(io::Error),
     WritingHeader(io::Error),
 }
 
@@ -98,7 +95,6 @@ impl Display for Error {
             NoRefcountClusters => write!(f, "no refcount clusters"),
             NotEnoughSpaceForRefcounts => write!(f, "not enough space for refcounts"),
             OpeningFile(e) => write!(f, "failed to open file: {}", e),
-            ReadingData(e) => write!(f, "failed to read data: {}", e),
             ReadingHeader(e) => write!(f, "failed to read header: {}", e),
             ReadingPointers(e) => write!(f, "failed to read pointers: {}", e),
             ReadingRefCountBlock(e) => write!(f, "failed to read ref count block: {}", e),
@@ -107,29 +103,22 @@ impl Display for Error {
             RefcountTableOffEnd => write!(f, "refcount table offset past file end"),
             RefcountTableTooLarge => write!(f, "too many clusters specified for refcount table"),
             SeekingFile(e) => write!(f, "failed to seek file: {}", e),
-            SettingFileSize(e) => write!(f, "failed to set file size: {}", e),
             SettingRefcountRefcount(e) => write!(f, "failed to set refcount refcount: {}", e),
             SizeTooSmallForNumberOfClusters => write!(f, "size too small for number of clusters"),
             TooManyL1Entries(count) => write!(f, "l1 entry table too large: {}", count),
             TooManyRefcounts(count) => write!(f, "ref count table too large: {}", count),
             UnsupportedRefcountOrder => write!(f, "unsupported refcount order"),
             UnsupportedVersion(v) => write!(f, "unsupported version: {}", v),
-            WritingData(e) => write!(f, "failed to write data: {}", e),
             WritingHeader(e) => write!(f, "failed to write header: {}", e),
         }
     }
 }
 
-pub enum ImageType {
-    Raw,
-    Qcow2,
-}
-
 // Maximum data size supported.
 const MAX_QCOW_FILE_SIZE: u64 = 0x01 << 44; // 16 TB.
 
 // QCOW magic constant that starts the header.
-const QCOW_MAGIC: u32 = 0x5146_49fb;
+pub const QCOW_MAGIC: u32 = 0x5146_49fb;
 // Default to a cluster size of 2^DEFAULT_CLUSTER_BITS
 const DEFAULT_CLUSTER_BITS: u32 = 16;
 // Limit clusters to reasonable sizes. Choose the same limits as qemu. Making the clusters smaller
@@ -1599,129 +1588,6 @@ fn div_round_up_u32(dividend: u32, divisor: u32) -> u32 {
     dividend / divisor + if dividend % divisor != 0 { 1 } else { 0 }
 }
 
-fn convert_copy<R, W>(reader: &mut R, writer: &mut W, offset: u64, size: u64) -> Result<()>
-where
-    R: Read + Seek,
-    W: Write + Seek,
-{
-    const CHUNK_SIZE: usize = 65536;
-    let mut buf = [0; CHUNK_SIZE];
-    let mut read_count = 0;
-    reader
-        .seek(SeekFrom::Start(offset))
-        .map_err(Error::SeekingFile)?;
-    writer
-        .seek(SeekFrom::Start(offset))
-        .map_err(Error::SeekingFile)?;
-    loop {
-        let this_count = min(CHUNK_SIZE as u64, size - read_count) as usize;
-        let nread = reader
-            .read(&mut buf[..this_count])
-            .map_err(Error::ReadingData)?;
-        writer.write(&buf[..nread]).map_err(Error::WritingData)?;
-        read_count += nread as u64;
-        if nread == 0 || read_count == size {
-            break;
-        }
-    }
-
-    Ok(())
-}
-
-fn convert_reader_writer<R, W>(reader: &mut R, writer: &mut W, size: u64) -> Result<()>
-where
-    R: Read + Seek + SeekHole,
-    W: Write + Seek,
-{
-    let mut offset = 0;
-    while offset < size {
-        // Find the next range of data.
-        let next_data = match reader.seek_data(offset).map_err(Error::SeekingFile)? {
-            Some(o) => o,
-            None => {
-                // No more data in the file.
-                break;
-            }
-        };
-        let next_hole = match reader.seek_hole(next_data).map_err(Error::SeekingFile)? {
-            Some(o) => o,
-            None => {
-                // This should not happen - there should always be at least one hole
-                // after any data.
-                return Err(Error::SeekingFile(io::Error::from_raw_os_error(EINVAL)));
-            }
-        };
-        let count = next_hole - next_data;
-        convert_copy(reader, writer, next_data, count)?;
-        offset = next_hole;
-    }
-
-    Ok(())
-}
-
-fn convert_reader<R>(reader: &mut R, dst_file: File, dst_type: ImageType) -> Result<()>
-where
-    R: Read + Seek + SeekHole,
-{
-    let src_size = reader.seek(SeekFrom::End(0)).map_err(Error::SeekingFile)?;
-    reader
-        .seek(SeekFrom::Start(0))
-        .map_err(Error::SeekingFile)?;
-
-    // Ensure the destination file is empty before writing to it.
-    dst_file.set_len(0).map_err(Error::SettingFileSize)?;
-
-    match dst_type {
-        ImageType::Qcow2 => {
-            let mut dst_writer = QcowFile::new(dst_file, src_size)?;
-            convert_reader_writer(reader, &mut dst_writer, src_size)
-        }
-        ImageType::Raw => {
-            let mut dst_writer = dst_file;
-            // Set the length of the destination file to convert it into a sparse file
-            // of the desired size.
-            dst_writer
-                .set_len(src_size)
-                .map_err(Error::SettingFileSize)?;
-            convert_reader_writer(reader, &mut dst_writer, src_size)
-        }
-    }
-}
-
-/// Copy the contents of a disk image in `src_file` into `dst_file`.
-/// The type of `src_file` is automatically detected, and the output file type is
-/// determined by `dst_type`.
-pub fn convert(src_file: File, dst_file: File, dst_type: ImageType) -> Result<()> {
-    let src_type = detect_image_type(&src_file)?;
-    match src_type {
-        ImageType::Qcow2 => {
-            let mut src_reader = QcowFile::from(src_file)?;
-            convert_reader(&mut src_reader, dst_file, dst_type)
-        }
-        ImageType::Raw => {
-            // src_file is a raw file.
-            let mut src_reader = src_file;
-            convert_reader(&mut src_reader, dst_file, dst_type)
-        }
-    }
-}
-
-/// Detect the type of an image file by checking for a valid qcow2 header.
-pub fn detect_image_type(file: &File) -> Result<ImageType> {
-    let mut f = file;
-    let orig_seek = f.seek(SeekFrom::Current(0)).map_err(Error::SeekingFile)?;
-    f.seek(SeekFrom::Start(0)).map_err(Error::SeekingFile)?;
-    let magic = read_u32_from_file(f)?;
-    let image_type = if magic == QCOW_MAGIC {
-        ImageType::Qcow2
-    } else {
-        ImageType::Raw
-    };
-    f.seek(SeekFrom::Start(orig_seek))
-        .map_err(Error::SeekingFile)?;
-    Ok(image_type)
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;