- save_dbg_namelen = dbg_namelen;
-
- i = 0;
-
- while (dbg_namelen > 0) {
- if (dbg_namelen >= 4) {
- dbg_parms[i++] = *(long *)dbg_nameptr;
- dbg_nameptr += sizeof(long);
- dbg_namelen -= sizeof(long);
- } else {
- for (n = 0; n < dbg_namelen; n++)
- dbg_buf[n] = *dbg_nameptr++;
- while (n <= 3) {
- if (*dbg_nameptr)
- dbg_buf[n++] = '>';
- else
- dbg_buf[n++] = 0;
- }
- dbg_parms[i++] = *(long *)&dbg_buf[0];
-
- break;
- }
- }
- while (i < NUMPARMS) {
- if (*dbg_nameptr)
- dbg_parms[i++] = *(long *)dbg_filler;
- else
- dbg_parms[i++] = 0;
- }
-
- KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW,36)) | DBG_FUNC_NONE,
- dp, dbg_parms[0], dbg_parms[1], dbg_parms[2], 0);
-
- for (dbg_namelen = save_dbg_namelen-12, i=3;
- dbg_namelen > 0;
- dbg_namelen -=(4 * sizeof(long)))
- {
- KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW,36)) | DBG_FUNC_NONE,
- dbg_parms[i++], dbg_parms[i++], dbg_parms[i++], dbg_parms[i++], 0);
- }
+
+ /* Copy the (possibly truncated) path itself */
+ memcpy(dbg_parms, dbg_nameptr, dbg_namelen);
+
+ /* Pad with '\0' or '>' */
+ if (dbg_namelen < (int)sizeof(dbg_parms)) {
+ memset((char *)dbg_parms + dbg_namelen,
+ *(cnp->cn_nameptr + cnp->cn_namelen) ? '>' : 0,
+ sizeof(dbg_parms) - dbg_namelen);
+ }
+
+ /*
+ * In the event that we collect multiple, consecutive pathname
+ * entries, we must mark the start of the path's string and the end.
+ */
+ code = (FSDBG_CODE(DBG_FSRW,36)) | DBG_FUNC_START;
+
+ if (dbg_namelen <= 12)
+ code |= DBG_FUNC_END;
+
+ KERNEL_DEBUG_CONSTANT(code, dp, dbg_parms[0], dbg_parms[1], dbg_parms[2], 0);
+
+ code &= ~DBG_FUNC_START;
+
+ for (i=3, dbg_namelen -= 12; dbg_namelen > 0; i+=4, dbg_namelen -= 16) {
+ if (dbg_namelen <= 16)
+ code |= DBG_FUNC_END;
+
+ KERNEL_DEBUG_CONSTANT(code, dbg_parms[i], dbg_parms[i+1], dbg_parms[i+2], dbg_parms[i+3], 0);
+ }
+}
+#else /* NO_KDEBUG */
+static void
+kdebug_lookup(struct vnode *dp __unused, struct componentname *cnp __unused)
+{
+}
+#endif /* NO_KDEBUG */
+
+int
+vfs_getbyid(fsid_t *fsid, ino64_t ino, vnode_t *vpp, vfs_context_t ctx)
+{
+ mount_t mp;
+ int error;
+
+ mp = mount_lookupby_volfsid(fsid->val[0], 1);
+ if (mp == NULL) {
+ return EINVAL;
+ }
+
+ /* Get the target vnode. */
+ if (ino == 2) {
+ error = VFS_ROOT(mp, vpp, ctx);
+ } else {
+ error = VFS_VGET(mp, ino, vpp, ctx);
+ }
+
+ vfs_unbusy(mp);
+ return error;
+}
+/*
+ * Obtain the real path from a legacy volfs style path.
+ *
+ * Valid formats of input path:
+ *
+ * "555/@"
+ * "555/2"
+ * "555/123456"
+ * "555/123456/foobar"
+ *
+ * Where:
+ * 555 represents the volfs file system id
+ * '@' and '2' are aliases to the root of a file system
+ * 123456 represents a file id
+ * "foobar" represents a file name
+ */
+#if CONFIG_VOLFS
+static int
+vfs_getrealpath(const char * path, char * realpath, size_t bufsize, vfs_context_t ctx)
+{
+ vnode_t vp;
+ struct mount *mp = NULL;
+ char *str;
+ char ch;
+ uint32_t id;
+ ino64_t ino;
+ int error;
+ int length;
+
+ /* Get file system id and move str to next component. */
+ id = strtoul(path, &str, 10);
+ if (id == 0 || str[0] != '/') {
+ return (EINVAL);
+ }
+ while (*str == '/') {
+ str++;
+ }
+ ch = *str;
+
+ mp = mount_lookupby_volfsid(id, 1);
+ if (mp == NULL) {
+ return (EINVAL); /* unexpected failure */
+ }
+ /* Check for an alias to a file system root. */
+ if (ch == '@' && str[1] == '\0') {
+ ino = 2;
+ str++;
+ } else {
+ /* Get file id and move str to next component. */
+ ino = strtouq(str, &str, 10);
+ }
+
+ /* Get the target vnode. */
+ if (ino == 2) {
+ error = VFS_ROOT(mp, &vp, ctx);
+ } else {
+ error = VFS_VGET(mp, ino, &vp, ctx);
+ }
+ vfs_unbusy(mp);
+ if (error) {
+ goto out;
+ }
+ realpath[0] = '\0';
+
+ /* Get the absolute path to this vnode. */
+ error = build_path(vp, realpath, bufsize, &length, 0, ctx);
+ vnode_put(vp);
+
+ if (error == 0 && *str != '\0') {
+ int attempt = strlcat(realpath, str, MAXPATHLEN);
+ if (attempt > MAXPATHLEN){
+ error = ENAMETOOLONG;
+ }
+ }
+out:
+ return (error);
+}
+#endif
+
+void
+lookup_compound_vnop_post_hook(int error, vnode_t dvp, vnode_t vp, struct nameidata *ndp, int did_create)
+{
+ if (error == 0 && vp == NULLVP) {
+ panic("NULL vp with error == 0.\n");
+ }
+
+ /*
+ * We don't want to do any of this if we didn't use the compound vnop
+ * to perform the lookup... i.e. if we're allowing and using the legacy pattern,
+ * where we did a full lookup.
+ */
+ if ((ndp->ni_flag & NAMEI_COMPOUND_OP_MASK) == 0) {
+ return;
+ }
+
+ /*
+ * If we're going to continue the lookup, we'll handle
+ * all lookup-related updates at that time.
+ */
+ if (error == EKEEPLOOKING) {
+ return;
+ }
+
+ /*
+ * Only audit or update cache for *found* vnodes. For creation
+ * neither would happen in the non-compound-vnop case.
+ */
+ if ((vp != NULLVP) && !did_create) {
+ /*
+ * If MAKEENTRY isn't set, and we've done a successful compound VNOP,
+ * then we certainly don't want to update cache or identity.
+ */
+ if ((error != 0) || (ndp->ni_cnd.cn_flags & MAKEENTRY)) {
+ lookup_consider_update_cache(dvp, vp, &ndp->ni_cnd, ndp->ni_ncgeneration);
+ }
+ if (ndp->ni_cnd.cn_flags & AUDITVNPATH1)
+ AUDIT_ARG(vnpath, vp, ARG_VNODE1);
+ else if (ndp->ni_cnd.cn_flags & AUDITVNPATH2)
+ AUDIT_ARG(vnpath, vp, ARG_VNODE2);
+ }
+
+ /*
+ * If you created (whether you opened or not), cut a lookup tracepoint
+ * for the parent dir (as would happen without a compound vnop). Note: we may need
+ * a vnode despite failure in this case!
+ *
+ * If you did not create:
+ * Found child (succeeded or not): cut a tracepoint for the child.
+ * Did not find child: cut a tracepoint with the parent.
+ */
+ if (kdebug_enable) {
+ kdebug_lookup(vp ? vp : dvp, &ndp->ni_cnd);
+ }