aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/file-utils.c
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2024-11-05 01:29:53 +0300
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2024-11-05 12:32:04 +0300
commit9cce7d263ea3f2984a619cdfcb54d264c6a4c51d (patch)
tree363314a72aa4fc3fda435086c8deb522aef247ec /src/file-utils.c
parent36c7526d60319289954bb0b49e9f4cb2c6dfe9da (diff)
downloadsciteco-9cce7d263ea3f2984a619cdfcb54d264c6a4c51d.tar.gz
fully support relocatable binaries, improving AppImages
* You can now specify `--with-scitecodatadir` as a relative path, that will be interpreted relative to the binary's location. * Win32 binaries already were relocatable, but this was a Windows-specific hack. Win32 binaries are now built with `--with-scitecodatadir=.` since everything is in a single directory. * Ubuntu packages are now also built `--with-scitecodatadir=../share/sciteco`. This is not crucial for ordinary installations, but is meant for AppImage creation. * Since AppImages are now built from relocatable packages, we no longer need the unionfs-workaround from pkg2appimage. This should fix the strange root contents when autocompleting in AppImage builds. * This might also fix the appimage.github.io CI issues. I assume that because I could reproduce the issue on FreeBSD's Linuxulator in dependence of pkg2appimage's "union"-setting. See https://github.com/AppImage/appimage.github.io/pull/3402 * Determining the binary location actually turned out be hard and very platform-dependant. There are now implementations for Windows (which could also read argv[0]), Linux and generic UNIX (which works on FreeBSD, but I am not sure about the others). I believe this could also be useful on Mac OS to create app bundles, but this needs to be tested - currently the Mac OS binaries are installed into fixed locations and don't use relocation.
Diffstat (limited to 'src/file-utils.c')
-rw-r--r--src/file-utils.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/file-utils.c b/src/file-utils.c
index 3f8f721..b7e5418 100644
--- a/src/file-utils.c
+++ b/src/file-utils.c
@@ -19,6 +19,7 @@
#include "config.h"
#endif
+#define _GNU_SOURCE
#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -35,6 +36,10 @@
#include <glib.h>
#include <glib/gstdio.h>
+#ifdef G_OS_UNIX
+#include <dlfcn.h>
+#endif
+
#include "sciteco.h"
#include "qreg.h"
#include "interface.h"
@@ -179,6 +184,86 @@ teco_file_is_visible(const gchar *path)
#endif /* !G_OS_WIN32 */
+#ifdef G_OS_WIN32
+
+gchar *
+teco_file_get_program_path(void)
+{
+ TCHAR buf[MAX_PATH];
+ if (!GetModuleFileNameW(NULL, buf, G_N_ELEMENTS(buf))
+ return g_get_current_dir();
+ g_autofree gchar *exe = g_utf16_to_utf8(buf, -1, NULL, NULL, NULL);
+ return g_path_get_dirname(exe);
+}
+
+#elif defined(__linux__)
+
+gchar *
+teco_file_get_program_path(void)
+{
+ gchar buf[PATH_MAX];
+ ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf)-1);
+ if (G_UNLIKELY(len < 0))
+ /* almost certainly wrong */
+ return g_get_current_dir();
+ buf[len] = '\0';
+
+ return g_path_get_dirname(buf);
+}
+
+#elif defined(G_OS_UNIX)
+
+/*
+ * At least works on FreeBSD, even though it also has
+ * sysctl(KERN_PROC_PATHNAME).
+ * We assume it works on all other UNIXes as well.
+ */
+gchar *
+teco_file_get_program_path(void)
+{
+ Dl_info info;
+ return dladdr(teco_file_get_program_path, &info)
+ ? g_path_get_dirname(info.dli_fname) : g_get_current_dir();
+}
+
+#else /* !G_OS_WIN32 && !__linux__ && !G_OS_UNIX */
+
+/*
+ * This is almost guaranteed to be wrong,
+ * meaning that SciTECO cannot be made relocatable on these platforms.
+ * It may be worth evaluating argv[0] on these platforms.
+ */
+gchar *
+teco_file_get_program_path(void)
+{
+ return g_get_current_dir();
+}
+
+#endif
+
+/**
+ * Get the datadir.
+ *
+ * By default it is hardcoded to an absolute path at
+ * build time.
+ * However, you can also build relocateable binaries
+ * where the datadir is relative to the program's executable.
+ *
+ * @note Beginning with glib v2.58, we could directly use
+ * g_canonicalize_filename().
+ */
+gchar *
+teco_file_get_datadir(void)
+{
+ if (g_path_is_absolute(SCITECODATADIR))
+ return g_strdup(SCITECODATADIR);
+
+ /* relocateable binary - datadir is relative to binary */
+ g_autofree gchar *program_path = teco_file_get_program_path();
+ g_autofree gchar *datadir = g_build_filename(program_path, SCITECODATADIR, NULL);
+ return teco_file_get_absolute_path(datadir);
+}
+
/**
* Perform tilde expansion on a file name or path.
*