What about the `seek` argument which skips over some blocks at the beginning but still allocates them (unix "holes")?
Also note that there are still unix systems out there which do not support byte-level granularity of access to block devices. On those devices you must actually use a buffer of exactly the size of the blocks on the device. Heck, linux was like this until at least v2.