Someone recently asked an interesting question: Why do Microsoft C and compatible DOS compilers have no truncate() and/or ftruncate() library functions? And how does one resize files on DOS?

OK, that’s actually two questions. The first one is easy enough to answer: Because XENIX had no truncate() or ftruncate() either. Instead, XENIX had a chsize() function which, sure enough, can be found in the Microsoft C libraries at least as far back as MS C 3.0 (early 1985).

The second question is rather more interesting. The way files are resized on DOS is moving the file pointer to the desired size by calling the LSEEK function (INT 21h/42h), and then calling the WRITE function (INT 21h/40h) with zero length (CX=0).

Now, this mechanism is rather curious, because the handle-based file API in DOS 2.0 was modeled on XENIX, yet on UNIX systems, the write() function asked to transfer zero bytes simply does nothing. If the mechanism didn’t come from XENIX, where did it come from?

I thought I’d check the DOS 2.x source code. But the $Write function in XENIX2.ASM has absolutely no special handling of zero-size writes. It just performs common setup code and hands off the real work to $FCB_RANDOM_WRITE_BLOCK .

Was this behavior some kind of oversight? No, certainly not. The MS-DOS 2.0 Programmer’s Reference Manual is quite clear that writing zero bytes either truncates or extends a file.

But the source code points in the right direction. $FCB_RANDOM_WRITE_BLOCK is in fact INT 21h/28h. And that function is documented to change the file size when called with CX=0.

Is this some kind of CP/M heritage? No, it’s not. CP/M 2.2 had no mechanism for resizing files, and CP/M 3 had a separate BDOS function to change file size, nothing like the DOS mechanism.

In fact this method of resizing files is unambiguously documented in the 86-DOS 0.3 Programmer’s Manual, published in 1980. It is also documented in the preliminary 86-DOS manual of unclear vintage; in that version, the functionality is only document to truncate files, not extend them. In the 86-DOS 0.3 manual, the documentation clearly states that both truncating and extending files can be achieved using this method.

It is thus clear that the DOS method of resizing files through zero-length writes originated in 86-DOS in 1980, and it is more or less guaranteed to be Tim Paterson’s invention. The 86-DOS method was adopted for handle-based I/O in DOS 2.0 by default, because the handle-based I/O was layered on top of FCB I/O.