diff options
Diffstat (limited to 'core/fs')
-rw-r--r-- | core/fs/chdir.c | 144 | ||||
-rw-r--r-- | core/fs/fs.c | 13 | ||||
-rw-r--r-- | core/fs/lib/searchconfig.c | 3 |
3 files changed, 79 insertions, 81 deletions
diff --git a/core/fs/chdir.c b/core/fs/chdir.c index c40e91bf..903cabce 100644 --- a/core/fs/chdir.c +++ b/core/fs/chdir.c @@ -17,96 +17,70 @@ void pm_realpath(com32sys_t *regs) realpath(dst, src, FILENAME_MAX); } -#define EMIT(x) \ -do { \ - if (++n < bufsize) \ - *q++ = (x); \ -} while (0) - - -static size_t join_paths(char *dst, size_t bufsize, - const char *s1, const char *s2) +static size_t copy_string(char *buf, size_t ix, size_t bufsize, const char *src) { - const char *list[2]; - int i; char c; - const char *p; - char *q = dst; - size_t n = 0; - bool slash; - struct bufstat { - struct bufstat *prev; - size_t n; - char *q; - }; - struct bufstat *stk = NULL; - struct bufstat *bp; - - slash = false; - - list[0] = s1; - list[1] = s2; - - for (i = 0; i < 2; i++) { - p = list[i]; - - while ((c = *p++)) { - if (c == '/') { - if (!slash) { - EMIT(c); - bp = malloc(sizeof *bp); - bp->n = n; - bp->q = q; - bp->prev = stk; - stk = bp; - } - slash = true; - } else if (c == '.' && slash) { - if (!*p || *p == '/') { - continue; /* Single dot */ - } - if (*p == '.' && (!p[1] || p[1] == '/')) { - /* Double dot; unwind one level */ - p++; - if (stk) { - bp = stk; - stk = stk->prev; - free(bp); - } - if (stk) { - n = stk->n; - q = stk->q; - } - continue; - } - } else { - EMIT(c); - slash = false; - } - } + + while ((c = *src++)) { + if (ix+1 < bufsize) + buf[ix] = c; + ix++; } - if (bufsize) - *q = '\0'; + if (ix < bufsize) + buf[ix] = '\0'; + + return ix; +} + +static size_t generic_inode_to_path(struct inode *inode, char *dst, size_t bufsize) +{ + size_t s = 0; + + dprintf("inode %p name %s\n", inode, inode->name); + + if (inode->parent) { + if (!inode->name) /* Only the root should have no name */ + return -1; + + s = generic_inode_to_path(inode->parent, dst, bufsize); + if (s == (size_t)-1) + return s; /* Error! */ - while ((bp = stk)) { - stk = stk->prev; - free(bp); + s = copy_string(dst, s, bufsize, "/"); + s = copy_string(dst, s, bufsize, inode->name); } - return n; + return s; } size_t realpath(char *dst, const char *src, size_t bufsize) { + int rv; + struct file *file; + size_t s; + + dprintf("realpath: input: %s\n", src); + if (this_fs->fs_ops->realpath) { - return this_fs->fs_ops->realpath(this_fs, dst, src, bufsize); + s = this_fs->fs_ops->realpath(this_fs, dst, src, bufsize); } else { - /* Filesystems with "common" pathname resolution */ - return join_paths(dst, bufsize, - src[0] == '/' ? "" : this_fs->cwd_name, - src); + rv = searchdir(src); + if (rv < 0) { + dprintf("realpath: searchpath failure\n"); + return -1; + } + + file = handle_to_file(rv); + s = generic_inode_to_path(file->inode, dst, bufsize); + if (s == 0) + s = copy_string(dst, 0, bufsize, "/"); + + _close_file(file); } + + dprintf("realpath: output: %s\n", dst); + return s; } int chdir(const char *src) @@ -114,8 +88,10 @@ int chdir(const char *src) int rv; struct file *file; char cwd_buf[CURRENTDIR_MAX]; + size_t s; - dprintf("chdir: from %s add %s\n", this_fs->cwd_name, src); + dprintf("chdir: from %s (inode %p) add %s\n", + this_fs->cwd_name, this_fs->cwd, src); if (this_fs->fs_ops->chdir) return this_fs->fs_ops->chdir(this_fs, src); @@ -136,12 +112,20 @@ int chdir(const char *src) _close_file(file); /* Save the current working directory */ - realpath(cwd_buf, src, CURRENTDIR_MAX); + s = generic_inode_to_path(this_fs->cwd, cwd_buf, CURRENTDIR_MAX-1); /* Make sure the cwd_name ends in a slash, it's supposed to be a prefix */ - join_paths(this_fs->cwd_name, CURRENTDIR_MAX, cwd_buf, "/"); + if (s < 1 || cwd_buf[s-1] != '/') + cwd_buf[s++] = '/'; + + if (s >= CURRENTDIR_MAX) + s = CURRENTDIR_MAX - 1; + + cwd_buf[s++] = '\0'; + memcpy(this_fs->cwd_name, cwd_buf, s); - dprintf("chdir: final: %s\n", this_fs->cwd_name); + dprintf("chdir: final %s (inode %p)\n", + this_fs->cwd_name, this_fs->cwd); return 0; } diff --git a/core/fs/fs.c b/core/fs/fs.c index ad2fb370..21f5dba0 100644 --- a/core/fs/fs.c +++ b/core/fs/fs.c @@ -37,6 +37,8 @@ void put_inode(struct inode *inode) while (inode && --inode->refcnt == 0) { struct inode *dead = inode; inode = inode->parent; + if (dead->name) + free((char *)dead->name); free(dead); } } @@ -207,6 +209,9 @@ int searchdir(const char *name) char *part, *p, echar; int symlink_count = MAX_SYMLINK_CNT; + dprintf("searchdir: %s root: %p cwd: %p\n", + name, this_fs->root, this_fs->cwd); + if (!(file = alloc_file())) goto err_no_close; file->fs = this_fs; @@ -305,6 +310,9 @@ int searchdir(const char *name) goto got_link; } + inode->name = strdup(part); + dprintf("path component: %s\n", inode->name); + inode->parent = parent; parent = NULL; @@ -349,6 +357,8 @@ int open_file(const char *name, struct com32_filedata *filedata) struct file *file; char mangled_name[FILENAME_MAX]; + dprintf("open_file %s\n", name); + mangle_name(mangled_name, name); rv = searchdir(mangled_name); @@ -376,6 +386,8 @@ void pm_open_file(com32sys_t *regs) const char *name = MK_PTR(regs->es, regs->esi.w[0]); char mangled_name[FILENAME_MAX]; + dprintf("pm_open_file %s\n", name); + mangle_name(mangled_name, name); rv = searchdir(mangled_name); if (rv < 0) { @@ -470,6 +482,7 @@ void fs_init(com32sys_t *regs) if (fs.fs_ops->iget_root) { fs.root = fs.fs_ops->iget_root(&fs); fs.cwd = get_inode(fs.root); + dprintf("init: root inode %p, cwd inode %p\n", fs.root, fs.cwd); } SectorShift = fs.sector_shift; diff --git a/core/fs/lib/searchconfig.c b/core/fs/lib/searchconfig.c index 24bfde31..f18836a8 100644 --- a/core/fs/lib/searchconfig.c +++ b/core/fs/lib/searchconfig.c @@ -25,7 +25,8 @@ int search_config(const char *search_directories[], const char *filenames[]) "%s%s%s", sd, (*sd && sd[strlen(sd)-1] == '/') ? "" : "/", sf); - realpath(ConfigName, confignamebuf, FILENAME_MAX); + if (realpath(ConfigName, confignamebuf, FILENAME_MAX) == (size_t)-1) + continue; regs.edi.w[0] = OFFS_WRT(ConfigName, 0); dprintf("Config search: %s\n", ConfigName); call16(core_open, ®s, ®s); |