1*36bb23f1Svisa /* $OpenBSD: cd9660_lookup.c,v 1.26 2018/04/28 03:13:04 visa Exp $ */ 2053e05a2Sniklas /* $NetBSD: cd9660_lookup.c,v 1.18 1997/05/08 16:19:59 mycroft Exp $ */ 3df930be7Sderaadt 4df930be7Sderaadt /*- 5df930be7Sderaadt * Copyright (c) 1989, 1993, 1994 6df930be7Sderaadt * The Regents of the University of California. All rights reserved. 7df930be7Sderaadt * 8df930be7Sderaadt * This code is derived from software contributed to Berkeley 9df930be7Sderaadt * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 10df930be7Sderaadt * Support code is derived from software contributed to Berkeley 11df930be7Sderaadt * by Atsushi Murai (amurai@spec.co.jp). 12df930be7Sderaadt * 13df930be7Sderaadt * Redistribution and use in source and binary forms, with or without 14df930be7Sderaadt * modification, are permitted provided that the following conditions 15df930be7Sderaadt * are met: 16df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright 17df930be7Sderaadt * notice, this list of conditions and the following disclaimer. 18df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 19df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the 20df930be7Sderaadt * documentation and/or other materials provided with the distribution. 2129295d1cSmillert * 3. Neither the name of the University nor the names of its contributors 22df930be7Sderaadt * may be used to endorse or promote products derived from this software 23df930be7Sderaadt * without specific prior written permission. 24df930be7Sderaadt * 25df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35df930be7Sderaadt * SUCH DAMAGE. 36df930be7Sderaadt * 37df930be7Sderaadt * from: @(#)ufs_lookup.c 7.33 (Berkeley) 5/19/91 38df930be7Sderaadt * 39df930be7Sderaadt * @(#)cd9660_lookup.c 8.5 (Berkeley) 12/5/94 40df930be7Sderaadt */ 41df930be7Sderaadt 42df930be7Sderaadt #include <sys/param.h> 43df930be7Sderaadt #include <sys/namei.h> 44df930be7Sderaadt #include <sys/buf.h> 45df930be7Sderaadt #include <sys/vnode.h> 46fde894e5Stedu #include <sys/lock.h> 47df930be7Sderaadt #include <sys/mount.h> 489d71829cSniklas #include <sys/systm.h> 498f6e076eSmickey #include <sys/malloc.h> 50df930be7Sderaadt 51df930be7Sderaadt #include <isofs/cd9660/iso.h> 52053e05a2Sniklas #include <isofs/cd9660/cd9660_extern.h> 53df930be7Sderaadt #include <isofs/cd9660/cd9660_node.h> 54df930be7Sderaadt #include <isofs/cd9660/iso_rrip.h> 55df930be7Sderaadt 56df930be7Sderaadt struct nchstats iso_nchstats; 57df930be7Sderaadt 58df930be7Sderaadt /* 59df930be7Sderaadt * Convert a component of a pathname into a pointer to a locked inode. 60df930be7Sderaadt * This is a very central and rather complicated routine. 61df930be7Sderaadt * If the file system is not maintained in a strict tree hierarchy, 62df930be7Sderaadt * this can result in a deadlock situation (see comments in code below). 63df930be7Sderaadt * 64df930be7Sderaadt * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 65df930be7Sderaadt * whether the name is to be looked up, created, renamed, or deleted. 66df930be7Sderaadt * When CREATE, RENAME, or DELETE is specified, information usable in 67df930be7Sderaadt * creating, renaming, or deleting a directory entry may be calculated. 68df930be7Sderaadt * If flag has LOCKPARENT or'ed into it and the target of the pathname 69df930be7Sderaadt * exists, lookup returns both the target and its parent directory locked. 70df930be7Sderaadt * When creating or renaming and LOCKPARENT is specified, the target may 71df930be7Sderaadt * not be ".". When deleting and LOCKPARENT is specified, the target may 72df930be7Sderaadt * be "."., but the caller must check to ensure it does an vrele and iput 73df930be7Sderaadt * instead of two iputs. 74df930be7Sderaadt * 75053e05a2Sniklas * Overall outline of cd9660_lookup: 76df930be7Sderaadt * 77df930be7Sderaadt * check accessibility of directory 78df930be7Sderaadt * look for name in cache, if found, then if at end of path 79df930be7Sderaadt * and deleting or creating, drop it, else return name 80df930be7Sderaadt * search for name in directory, to found or notfound 81df930be7Sderaadt * notfound: 82df930be7Sderaadt * if creating, return locked directory, leaving info on available slots 83df930be7Sderaadt * else return error 84df930be7Sderaadt * found: 85df930be7Sderaadt * if at end of path and deleting, return information to allow delete 86df930be7Sderaadt * if at end of path and rewriting (RENAME and LOCKPARENT), lock target 87df930be7Sderaadt * inode and return info to allow rewrite 88df930be7Sderaadt * if not at end, add name to cache; if at end and neither creating 89df930be7Sderaadt * nor deleting, add name to cache 90df930be7Sderaadt * 91df930be7Sderaadt * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent inode unlocked. 92df930be7Sderaadt */ 93df930be7Sderaadt int 949d71829cSniklas cd9660_lookup(v) 959d71829cSniklas void *v; 969d71829cSniklas { 9799bc9d31Sderaadt struct vop_lookup_args *ap = v; 98df930be7Sderaadt register struct vnode *vdp; /* vnode for directory being searched */ 99df930be7Sderaadt register struct iso_node *dp; /* inode for directory being searched */ 100df930be7Sderaadt register struct iso_mnt *imp; /* file system that directory is in */ 101df930be7Sderaadt struct buf *bp; /* a buffer of directory entries */ 1029d71829cSniklas struct iso_directory_record *ep = NULL; 1039d71829cSniklas /* the current directory entry */ 104df930be7Sderaadt int entryoffsetinblock; /* offset of ep in bp's buffer */ 1059d71829cSniklas int saveoffset = -1; /* offset of last directory entry in dir */ 106df930be7Sderaadt int numdirpasses; /* strategy for directory search */ 107df930be7Sderaadt doff_t endsearch; /* offset to end directory search */ 108df930be7Sderaadt struct vnode *pdp; /* saved dp during symlink work */ 109df930be7Sderaadt struct vnode *tdp; /* returned by cd9660_vget_internal */ 110df930be7Sderaadt u_long bmask; /* block offset mask */ 111df930be7Sderaadt int lockparent; /* 1 => lockparent flag is set */ 112df930be7Sderaadt int error; 1130cad8b22Sguenther cdino_t ino = 0; 114df930be7Sderaadt int reclen; 115df930be7Sderaadt u_short namelen; 1168f6e076eSmickey char *altname; 117df930be7Sderaadt int res; 118df930be7Sderaadt int assoc, len; 119df930be7Sderaadt char *name; 120df930be7Sderaadt struct vnode **vpp = ap->a_vpp; 121df930be7Sderaadt struct componentname *cnp = ap->a_cnp; 122df930be7Sderaadt struct ucred *cred = cnp->cn_cred; 12309308f32Sart int flags; 124df930be7Sderaadt int nameiop = cnp->cn_nameiop; 12507feb63cScsapuntz struct proc *p = cnp->cn_proc; 126df930be7Sderaadt 12709308f32Sart cnp->cn_flags &= ~PDIRUNLOCK; 12809308f32Sart flags = cnp->cn_flags; 12909308f32Sart 130df930be7Sderaadt bp = NULL; 131df930be7Sderaadt *vpp = NULL; 132df930be7Sderaadt vdp = ap->a_dvp; 133df930be7Sderaadt dp = VTOI(vdp); 134df930be7Sderaadt imp = dp->i_mnt; 135df930be7Sderaadt lockparent = flags & LOCKPARENT; 136df930be7Sderaadt 137df930be7Sderaadt /* 138df930be7Sderaadt * Check accessiblity of directory. 139df930be7Sderaadt */ 1409d71829cSniklas if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)) != 0) 141df930be7Sderaadt return (error); 142df930be7Sderaadt 14307feb63cScsapuntz if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) && 14407feb63cScsapuntz (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 14507feb63cScsapuntz return (EROFS); 14607feb63cScsapuntz 147df930be7Sderaadt /* 148df930be7Sderaadt * We now have a segment name to search for, and a directory to search. 149df930be7Sderaadt * 150df930be7Sderaadt * Before tediously performing a linear scan of the directory, 151df930be7Sderaadt * check the name cache to see if the directory/name pair 152df930be7Sderaadt * we are looking for is known already. 153df930be7Sderaadt */ 15409308f32Sart if ((error = cache_lookup(vdp, vpp, cnp)) >= 0) 155df930be7Sderaadt return (error); 156df930be7Sderaadt 157df930be7Sderaadt len = cnp->cn_namelen; 158df930be7Sderaadt name = cnp->cn_nameptr; 159df930be7Sderaadt /* 160df930be7Sderaadt * A leading `=' means, we are looking for an associated file 161df930be7Sderaadt */ 1629d71829cSniklas assoc = (imp->iso_ftype != ISO_FTYPE_RRIP && *name == ASSOCCHAR); 1639d71829cSniklas if (assoc) { 164df930be7Sderaadt len--; 165df930be7Sderaadt name++; 166df930be7Sderaadt } 167df930be7Sderaadt 168df930be7Sderaadt /* 169df930be7Sderaadt * If there is cached information on a previous search of 170df930be7Sderaadt * this directory, pick up where we last left off. 171df930be7Sderaadt * We cache only lookups as these are the most common 172df930be7Sderaadt * and have the greatest payoff. Caching CREATE has little 173df930be7Sderaadt * benefit as it usually must search the entire directory 174df930be7Sderaadt * to determine that the entry does not exist. Caching the 175df930be7Sderaadt * location of the last DELETE or RENAME has not reduced 176df930be7Sderaadt * profiling time and hence has been removed in the interest 177df930be7Sderaadt * of simplicity. 178df930be7Sderaadt */ 179df930be7Sderaadt bmask = imp->im_bmask; 180df930be7Sderaadt if (nameiop != LOOKUP || dp->i_diroff == 0 || 181df930be7Sderaadt dp->i_diroff > dp->i_size) { 182df930be7Sderaadt entryoffsetinblock = 0; 183df930be7Sderaadt dp->i_offset = 0; 184df930be7Sderaadt numdirpasses = 1; 185df930be7Sderaadt } else { 186df930be7Sderaadt dp->i_offset = dp->i_diroff; 187df930be7Sderaadt if ((entryoffsetinblock = dp->i_offset & bmask) && 188574066a2Scsapuntz (error = cd9660_bufatoff(dp, (off_t)dp->i_offset, NULL, 189574066a2Scsapuntz &bp))) 190df930be7Sderaadt return (error); 191df930be7Sderaadt numdirpasses = 2; 192df930be7Sderaadt iso_nchstats.ncs_2passes++; 193df930be7Sderaadt } 194df930be7Sderaadt endsearch = dp->i_size; 195df930be7Sderaadt 196df930be7Sderaadt searchloop: 197df930be7Sderaadt while (dp->i_offset < endsearch) { 198df930be7Sderaadt /* 199df930be7Sderaadt * If offset is on a block boundary, 200df930be7Sderaadt * read the next directory block. 201df930be7Sderaadt * Release previous if it exists. 202df930be7Sderaadt */ 203df930be7Sderaadt if ((dp->i_offset & bmask) == 0) { 204df930be7Sderaadt if (bp != NULL) 205df930be7Sderaadt brelse(bp); 206574066a2Scsapuntz error = cd9660_bufatoff(dp, (off_t)dp->i_offset, 2079d71829cSniklas NULL, &bp); 2089d71829cSniklas if (error) 209df930be7Sderaadt return (error); 210df930be7Sderaadt entryoffsetinblock = 0; 211df930be7Sderaadt } 212df930be7Sderaadt /* 213df930be7Sderaadt * Get pointer to next entry. 214df930be7Sderaadt */ 215df930be7Sderaadt ep = (struct iso_directory_record *) 216df930be7Sderaadt ((char *)bp->b_data + entryoffsetinblock); 217df930be7Sderaadt 218df930be7Sderaadt reclen = isonum_711(ep->length); 219df930be7Sderaadt if (reclen == 0) { 220df930be7Sderaadt /* skip to next block, if any */ 221df930be7Sderaadt dp->i_offset = 222df930be7Sderaadt (dp->i_offset & ~bmask) + imp->logical_block_size; 223df930be7Sderaadt continue; 224df930be7Sderaadt } 225df930be7Sderaadt 226df930be7Sderaadt if (reclen < ISO_DIRECTORY_RECORD_SIZE) 227df930be7Sderaadt /* illegal entry, stop */ 228df930be7Sderaadt break; 229df930be7Sderaadt 230df930be7Sderaadt if (entryoffsetinblock + reclen > imp->logical_block_size) 231df930be7Sderaadt /* entries are not allowed to cross boundaries */ 232df930be7Sderaadt break; 233df930be7Sderaadt 234df930be7Sderaadt namelen = isonum_711(ep->name_len); 235df930be7Sderaadt 236df930be7Sderaadt if (reclen < ISO_DIRECTORY_RECORD_SIZE + namelen) 237df930be7Sderaadt /* illegal entry, stop */ 238df930be7Sderaadt break; 239df930be7Sderaadt 240df930be7Sderaadt /* 241df930be7Sderaadt * Check for a name match. 242df930be7Sderaadt */ 243df930be7Sderaadt switch (imp->iso_ftype) { 244df930be7Sderaadt default: 245df930be7Sderaadt if ((!(isonum_711(ep->flags)&4)) == !assoc) { 246df930be7Sderaadt if ((len == 1 247df930be7Sderaadt && *name == '.') 248df930be7Sderaadt || (flags & ISDOTDOT)) { 249df930be7Sderaadt if (namelen == 1 250df930be7Sderaadt && ep->name[0] == ((flags & ISDOTDOT) ? 1 : 0)) { 251df930be7Sderaadt /* 252df930be7Sderaadt * Save directory entry's inode number and 253df930be7Sderaadt * release directory buffer. 254df930be7Sderaadt */ 255df930be7Sderaadt dp->i_ino = isodirino(ep, imp); 256df930be7Sderaadt goto found; 257df930be7Sderaadt } 258df930be7Sderaadt if (namelen != 1 259df930be7Sderaadt || ep->name[0] != 0) 260df930be7Sderaadt goto notfound; 261df930be7Sderaadt } else if (!(res = isofncmp(name, len, 26249f343b7Sd ep->name, namelen, imp->joliet_level))) { 263df930be7Sderaadt if (isonum_711(ep->flags)&2) 264df930be7Sderaadt ino = isodirino(ep, imp); 265df930be7Sderaadt else 266df930be7Sderaadt ino = dbtob(bp->b_blkno) 267df930be7Sderaadt + entryoffsetinblock; 268df930be7Sderaadt saveoffset = dp->i_offset; 269df930be7Sderaadt } else if (ino) 270df930be7Sderaadt goto foundino; 271df930be7Sderaadt #ifdef NOSORTBUG /* On some CDs directory entries are not sorted correctly */ 272df930be7Sderaadt else if (res < 0) 273df930be7Sderaadt goto notfound; 274df930be7Sderaadt else if (res > 0 && numdirpasses == 2) 275df930be7Sderaadt numdirpasses++; 276df930be7Sderaadt #endif 277df930be7Sderaadt } 278df930be7Sderaadt break; 279df930be7Sderaadt case ISO_FTYPE_RRIP: 280df930be7Sderaadt if (isonum_711(ep->flags)&2) 281df930be7Sderaadt ino = isodirino(ep, imp); 282df930be7Sderaadt else 283df930be7Sderaadt ino = dbtob(bp->b_blkno) + entryoffsetinblock; 284df930be7Sderaadt dp->i_ino = ino; 285808d1e2bSchl altname = malloc(NAME_MAX, M_TEMP, M_WAITOK); 286df930be7Sderaadt cd9660_rrip_getname(ep,altname,&namelen,&dp->i_ino,imp); 287df930be7Sderaadt if (namelen == cnp->cn_namelen 2888f6e076eSmickey && !bcmp(name,altname,namelen)) { 2890e5ae731Stedu free(altname, M_TEMP, 0); 290df930be7Sderaadt goto found; 2918f6e076eSmickey } 2920e5ae731Stedu free(altname, M_TEMP, 0); 293df930be7Sderaadt ino = 0; 294df930be7Sderaadt break; 295df930be7Sderaadt } 296df930be7Sderaadt dp->i_offset += reclen; 297df930be7Sderaadt entryoffsetinblock += reclen; 298df930be7Sderaadt } 299df930be7Sderaadt if (ino) { 300df930be7Sderaadt foundino: 301df930be7Sderaadt dp->i_ino = ino; 302df930be7Sderaadt if (saveoffset != dp->i_offset) { 303df930be7Sderaadt if (lblkno(imp, dp->i_offset) != 304df930be7Sderaadt lblkno(imp, saveoffset)) { 305df930be7Sderaadt if (bp != NULL) 306df930be7Sderaadt brelse(bp); 307574066a2Scsapuntz if ((error = cd9660_bufatoff(dp, 3089d71829cSniklas (off_t)saveoffset, NULL, &bp)) != 0) 309df930be7Sderaadt return (error); 310df930be7Sderaadt } 311df930be7Sderaadt entryoffsetinblock = saveoffset & bmask; 312df930be7Sderaadt ep = (struct iso_directory_record *) 313df930be7Sderaadt ((char *)bp->b_data + entryoffsetinblock); 314df930be7Sderaadt dp->i_offset = saveoffset; 315df930be7Sderaadt } 316df930be7Sderaadt goto found; 317df930be7Sderaadt } 318df930be7Sderaadt notfound: 319df930be7Sderaadt /* 320df930be7Sderaadt * If we started in the middle of the directory and failed 321df930be7Sderaadt * to find our target, we must check the beginning as well. 322df930be7Sderaadt */ 323df930be7Sderaadt if (numdirpasses == 2) { 324df930be7Sderaadt numdirpasses--; 325df930be7Sderaadt dp->i_offset = 0; 326df930be7Sderaadt endsearch = dp->i_diroff; 327df930be7Sderaadt goto searchloop; 328df930be7Sderaadt } 329df930be7Sderaadt if (bp != NULL) 330df930be7Sderaadt brelse(bp); 331df930be7Sderaadt 332df930be7Sderaadt /* 333df930be7Sderaadt * Insert name into cache (as non-existent) if appropriate. 334df930be7Sderaadt */ 335df930be7Sderaadt if (cnp->cn_flags & MAKEENTRY) 336df930be7Sderaadt cache_enter(vdp, *vpp, cnp); 337df930be7Sderaadt if (nameiop == CREATE || nameiop == RENAME) 338df930be7Sderaadt return (EJUSTRETURN); 339df930be7Sderaadt return (ENOENT); 340df930be7Sderaadt 341df930be7Sderaadt found: 342df930be7Sderaadt if (numdirpasses == 2) 343df930be7Sderaadt iso_nchstats.ncs_pass2++; 344df930be7Sderaadt 345df930be7Sderaadt /* 346df930be7Sderaadt * Found component in pathname. 347df930be7Sderaadt * If the final component of path name, save information 348df930be7Sderaadt * in the cache as to where the entry was found. 349df930be7Sderaadt */ 350df930be7Sderaadt if ((flags & ISLASTCN) && nameiop == LOOKUP) 351df930be7Sderaadt dp->i_diroff = dp->i_offset; 352df930be7Sderaadt 353df930be7Sderaadt /* 354df930be7Sderaadt * Step through the translation in the name. We do not `iput' the 355df930be7Sderaadt * directory because we may need it again if a symbolic link 356df930be7Sderaadt * is relative to the current directory. Instead we save it 357df930be7Sderaadt * unlocked as "pdp". We must get the target inode before unlocking 358df930be7Sderaadt * the directory to insure that the inode will not be removed 359df930be7Sderaadt * before we get it. We prevent deadlock by always fetching 360df930be7Sderaadt * inodes from the root, moving down the directory tree. Thus 361df930be7Sderaadt * when following backward pointers ".." we must unlock the 362df930be7Sderaadt * parent directory before getting the requested directory. 363df930be7Sderaadt * There is a potential race condition here if both the current 364df930be7Sderaadt * and parent directories are removed before the `iget' for the 365df930be7Sderaadt * inode associated with ".." returns. We hope that this occurs 366df930be7Sderaadt * infrequently since we cannot avoid this race condition without 367df930be7Sderaadt * implementing a sophisticated deadlock detection algorithm. 368df930be7Sderaadt * Note also that this simple deadlock detection scheme will not 369df930be7Sderaadt * work if the file system has any hard links other than ".." 370df930be7Sderaadt * that point backwards in the directory structure. 371df930be7Sderaadt */ 372df930be7Sderaadt pdp = vdp; 373df930be7Sderaadt /* 374df930be7Sderaadt * If ino is different from dp->i_ino, 375df930be7Sderaadt * it's a relocated directory. 376df930be7Sderaadt */ 377df930be7Sderaadt if (flags & ISDOTDOT) { 37812e8170cScsapuntz brelse(bp); 379*36bb23f1Svisa VOP_UNLOCK(pdp); /* race to get the inode */ 38009308f32Sart cnp->cn_flags |= PDIRUNLOCK; 381df930be7Sderaadt error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp, 38212e8170cScsapuntz dp->i_ino != ino, NULL); 383df930be7Sderaadt if (error) { 38409308f32Sart if (vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p) == 0) 38509308f32Sart cnp->cn_flags &= ~PDIRUNLOCK; 386df930be7Sderaadt return (error); 387df930be7Sderaadt } 38809308f32Sart if (lockparent && (flags & ISLASTCN)) { 38909308f32Sart if ((error = vn_lock(pdp, LK_EXCLUSIVE, p))) { 390df930be7Sderaadt vput(tdp); 391df930be7Sderaadt return (error); 392df930be7Sderaadt } 39309308f32Sart cnp->cn_flags &= ~PDIRUNLOCK; 39409308f32Sart } 395df930be7Sderaadt *vpp = tdp; 396df930be7Sderaadt } else if (dp->i_number == dp->i_ino) { 397df930be7Sderaadt brelse(bp); 398627b2c48Sthib vref(vdp); /* we want ourself, ie "." */ 399df930be7Sderaadt *vpp = vdp; 400df930be7Sderaadt } else { 401df930be7Sderaadt error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp, 402df930be7Sderaadt dp->i_ino != ino, ep); 403df930be7Sderaadt brelse(bp); 404df930be7Sderaadt if (error) 405df930be7Sderaadt return (error); 40609308f32Sart if (!lockparent || !(flags & ISLASTCN)) { 407*36bb23f1Svisa VOP_UNLOCK(pdp); 40809308f32Sart cnp->cn_flags |= PDIRUNLOCK; 40909308f32Sart } 410df930be7Sderaadt *vpp = tdp; 411df930be7Sderaadt } 412df930be7Sderaadt 413df930be7Sderaadt /* 414df930be7Sderaadt * Insert name into cache if appropriate. 415df930be7Sderaadt */ 416df930be7Sderaadt if (cnp->cn_flags & MAKEENTRY) 417df930be7Sderaadt cache_enter(vdp, *vpp, cnp); 418df930be7Sderaadt return (0); 419df930be7Sderaadt } 420df930be7Sderaadt 421df930be7Sderaadt /* 422df930be7Sderaadt * Return buffer with the contents of block "offset" from the beginning of 423df930be7Sderaadt * directory "ip". If "res" is non-zero, fill it in with a pointer to the 424df930be7Sderaadt * remaining space in the directory. 425df930be7Sderaadt */ 426df930be7Sderaadt int 427574066a2Scsapuntz cd9660_bufatoff(struct iso_node *ip, off_t offset, char **res, 428574066a2Scsapuntz struct buf **bpp) 4299d71829cSniklas { 430574066a2Scsapuntz struct iso_mnt *imp; 431df930be7Sderaadt struct buf *bp; 4321abdbfdeSderaadt daddr_t lbn; 433df930be7Sderaadt int bsize, error; 434574066a2Scsapuntz struct vnode *vp = ITOV(ip); 435df930be7Sderaadt 436df930be7Sderaadt imp = ip->i_mnt; 437574066a2Scsapuntz lbn = lblkno(imp, offset); 438df930be7Sderaadt bsize = blksize(imp, ip, lbn); 439df930be7Sderaadt 44093f62a9eStedu if ((error = bread(vp, lbn, bsize, &bp)) != 0) { 441df930be7Sderaadt brelse(bp); 442574066a2Scsapuntz *bpp = NULL; 443df930be7Sderaadt return (error); 444df930be7Sderaadt } 445574066a2Scsapuntz if (res) 446574066a2Scsapuntz *res = (char *)bp->b_data + blkoff(imp, offset); 447574066a2Scsapuntz *bpp = bp; 448df930be7Sderaadt return (0); 449df930be7Sderaadt } 450