Welcome to little lamb

Code » limb » commit c1e0186

Add sareadlinkat()

author Olivier Brunel
2023-02-17 20:24:58 UTC
committer Olivier Brunel
2023-02-20 09:02:52 UTC
parent e67fdf6afe0f97a6db279ae227579248ec992e9e

Add sareadlinkat()

doc/sareadlinkat.3.md +40 -0
include/limb/djbunix.h +8 -0
meta/libs/limb +1 -0
src/sareadlinkat.c +22 -0

diff --git a/doc/sareadlinkat.3.md b/doc/sareadlinkat.3.md
new file mode 100644
index 0000000..780b7de
--- /dev/null
+++ b/doc/sareadlinkat.3.md
@@ -0,0 +1,40 @@
+% limb manual
+% sareadlinkat(3)
+
+# NAME
+
+sareadlinkat - read the content of a symbolic link
+
+# SYNOPSIS
+
+    #include <limb/djbunix.h>
+
+```pre hl
+int sareadlinkat(stralloc *<em>sa</em>, int <em>fd</em>, const char * restrict <em>file</em>)
+```
+
+# DESCRIPTION
+
+The `sareadlinkat`() function places the content of the symbolic link referred
+to by `file` in the stralloc `sa`.
+
+The symbolic link whose content is read is relative to the directory associated
+with the file descriptor `fd`. If passed the special value `AT_FDCWD` in the
+`fd` parameter, the current working directory is used.
+
+For more details, refer to [`readlinkat`](3).
+
+# RETURN VALUE
+
+Upon successful completion the function returns 0. Otherwise it returns -1 and
+sets `errno` to indicate the error.
+
+# ERRORS
+
+This function may fail if:
+
+: *ENOMEM*
+:: Insufficient memory available to grow `sa`
+
+This function may also fail and set `errno` for any of the errors specified for
+the function [`readlinkat`](3).
diff --git a/include/limb/djbunix.h b/include/limb/djbunix.h
new file mode 100644
index 0000000..7c67b6f
--- /dev/null
+++ b/include/limb/djbunix.h
@@ -0,0 +1,8 @@
+#ifndef LIMB_DJBUNIX_H
+#define LIMB_DJBUNIX_H
+
+#include <skalibs/stralloc.h>
+
+extern int sareadlinkat(stralloc *sa, int fd, const char * restrict file);
+
+#endif /* LIMB_DJBUNIX_H */
diff --git a/meta/libs/limb b/meta/libs/limb
index af6f2cc..f7e49f0 100644
--- a/meta/libs/limb
+++ b/meta/libs/limb
@@ -5,6 +5,7 @@ obj/open_exclat.o
 obj/open_createat.o
 obj/openc_exclat.o
 obj/openc_createat.o
+obj/sareadlinkat.o
 # find msb
 obj/msb64.o
 # {,un}pack u64
diff --git a/src/sareadlinkat.c b/src/sareadlinkat.c
new file mode 100644
index 0000000..6089c6a
--- /dev/null
+++ b/src/sareadlinkat.c
@@ -0,0 +1,22 @@
+#include <unistd.h>
+#include <errno.h>
+#include "limb/djbunix.h"
+#include "err.h"
+
+int
+sareadlinkat(stralloc *sa, int fd, const char * restrict file)
+{
+    size_t len = 256;
+    ssize_t r;
+    for (;;) {
+        if (!stralloc_readyplus(sa, len))
+            return (errno = ENOMEM, ERR_MEM);
+        r = readlinkat(fd, file, sa->s + sa->len, len);
+        if (r < 0) return ERR_IO;
+        if ((size_t) r < len)
+            break;
+        len += 256;
+    }
+    sa->len += r;
+    return 0;
+}