I need to construct, in code suitable for scripting/make/automation, a disk image (two partitions, a FAT filesystem and an ext4 filesystem, for UEFI/Syslinux USB Linux booting [OS installer], which will never change in production) of a size that holds exactly (or very close to) a set of files of arbitrary size. In other words given a set of built files, I need to know how to generate FAT and ext4 filesystem images, and the disk image that is partitioned to hold them, that have sizes computed to result in as close to zero space free as reasonable to have. It's OK to err on the side of a little extra room but it's not OK to fail when someone adds N+1 bytes to the file two years from now. This needs to be suitable for a makefile, i.e., trial and error doesn't cut it (although I suppose if worse came to worst, an iterative solution with a threshold might work). This is something like an ISO-9660 image (which it used to be on a previous project, but Syslinux doesn't support ISO-9660 images on UEFI).
I'm creating the files using dd
(to allocate the disk image), parted
, dd
(to allocation the FAT filesystem), mkfs.vfat
, dd
(for the ext4), mkfs.ext4
, kpartx
(to map the partitions), dd
(to write the FAT partition), dd
(to write the ext4 partition), and finally dd
to write the disk image to a USB for booting on actual hardware.
My current idea is to use du
to determine how much space the files take on the build disk, then add some margin for additional filesystem and partition overhead, and margin of error. So I need to know the block counts for each of the dd
's given the du
outputs.
Another option is to construct a fixed-size large image, write the files, then resize the FAT, ext4, and partitions to minimum size. ext4 filesystems can be shrunk and I see FAT filesystems can be shrunk. But then you're still left with the problem of computing how much to shrink it to. Wondering if anyone has done this before had has some concrete ideas (or sample code).