Author: marcus (doc,ports committer)
Date: Fri Dec 12 01:00:38 2008
New Revision: 185959
URL: http://svn.freebsd.org/changeset/base/185959

Log:
  Implement VOP_VPTOCNP for devfs.  Directory and character device vnodes are
  properly translated to their component names.
  
  Reviewed by:  arch
  Approved by:  kib

Modified:
  head/sys/fs/devfs/devfs_vnops.c

Modified: head/sys/fs/devfs/devfs_vnops.c
==============================================================================
--- head/sys/fs/devfs/devfs_vnops.c     Fri Dec 12 00:59:36 2008        
(r185958)
+++ head/sys/fs/devfs/devfs_vnops.c     Fri Dec 12 01:00:38 2008        
(r185959)
@@ -185,6 +185,69 @@ devfs_clear_cdevpriv(void)
        devfs_fpdrop(fp);
 }
 
+static int
+devfs_vptocnp(struct vop_vptocnp_args *ap)
+{
+       struct vnode *vp = ap->a_vp;
+       struct vnode **dvp = ap->a_vpp;
+       struct devfs_mount *dmp;
+       char *buf = ap->a_buf;
+       int *buflen = ap->a_buflen;
+       struct devfs_dirent *dd, *de;
+       int i, error;
+
+       dmp = VFSTODEVFS(vp->v_mount);
+       i = *buflen;
+       dd = vp->v_data;
+       error = 0;
+
+       sx_xlock(&dmp->dm_lock);
+
+       if (vp->v_type == VCHR) {
+               i -= strlen(dd->de_cdp->cdp_c.si_name);
+               if (i < 0) {
+                       error = ENOMEM;
+                       goto finished;
+               }
+               bcopy(dd->de_cdp->cdp_c.si_name, buf + i,
+                   strlen(dd->de_cdp->cdp_c.si_name));
+               de = dd->de_dir;
+       } else if (vp->v_type == VDIR) {
+               if (dd == dmp->dm_rootdir) {
+                       *dvp = vp;
+                       vhold(*dvp);
+                       goto finished;
+               }
+               i -= dd->de_dirent->d_namlen;
+               if (i < 0) {
+                       error = ENOMEM;
+                       goto finished;
+               }
+               bcopy(dd->de_dirent->d_name, buf + i,
+                   dd->de_dirent->d_namlen);
+               de = dd;
+       } else {
+               error = ENOENT;
+               goto finished;
+       }
+       *buflen = i;
+       de = TAILQ_FIRST(&de->de_dlist);        /* "." */
+       de = TAILQ_NEXT(de, de_list);           /* ".." */
+       de = de->de_dir;
+       mtx_lock(&devfs_de_interlock);
+       *dvp = de->de_vnode;
+       if (*dvp != NULL) {
+               VI_LOCK(*dvp);
+               mtx_unlock(&devfs_de_interlock);
+               vholdl(*dvp);
+               VI_UNLOCK(*dvp);
+       } else
+               error = ENOENT;
+finished:
+       sx_xunlock(&dmp->dm_lock);
+       return (error);
+}
+
 /*
  * Construct the fully qualified path name relative to the mountpoint
  */
@@ -1465,6 +1528,7 @@ static struct vop_vector devfs_vnodeops 
        .vop_setlabel =         devfs_setlabel,
 #endif
        .vop_symlink =          devfs_symlink,
+       .vop_vptocnp =          devfs_vptocnp,
 };
 
 static struct vop_vector devfs_specops = {
@@ -1499,6 +1563,7 @@ static struct vop_vector devfs_specops =
 #endif
        .vop_strategy =         VOP_PANIC,
        .vop_symlink =          VOP_PANIC,
+       .vop_vptocnp =          devfs_vptocnp,
        .vop_write =            VOP_PANIC,
 };
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to