The early history of Windows file attributes, and why there is a gap between System and Directory

Raymond Chen

Raymond

Let’s look at the values for the basic Windows file attributes. There’s a gap where 8 should be.

FILE_ATTRIBUTE_...Value
READONLY0x00000001
HIDDEN0x00000002
SYSTEM0x00000004
 0x00000008
DIRECTORY0x00000010
ARCHIVE0x00000020

Rewind to CP/M.

CP/M supported eleven attributes:

NameMeaning
F1, F2, F3, F4User-defined
F5, F6, F7, F8Interface-defined
T1Read-only
T2System
T3Archive

The operating system imposed no semantics for user-defined attributes. You can use them for whatever you want.

The meanings of the interface-defined attributes were defined by each operating system interface. Think of them as four bonus flag parameters for each syscall that takes a file control block. You could set interface-defined attributes before calling a function, and that passed four additional flags in. Or the function could manipulate those attributes before returning, allowing it to return four flags out. Interface-defined attributes are always clear on disk.

The read-only bit marked a file as read-only.

The system bit had two effects: First, it hid the file from directory listings. Second, if the file belonged to user 0,¹ then the file was available to all users. (This was handy for program files.)

The archive bit reported whether the file has been backed up.

These attributes were retrofitted onto the existing directory structure by taking over the high bits of the eleven filename characters! That’s why they are named F1 through F8 (high bits of the eight-character file base name) and T1 through T3 (high bits of the three-character extension, also known as the file type).

You can infer from this that CP/M file names were limited to 7-bit ASCII.

Anyway, MS-DOS 1.0 split the dual meaning of the system attribute into two attribute (hidden and system), and even though it didn’t implement the read-only attribute, it reserved space for it.

That explains why the first three attributes are read-only (1), hidden (2), and system (4).

MS-DOS 2.0 most notably added support for subdirectories, but another feature that came along was volume labels. Since there was no space for the volume label in the disk header, the volume label was added as a directory entry in the root directory, with a special attribute that says “This is a volume label, not a file.”²

The next attributes became volume label (8), directory (16), and archive (32).

Win32 adopted the same file attribute values as MS-DOS and 16-bit Windows, presumably in an effort to minimize surprises when porting code from 16-bit to 32-bit. The volume label attribute disappeared from Win32, but the bits for directory and archive were left at their original values to avoid problems with programs that operated with file attributes. Those programs contained their own definitions for the file attributes because 16-bit Windows didn’t provide any.

¹ CP/M supported up to 16 users, numbered 0 through 15. When you started the computer, you were user 0, but you could change users by saying USER n. Files belonging to other users were inaccessible, except that system files belong to user 0 were available to everyone. Anybody could change to any user at any time, so this was a file organization feature, not a security feature. In practice, nobody really used it because floppy discs were so small that it was easier to organize your files by putting them on different floppies than by trying to remember which user you used for each file.

² Windows 95 later repurposed the volume label attribute to mark directory entries as being used for long file names. Disk utilities often parsed directory entries directly, so any change in the disk format was a compatibility risk. The choice to use the volume label attribute for this purpose came after a lot of experimentation to find the least disruptive file format for long file names. It turns out that most low-level disk utility programs ignored anything marked with the volume label attribute.

Raymond Chen
Raymond Chen

Follow Raymond