pub fn write(
    f: &mut File,
    buf: &[u8],
    disk_spec: &mut DiskSpec,
    bat_offset: u64,
    bat: &mut [BatEntry],
    mut sector_index: u64,
    mut sector_count: u64,
) -> Result<usize> {
    let mut write_count: usize = 0;

    while sector_count > 0 {
        if disk_spec.has_parent {
            return Err(VhdxIoError::UnsupportedMode);
        } else {
            let sector = Sector::new(disk_spec, bat, sector_index, sector_count)?;

            let bat_entry = match bat.get(sector.bat_index as usize) {
                Some(entry) => entry.0,
                None => {
                    return Err(VhdxIoError::InvalidBatIndex);
                }
            };

            match bat_entry & vhdx_bat::BAT_STATE_BIT_MASK {
                vhdx_bat::PAYLOAD_BLOCK_NOT_PRESENT
                | vhdx_bat::PAYLOAD_BLOCK_UNDEFINED
                | vhdx_bat::PAYLOAD_BLOCK_UNMAPPED
                | vhdx_bat::PAYLOAD_BLOCK_ZERO => {
                    let file_offset =
                        align!(disk_spec.image_size, vhdx_metadata::BLOCK_SIZE_MIN as u64);
                    let new_size = file_offset
                        .checked_add(disk_spec.block_size as u64)
                        .ok_or(VhdxIoError::InvalidDiskSize)?;

                    f.set_len(new_size).map_err(VhdxIoError::ResizeFile)?;
                    disk_spec.image_size = new_size;

                    let new_bat_entry = file_offset
                        | (vhdx_bat::PAYLOAD_BLOCK_FULLY_PRESENT & vhdx_bat::BAT_STATE_BIT_MASK);
                    bat[sector.bat_index as usize] = BatEntry(new_bat_entry);
                    BatEntry::write_bat_entries(f, bat_offset, bat)
                        .map_err(VhdxIoError::WriteBat)?;

                    if file_offset < vhdx_metadata::BLOCK_SIZE_MIN as u64 {
                        break;
                    }

                    f.seek(SeekFrom::Start(file_offset))
                        .map_err(VhdxIoError::ReadSectorBlock)?;
                    f.write_all(
                        &buf[write_count
                            ..(write_count + (sector.free_sectors * SECTOR_SIZE) as usize)],
                    )
                    .map_err(VhdxIoError::ReadSectorBlock)?;
                }
                vhdx_bat::PAYLOAD_BLOCK_FULLY_PRESENT => {
                    if sector.file_offset < vhdx_metadata::BLOCK_SIZE_MIN as u64 {
                        break;
                    }

                    f.seek(SeekFrom::Start(sector.file_offset))
                        .map_err(VhdxIoError::ReadSectorBlock)?;
                    f.write_all(
                        &buf[write_count
                            ..(write_count + (sector.free_sectors * SECTOR_SIZE) as usize)],
                    )
                    .map_err(VhdxIoError::ReadSectorBlock)?;
                }
                vhdx_bat::PAYLOAD_BLOCK_PARTIALLY_PRESENT => {
                    return Err(VhdxIoError::UnsupportedMode);
                }
                _ => {
                    return Err(VhdxIoError::InvalidBatEntryState);
                }
            };
            sector_count -= sector.free_sectors;
            sector_index += sector.free_sectors;
            write_count = sector.free_bytes as usize;
        };
    }
    Ok(write_count)
}
/// VHDx IO write routine: requires relative sector index and count for the
/// requested data.
VHDx IO write routine: requires relative sector index and count for the
requested data.
VHDx IO write routine : requires relative sector index and count for the requested data .
pub fn write(
    f: &mut File,
    buf: &[u8],
    disk_spec: &mut DiskSpec,
    bat_offset: u64,
    bat: &mut [BatEntry],
    mut sector_index: u64,
    mut sector_count: u64,
) -> Result<usize> {
    let mut write_count: usize = 0;
    while sector_count > 0 {
        if disk_spec.has_parent {
            return Err(VhdxIoError::UnsupportedMode);
        } else {
            let sector = Sector::new(disk_spec, bat, sector_index, sector_count)?;
            let bat_entry = match bat.get(sector.bat_index as usize) {
                Some(entry) => entry.0,
                None => {
                    return Err(VhdxIoError::InvalidBatIndex);
                }
            };
            match bat_entry & vhdx_bat::BAT_STATE_BIT_MASK {
                vhdx_bat::PAYLOAD_BLOCK_NOT_PRESENT
                | vhdx_bat::PAYLOAD_BLOCK_UNDEFINED
                | vhdx_bat::PAYLOAD_BLOCK_UNMAPPED
                | vhdx_bat::PAYLOAD_BLOCK_ZERO => {
                    let file_offset =
                        align!(disk_spec.image_size, vhdx_metadata::BLOCK_SIZE_MIN as u64);
                    let new_size = file_offset
                        .checked_add(disk_spec.block_size as u64)
                        .ok_or(VhdxIoError::InvalidDiskSize)?;
                    f.set_len(new_size).map_err(VhdxIoError::ResizeFile)?;
                    disk_spec.image_size = new_size;
                    let new_bat_entry = file_offset
                        | (vhdx_bat::PAYLOAD_BLOCK_FULLY_PRESENT & vhdx_bat::BAT_STATE_BIT_MASK);
                    bat[sector.bat_index as usize] = BatEntry(new_bat_entry);
                    BatEntry::write_bat_entries(f, bat_offset, bat)
                        .map_err(VhdxIoError::WriteBat)?;
                    if file_offset < vhdx_metadata::BLOCK_SIZE_MIN as u64 {
                        break;
                    }
                    f.seek(SeekFrom::Start(file_offset))
                        .map_err(VhdxIoError::ReadSectorBlock)?;
                    f.write_all(
                        &buf[write_count
                            ..(write_count + (sector.free_sectors * SECTOR_SIZE) as usize)],
                    )
                    .map_err(VhdxIoError::ReadSectorBlock)?;
                }
                vhdx_bat::PAYLOAD_BLOCK_FULLY_PRESENT => {
                    if sector.file_offset < vhdx_metadata::BLOCK_SIZE_MIN as u64 {
                        break;
                    }
                    f.seek(SeekFrom::Start(sector.file_offset))
                        .map_err(VhdxIoError::ReadSectorBlock)?;
                    f.write_all(
                        &buf[write_count
                            ..(write_count + (sector.free_sectors * SECTOR_SIZE) as usize)],
                    )
                    .map_err(VhdxIoError::ReadSectorBlock)?;
                }
                vhdx_bat::PAYLOAD_BLOCK_PARTIALLY_PRESENT => {
                    return Err(VhdxIoError::UnsupportedMode);
                }
                _ => {
                    return Err(VhdxIoError::InvalidBatEntryState);
                }
            };
            sector_count -= sector.free_sectors;
            sector_index += sector.free_sectors;
            write_count = sector.free_bytes as usize;
        };
    }
    Ok(write_count)
}
pub fn write ( f : & mut File , buf : & [ u8 ] , disk_spec : & mut DiskSpec , bat_offset : u64 , bat : & mut [ BatEntry ] , mut sector_index : u64 , mut sector_count : u64 , ) -> Result < usize > { let mut write_count : usize = 0 ; while sector_count > 0 { if disk_spec . has_parent { return Err ( VhdxIoError :: UnsupportedMode ) ; } else { let sector = Sector :: new ( disk_spec , bat , sector_index , sector_count ) ? ; let bat_entry = match bat . get ( sector . bat_index as usize ) { Some ( entry ) => entry . 0 , None => { return Err ( VhdxIoError :: InvalidBatIndex ) ; } } ; match bat_entry & vhdx_bat :: BAT_STATE_BIT_MASK { vhdx_bat :: PAYLOAD_BLOCK_NOT_PRESENT | vhdx_bat :: PAYLOAD_BLOCK_UNDEFINED | vhdx_bat :: PAYLOAD_BLOCK_UNMAPPED | vhdx_bat :: PAYLOAD_BLOCK_ZERO => { let file_offset = align ! ( disk_spec image_size vhdx_metadata BLOCK_SIZE_MIN as u64 ) ; let new_size = file_offset . checked_add ( disk_spec . block_size as u64 ) . ok_or ( VhdxIoError :: InvalidDiskSize ) ? ; f . set_len ( new_size ) . map_err ( VhdxIoError :: ResizeFile ) ? ; disk_spec . image_size = new_size ; let new_bat_entry = file_offset | ( vhdx_bat :: PAYLOAD_BLOCK_FULLY_PRESENT & vhdx_bat :: BAT_STATE_BIT_MASK ) ; bat [ sector . bat_index as usize ] = BatEntry ( new_bat_entry ) ; BatEntry :: write_bat_entries ( f , bat_offset , bat ) . map_err ( VhdxIoError :: WriteBat ) ? ; if file_offset < vhdx_metadata :: BLOCK_SIZE_MIN as u64 { break ; } f . seek ( SeekFrom :: Start ( file_offset ) ) . map_err ( VhdxIoError :: ReadSectorBlock ) ? ; f . write_all ( & buf [ write_count .. ( write_count + ( sector . free_sectors * SECTOR_SIZE ) as usize ) ] , ) . map_err ( VhdxIoError :: ReadSectorBlock ) ? ; } vhdx_bat :: PAYLOAD_BLOCK_FULLY_PRESENT => { if sector . file_offset < vhdx_metadata :: BLOCK_SIZE_MIN as u64 { break ; } f . seek ( SeekFrom :: Start ( sector . file_offset ) ) . map_err ( VhdxIoError :: ReadSectorBlock ) ? ; f . write_all ( & buf [ write_count .. ( write_count + ( sector . free_sectors * SECTOR_SIZE ) as usize ) ] , ) . map_err ( VhdxIoError :: ReadSectorBlock ) ? ; } vhdx_bat :: PAYLOAD_BLOCK_PARTIALLY_PRESENT => { return Err ( VhdxIoError :: UnsupportedMode ) ; } _ => { return Err ( VhdxIoError :: InvalidBatEntryState ) ; } } ; sector_count -= sector . free_sectors ; sector_index += sector . free_sectors ; write_count = sector . free_bytes as usize ; } ; } Ok ( write_count ) }
VHDx IO write routine: requires relative sector index and count for the
requested data.
VHDx IO write routine : requires relative sector index and count for the requested data .
f
&mut File
buf
&[u8]
disk_spec
&mut DiskSpec
bat_offset
u64
bat
&mut [BatEntry]
sector_index
u64
sector_count
u64
f
&mut File
buf
&[u8]
disk_spec
&mut DiskSpec
bat_offset
u64
bat
&mut [BatEntry]
sector_index
u64
sector_count
u64