static uint64_t vhd_resize(uint64_t origsz) { struct vhd_geom geom; uint64_t newsz; /* * Round the image size to the pre-determined geometry that * matches the image size. This circular dependency implies * that we need to loop to handle boundary conditions. * The first time, newsz equals origsz and the geometry will * typically yield a new size that's smaller. We keep adding * cylinder's worth of sectors to the new size until its * larger or equal or origsz. But during those iterations, * the geometry can change, so we need to account for that. */ newsz = origsz; while (1) { vhd_geometry(newsz, &geom); newsz = (int64_t)geom.cylinders * geom.heads * geom.sectors * VHD_SECTOR_SIZE; if (newsz >= origsz) break; newsz += geom.heads * geom.sectors * VHD_SECTOR_SIZE; } return (newsz); }
static int vhd_fix_resize(lba_t imgsz) { struct vhd_geom geom; int64_t imagesz; /* * Round the image size to the pre-determined geometry that * matches the image size. This circular dependency implies * that we need to loop to handle boundary conditions. */ imgsz *= secsz; imagesz = imgsz; while (1) { vhd_geometry(imagesz, &geom); imagesz = (int64_t)geom.cylinders * geom.heads * geom.sectors * VHD_SECTOR_SIZE; if (imagesz >= imgsz) break; imagesz += geom.heads * geom.sectors * VHD_SECTOR_SIZE; } /* * Azure demands that images are a whole number of megabytes. */ imagesz = (imagesz + 0xfffffULL) & ~0xfffffULL; return (image_set_size(imagesz / secsz)); }
static void vhd_make_footer(struct vhd_footer *footer, uint64_t image_size, uint32_t disk_type, uint64_t data_offset) { uuid_t id; memset(footer, 0, sizeof(*footer)); be64enc(&footer->cookie, VHD_FOOTER_COOKIE); be32enc(&footer->features, VHD_FEATURES_RESERVED); be32enc(&footer->version, VHD_VERSION); be64enc(&footer->data_offset, data_offset); be32enc(&footer->timestamp, vhd_timestamp()); be32enc(&footer->creator_tool, VHD_CREATOR_TOOL); be32enc(&footer->creator_version, VHD_CREATOR_VERSION); be32enc(&footer->creator_os, VHD_CREATOR_OS); be64enc(&footer->original_size, image_size); be64enc(&footer->current_size, image_size); vhd_geometry(footer, image_size); be32enc(&footer->disk_type, disk_type); mkimg_uuid(&id); vhd_uuid_enc(&footer->id, &id); be32enc(&footer->checksum, vhd_checksum(footer, sizeof(*footer))); }