text: #ifndef MINIVHD_IO_H
  #define MINIVHD_IO_H
  #include "minivhd.h"
  
  /**
   * \brief Write zero filled sectors to file.
   * 
   * Note, the caller should set the file position before calling this 
   * function for correct operation.
   * 
   * \param [in] f File to write sectors to
   * \param [in] sector_count The number of sectors to write
   */
  void mvhd_write_empty_sectors(FILE* f, int sector_count);
  
  /**
   * \brief Read a fixed VHD image
   * 
   * Fixed VHD images are essentially raw image files with a footer tacked on 
   * the end. They are therefore straightforward to write
   * 
   * \param [in] vhdm MiniVHD data structure
   * \param [in] offset Sector offset to read from
   * \param [in] num_sectors The desired number of sectors to read
   * \param [out] out_buff An output buffer to store read sectors. Must be 
   * large enough to hold num_sectors worth of sectors.
   * 
   * \retval 0 num_sectors were read from file
   * \retval >0 < num_sectors were read from file
   */
  int mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff);
  
  /**
   * \brief Read a sparse VHD image
   * 
   * Sparse, or dynamic images are VHD images that grow as data is written to them. 
   * 
   * This function implements the logic to read sectors from the file, taking into 
   * account the fact that blocks may be stored on disk in any order, and that the 
   * read could cross block boundaries.
   * 
   * \param [in] vhdm MiniVHD data structure
   * \param [in] offset Sector offset to read from
   * \param [in] num_sectors The desired number of sectors to read
   * \param [out] out_buff An output buffer to store read sectors. Must be 
   * large enough to hold num_sectors worth of sectors.
   * 
   * \retval 0 num_sectors were read from file
   * \retval >0 < num_sectors were read from file
   */
  int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff);
  
  /**
   * \brief Read a differencing VHD image
   * 
   * Differencing images are a variant of a sparse image. They contain the grow-on-demand 
   * properties of sparse images, but also reference a parent image. Data is read from the 
   * child image only if it is newer than the data stored in the parent image.
   * 
   * This function implements the logic to read sectors from the child, or a parent image. 
   * Differencing images may have a differencing image as a parent, creating a chain of images. 
   * There is no theoretical chain length limit, although I do not consider long chains to be 
   * advisable. Verifying the parent-child relationship is not very robust.
   * 
   * \param [in] vhdm MiniVHD data structure
   * \param [in] offset Sector offset to read from
   * \param [in] num_sectors The desired number of sectors to read
   * \param [out] out_buff An output buffer to store read sectors. Must be 
   * large enough to hold num_sectors worth of sectors.
   * 
   * \retval 0 num_sectors were read from file
   * \retval >0 < num_sectors were read from file
   */
  int mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff);
  
  /**
   * \brief Write to a fixed VHD image
   * 
   * Fixed VHD images are essentially raw image files with a footer tacked on 
   * the end. They are therefore straightforward to write
   * 
   * \param [in] vhdm MiniVHD data structure
   * \param [in] offset Sector offset to write to
   * \param [in] num_sectors The desired number of sectors to write
   * \param [in] in_buff A source buffer to write sectors from. Must be 
   * large enough to hold num_sectors worth of sectors.
   * 
   * \retval 0 num_sectors were written to file
   * \retval >0 < num_sectors were written to file
   */
  int mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff);
  
  /**
   * \brief Write to a sparse or differencing VHD image
   * 
   * Sparse, or dynamic images are VHD images that grow as data is written to them. 
   * 
   * Differencing images are a variant of a sparse image. They contain the grow-on-demand 
   * properties of sparse images, but also reference a parent image. Data is always written 
   * to the child image. This makes writing to differencing images essentially identical to 
   * writing to sparse images, hence they use the same function.
   * 
   * This function implements the logic to write sectors to the file, taking into 
   * account the fact that blocks may be stored on disk in any order, and that the 
   * write operation could cross block boundaries.
   * 
   * \param [in] vhdm MiniVHD data structure
   * \param [in] offset Sector offset to write to
   * \param [in] num_sectors The desired number of sectors to write
   * \param [in] in_buff A source buffer to write sectors from. Must be 
   * large enough to hold num_sectors worth of sectors.
   * 
   * \retval 0 num_sectors were written to file
   * \retval >0 < num_sectors were written to file
   */
  int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff);
  
  /**
   * \brief A no-op function to "write" to read-only VHD images
   * 
   * \param [in] vhdm MiniVHD data structure
   * \param [in] offset Sector offset to write to
   * \param [in] num_sectors The desired number of sectors to write
   * \param [in] in_buff A source buffer to write sectors from. Must be 
   * large enough to hold num_sectors worth of sectors.
   * 
   * \retval 0 num_sectors were written to file
   * \retval >0 < num_sectors were written to file
   */
  int mvhd_noop_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff);
  
  #endif