diff options
-rw-r--r-- | libdiskfs/dir-lookup.c | 26 | ||||
-rw-r--r-- | libdiskfs/diskfs.h | 3 | ||||
-rw-r--r-- | libdiskfs/fsys-getroot.c | 3 | ||||
-rw-r--r-- | libdiskfs/peropen-make.c | 8 | ||||
-rw-r--r-- | libdiskfs/peropen-rele.c | 1 |
5 files changed, 39 insertions, 2 deletions
diff --git a/libdiskfs/dir-lookup.c b/libdiskfs/dir-lookup.c index 923be033..15a9b0cf 100644 --- a/libdiskfs/dir-lookup.c +++ b/libdiskfs/dir-lookup.c @@ -1,6 +1,6 @@ /* libdiskfs implementation of fs.defs:dir_lookup Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2008 Free Software Foundation, Inc. + 2002, 2008, 2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -41,6 +41,7 @@ diskfs_S_dir_lookup (struct protid *dircred, struct node *np; int nsymlink = 0; char *nextname; + char *relpath; int nextnamelen; error_t error = 0; char *pathbuf = 0; @@ -68,6 +69,11 @@ diskfs_S_dir_lookup (struct protid *dircred, while (path[0] == '/') path++; + /* Preserve the path relative to diruser->po->path. */ + relpath = strdup (path); + if (! relpath) + return ENOMEM; + *returned_port_poly = MACH_MSG_TYPE_MAKE_SEND; *retry = FS_RETRY_NORMAL; retryname[0] = '\0'; @@ -479,6 +485,22 @@ diskfs_S_dir_lookup (struct protid *dircred, if (! error) { + free (newpi->po->path); + if (dircred->po->path == NULL) + { + /* dircred is the root directory. */ + newpi->po->path = relpath; + relpath = NULL; /* Do not free relpath. */ + } + else + { + newpi->po->path = NULL; + asprintf (&newpi->po->path, "%s/%s", dircred->po->path, relpath); + } + + if (! newpi->po->path) + error = errno; + *returned_port = ports_get_right (newpi); ports_port_deref (newpi); newpi = 0; @@ -500,5 +522,7 @@ diskfs_S_dir_lookup (struct protid *dircred, if (newpo) diskfs_release_peropen (newpo); + free (relpath); + return error; } diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h index 0f9c1d39..24895172 100644 --- a/libdiskfs/diskfs.h +++ b/libdiskfs/diskfs.h @@ -69,6 +69,9 @@ struct peropen mach_port_t shadow_root_parent; /* If in a shadow tree, its root node in this translator. */ struct node *shadow_root; + + /* Path relative to the root of the translator. */ + char *path; }; /* A unique one of these exists for each node currently in use (and diff --git a/libdiskfs/fsys-getroot.c b/libdiskfs/fsys-getroot.c index 2e11da4c..39973a80 100644 --- a/libdiskfs/fsys-getroot.c +++ b/libdiskfs/fsys-getroot.c @@ -51,7 +51,8 @@ diskfs_S_fsys_getroot (fsys_t controlport, { root_parent: dotdot, shadow_root_parent: MACH_PORT_NULL, - shadow_root: _diskfs_chroot_directory ? diskfs_root_node : NULL /* XXX */ + shadow_root: _diskfs_chroot_directory ? diskfs_root_node : NULL, /* XXX */ + path: NULL, }; if (!pt) diff --git a/libdiskfs/peropen-make.c b/libdiskfs/peropen-make.c index d37516c1..b11b2ad6 100644 --- a/libdiskfs/peropen-make.c +++ b/libdiskfs/peropen-make.c @@ -34,6 +34,7 @@ diskfs_make_peropen (struct node *np, int flags, struct peropen *context, po->refcnt = 0; po->openstat = flags; po->np = np; + po->path = NULL; if (context) { @@ -50,6 +51,13 @@ diskfs_make_peropen (struct node *np, int flags, struct peropen *context, if (po->shadow_root_parent != MACH_PORT_NULL) mach_port_mod_refs (mach_task_self (), po->shadow_root_parent, MACH_PORT_RIGHT_SEND, 1); + + if (context->path) + { + po->path = strdup (context->path); + if (! po->path) + return ENOMEM; + } } else { diff --git a/libdiskfs/peropen-rele.c b/libdiskfs/peropen-rele.c index 08276ec3..d3f74921 100644 --- a/libdiskfs/peropen-rele.c +++ b/libdiskfs/peropen-rele.c @@ -45,5 +45,6 @@ diskfs_release_peropen (struct peropen *po) diskfs_nput (po->np); + free (po->path); free (po); } |