|
|
1.1 ! root 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 <sys/types.h> ! 7: #include <dirent.h> ! 8: #include <unistd.h> ! 9: #include <stdlib.h> ! 10: #include <string.h> ! 11: #include <errno.h> ! 12: #include <stdio.h> ! 13: #include "qemu.h" ! 14: ! 15: struct pathelem ! 16: { ! 17: /* Name of this, eg. lib */ ! 18: char *name; ! 19: /* Full path name, eg. /usr/gnemul/x86-linux/lib. */ ! 20: char *pathname; ! 21: struct pathelem *parent; ! 22: /* Children */ ! 23: unsigned int num_entries; ! 24: struct pathelem *entries[0]; ! 25: }; ! 26: ! 27: static struct pathelem *base; ! 28: ! 29: /* First N chars of S1 match S2, and S2 is N chars long. */ ! 30: static int strneq(const char *s1, unsigned int n, const char *s2) ! 31: { ! 32: unsigned int i; ! 33: ! 34: for (i = 0; i < n; i++) ! 35: if (s1[i] != s2[i]) ! 36: return 0; ! 37: return s2[i] == 0; ! 38: } ! 39: ! 40: static struct pathelem *add_entry(struct pathelem *root, const char *name); ! 41: ! 42: static struct pathelem *new_entry(const char *root, ! 43: struct pathelem *parent, ! 44: const char *name) ! 45: { ! 46: struct pathelem *new = malloc(sizeof(*new)); ! 47: new->name = strdup(name); ! 48: asprintf(&new->pathname, "%s/%s", root, name); ! 49: new->num_entries = 0; ! 50: return new; ! 51: } ! 52: ! 53: #define streq(a,b) (strcmp((a), (b)) == 0) ! 54: ! 55: static struct pathelem *add_dir_maybe(struct pathelem *path) ! 56: { ! 57: DIR *dir; ! 58: ! 59: if ((dir = opendir(path->pathname)) != NULL) { ! 60: struct dirent *dirent; ! 61: ! 62: while ((dirent = readdir(dir)) != NULL) { ! 63: if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){ ! 64: path = add_entry(path, dirent->d_name); ! 65: } ! 66: } ! 67: closedir(dir); ! 68: } ! 69: return path; ! 70: } ! 71: ! 72: static struct pathelem *add_entry(struct pathelem *root, const char *name) ! 73: { ! 74: root->num_entries++; ! 75: ! 76: root = realloc(root, sizeof(*root) ! 77: + sizeof(root->entries[0])*root->num_entries); ! 78: ! 79: root->entries[root->num_entries-1] = new_entry(root->pathname, root, name); ! 80: root->entries[root->num_entries-1] ! 81: = add_dir_maybe(root->entries[root->num_entries-1]); ! 82: return root; ! 83: } ! 84: ! 85: /* This needs to be done after tree is stabalized (ie. no more reallocs!). */ ! 86: static void set_parents(struct pathelem *child, struct pathelem *parent) ! 87: { ! 88: unsigned int i; ! 89: ! 90: child->parent = parent; ! 91: for (i = 0; i < child->num_entries; i++) ! 92: set_parents(child->entries[i], child); ! 93: } ! 94: ! 95: void init_paths(const char *prefix) ! 96: { ! 97: if (prefix[0] != '/' || ! 98: prefix[0] == '\0' || ! 99: !strcmp(prefix, "/")) ! 100: return; ! 101: ! 102: base = new_entry("", NULL, prefix+1); ! 103: base = add_dir_maybe(base); ! 104: if (base->num_entries == 0) { ! 105: free (base); ! 106: base = NULL; ! 107: } else { ! 108: set_parents(base, base); ! 109: } ! 110: } ! 111: ! 112: /* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */ ! 113: static const char * ! 114: follow_path(const struct pathelem *cursor, const char *name) ! 115: { ! 116: unsigned int i, namelen; ! 117: ! 118: name += strspn(name, "/"); ! 119: namelen = strcspn(name, "/"); ! 120: ! 121: if (namelen == 0) ! 122: return cursor->pathname; ! 123: ! 124: if (strneq(name, namelen, "..")) ! 125: return follow_path(cursor->parent, name + namelen); ! 126: ! 127: if (strneq(name, namelen, ".")) ! 128: return follow_path(cursor, name + namelen); ! 129: ! 130: for (i = 0; i < cursor->num_entries; i++) ! 131: if (strneq(name, namelen, cursor->entries[i]->name)) ! 132: return follow_path(cursor->entries[i], name + namelen); ! 133: ! 134: /* Not found */ ! 135: return NULL; ! 136: } ! 137: ! 138: /* Look for path in emulation dir, otherwise return name. */ ! 139: const char *path(const char *name) ! 140: { ! 141: /* Only do absolute paths: quick and dirty, but should mostly be OK. ! 142: Could do relative by tracking cwd. */ ! 143: if (!base || name[0] != '/') ! 144: return name; ! 145: ! 146: return follow_path(base, name) ?: name; ! 147: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.