qemu/softmmu/datadir.c
<<
>>
Prefs
   1/*
   2 * QEMU firmware and keymap file search
   3 *
   4 * Copyright (c) 2003-2020 QEMU contributors
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24
  25#include "qemu/osdep.h"
  26#include "qemu-common.h"
  27#include "qemu/datadir.h"
  28#include "qemu/cutils.h"
  29#include "trace.h"
  30
  31static const char *data_dir[16];
  32static int data_dir_idx;
  33
  34char *qemu_find_file(int type, const char *name)
  35{
  36    int i;
  37    const char *subdir;
  38    char *buf;
  39
  40    /* Try the name as a straight path first */
  41    if (access(name, R_OK) == 0) {
  42        trace_load_file(name, name);
  43        return g_strdup(name);
  44    }
  45
  46    switch (type) {
  47    case QEMU_FILE_TYPE_BIOS:
  48        subdir = "";
  49        break;
  50    case QEMU_FILE_TYPE_KEYMAP:
  51        subdir = "keymaps/";
  52        break;
  53    default:
  54        abort();
  55    }
  56
  57    for (i = 0; i < data_dir_idx; i++) {
  58        buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name);
  59        if (access(buf, R_OK) == 0) {
  60            trace_load_file(name, buf);
  61            return buf;
  62        }
  63        g_free(buf);
  64    }
  65    return NULL;
  66}
  67
  68void qemu_add_data_dir(char *path)
  69{
  70    int i;
  71
  72    if (path == NULL) {
  73        return;
  74    }
  75    if (data_dir_idx == ARRAY_SIZE(data_dir)) {
  76        return;
  77    }
  78    for (i = 0; i < data_dir_idx; i++) {
  79        if (strcmp(data_dir[i], path) == 0) {
  80            g_free(path); /* duplicate */
  81            return;
  82        }
  83    }
  84    data_dir[data_dir_idx++] = path;
  85}
  86
  87/*
  88 * Find a likely location for support files using the location of the binary.
  89 * When running from the build tree this will be "$bindir/pc-bios".
  90 * Otherwise, this is CONFIG_QEMU_DATADIR (possibly relocated).
  91 *
  92 * The caller must use g_free() to free the returned data when it is
  93 * no longer required.
  94 */
  95static char *find_datadir(void)
  96{
  97    g_autofree char *dir = NULL;
  98
  99    dir = g_build_filename(qemu_get_exec_dir(), "pc-bios", NULL);
 100    if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
 101        return g_steal_pointer(&dir);
 102    }
 103
 104    return get_relocated_path(CONFIG_QEMU_DATADIR);
 105}
 106
 107void qemu_add_default_firmwarepath(void)
 108{
 109    char **dirs;
 110    size_t i;
 111
 112    /* add configured firmware directories */
 113    dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0);
 114    for (i = 0; dirs[i] != NULL; i++) {
 115        qemu_add_data_dir(get_relocated_path(dirs[i]));
 116    }
 117    g_strfreev(dirs);
 118
 119    /* try to find datadir relative to the executable path */
 120    qemu_add_data_dir(find_datadir());
 121}
 122
 123void qemu_list_data_dirs(void)
 124{
 125    int i;
 126    for (i = 0; i < data_dir_idx; i++) {
 127        printf("%s\n", data_dir[i]);
 128    }
 129}
 130