From b550a5ba0261f3b6aba8988e37f1005102544568 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Mon, 1 Jul 2024 20:11:29 +0200 Subject: Add readlink and readmagiclink functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 12 ++++++++++ efreadlink.c | 18 ++++++++++++++ enfreadlink.c | 18 ++++++++++++++ enreadlink.c | 18 ++++++++++++++ enreadlinkat.c | 29 +++++++++++++++++++++++ enreadmagiclink.c | 25 ++++++++++++++++++++ ereadlink.c | 18 ++++++++++++++ ereadlinkat.c | 18 ++++++++++++++ ereadmagiclink.c | 18 ++++++++++++++ freadlink.c | 18 ++++++++++++++ libsimple/path.h | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ readlink.c | 18 ++++++++++++++ readlinkat.c | 41 ++++++++++++++++++++++++++++++++ readmagiclink.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 383 insertions(+) create mode 100644 efreadlink.c create mode 100644 enfreadlink.c create mode 100644 enreadlink.c create mode 100644 enreadlinkat.c create mode 100644 enreadmagiclink.c create mode 100644 ereadlink.c create mode 100644 ereadlinkat.c create mode 100644 ereadmagiclink.c create mode 100644 freadlink.c create mode 100644 readlink.c create mode 100644 readlinkat.c create mode 100644 readmagiclink.c 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 -- cgit v1.2.3-70-g09d2