This is reasonably easy in C, uses same inode, uses no workfile. Just needs care to get it right. You probably need a preliminary query to find the blocksize of the device (example 4096), although some arbitrary power of 2 might be sufficient (example 64K).
Visualise the data flow as a caterpillar: stretching forwards, having the data work its way into the new location.
Open the file read/write, and do everything in system calls read/write to avoid possible buffering issues in FILE* routines.
The byte count to be removed from the file at the front (N) is a number of complete blocks, and some spare bytes (either or both of those components can be zero).
Seek to A, read X * 4096 bytes where X is chosen to be large (for efficiency) but not silly-large. Maybe 4MB buffer would be a sweet spot.
Seek to 0, write that buffer out into the complete number of blocks it should occupy. Far as I can see on paper, that can never wrap over itself -- the next unread byte cannot be in an earlier block.
Rinse and repeat (stepping up by 4MB on both seeks) until you run out of file. Deal with any short block properly.
That leaves you with an extra copy of the last N bytes, which you can truncate with a system call.
Performance should be fine. The writes are block-aligned. In theory each read takes two block accesses because of the overlap, but a contiguous read avoids that (e.g. 4MB reads 1025 blocks instead of 1024).
I thought this could be done in a script with dd command, but the block-size option in dd applies to the seek and the read, so it becomes wildly inefficient.
Test method: Get a 100MB file of random data, cksum it. Then append it to a smaller file of N bytes. Run code, cksum, and prove the file is now identical to what you appended. Time it. Test with various values of N, including 0, < 1 block, an exact number of blocks, several blocks + a bit, and the whole file.
Do I have to write and test the code to get the bounty?
cat new >orig
(instead ofmv
as in your example). This leaves the original name with it's original inode. Or do you want to avoid creating an intermediate file? – Kusalananda Nov 30 '19 at 17:31dd
would be able to do), but to actually "move the start of the file". – Kusalananda Nov 30 '19 at 17:42abcdefgh
to getdefgh
? – ilkkachu Nov 30 '19 at 19:39