aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2024-07-01 20:11:29 +0200
committerMattias Andrée <maandree@kth.se>2024-07-01 20:46:56 +0200
commitb550a5ba0261f3b6aba8988e37f1005102544568 (patch)
tree77d996b805cf8561847872636b4c94039d329756
parentFix libsimple_abspath (diff)
downloadlibsimple-b550a5ba0261f3b6aba8988e37f1005102544568.tar.gz
libsimple-b550a5ba0261f3b6aba8988e37f1005102544568.tar.bz2
libsimple-b550a5ba0261f3b6aba8988e37f1005102544568.tar.xz
Add readlink and readmagiclink functions
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--Makefile12
-rw-r--r--efreadlink.c18
-rw-r--r--enfreadlink.c18
-rw-r--r--enreadlink.c18
-rw-r--r--enreadlinkat.c29
-rw-r--r--enreadmagiclink.c25
-rw-r--r--ereadlink.c18
-rw-r--r--ereadlinkat.c18
-rw-r--r--ereadmagiclink.c18
-rw-r--r--freadlink.c18
-rw-r--r--libsimple/path.h71
-rw-r--r--readlink.c18
-rw-r--r--readlinkat.c41
-rw-r--r--readmagiclink.c61
14 files changed, 383 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index e1401b8..d44d559 100644
--- a/Makefile
+++ b/Makefile
@@ -411,6 +411,7 @@ OBJ =\
ealigned_wmemdup.o\
ecalloc.o\
ecallocn.o\
+ efreadlink.o\
egetcwd.o\
egmtime.o\
elocaltime.o\
@@ -440,6 +441,7 @@ OBJ =\
enaligned_wmemdup.o\
encalloc.o\
encallocn.o\
+ enfreadlink.o\
engetcwd.o\
engmtime.o\
enlocaltime.o\
@@ -463,6 +465,9 @@ OBJ =\
enpvallocn.o\
enpvallocz.o\
enpvalloczn.o\
+ enreadlink.o\
+ enreadlinkat.o\
+ enreadmagiclink.o\
enrealloc.o\
enreallocarray.o\
enreallocn.o\
@@ -502,6 +507,9 @@ OBJ =\
epvallocn.o\
epvallocz.o\
epvalloczn.o\
+ ereadlink.o\
+ ereadlinkat.o\
+ ereadmagiclink.o\
erealloc.o\
ereallocarray.o\
ereallocn.o\
@@ -540,6 +548,7 @@ OBJ =\
fexecl.o\
fexecle.o\
fexecv.o\
+ freadlink.o\
generate_seed.o\
getcwd.o\
getenv_e.o\
@@ -943,6 +952,9 @@ OBJ =\
rawmemrchr_inv.o\
rawmemrelem.o\
rawmemrelem_inv.o\
+ readlink.o\
+ readlinkat.o\
+ readmagiclink.o\
reallocarray.o\
reallocarrayf.o\
reallocf.o\
diff --git a/efreadlink.c b/efreadlink.c
new file mode 100644
index 0000000..a76c411
--- /dev/null
+++ b/efreadlink.c
@@ -0,0 +1,18 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+extern inline char *libsimple_efreadlink(int);
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/enfreadlink.c b/enfreadlink.c
new file mode 100644
index 0000000..9f6a055
--- /dev/null
+++ b/enfreadlink.c
@@ -0,0 +1,18 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+extern inline char *libsimple_enfreadlink(int, int);
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/enreadlink.c b/enreadlink.c
new file mode 100644
index 0000000..669e1fd
--- /dev/null
+++ b/enreadlink.c
@@ -0,0 +1,18 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+extern inline char *libsimple_enreadlink(int, const char *);
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/enreadlinkat.c b/enreadlinkat.c
new file mode 100644
index 0000000..74b4562
--- /dev/null
+++ b/enreadlinkat.c
@@ -0,0 +1,29 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+char *
+libsimple_enreadlinkat(int status, int dirfd, const char *path)
+{
+ char *ret = libsimple_readlinkat(dirfd, path);
+ if (!ret) {
+ if (dirfd == AT_FDCWD)
+ libsimple_enprintf(status, "libsimple_readlinkat AT_FDCWD %s:", path);
+ else
+ libsimple_enprintf(status, "libsimple_readlinkat %i %s:", dirfd, path);
+ }
+ return ret;
+}
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/enreadmagiclink.c b/enreadmagiclink.c
new file mode 100644
index 0000000..a4a99a4
--- /dev/null
+++ b/enreadmagiclink.c
@@ -0,0 +1,25 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+char *
+libsimple_enreadmagiclink(int status, const char *path)
+{
+ char *ret = libsimple_readmagiclink(path);
+ if (!ret)
+ libsimple_enprintf(status, "libsimple_readmagiclinkat %s:", path);
+ return ret;
+}
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/ereadlink.c b/ereadlink.c
new file mode 100644
index 0000000..3b990e4
--- /dev/null
+++ b/ereadlink.c
@@ -0,0 +1,18 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+extern inline char *libsimple_ereadlink(const char *);
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/ereadlinkat.c b/ereadlinkat.c
new file mode 100644
index 0000000..7294ade
--- /dev/null
+++ b/ereadlinkat.c
@@ -0,0 +1,18 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+extern inline char *libsimple_ereadlinkat(int, const char *);
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/ereadmagiclink.c b/ereadmagiclink.c
new file mode 100644
index 0000000..396e618
--- /dev/null
+++ b/ereadmagiclink.c
@@ -0,0 +1,18 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+extern inline char *libsimple_ereadmagiclink(const char *);
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/freadlink.c b/freadlink.c
new file mode 100644
index 0000000..90f5380
--- /dev/null
+++ b/freadlink.c
@@ -0,0 +1,18 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+extern inline char *libsimple_freadlink(int);
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/libsimple/path.h b/libsimple/path.h
index 65f2751..6f2a8b8 100644
--- a/libsimple/path.h
+++ b/libsimple/path.h
@@ -68,3 +68,74 @@ libsimple_eabspath(const char *p__, const char *r__) /* TODO man */
{
return libsimple_enabspath(libsimple_default_failure_exit, p__, r__);
}
+
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__)))
+char *libsimple_readlinkat(int, const char *); /* TODO man, doc */
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__)))
+char *libsimple_enreadlinkat(int, int, const char *); /* TODO man, doc */
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__)))
+inline char *
+libsimple_ereadlinkat(int dirfd__, const char *path__) /* TODO man, doc */
+{
+ return libsimple_enreadlinkat(libsimple_default_failure_exit, dirfd__, path__);
+}
+
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__)))
+inline char *
+libsimple_readlink(const char *path__) /* TODO man, doc */
+{
+ return libsimple_readlinkat(AT_FDCWD, path__);
+}
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__)))
+inline char *
+libsimple_enreadlink(int status__, const char *path__) /* TODO man, doc */
+{
+ return libsimple_enreadlinkat(status__, AT_FDCWD, path__);
+}
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__)))
+inline char *
+libsimple_ereadlink(const char *path__) /* TODO man, doc */
+{
+ return libsimple_enreadlinkat(libsimple_default_failure_exit, AT_FDCWD, path__);
+}
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__)))
+inline char *
+libsimple_freadlink(int fd__) /* TODO man, doc */
+{
+ return libsimple_readlinkat(fd__, "");
+}
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__)))
+inline char *
+libsimple_enfreadlink(int status__, int fd__) /* TODO man, doc */
+{
+ return libsimple_enreadlinkat(status__, fd__, "");
+}
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__)))
+inline char *
+libsimple_efreadlink(int fd__) /* TODO man, doc */
+{
+ return libsimple_enreadlinkat(libsimple_default_failure_exit, fd__, "");
+}
+
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__)))
+char *libsimple_readmagiclink(const char *); /* TODO man, doc */
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__)))
+char *libsimple_enreadmagiclink(int, const char *); /* TODO man, doc */
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__)))
+inline char *
+libsimple_ereadmagiclink(const char *path__) /* TODO man, doc */
+{
+ return libsimple_enreadmagiclink(libsimple_default_failure_exit, path__);
+}
diff --git a/readlink.c b/readlink.c
new file mode 100644
index 0000000..2bd9ffb
--- /dev/null
+++ b/readlink.c
@@ -0,0 +1,18 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+extern inline char *libsimple_readlink(const char *);
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/readlinkat.c b/readlinkat.c
new file mode 100644
index 0000000..2ec5e88
--- /dev/null
+++ b/readlinkat.c
@@ -0,0 +1,41 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+char *
+libsimple_readlinkat(int dirfd, const char *path)
+{
+ char *ret = NULL, *new;
+ size_t size = 0;
+ ssize_t r;
+
+ do {
+ new = realloc(ret, size += 128);
+ if (!new) {
+ errno = ENOMEM;
+ fail:
+ free(ret);
+ return NULL;
+ }
+ ret = new;
+ r = readlinkat(dirfd, path, ret, size - 1U);
+ if (r < 0)
+ goto fail;
+ } while ((size_t)r >= size - 2U);
+
+ ret[r] = '\0';
+ return ret;
+}
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/readmagiclink.c b/readmagiclink.c
new file mode 100644
index 0000000..160dd96
--- /dev/null
+++ b/readmagiclink.c
@@ -0,0 +1,61 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+char *
+libsimple_readmagiclink(const char *path)
+{
+ int fd;
+ struct stat st;
+ char *target1;
+ char *target2;
+
+ fd = open(path, O_PATH | O_NOFOLLOW);
+ if (fd < 0)
+ return NULL;
+
+ target1 = libsimple_efreadlink(fd);
+ if (!strends(target1, " (deleted)")) {
+ close(fd);
+ return target1;
+ }
+
+ if (fstat(fd, &st)) {
+ free(target1);
+ close(fd);
+ return NULL;
+ }
+
+ target2 = libsimple_efreadlink(fd);
+ if (!strends(target2, " (deleted)")) {
+ free(target1);
+ close(fd);
+ return target2;
+ }
+
+ close(fd);
+
+ if (strcmp(target1, target2)) {
+ free(target2);
+ return target1;
+ } else {
+ free(target1);
+ if (st.st_nlink)
+ return target2;
+ target2[strlen(target2) - (sizeof(" (deleted)") - 1U)] = '\0';
+ return target2;
+ }
+}
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif