diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2020-08-18 11:55:47 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2020-09-30 19:11:36 +0200 |
commit | f4f5ed2cbde65acaa1bd88d00cc23fa8bf6b5ed9 (patch) | |
tree | 360170b2967cd6586b9c32744c3b16671b283880 /util | |
parent | 9386a4a7150fe11690af1897cf28c206c54cde9c (diff) |
cutils: introduce get_relocated_path
Add the function that will compute a relocated version of the
directories in CONFIG_QEMU_*DIR and CONFIG_QEMU_*PATH.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'util')
-rw-r--r-- | util/cutils.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/util/cutils.c b/util/cutils.c index 36ce712271..8da34e04b0 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -889,3 +889,64 @@ int qemu_pstrcmp0(const char **str1, const char **str2) { return g_strcmp0(*str1, *str2); } + +static inline bool starts_with_prefix(const char *dir) +{ + size_t prefix_len = strlen(CONFIG_PREFIX); + return !memcmp(dir, CONFIG_PREFIX, prefix_len) && + (!dir[prefix_len] || G_IS_DIR_SEPARATOR(dir[prefix_len])); +} + +/* Return the next path component in dir, and store its length in *p_len. */ +static inline const char *next_component(const char *dir, int *p_len) +{ + int len; + while (*dir && G_IS_DIR_SEPARATOR(*dir)) { + dir++; + } + len = 0; + while (dir[len] && !G_IS_DIR_SEPARATOR(dir[len])) { + len++; + } + *p_len = len; + return dir; +} + +char *get_relocated_path(const char *dir) +{ + size_t prefix_len = strlen(CONFIG_PREFIX); + const char *bindir = CONFIG_BINDIR; + const char *exec_dir = qemu_get_exec_dir(); + GString *result; + int len_dir, len_bindir; + + /* Fail if qemu_init_exec_dir was not called. */ + assert(exec_dir[0]); + if (!starts_with_prefix(dir) || !starts_with_prefix(bindir)) { + return strdup(dir); + } + + result = g_string_new(exec_dir); + + /* Advance over common components. */ + len_dir = len_bindir = prefix_len; + do { + dir += len_dir; + bindir += len_bindir; + dir = next_component(dir, &len_dir); + bindir = next_component(bindir, &len_bindir); + } while (len_dir == len_bindir && !memcmp(dir, bindir, len_dir)); + + /* Ascend from bindir to the common prefix with dir. */ + while (len_bindir) { + bindir += len_bindir; + g_string_append(result, "/.."); + bindir = next_component(bindir, &len_bindir); + } + + if (*dir) { + assert(G_IS_DIR_SEPARATOR(dir[-1])); + g_string_append(result, dir - 1); + } + return result->str; +} |