[syslinux:master] core, fs: handle .. resolution in the filesystem core
syslinux-bot for H. Peter Anvin
hpa at zytor.com
Fri Jun 25 20:39:02 PDT 2010
Commit-ID: 4deec2c8fb4f93204187f54f9b722072be537832
Gitweb: http://syslinux.zytor.com/commit/4deec2c8fb4f93204187f54f9b722072be537832
Author: H. Peter Anvin <hpa at zytor.com>
AuthorDate: Fri, 25 Jun 2010 20:36:59 -0700
Committer: H. Peter Anvin <hpa at zytor.com>
CommitDate: Fri, 25 Jun 2010 20:36:59 -0700
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 at zytor.com>
---
core/fs/fs.c | 39 ++++++++++++++++++++++++++++++---------
core/include/fs.h | 8 +++-----
2 files changed, 33 insertions(+), 14 deletions(-)
diff --git a/core/fs/fs.c b/core/fs/fs.c
index c16f955..a101dfd 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);
diff --git a/core/include/fs.h b/core/include/fs.h
index f1d35bb..bb629c9 100644
--- a/core/include/fs.h
+++ b/core/include/fs.h
@@ -94,6 +94,7 @@ struct extent {
*/
struct inode {
struct fs_info *fs; /* The filesystem this inode is associated with */
+ struct inode *parent; /* Parent directory, if any */
int refcnt;
int mode; /* FILE , DIR or SYMLINK */
uint32_t size;
@@ -157,11 +158,8 @@ static inline struct inode *get_inode(struct inode *inode)
inode->refcnt++;
return inode;
}
-static inline void put_inode(struct inode *inode)
-{
- if (! --inode->refcnt)
- free(inode);
-}
+
+void put_inode(struct inode *inode);
static inline void malloc_error(char *obj)
{
More information about the Syslinux-commits
mailing list