- /* We have a name that matched */
- pdp = vdp;
- vdp = *vpp;
- vpid = vdp->v_id;
- if (pdp == vdp) { /* lookup on "." */
- VREF(vdp);
- error = 0;
- } else if (flags & ISDOTDOT) {
- /*
- * Carefull on the locking policy,
- * remember we always lock from parent to child, so have
- * to release lock on child before trying to lock parent
- * then regain lock if needed
- */
- VOP_UNLOCK(pdp, 0, p);
- error = vget(vdp, LK_EXCLUSIVE, p);
- if (!error && lockparent && (flags & ISLASTCN))
- error = vn_lock(pdp, LK_EXCLUSIVE, p);
- } else {
- /*
- * Check to see if a specific fork is not being requested.
- *
- * If it is a file and not the last path item
- * then check if its a proper fork
- * If it is, check to see if the matched vnode is the same fork
- * else see if the proper fork exists.
- * If it does, return that one, else do VOP_CACHEDLOOKUP()
- * Notice that nothing is done if an undefined fork is named. Just leave and let lookup()
- * handle strange cases.
- *
- * XXX SER Notice that when the target is not what was in the name cache,
- * it is locked, before trying to get its sibling. Could this be a problem since both
- * siblings can be locked, but not in a determinalistic order????
- */
- u_int16_t forkType;
-
- error = vget(vdp, LK_EXCLUSIVE, p);
- if ((! error) && (vdp->v_type == VREG) && (vpid == vdp->v_id)) {
- if (!(flags & ISLASTCN)) {
- forkType = GetForkFromName(cnp);
- if (forkType != kUndefinedFork) {
- flags |= ISLASTCN;
- if (H_FORKTYPE(VTOH(vdp)) != forkType) {
- error = hfs_vget_sibling(vdp, forkType, vpp);
- vput(vdp);
- if (! error) {
- vdp = *vpp;
- vpid = vdp->v_id;
- }
- }
- }
- }
- else {
- /* Its the last item, so we want the data fork */
- if (H_FORKTYPE(VTOH(vdp)) != kDataFork) {
- error = hfs_vget_sibling(vdp, kDataFork, vpp);
- vput(vdp);
- if (! error) {
- vdp = *vpp;
- vpid = vdp->v_id;
- }
- }
- };
- };
- if (!lockparent || error || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp, 0, p);
- };