Annotation of qemu/bsd-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 <sys/param.h>
        !             8: #include <dirent.h>
        !             9: #include <unistd.h>
        !            10: #include <stdlib.h>
        !            11: #include <string.h>
        !            12: #include <errno.h>
        !            13: #include <stdio.h>
        !            14: #include "qemu.h"
        !            15: #include "qemu-common.h"
        !            16: 
        !            17: struct pathelem
        !            18: {
        !            19:     /* Name of this, eg. lib */
        !            20:     char *name;
        !            21:     /* Full path name, eg. /usr/gnemul/x86-linux/lib. */
        !            22:     char *pathname;
        !            23:     struct pathelem *parent;
        !            24:     /* Children */
        !            25:     unsigned int num_entries;
        !            26:     struct pathelem *entries[0];
        !            27: };
        !            28: 
        !            29: static struct pathelem *base;
        !            30: 
        !            31: /* First N chars of S1 match S2, and S2 is N chars long. */
        !            32: static int strneq(const char *s1, unsigned int n, const char *s2)
        !            33: {
        !            34:     unsigned int i;
        !            35: 
        !            36:     for (i = 0; i < n; i++)
        !            37:         if (s1[i] != s2[i])
        !            38:             return 0;
        !            39:     return s2[i] == 0;
        !            40: }
        !            41: 
        !            42: static struct pathelem *add_entry(struct pathelem *root, const char *name);
        !            43: 
        !            44: static struct pathelem *new_entry(const char *root,
        !            45:                                   struct pathelem *parent,
        !            46:                                   const char *name)
        !            47: {
        !            48:     struct pathelem *new = malloc(sizeof(*new));
        !            49:     new->name = strdup(name);
        !            50:     asprintf(&new->pathname, "%s/%s", root, name);
        !            51:     new->num_entries = 0;
        !            52:     return new;
        !            53: }
        !            54: 
        !            55: #define streq(a,b) (strcmp((a), (b)) == 0)
        !            56: 
        !            57: static struct pathelem *add_dir_maybe(struct pathelem *path)
        !            58: {
        !            59:     DIR *dir;
        !            60: 
        !            61:     if ((dir = opendir(path->pathname)) != NULL) {
        !            62:         struct dirent *dirent;
        !            63: 
        !            64:         while ((dirent = readdir(dir)) != NULL) {
        !            65:             if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
        !            66:                 path = add_entry(path, dirent->d_name);
        !            67:             }
        !            68:         }
        !            69:         closedir(dir);
        !            70:     }
        !            71:     return path;
        !            72: }
        !            73: 
        !            74: static struct pathelem *add_entry(struct pathelem *root, const char *name)
        !            75: {
        !            76:     root->num_entries++;
        !            77: 
        !            78:     root = realloc(root, sizeof(*root)
        !            79:                    + sizeof(root->entries[0])*root->num_entries);
        !            80: 
        !            81:     root->entries[root->num_entries-1] = new_entry(root->pathname, root, name);
        !            82:     root->entries[root->num_entries-1]
        !            83:         = add_dir_maybe(root->entries[root->num_entries-1]);
        !            84:     return root;
        !            85: }
        !            86: 
        !            87: /* This needs to be done after tree is stabilized (ie. no more reallocs!). */
        !            88: static void set_parents(struct pathelem *child, struct pathelem *parent)
        !            89: {
        !            90:     unsigned int i;
        !            91: 
        !            92:     child->parent = parent;
        !            93:     for (i = 0; i < child->num_entries; i++)
        !            94:         set_parents(child->entries[i], child);
        !            95: }
        !            96: 
        !            97: /* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
        !            98: static const char *
        !            99: follow_path(const struct pathelem *cursor, const char *name)
        !           100: {
        !           101:     unsigned int i, namelen;
        !           102: 
        !           103:     name += strspn(name, "/");
        !           104:     namelen = strcspn(name, "/");
        !           105: 
        !           106:     if (namelen == 0)
        !           107:         return cursor->pathname;
        !           108: 
        !           109:     if (strneq(name, namelen, ".."))
        !           110:         return follow_path(cursor->parent, name + namelen);
        !           111: 
        !           112:     if (strneq(name, namelen, "."))
        !           113:         return follow_path(cursor, name + namelen);
        !           114: 
        !           115:     for (i = 0; i < cursor->num_entries; i++)
        !           116:         if (strneq(name, namelen, cursor->entries[i]->name))
        !           117:             return follow_path(cursor->entries[i], name + namelen);
        !           118: 
        !           119:     /* Not found */
        !           120:     return NULL;
        !           121: }
        !           122: 
        !           123: void init_paths(const char *prefix)
        !           124: {
        !           125:     char pref_buf[PATH_MAX];
        !           126: 
        !           127:     if (prefix[0] == '\0' ||
        !           128:         !strcmp(prefix, "/"))
        !           129:         return;
        !           130: 
        !           131:     if (prefix[0] != '/') {
        !           132:         char *cwd = getcwd(NULL, 0);
        !           133:         size_t pref_buf_len = sizeof(pref_buf);
        !           134: 
        !           135:         if (!cwd)
        !           136:             abort();
        !           137:         pstrcpy(pref_buf, sizeof(pref_buf), cwd);
        !           138:         pstrcat(pref_buf, pref_buf_len, "/");
        !           139:         pstrcat(pref_buf, pref_buf_len, prefix);
        !           140:         free(cwd);
        !           141:     } else
        !           142:         pstrcpy(pref_buf, sizeof(pref_buf), prefix + 1);
        !           143: 
        !           144:     base = new_entry("", NULL, pref_buf);
        !           145:     base = add_dir_maybe(base);
        !           146:     if (base->num_entries == 0) {
        !           147:         free (base);
        !           148:         base = NULL;
        !           149:     } else {
        !           150:         set_parents(base, base);
        !           151:     }
        !           152: }
        !           153: 
        !           154: /* Look for path in emulation dir, otherwise return name. */
        !           155: const char *path(const char *name)
        !           156: {
        !           157:     /* Only do absolute paths: quick and dirty, but should mostly be OK.
        !           158:        Could do relative by tracking cwd. */
        !           159:     if (!base || name[0] != '/')
        !           160:         return name;
        !           161: 
        !           162:     return follow_path(base, name) ?: name;
        !           163: }

unix.superglobalmegacorp.com

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