readdir_r(3)

✨ readdir_r β€” read a directory ✨

okay so bestie, this one's from the Library Functions Manual section of your friendly neighborhood man pages πŸ’– (that's the readdir_r(3) girlies, iykyk). buckle up because this function is lowkey a relic and we're gonna talk about why πŸ’…


πŸ“š LIBRARY

Standard C library (libc, -lc) β€” she lives in libc, she's always been there, she's just… tired 🫠


🌸 SYNOPSIS

#include <dirent.h>

[[deprecated]] int readdir_r(DIR *restrict dirp,
                             struct dirent *restrict entry,
                             struct dirent **restrict result);
not the [[deprecated]] right there in the signature πŸ’€ she's marked, she's been marked for a WHILE.

🧚 Feature Test Macro Requirements for glibc

(peep feature_test_macros(7) for the whole lore)

readdir_r():

  • _POSIX_C_SOURCE
  • || /* glibc <= 2.19: */ _BSD_SOURCE || _SVID_SOURCE

yes you need to define the right macro or she will simply not appear ✨ classic glibc behavior, no cap.


πŸ’œ DESCRIPTION

This function is deprecated; use readdir(3) instead. periodt. that's the whole tea, but let's keep going because there's lore πŸ“–

So readdir_r() was invented as a reentrant version of readdir(3) β€” like, the version you could call from multiple threads without the whole thing falling apart. It reads the next directory entry from the directory stream dirp, and returns it in the caller-allocated buffer pointed to by entry. (For the details of the dirent structure, go look at readdir(3) β€” she has the blueprint πŸ—ΊοΈ)

A pointer to the returned buffer gets placed in *result. And if you hit the end of the directory stream? Then NULL is placed in *result instead. bye bestie πŸ‘‹

But here's the thing, and I need you to hear me: applications should use readdir(3) instead of readdir_r(). And since glibc 2.24, glibc itself deprecates readdir_r(). The reasons are as follows, and they are giving red flags 🚩:

  • On systems where NAME_MAX is undefined, calling readdir_r() may be unsafe, because the interface does not let the caller specify the length of the buffer used for the returned directory entry. like… she can't tell you how much room she needs?? be serious rn 😭
  • On some systems, readdir_r() can't read directory entries with very long names. When the glibc implementation encounters such a name, readdir_r() fails with the error ENAMETOOLONG after the final directory entry has been read. And on some other systems, readdir_r() may return a success status, but the returned d_name field may not be null terminated or may be truncated. truncated names and false success?? absolutely not. πŸ’€
  • In the current POSIX.1 specification (POSIX.1-2008), readdir(3) is not required to be thread-safe. HOWEVER β€” in modern implementations (including the glibc implementation), concurrent calls to readdir(3) that specify different directory streams are thread-safe. So the use of readdir_r() is generally just… unnecessary in multithreaded programs. And in the cases where multiple threads genuinely must read from the same directory stream? Using readdir(3) with external synchronization is still preferable to using readdir_r(), for the reasons listed in the points above. slay πŸ’…
  • And it is expected that a future version of POSIX.1 will make readdir_r() obsolete, and will require that readdir(3) be thread-safe when concurrently employed on different directory streams. so like… she's getting sunset bestie πŸŒ‡

πŸŽ€ RETURN VALUE

  • On success, readdir_r() returns 0 ✨
  • On error, it returns a positive error number (the ones listed under ERRORS, keep reading bestie)
  • If the end of the directory stream is reached, readdir_r() returns 0, and returns NULL in *result. cute little double signal, but ok 🫢

πŸ™ˆ ERRORS

  • EBADF β€” Invalid directory stream descriptor dirp. like, that's not a directory stream babe, what is that 🫠
  • ENAMETOOLONG β€” A directory entry whose name was too long to be read was encountered. the name was simply too much for her to handle, and honestly? relatable 😭

πŸ”₯ ATTRIBUTES

For an explanation of the terms used in this section, peep attributes(7) πŸ‘‘

  • readdir_r() β€” Thread safety: MT-Safe

(yes she's thread-safe, that was literally her whole personality, and we're still not using her 🧍)


⭐ STANDARDS

POSIX.1-2008.


🌈 HISTORY

POSIX.1-2001.


πŸ‘‘ SEE ALSO

  • readdir(3) β€” the one you should actually be using, the main character, the upgrade πŸ’–

okay that's the whole page bestie 🫢 this was Linux man-pages 6.20, dated 2026-02-08, and she said what she said β€” go use readdir(3) instead, it's giving mature and stable ✨ mwah, stay deprecated-free πŸ’…πŸ’–

πŸ“¦ where this page comes from
  • arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • πŸ“œ the page's license: Linux-man-pages-copyleft
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms