forked from brl/citadel
138 lines
4.3 KiB
Diff
138 lines
4.3 KiB
Diff
By default qemu builds a complete list of directories within the user
|
|
emulation sysroot (-L option). The OE sysroot directory is large and
|
|
this is confusing, for example it indexes all pkgdata. In particular this
|
|
confuses strace of qemu binaries with tons of irrelevant paths.
|
|
|
|
This patch stops the code indexing up front and instead only indexes
|
|
things if/as/when it needs to. This drastically reduces the files it
|
|
reads and reduces memory usage and cleans up strace.
|
|
|
|
It would also avoid the infinite directory traversal bug in [YOCTO #6996]
|
|
although the code could still be vulnerable if it parsed those specific
|
|
paths.
|
|
|
|
RP
|
|
2016/3/9
|
|
Upstream-Status: Pending
|
|
|
|
Index: qemu-2.5.0/util/path.c
|
|
===================================================================
|
|
--- qemu-2.5.0.orig/util/path.c
|
|
+++ qemu-2.5.0/util/path.c
|
|
@@ -19,6 +19,7 @@ struct pathelem
|
|
char *name;
|
|
/* Full path name, eg. /usr/gnemul/x86-linux/lib. */
|
|
char *pathname;
|
|
+ int populated_entries;
|
|
struct pathelem *parent;
|
|
/* Children */
|
|
unsigned int num_entries;
|
|
@@ -49,6 +50,7 @@ static struct pathelem *new_entry(const
|
|
new->name = g_strdup(name);
|
|
new->pathname = g_strdup_printf("%s/%s", root, name);
|
|
new->num_entries = 0;
|
|
+ new->populated_entries = 0;
|
|
return new;
|
|
}
|
|
|
|
@@ -57,15 +59,16 @@ static struct pathelem *new_entry(const
|
|
/* Not all systems provide this feature */
|
|
#if defined(DT_DIR) && defined(DT_UNKNOWN) && defined(DT_LNK)
|
|
# define dirent_type(dirent) ((dirent)->d_type)
|
|
-# define is_dir_maybe(type) \
|
|
- ((type) == DT_DIR || (type) == DT_UNKNOWN || (type) == DT_LNK)
|
|
+# define is_not_dir(type) \
|
|
+ ((type) != DT_DIR && (type) != DT_UNKNOWN && (type) != DT_LNK)
|
|
#else
|
|
# define dirent_type(dirent) (1)
|
|
-# define is_dir_maybe(type) (type)
|
|
+# define is_not_dir(type) (0)
|
|
#endif
|
|
|
|
static struct pathelem *add_dir_maybe(struct pathelem *path)
|
|
{
|
|
+ unsigned int i;
|
|
DIR *dir;
|
|
|
|
if ((dir = opendir(path->pathname)) != NULL) {
|
|
@@ -78,6 +81,11 @@ static struct pathelem *add_dir_maybe(st
|
|
}
|
|
closedir(dir);
|
|
}
|
|
+
|
|
+ for (i = 0; i < path->num_entries; i++)
|
|
+ (path->entries[i])->parent = path;
|
|
+
|
|
+ path->populated_entries = 1;
|
|
return path;
|
|
}
|
|
|
|
@@ -93,26 +101,16 @@ static struct pathelem *add_entry(struct
|
|
e = &root->entries[root->num_entries-1];
|
|
|
|
*e = new_entry(root->pathname, root, name);
|
|
- if (is_dir_maybe(type)) {
|
|
- *e = add_dir_maybe(*e);
|
|
+ if (is_not_dir(type)) {
|
|
+ (*e)->populated_entries = 1;
|
|
}
|
|
|
|
return root;
|
|
}
|
|
|
|
-/* This needs to be done after tree is stabilized (ie. no more reallocs!). */
|
|
-static void set_parents(struct pathelem *child, struct pathelem *parent)
|
|
-{
|
|
- unsigned int i;
|
|
-
|
|
- child->parent = parent;
|
|
- for (i = 0; i < child->num_entries; i++)
|
|
- set_parents(child->entries[i], child);
|
|
-}
|
|
-
|
|
/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
|
|
static const char *
|
|
-follow_path(const struct pathelem *cursor, const char *name)
|
|
+follow_path(struct pathelem *cursor, struct pathelem **source, const char *name)
|
|
{
|
|
unsigned int i, namelen;
|
|
|
|
@@ -123,14 +121,18 @@ follow_path(const struct pathelem *curso
|
|
return cursor->pathname;
|
|
|
|
if (strneq(name, namelen, ".."))
|
|
- return follow_path(cursor->parent, name + namelen);
|
|
+ return follow_path(cursor->parent, &cursor->parent, name + namelen);
|
|
|
|
if (strneq(name, namelen, "."))
|
|
- return follow_path(cursor, name + namelen);
|
|
+ return follow_path(cursor, source, name + namelen);
|
|
+
|
|
+ if (!cursor->populated_entries)
|
|
+ *source = add_dir_maybe(cursor);
|
|
+ cursor = *source;
|
|
|
|
for (i = 0; i < cursor->num_entries; i++)
|
|
if (strneq(name, namelen, cursor->entries[i]->name))
|
|
- return follow_path(cursor->entries[i], name + namelen);
|
|
+ return follow_path(cursor->entries[i], &cursor->entries[i], name + namelen);
|
|
|
|
/* Not found */
|
|
return NULL;
|
|
@@ -164,8 +166,6 @@ void init_paths(const char *prefix)
|
|
g_free(base->name);
|
|
g_free(base);
|
|
base = NULL;
|
|
- } else {
|
|
- set_parents(base, base);
|
|
}
|
|
}
|
|
|
|
@@ -177,5 +177,5 @@ const char *path(const char *name)
|
|
if (!base || !name || name[0] != '/')
|
|
return name;
|
|
|
|
- return follow_path(base, name) ?: name;
|
|
+ return follow_path(base, &base, name) ?: name;
|
|
}
|