|
|
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.