summaryrefslogtreecommitdiff
path: root/libgcompat/realpath.c
diff options
context:
space:
mode:
authorA. Wilcox <awilcox@wilcox-tech.com>2018-09-21 21:30:18 +0000
committerA. Wilcox <awilcox@wilcox-tech.com>2018-09-21 21:30:18 +0000
commite7fd895295db6291319af09ffaa3b6d93180788c (patch)
tree6ad80501db199c916e8fc2ed5648bf694a257675 /libgcompat/realpath.c
parent938c8095e7456fbcdf4ce261bdb6dfa3a8e41b80 (diff)
parent9bc7c737b311fcbba71af11884b7f9111dba57ba (diff)
downloadgcompat-e7fd895295db6291319af09ffaa3b6d93180788c.tar.gz
gcompat-e7fd895295db6291319af09ffaa3b6d93180788c.tar.bz2
gcompat-e7fd895295db6291319af09ffaa3b6d93180788c.tar.xz
gcompat-e7fd895295db6291319af09ffaa3b6d93180788c.zip
Merge branch 'patch-3' into 'master'
Add some more functions (notably __cxa_thread_atexit_impl and realpath) and run clang-format See merge request !3
Diffstat (limited to 'libgcompat/realpath.c')
-rw-r--r--libgcompat/realpath.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/libgcompat/realpath.c b/libgcompat/realpath.c
new file mode 100644
index 0000000..ab68cc4
--- /dev/null
+++ b/libgcompat/realpath.c
@@ -0,0 +1,51 @@
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef LINKER
+#error LINKER must be defined
+#endif
+
+static char *(*real_realpath)(const char *restrict, char *restrict);
+
+char *realpath(const char *restrict path, char *restrict resolved)
+{
+ if (real_realpath == NULL) {
+ real_realpath = dlsym(RTLD_NEXT, "realpath");
+ if (real_realpath == NULL) {
+ errno = ENOSYS;
+ return NULL;
+ }
+ }
+
+ if (!strcmp(path, "/proc/self/exe")) {
+ char *fixed = resolved;
+
+ if (fixed == NULL) {
+ fixed = malloc(PATH_MAX);
+ if (fixed == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+
+ /* If passed in, the buffer is at least PATH_MAX per POSIX. */
+ ssize_t written = readlink(path, fixed, PATH_MAX - 1);
+ if (written == -1) {
+ /* Free the buffer iff we allocated it. */
+ if (fixed != resolved)
+ free(fixed);
+ return NULL;
+ }
+ fixed[written] = '\0';
+
+ return fixed;
+ }
+
+ return real_realpath(path, resolved);
+}