FUSE 2.9 added support for zero copy reads/writes through two new
callbacks, read_buf and write_buf. We now imeplement read_buf,
which iterates over the bands using the generic code, but instead
of opening and reading the content of the band into memory, we just
open the file and pass a structure back to FUSE with the file
descriptor, size, and offset, and FUSE will then use this on the
kernel side if possible (using splice on GNU/Linux).
For padding with zeroes we open /dev/zero and treat it as any
other file.
Since FUSE does not provide a callback when it's done with the
buffers there's no way for us to know when to close the bands
we opened. To work around this we keep the files open until
either the main image (dmg) file has been closed, or we run
out of file descriptors, at which point we gc the open files
and continue.
If a read was requested at an offset just before the end of a band,
with a length sufficiently large to cross over to the next band, we
would pad the remaining space after the initial band with zeroes,
and never proceed to read the second band.
We now limit the size of each consecutive band read to the end of the
band, so that the while loop will correctly continue with the next
band if there's still more data to be read.
Adds some sanity checking of the 'size' and 'band-size' values from the
Info.plist file, and ensures they are within the range of off_t, which
happens to be 64 bit due to FUSE forcing the use of _FILE_OFFSET_BITS=64.
We should perhaps check if PKG_CONFIG_PATH has been set, which would
indicate that the FUSE libraries are in a non-default location, but
for now this is okey.