Linux kernel represents an opened file as an entry in the file descriptor table, an entry in the v-node table, and an entry in the open file table.

Does Linux kernel represent an opened directory in the same way?

It might be not, because I was wondering why an directory is opened by:

DIR *opendir(const char *pathname);

while a file is opened by:

int open(const char *path, int oflag, ... /* mode_t mode */ );

It might be yes, because

DIR *fdopendir(int fd);

converts an open file descriptor into a DIR structure. So is there some function (open()?) which can open a directory just like a file, and return a file descriptor fd?

Is opendir() implemented by first using open() to get a file descriptor of a directory, and then calling fdopendir() or some equivalence on the file descriptor?


  • @炸鱼薯条德里克, O_PATH doesn't seem to have anything to with reading the listing of a directory, though: "Obtain a file descriptor that can be used [...] to indicate a location in the filesystem tree." -- "The file itself is not opened, and other file operations fail" – ilkkachu Mar 5 at 8:41
  • Does linux really have a "v-node table"? Where? – mosvy Mar 5 at 10:48
  • @ilkkachu You're right, I misread open () – 炸鱼薯条德里克 Mar 5 at 11:36
  • @mosvy Is it an inode table instead? I think you got the idea? – Tim Mar 5 at 11:42

opendir is a library function that calls the open system call internally, just like fopen is a library function that internally calls open. opendir returns a pointer to a directory stream DIR, analogously to fopen, which returns a pointer to a file stream FILE. You can also use the open system call directly on a directory, if you so wish.


So is there some function (open()?) which can open a directory just like a file, and return a file descriptor fd?

Yes, you can open a directory with open() and get a file descriptor to it. You'll need the file descriptor if you use openat().

On Linux, you can't read() from a directory, though, it'll return EISDIR, ("Is a directory"). Instead the kernel has the getdents() system call to read directory entries from an opened directory. Confusingly, there's also the obsolete readdir() system call (though not on newer architectures), which is different from the POSIX function with the same name.

As the man page for getdents() says, glibc doesn't provide wrappers for it, so you should probably use the POSIX readdir() and opendir() functions instead. So yes, opendir() uses open() internally, the C library just does what it needs on top to provide the standard API with DIR *.

As far as I understand, some other Unix-likes allow using read() on directories too, instead (or in addition to?) having a distinct system call for getting a listing of files.

Linux's open() also has the O_DIRECTORY flag which causes the open to fail if the named file isn't a directory, but using that is not mandatory.

  • Linux does not have a readdir() system call. I know that there's such a compatibility syscall on i386 (which is using a different struct dirent), but for all intents and purposes, that syscall does not exist ;-) -- namely, there's no such syscall on x86-64, arm/eabi and arm64. – mosvy Mar 5 at 9:36
  • @mosvy, right, the man page does say at the bottom "This system call does not exist on x86-64." – ilkkachu Mar 5 at 10:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.