|
|
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:
1.1.1.3 ! root 85: /* This needs to be done after tree is stabilized (ie. no more reallocs!). */
1.1 root 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: /* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
96: static const char *
97: follow_path(const struct pathelem *cursor, const char *name)
98: {
99: unsigned int i, namelen;
100:
101: name += strspn(name, "/");
102: namelen = strcspn(name, "/");
103:
104: if (namelen == 0)
105: return cursor->pathname;
106:
107: if (strneq(name, namelen, ".."))
108: return follow_path(cursor->parent, name + namelen);
109:
110: if (strneq(name, namelen, "."))
111: return follow_path(cursor, name + namelen);
112:
113: for (i = 0; i < cursor->num_entries; i++)
114: if (strneq(name, namelen, cursor->entries[i]->name))
115: return follow_path(cursor->entries[i], name + namelen);
116:
117: /* Not found */
118: return NULL;
119: }
120:
1.1.1.2 root 121: void init_paths(const char *prefix)
122: {
123: char pref_buf[PATH_MAX];
124:
125: if (prefix[0] == '\0' ||
126: !strcmp(prefix, "/"))
127: return;
128:
129: if (prefix[0] != '/') {
130: char *cwd = get_current_dir_name();
131: if (!cwd)
132: abort();
133: strcpy(pref_buf, cwd);
134: strcat(pref_buf, "/");
135: strcat(pref_buf, prefix);
136: free(cwd);
137: } else
138: strcpy(pref_buf,prefix + 1);
139:
140: base = new_entry("", NULL, pref_buf);
141: base = add_dir_maybe(base);
142: if (base->num_entries == 0) {
143: free (base);
144: base = NULL;
145: } else {
146: set_parents(base, base);
147: }
148: }
149:
1.1 root 150: /* Look for path in emulation dir, otherwise return name. */
151: const char *path(const char *name)
152: {
153: /* Only do absolute paths: quick and dirty, but should mostly be OK.
154: Could do relative by tracking cwd. */
1.1.1.3 ! root 155: if (!base || !name || name[0] != '/')
1.1 root 156: return name;
157:
158: return follow_path(base, name) ?: name;
159: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.