Search code examples
fileunixdirectory

Can you read macOS directories as files?


I was reading The Unix Programming Environment and according to the book UNIX directories are files that contain a list of file names and their inode number. According to the examples in the book, one could run od -c . and get the contents of the current working directory just like it was a simple file.

However, things seem to have changed since the book was published in 1984 and running the above command outputs od: .: Is a directory. This was ran on a machine running macOS 12.0.1, however I would guess this behaviour to be the same in other modern UNIX derived operating systems.

My question is, what happened exactly? Are directories not files anymore? If yes, what happened to the everything is a file principle? If not, why can't you read the contents of a directory just like it is a file?


Solution

  • Modern Unix systems still allow processes to open a directory like any other file. They just can't be read or written. Directories aren't the only kind of files that allow neither reading nor writing: many operating systems have device files that support some ioctl, but neither read nor write.

    The error “Is a directory” is coming from the read system call, not from open.

    $ perl -e 'sysopen D, ".", 0 or die "open: $!"; sysread D, $a, 42 or die "read: $!"'
    read: Is a directory at -e line 1.
    

    The earliest Unix systems treated a directory as a regular file internally. To list a directory's content, a process could read the file, and code in the standard library knew how to decode the filesystem format and translate a bunch of bytes into a list of file names and attributes.

    When Unix systems started supporting multiple filesystems, this didn't scale anymore. Different filesystem types encode the directory content in different ways. With network filesystems, the content of a directory could be encoded differently on different machines, so applications couldn't expect all directories to be in the local standard format anymore unless the kernel translated for them.

    Some Unix systems still allow processes to read directories, but the content is just a stream of bytes with no guaranteed meaning, or the ability is restricted to directories on their native filesystem. Many modern systems (at least Linux, FreeBSD and macOS) forbid reading from a directory altogether.

    Modern filesystems have become increasingly complex and do not necessarily represent a directory as a sequence of bytes. Some filesystems allow the content of small files to be stored directly in the directory data structures, and in this case the kernel must not allow the directory to be read since a reader who has permission to read the directory does not necessarily have permission to read the files in it.

    Writing to a directory file was forbidden to unprivileged processes as soon as the concept of unprivileged processes appeared, since this could very easily make the filesystem inconsistent, and then was forbidden even to privileged processes, since two processes editing directories at the same time would be likely to make conflicting changes that made the filesystem inconsistent.