master
c 68 lines 1.72 KB
Raw
1 /* Code to mangle pathnames into those matching a given prefix.
2 eg. open("/lib/foo.so") => open("/usr/gnemul/i386-linux/lib/foo.so");
3
4 The assumption is that this area does not change.
5 */
6 #include "qemu/osdep.h"
7 #include "qemu/cutils.h"
8 #include "qemu/path.h"
9 #include "qemu/thread.h"
10
11 static const char *base;
12 static GHashTable *hash;
13 static QemuMutex lock;
14
15 void init_paths(const char *prefix)
16 {
17 if (prefix[0] == '\0' || !strcmp(prefix, "/")) {
18 return;
19 }
20
21 if (prefix[0] == '/') {
22 base = g_strdup(prefix);
23 } else {
24 char *cwd = g_get_current_dir();
25 base = g_build_filename(cwd, prefix, NULL);
26 g_free(cwd);
27 }
28
29 hash = g_hash_table_new(g_str_hash, g_str_equal);
30 qemu_mutex_init(&lock);
31 }
32
33 /* Look for path in emulation dir, otherwise return name. */
34 const char *path(const char *name)
35 {
36 gpointer key, value;
37 const char *ret;
38
39 /* Only do absolute paths: quick and dirty, but should mostly be OK. */
40 if (!base || !name || name[0] != '/') {
41 return name;
42 }
43
44 qemu_mutex_lock(&lock);
45
46 /* Have we looked up this file before? */
47 if (g_hash_table_lookup_extended(hash, name, &key, &value)) {
48 ret = value ? value : name;
49 } else {
50 char *save = g_strdup(name);
51 char *full = g_build_filename(base, name, NULL);
52
53 /* Look for the path; record the result, pass or fail. */
54 if (access(full, F_OK) == 0) {
55 /* Exists. */
56 g_hash_table_insert(hash, save, full);
57 ret = full;
58 } else {
59 /* Does not exist. */
60 g_free(full);
61 g_hash_table_insert(hash, save, NULL);
62 ret = name;
63 }
64 }
65
66 qemu_mutex_unlock(&lock);
67 return ret;
68 }