📄 path.c
字号:
/* Code to mangle pathnames into those matching a given prefix. eg. open("/lib/foo.so") => open("/usr/gnemul/i386-linux/lib/foo.so"); The assumption is that this area does not change.*/#include <sys/types.h>#include <dirent.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <stdio.h>#include "qemu.h"struct pathelem{ /* Name of this, eg. lib */ char *name; /* Full path name, eg. /usr/gnemul/x86-linux/lib. */ char *pathname; struct pathelem *parent; /* Children */ unsigned int num_entries; struct pathelem *entries[0];};static struct pathelem *base;/* First N chars of S1 match S2, and S2 is N chars long. */static int strneq(const char *s1, unsigned int n, const char *s2){ unsigned int i; for (i = 0; i < n; i++) if (s1[i] != s2[i]) return 0; return s2[i] == 0;}static struct pathelem *add_entry(struct pathelem *root, const char *name);static struct pathelem *new_entry(const char *root, struct pathelem *parent, const char *name){ struct pathelem *new = malloc(sizeof(*new)); new->name = strdup(name); asprintf(&new->pathname, "%s/%s", root, name); new->num_entries = 0; return new;}#define streq(a,b) (strcmp((a), (b)) == 0)static struct pathelem *add_dir_maybe(struct pathelem *path){ DIR *dir; if ((dir = opendir(path->pathname)) != NULL) { struct dirent *dirent; while ((dirent = readdir(dir)) != NULL) { if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){ path = add_entry(path, dirent->d_name); } } closedir(dir); } return path;}static struct pathelem *add_entry(struct pathelem *root, const char *name){ root->num_entries++; root = realloc(root, sizeof(*root) + sizeof(root->entries[0])*root->num_entries); root->entries[root->num_entries-1] = new_entry(root->pathname, root, name); root->entries[root->num_entries-1] = add_dir_maybe(root->entries[root->num_entries-1]); return root;}/* This needs to be done after tree is stabalized (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);}void init_paths(const char *prefix){ if (prefix[0] != '/' || prefix[0] == '\0' || !strcmp(prefix, "/")) return; base = new_entry("", NULL, prefix+1); base = add_dir_maybe(base); if (base->num_entries == 0) { free (base); base = NULL; } else { set_parents(base, base); }}/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */static const char *follow_path(const struct pathelem *cursor, const char *name){ unsigned int i, namelen; name += strspn(name, "/"); namelen = strcspn(name, "/"); if (namelen == 0) return cursor->pathname; if (strneq(name, namelen, "..")) return follow_path(cursor->parent, name + namelen); if (strneq(name, namelen, ".")) return follow_path(cursor, name + namelen); for (i = 0; i < cursor->num_entries; i++) if (strneq(name, namelen, cursor->entries[i]->name)) return follow_path(cursor->entries[i], name + namelen); /* Not found */ return NULL;}/* Look for path in emulation dir, otherwise return name. */const char *path(const char *name){ /* Only do absolute paths: quick and dirty, but should mostly be OK. Could do relative by tracking cwd. */ if (!base || name[0] != '/') return name; return follow_path(base, name) ?: name;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -