Annotation of qemu/linux-user/path.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.