readdir_r is now deprecated.[1][2]
The readdir_r() function was invented as a reentrant version of
readdir(3). It reads the next directory entry from the directory
stream dirp, and returns it in the caller-allocated buffer pointed to
by entry. For details of the dirent structure, see readdir(3).
A pointer to the returned buffer is placed in *result; if the end of
the directory stream was encountered, then NULL is instead returned
in *result.
It is recommended that applications use readdir(3) instead of
readdir_r(). Furthermore, since version 2.24, glibc deprecates
readdir_r(). The reasons are as follows:
* On systems where NAME_MAX is undefined, calling readdir_r() may be
unsafe because the interface does not allow the caller to specify
the length of the buffer used for the returned directory entry.
* 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. 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.
* 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. Therefore, the use of readdir_r() is generally
unnecessary in multithreaded programs. In cases where multiple
threads must read from the same directory stream, using readdir(3)
with external synchronization is still preferable to the use of
readdir_r(), for the reasons given in the points above.
* It is expected that a future version of POSIX.1 will make
readdir_r() obsolete, and require that readdir(3) be thread-safe
when concurrently employed on different directory streams.
[1]:
http://man7.org/linux/man-pages/man3/readdir_r.3.html
[2]:
https://lwn.net/Articles/696475/
---
luxio.c | 73 ++++++++++++++++++-----------------------------------------------
1 file changed, 20 insertions(+), 53 deletions(-)
diff --git a/luxio.c b/luxio.c
index 4b7b707..7501af3 100644
--- a/luxio.c
+++ b/luxio.c
@@ -82,13 +82,6 @@ static int safe_pathconf(const char *path, int conf)
return (pc < LUXIO_MIN_PATHSIZE) ? LUXIO_MIN_PATHSIZE : pc;
}
-static int safe_fpathconf(int fd, int conf)
-{
- int pc = fpathconf(fd, conf);
-
- return (pc < LUXIO_MIN_PATHSIZE) ? LUXIO_MIN_PATHSIZE : pc;
-}
-
#undef LUXIO_MIN_PATHSIZE
/* External interface to Lua *************************************************/
@@ -731,7 +724,6 @@ otherwise everything is just too painful.
typedef struct {
DIR *dirp;
- struct dirent *buf, *ent;
} luxio_readdir_state;
static int
@@ -740,7 +732,6 @@ luxio_readdir_gc(lua_State *L)
luxio_readdir_state *s = luaL_checkudata(L, 1, LUXIO_READDIR_METATABLE);
closedir(s->dirp);
- free(s->buf);
return 0;
}
@@ -786,7 +777,6 @@ luxio_opendir(lua_State *L) /* 5.1.2 */
{
const char *path = luaL_checkstring(L, 1);
DIR *d = opendir(path);
- size_t bufz;
luxio_readdir_state *s;
if (d == NULL) {
@@ -796,16 +786,7 @@ luxio_opendir(lua_State *L) /* 5.1.2 */
}
s = lua_newuserdata(L, sizeof(*s));
-
s->dirp = d;
- /* + 256 because it'd always be +1 if it weren't for the horrors
- * of Solaris. If we were using autoconf, we could use Ben
- * Hutchings' function mentioned in his article "readdir_r considered
- * harmful".
- */
- bufz = sizeof(struct dirent) + safe_pathconf(path, _PC_NAME_MAX) + 256;
- s->buf = malloc(bufz);
-
luxio__bless_readdir(L);
return 1;
@@ -822,7 +803,6 @@ luxio_fdopendir(lua_State *L) /* POSIX.1-2008 */
{
int fd = luaL_checkinteger(L, 1);
DIR *d = fdopendir(fd);
- size_t bufz;
luxio_readdir_state *s;
if (d == NULL) {
@@ -834,14 +814,6 @@ luxio_fdopendir(lua_State *L) /* POSIX.1-2008 */
s = lua_newuserdata(L, sizeof(*s));
s->dirp = d;
- /* + 256 because it'd always be +1 if it weren't for the horrors
- * of Solaris. If we were using autoconf, we could use Ben
- * Hutchings' function mentioned in his article "readdir_r considered
- * harmful".
- */
- bufz = sizeof(struct dirent) + safe_fpathconf(fd, _PC_NAME_MAX) + 256;
- s->buf = malloc(bufz);
-
luxio__bless_readdir(L);
return 1;
@@ -861,9 +833,6 @@ luxio_closedir(lua_State *L) /* 5.1.2 */
s->dirp = NULL;
}
- free(s->buf);
- s->buf = NULL;
-
return 0;
}
@@ -885,34 +854,32 @@ static int
luxio_readdir(lua_State *L) /* 5.1.2 */
{
luxio_readdir_state *s = luaL_checkudata(L, 1, LUXIO_READDIR_METATABLE);
- int err;
-
- err = readdir_r(s->dirp, s->buf, &s->ent);
- if (err == 0 && s->ent != NULL) {
- lua_pushinteger(L, 0);
- lua_createtable(L, 0, 3);
- lua_pushinteger(L, s->ent->d_ino);
- lua_setfield(L, -2, "d_ino");
- lua_pushstring(L, s->ent->d_name);
- lua_setfield(L, -2, "d_name");
-#ifdef HAVE_D_TYPE
- lua_pushinteger(L, s->ent->d_type);
- lua_setfield(L, -2, "d_type");
-#endif
- return 2;
- }
+ errno = 0;
+ struct dirent *ent = readdir(s->dirp);
- if (s->ent == NULL) {
- /* end of directory */
- lua_pushnil(L);
+ if (ent == NULL) {
+ if (errno != 0) {
+ lua_pushinteger(L, errno);
+ } else {
+ /* end of directory */
+ lua_pushnil(L);
+ }
return 1;
}
- lua_pushinteger(L, err);
-
- return 1;
+ lua_pushinteger(L, 0);
+ lua_createtable(L, 0, 3);
+ lua_pushinteger(L, ent->d_ino);
+ lua_setfield(L, -2, "d_ino");
+ lua_pushstring(L, ent->d_name);
+ lua_setfield(L, -2, "d_name");
+#ifdef HAVE_D_TYPE
+ lua_pushinteger(L, ent->d_type);
+ lua_setfield(L, -2, "d_type");
+#endif
+ return 2;
}
/*** Reset directory stream
--
2.12.2.510.ge1104a5.dirty