2
0

path.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  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. The assumption is that this area does not change.
  4. */
  5. #include "qemu/osdep.h"
  6. #include <sys/param.h>
  7. #include <dirent.h>
  8. #include "qemu/cutils.h"
  9. #include "qemu/path.h"
  10. #include "qemu/thread.h"
  11. static const char *base;
  12. static GHashTable *hash;
  13. static QemuMutex lock;
  14. void init_paths(const char *prefix)
  15. {
  16. if (prefix[0] == '\0' || !strcmp(prefix, "/")) {
  17. return;
  18. }
  19. if (prefix[0] == '/') {
  20. base = g_strdup(prefix);
  21. } else {
  22. char *cwd = g_get_current_dir();
  23. base = g_build_filename(cwd, prefix, NULL);
  24. g_free(cwd);
  25. }
  26. hash = g_hash_table_new(g_str_hash, g_str_equal);
  27. qemu_mutex_init(&lock);
  28. }
  29. /* Look for path in emulation dir, otherwise return name. */
  30. const char *path(const char *name)
  31. {
  32. gpointer key, value;
  33. const char *ret;
  34. /* Only do absolute paths: quick and dirty, but should mostly be OK. */
  35. if (!base || !name || name[0] != '/') {
  36. return name;
  37. }
  38. qemu_mutex_lock(&lock);
  39. /* Have we looked up this file before? */
  40. if (g_hash_table_lookup_extended(hash, name, &key, &value)) {
  41. ret = value ? value : name;
  42. } else {
  43. char *save = g_strdup(name);
  44. char *full = g_build_filename(base, name, NULL);
  45. /* Look for the path; record the result, pass or fail. */
  46. if (access(full, F_OK) == 0) {
  47. /* Exists. */
  48. g_hash_table_insert(hash, save, full);
  49. ret = full;
  50. } else {
  51. /* Does not exist. */
  52. g_free(full);
  53. g_hash_table_insert(hash, save, NULL);
  54. ret = name;
  55. }
  56. }
  57. qemu_mutex_unlock(&lock);
  58. return ret;
  59. }