diff options
author | H. Peter Anvin <hpa@zytor.com> | 2010-06-25 20:36:59 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-06-25 20:36:59 -0700 |
commit | 4deec2c8fb4f93204187f54f9b722072be537832 (patch) | |
tree | cd539c52dbe8c2980bb61b632580014479b6cd60 /core/fs/fs.c | |
parent | 4b038f7218b382a146a101b685264ca425c13811 (diff) | |
download | syslinux-4deec2c8fb4f93204187f54f9b722072be537832.tar.gz |
core, fs: handle .. resolution in the filesystem core
Some filesystems, including btrfs, don't have .. directory entries.
We already handle . in the filesystem core, handle .. as well.
This means keeping chains of parent inodes for all open inodes, at
least for the duration of a path search; we might as well hang onto
them.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'core/fs/fs.c')
-rw-r--r-- | core/fs/fs.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/core/fs/fs.c b/core/fs/fs.c index c16f9550..a101dfda 100644 --- a/core/fs/fs.c +++ b/core/fs/fs.c @@ -30,6 +30,19 @@ struct inode *alloc_inode(struct fs_info *fs, uint32_t ino, size_t data) } /* + * Free a refcounted inode + */ +void put_inode(struct inode *inode) +{ + if (inode) { + if (! --inode->refcnt) { + put_inode(inode->parent); + free(inode); + } + } +} + +/* * Get an empty file structure */ static struct file *alloc_file(void) @@ -235,7 +248,20 @@ int searchdir(const char *name) p++; *p++ = '\0'; - if (part[0] != '.' || part[1] != '\0') { + if (part[0] == '.' && part[1] == '.' && part[2] == '\0') { + if (inode->parent) { + put_inode(parent); + parent = get_inode(inode->parent); + put_inode(inode); + inode = NULL; + if (!echar) { + /* Terminal double dots */ + inode = parent; + parent = inode->parent ? + get_inode(inode->parent) : NULL; + } + } + } else if (part[0] != '.' || part[1] != '\0') { inode = this_fs->fs_ops->iget(part, parent); if (!inode) goto err; @@ -278,7 +304,7 @@ int searchdir(const char *name) goto got_link; } - put_inode(parent); + inode->parent = parent; parent = NULL; if (!echar) @@ -304,16 +330,11 @@ int searchdir(const char *name) file->inode = inode; file->offset = 0; - dprintf("File %s -> %p (inode %p) len %u\n", name, file, - inode, inode->size); - return file_to_handle(file); err: - if (inode) - put_inode(inode); - if (parent) - put_inode(parent); + put_inode(inode); + put_inode(parent); if (pathbuf) free(pathbuf); _close_file(file); |