|
26 | 26 | #include "qemu/host-utils.h"
|
27 | 27 | #include <math.h>
|
28 | 28 |
|
| 29 | +#ifdef __FreeBSD__ |
| 30 | +#include <sys/sysctl.h> |
| 31 | +#include <sys/user.h> |
| 32 | +#endif |
| 33 | + |
| 34 | +#ifdef __NetBSD__ |
| 35 | +#include <sys/sysctl.h> |
| 36 | +#endif |
| 37 | + |
29 | 38 | #include "qemu/ctype.h"
|
30 | 39 | #include "qemu/cutils.h"
|
31 | 40 | #include "qemu/error-report.h"
|
@@ -931,6 +940,114 @@ static inline const char *next_component(const char *dir, int *p_len)
|
931 | 940 | return dir;
|
932 | 941 | }
|
933 | 942 |
|
| 943 | +static const char *exec_dir; |
| 944 | + |
| 945 | +void qemu_init_exec_dir(const char *argv0) |
| 946 | +{ |
| 947 | +#ifdef G_OS_WIN32 |
| 948 | + char *p; |
| 949 | + char buf[MAX_PATH]; |
| 950 | + DWORD len; |
| 951 | + |
| 952 | + if (exec_dir) { |
| 953 | + return; |
| 954 | + } |
| 955 | + |
| 956 | + len = GetModuleFileName(NULL, buf, sizeof(buf) - 1); |
| 957 | + if (len == 0) { |
| 958 | + return; |
| 959 | + } |
| 960 | + |
| 961 | + buf[len] = 0; |
| 962 | + p = buf + len - 1; |
| 963 | + while (p != buf && *p != '\\') { |
| 964 | + p--; |
| 965 | + } |
| 966 | + *p = 0; |
| 967 | + if (access(buf, R_OK) == 0) { |
| 968 | + exec_dir = g_strdup(buf); |
| 969 | + } else { |
| 970 | + exec_dir = CONFIG_BINDIR; |
| 971 | + } |
| 972 | +#else |
| 973 | + char *p = NULL; |
| 974 | + char buf[PATH_MAX]; |
| 975 | + |
| 976 | + if (exec_dir) { |
| 977 | + return; |
| 978 | + } |
| 979 | + |
| 980 | +#if defined(__linux__) |
| 981 | + { |
| 982 | + int len; |
| 983 | + len = readlink("/proc/self/exe", buf, sizeof(buf) - 1); |
| 984 | + if (len > 0) { |
| 985 | + buf[len] = 0; |
| 986 | + p = buf; |
| 987 | + } |
| 988 | + } |
| 989 | +#elif defined(__FreeBSD__) \ |
| 990 | + || (defined(__NetBSD__) && defined(KERN_PROC_PATHNAME)) |
| 991 | + { |
| 992 | +#if defined(__FreeBSD__) |
| 993 | + static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; |
| 994 | +#else |
| 995 | + static int mib[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME}; |
| 996 | +#endif |
| 997 | + size_t len = sizeof(buf) - 1; |
| 998 | + |
| 999 | + *buf = '\0'; |
| 1000 | + if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) && |
| 1001 | + *buf) { |
| 1002 | + buf[sizeof(buf) - 1] = '\0'; |
| 1003 | + p = buf; |
| 1004 | + } |
| 1005 | + } |
| 1006 | +#elif defined(__APPLE__) |
| 1007 | + { |
| 1008 | + char fpath[PATH_MAX]; |
| 1009 | + uint32_t len = sizeof(fpath); |
| 1010 | + if (_NSGetExecutablePath(fpath, &len) == 0) { |
| 1011 | + p = realpath(fpath, buf); |
| 1012 | + if (!p) { |
| 1013 | + return; |
| 1014 | + } |
| 1015 | + } |
| 1016 | + } |
| 1017 | +#elif defined(__HAIKU__) |
| 1018 | + { |
| 1019 | + image_info ii; |
| 1020 | + int32_t c = 0; |
| 1021 | + |
| 1022 | + *buf = '\0'; |
| 1023 | + while (get_next_image_info(0, &c, &ii) == B_OK) { |
| 1024 | + if (ii.type == B_APP_IMAGE) { |
| 1025 | + strncpy(buf, ii.name, sizeof(buf)); |
| 1026 | + buf[sizeof(buf) - 1] = 0; |
| 1027 | + p = buf; |
| 1028 | + break; |
| 1029 | + } |
| 1030 | + } |
| 1031 | + } |
| 1032 | +#endif |
| 1033 | + /* If we don't have any way of figuring out the actual executable |
| 1034 | + location then try argv[0]. */ |
| 1035 | + if (!p && argv0) { |
| 1036 | + p = realpath(argv0, buf); |
| 1037 | + } |
| 1038 | + if (p) { |
| 1039 | + exec_dir = g_path_get_dirname(p); |
| 1040 | + } else { |
| 1041 | + exec_dir = CONFIG_BINDIR; |
| 1042 | + } |
| 1043 | +#endif |
| 1044 | +} |
| 1045 | + |
| 1046 | +const char *qemu_get_exec_dir(void) |
| 1047 | +{ |
| 1048 | + return exec_dir; |
| 1049 | +} |
| 1050 | + |
934 | 1051 | char *get_relocated_path(const char *dir)
|
935 | 1052 | {
|
936 | 1053 | size_t prefix_len = strlen(CONFIG_PREFIX);
|
|
0 commit comments