|
@@ -26,6 +26,15 @@
|
|
#include "qemu/host-utils.h"
|
|
#include "qemu/host-utils.h"
|
|
#include <math.h>
|
|
#include <math.h>
|
|
|
|
|
|
|
|
+#ifdef __FreeBSD__
|
|
|
|
+#include <sys/sysctl.h>
|
|
|
|
+#include <sys/user.h>
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#ifdef __NetBSD__
|
|
|
|
+#include <sys/sysctl.h>
|
|
|
|
+#endif
|
|
|
|
+
|
|
#include "qemu/ctype.h"
|
|
#include "qemu/ctype.h"
|
|
#include "qemu/cutils.h"
|
|
#include "qemu/cutils.h"
|
|
#include "qemu/error-report.h"
|
|
#include "qemu/error-report.h"
|
|
@@ -931,6 +940,114 @@ static inline const char *next_component(const char *dir, int *p_len)
|
|
return dir;
|
|
return dir;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static const char *exec_dir;
|
|
|
|
+
|
|
|
|
+void qemu_init_exec_dir(const char *argv0)
|
|
|
|
+{
|
|
|
|
+#ifdef G_OS_WIN32
|
|
|
|
+ char *p;
|
|
|
|
+ char buf[MAX_PATH];
|
|
|
|
+ DWORD len;
|
|
|
|
+
|
|
|
|
+ if (exec_dir) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
|
|
|
|
+ if (len == 0) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ buf[len] = 0;
|
|
|
|
+ p = buf + len - 1;
|
|
|
|
+ while (p != buf && *p != '\\') {
|
|
|
|
+ p--;
|
|
|
|
+ }
|
|
|
|
+ *p = 0;
|
|
|
|
+ if (access(buf, R_OK) == 0) {
|
|
|
|
+ exec_dir = g_strdup(buf);
|
|
|
|
+ } else {
|
|
|
|
+ exec_dir = CONFIG_BINDIR;
|
|
|
|
+ }
|
|
|
|
+#else
|
|
|
|
+ char *p = NULL;
|
|
|
|
+ char buf[PATH_MAX];
|
|
|
|
+
|
|
|
|
+ if (exec_dir) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+#if defined(__linux__)
|
|
|
|
+ {
|
|
|
|
+ int len;
|
|
|
|
+ len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
|
|
|
|
+ if (len > 0) {
|
|
|
|
+ buf[len] = 0;
|
|
|
|
+ p = buf;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+#elif defined(__FreeBSD__) \
|
|
|
|
+ || (defined(__NetBSD__) && defined(KERN_PROC_PATHNAME))
|
|
|
|
+ {
|
|
|
|
+#if defined(__FreeBSD__)
|
|
|
|
+ static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
|
|
|
|
+#else
|
|
|
|
+ static int mib[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME};
|
|
|
|
+#endif
|
|
|
|
+ size_t len = sizeof(buf) - 1;
|
|
|
|
+
|
|
|
|
+ *buf = '\0';
|
|
|
|
+ if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) &&
|
|
|
|
+ *buf) {
|
|
|
|
+ buf[sizeof(buf) - 1] = '\0';
|
|
|
|
+ p = buf;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+#elif defined(__APPLE__)
|
|
|
|
+ {
|
|
|
|
+ char fpath[PATH_MAX];
|
|
|
|
+ uint32_t len = sizeof(fpath);
|
|
|
|
+ if (_NSGetExecutablePath(fpath, &len) == 0) {
|
|
|
|
+ p = realpath(fpath, buf);
|
|
|
|
+ if (!p) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+#elif defined(__HAIKU__)
|
|
|
|
+ {
|
|
|
|
+ image_info ii;
|
|
|
|
+ int32_t c = 0;
|
|
|
|
+
|
|
|
|
+ *buf = '\0';
|
|
|
|
+ while (get_next_image_info(0, &c, &ii) == B_OK) {
|
|
|
|
+ if (ii.type == B_APP_IMAGE) {
|
|
|
|
+ strncpy(buf, ii.name, sizeof(buf));
|
|
|
|
+ buf[sizeof(buf) - 1] = 0;
|
|
|
|
+ p = buf;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
+ /* If we don't have any way of figuring out the actual executable
|
|
|
|
+ location then try argv[0]. */
|
|
|
|
+ if (!p && argv0) {
|
|
|
|
+ p = realpath(argv0, buf);
|
|
|
|
+ }
|
|
|
|
+ if (p) {
|
|
|
|
+ exec_dir = g_path_get_dirname(p);
|
|
|
|
+ } else {
|
|
|
|
+ exec_dir = CONFIG_BINDIR;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const char *qemu_get_exec_dir(void)
|
|
|
|
+{
|
|
|
|
+ return exec_dir;
|
|
|
|
+}
|
|
|
|
+
|
|
char *get_relocated_path(const char *dir)
|
|
char *get_relocated_path(const char *dir)
|
|
{
|
|
{
|
|
size_t prefix_len = strlen(CONFIG_PREFIX);
|
|
size_t prefix_len = strlen(CONFIG_PREFIX);
|