[syslinux:master] Actually keep track of the pathnames for all elements

syslinux-bot for H. Peter Anvin hpa at zytor.com
Thu Jun 28 21:24:03 PDT 2012


Commit-ID:  15cbfdfd390402057d237664ac087140608bf80b
Gitweb:     http://www.syslinux.org/commit/15cbfdfd390402057d237664ac087140608bf80b
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Thu, 28 Jun 2012 19:33:16 -0700
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Thu, 28 Jun 2012 19:33:16 -0700

Actually keep track of the pathnames for all elements

Actually keep track of the pathnames for all elements for on-disk
filesystems.  This makes sure we can always reconstruct the correct
path.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>

---
 core/fs/chdir.c            |  144 +++++++++++++++++++------------------------
 core/fs/fs.c               |   13 ++++
 core/fs/lib/searchconfig.c |    3 +-
 core/include/fs.h          |    1 +
 4 files changed, 80 insertions(+), 81 deletions(-)

diff --git a/core/fs/chdir.c b/core/fs/chdir.c
index c40e91b..903cabc 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 ad2fb37..21f5dba 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 24bfde3..f18836a 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, &regs, &regs);
diff --git a/core/include/fs.h b/core/include/fs.h
index ecd148d..e1f5733 100644
--- a/core/include/fs.h
+++ b/core/include/fs.h
@@ -95,6 +95,7 @@ struct extent {
 struct inode {
     struct fs_info *fs;	 /* The filesystem this inode is associated with */
     struct inode *parent;	/* Parent directory, if any */
+    const char *name;		/* Name, valid for generic path search only */
     int		 refcnt;
     int          mode;   /* FILE , DIR or SYMLINK */
     uint32_t     size;


More information about the Syslinux-commits mailing list