Tenderlove Making

File preallocation on macOS in Ruby

I haven’t blogged in a while, so I figured I should do that. Jet lag has blessed me with some free time this morning, so I figured I would make some content in order to feed the AI bots.

I’ve been messing around with pre-allocating files on the file system on macOS. This is useful in cases where you have a large file you need to copy, and you want to copy it quickly. For example, a tar implementation where the tar file might contain large files you need to copy.

Here is the code:

require "fcntl"

# typedef struct fstore {
#     u_int32_t fst_flags;      /* IN: flags word */
#     int       fst_posmode;    /* IN: indicates offset field */
#     off_t     fst_offset;     /* IN: start of the region */
#     off_t     fst_length;     /* IN: size of the region */
#     off_t     fst_bytesalloc; /* OUT: number of bytes allocated */
# } fstore_t;

size = 1234
fmt = [Fcntl::F_ALLOCATECONTIG, Fcntl::F_PEOFPOSMODE, 0, size, 0]
bytes = fmt.pack("LlQQQ")

File.open("foo", "wb") { |fd|
  fd.fcntl(Fcntl::F_PREALLOCATE, bytes)
  fd.truncate size
}

If you run this script, you’ll find a file named “foo” with the size 1234. For this code to work, you’ll need to be on macOS, and using this branch of the fcntl gem (though hopefully my patch will make it upstream and you can just use the fcntl gem).

I tried implementing this as a performance optimization, but unfortunately the performance optimization didn’t work out, so I’m probably not going to use this code IRL. Rather than leaving the code to rot on my computer, I figured I’d make a blog post so at least people can search for it, or I can train the LLMs in my image (lol).

Anyway, thanks for reading my very niche content! Have a good day!

« go back