Welcome to little lamb

Code » limb » commit 2555d41

Add opendirat()

author Olivier Brunel
2023-02-28 08:52:34 UTC
committer Olivier Brunel
2023-02-28 09:25:43 UTC
parent 59a538e44fc148fcd65f2b211dd8b77fb18c4f26

Add opendirat()

Similar to opendir(3) but with a fd for interpreting relative path
relative to the opened directory instead of cwd.

doc/opendirat.3.md +41 -0
include/limb/direntry.h +8 -0
meta/libs/limb +2 -0
src/opendirat.c +17 -0

diff --git a/doc/opendirat.3.md b/doc/opendirat.3.md
new file mode 100644
index 0000000..837d49b
--- /dev/null
+++ b/doc/opendirat.3.md
@@ -0,0 +1,41 @@
+% limb manual
+% opendirat(3)
+
+# NAME
+
+opendirat - open a directory
+
+# SYNOPSIS
+
+    #include <fcntl.h> /* AT_FDCWD */
+    #include <limb/direntry.h>
+
+```pre hl
+DIR *opendirat(int <em>fd</em>, const char *<em>name</em>)
+```
+
+# DESCRIPTION
+
+The `opendirat`() function opens a directory stream corresponding to the
+directory `name` and returns a pointer to the directory stream. The stream is
+positioned at the first entry in the directory.
+
+It is equivalent to the function [opendir](3) except when `name` specifies a
+relative path, the directory to be opened is then determined relative to the
+directory associated with the file descriptor `fd` instead of the current
+working directory.
+
+If passed the special value *AT_FDCWD* in the `fd` parameter, the current
+working directory shall be used and the behavior shall be identical to a call to
+[opendir](3).
+
+# RETURN VALUE
+
+Upon successful completion, the `opendirat` function returns a pointer to the
+opened directory stream. Otherwise, it returns NULL and sets `errno` to indicate
+the error.
+
+# ERRORS
+
+The `opendirat`() function may fail and set errno for any of the errors
+specified for the functions [open](3) and [fdopendir](3).
diff --git a/include/limb/direntry.h b/include/limb/direntry.h
new file mode 100644
index 0000000..f78022b
--- /dev/null
+++ b/include/limb/direntry.h
@@ -0,0 +1,8 @@
+#ifndef LIMB_DIRENTRY_H
+#define LIMB_DIRENTRY_H
+
+#include <skalibs/direntry.h>
+
+extern DIR *opendirat(int bfd, const char *name);
+
+#endif /* LIMB_DIRENTRY_H */
diff --git a/meta/libs/limb b/meta/libs/limb
index d6e7319..97be95c 100644
--- a/meta/libs/limb
+++ b/meta/libs/limb
@@ -5,6 +5,8 @@ obj/open_exclat.o
 obj/open_createat.o
 obj/openc_exclat.o
 obj/openc_createat.o
+# direntry.h
+obj/opendirat.o
 # djbunix.h
 obj/sareadlinkat.o
 # buffer
diff --git a/src/opendirat.c b/src/opendirat.c
new file mode 100644
index 0000000..e10689d
--- /dev/null
+++ b/src/opendirat.c
@@ -0,0 +1,17 @@
+#include <skalibs/djbunix.h>
+#include <skalibs/unix-transactional.h>
+#include "limb/direntry.h"
+
+DIR *
+opendirat(int bfd, const char *name)
+{
+    int fd = open2_at(bfd, name, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NONBLOCK);
+    if (fd < 0)
+        return NULL;
+
+    DIR *dir = fdopendir(fd);
+    if (!dir)
+        fd_close(fd);
+
+    return dir;
+}