aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2024-07-01 21:04:33 +0200
committerMattias Andrée <maandree@kth.se>2024-07-01 21:04:33 +0200
commit8b367c7f2d77bb5e1d7586853669df644a2b1d52 (patch)
tree4baf58c802d3b8c6816167c976010ff003f2f1cb
parentAdd readlink and readmagiclink functions (diff)
downloadlibsimple-8b367c7f2d77bb5e1d7586853669df644a2b1d52.tar.gz
libsimple-8b367c7f2d77bb5e1d7586853669df644a2b1d52.tar.bz2
libsimple-8b367c7f2d77bb5e1d7586853669df644a2b1d52.tar.xz
Add getexecpath functions
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-rw-r--r--Makefile3
-rw-r--r--egetexecpath.c18
-rw-r--r--engetexecpath.c34
-rw-r--r--getexecpath.c125
-rw-r--r--libsimple/path.h14
5 files changed, 194 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index d44d559..5a2ada3 100644
--- a/Makefile
+++ b/Makefile
@@ -413,6 +413,7 @@ OBJ =\
ecallocn.o\
efreadlink.o\
egetcwd.o\
+ egetexecpath.o\
egmtime.o\
elocaltime.o\
emalloc.o\
@@ -443,6 +444,7 @@ OBJ =\
encallocn.o\
enfreadlink.o\
engetcwd.o\
+ engetexecpath.o\
engmtime.o\
enlocaltime.o\
enmalloc.o\
@@ -553,6 +555,7 @@ OBJ =\
getcwd.o\
getenv_e.o\
getenv_ne.o\
+ getexecpath.o\
gmtime.o\
habs.o\
hdiff.o\
diff --git a/egetexecpath.c b/egetexecpath.c
new file mode 100644
index 0000000..17998de
--- /dev/null
+++ b/egetexecpath.c
@@ -0,0 +1,18 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+extern inline char *libsimple_egetexecpath(void);
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/engetexecpath.c b/engetexecpath.c
new file mode 100644
index 0000000..14994e8
--- /dev/null
+++ b/engetexecpath.c
@@ -0,0 +1,34 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+char *
+libsimple_engetexecpath(int status)
+{
+ int saved_errno;
+ char *ret;
+ saved_errno = errno;;
+ errno = 0;
+ ret = libsimple_getexecpath();
+ if (!ret) {
+ if (errno)
+ libsimple_enprintf(status, "libsimple_getexecpath:");
+ else
+ libsimple_enprintf(status, "libsimple_getexecpath: unable to determine path\n");
+ }
+ errno = saved_errno;
+ return ret;
+}
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/getexecpath.c b/getexecpath.c
new file mode 100644
index 0000000..84bfea4
--- /dev/null
+++ b/getexecpath.c
@@ -0,0 +1,125 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+#include <sys/auxv.h>
+
+
+extern char *argv0;
+
+
+static char *
+getexecpath_by_execfn(void)
+{
+ unsigned long auxval;
+ char *execpath, *path, *target;
+ const char *name, *s, *fdlink;
+ size_t n;
+
+ auxval = getauxval(AT_EXECFN);
+ if (!auxval)
+ return NULL;
+
+ name = (void *)auxval;
+ if (strstarts(name, "/dev/fd/"))
+ s = &name[sizeof("/dev/fd/") - 1U];
+ else if (strstarts(name, "/proc/self/fd/"))
+ s = &name[sizeof("/proc/self/fd/") - 1U];
+ else
+ return libsimple_abspath(name, NULL);
+
+ while (isdigit(*s))
+ s++;
+ if (*s) {
+ n = (size_t)(s - name);
+ path = malloc(n + 1U);
+ if (!path)
+ return NULL;
+ memcpy(path, name, n);
+ path[n] = '\0';
+ fdlink = path;
+ } else {
+ path = NULL;
+ fdlink = name;
+ }
+ target = libsimple_readmagiclink(fdlink);
+ free(path);
+ if (!target)
+ return NULL;
+ execpath = malloc(strlen(target) + strlen(s) + 1U);
+ if (!execpath) {
+ free(target);
+ return NULL;
+ }
+ stpcpy(stpcpy(execpath, target), s);
+ free(target);
+
+ return execpath;
+}
+
+
+static char *
+getexecpath_by_execfd(void)
+{
+ unsigned long auxval;
+ int fd;
+ char path[sizeof("/dev/fd/") + 3U * sizeof(int)];
+
+ errno = 0;
+ auxval = getauxval(AT_EXECFN);
+ if (!auxval && errno)
+ return NULL;
+ fd = (int)auxval;
+
+ sprintf(path, "/dev/fd/%i", fd);
+ return libsimple_readmagiclink(path);
+}
+
+
+static char *
+getexecpath_by_proc_exe(void)
+{
+ return libsimple_readmagiclink("/proc/self/exe");
+}
+
+
+static char *
+getexecpath_by_argv0(void)
+{
+ char *s = argv0;
+
+ if (strchr(s, '/'))
+ return libsimple_abspath(s, NULL);
+
+ return NULL;
+}
+
+
+char *
+libsimple_getexecpath(void)
+{
+ char *r;
+
+ if ((r = getexecpath_by_execfn()))
+ return r;
+ if ((r = getexecpath_by_execfd()))
+ return r;
+ if ((r = getexecpath_by_proc_exe()))
+ return r;
+ if ((r = getexecpath_by_argv0()))
+ return r;
+
+ return NULL;
+}
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO test */
+{
+ return 0;
+}
+
+#endif
diff --git a/libsimple/path.h b/libsimple/path.h
index 6f2a8b8..cb78863 100644
--- a/libsimple/path.h
+++ b/libsimple/path.h
@@ -139,3 +139,17 @@ libsimple_ereadmagiclink(const char *path__) /* TODO man, doc */
{
return libsimple_enreadmagiclink(libsimple_default_failure_exit, path__);
}
+
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__)))
+char *libsimple_getexecpath(void); /* TODO man, doc */
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__)))
+char *libsimple_engetexecpath(int); /* TODO man, doc */
+
+LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__)))
+inline char *
+libsimple_egetexecpath(void) /* TODO man, doc */
+{
+ return libsimple_engetexecpath(libsimple_default_failure_exit);
+}