If you take this approach, you need to update relpath on renames. Do you? (I may have missed that.)
Neal At Fri, 19 Jul 2013 17:25:05 +0200, Justus Winter wrote: > > --- > libdiskfs/dir-lookup.c | 24 ++++++++++++++++++++++++ > libdiskfs/diskfs.h | 3 +++ > libdiskfs/fsys-getroot.c | 3 ++- > libdiskfs/peropen-make.c | 8 ++++++++ > libdiskfs/peropen-rele.c | 1 + > 5 files changed, 38 insertions(+), 1 deletion(-) > > diff --git a/libdiskfs/dir-lookup.c b/libdiskfs/dir-lookup.c > index 923be03..08047cf 100644 > --- a/libdiskfs/dir-lookup.c > +++ b/libdiskfs/dir-lookup.c > @@ -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 0f9c1d3..2489517 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 2e11da4..39973a8 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 d37516c..d0ac698 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 08276ec..d3f7492 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); > } > -- > 1.7.10.4 > > >