[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