/*
- * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* from: @(#)ufs_lookup.c 7.33 (Berkeley) 5/19/91
*
* @(#)cd9660_lookup.c 8.5 (Berkeley) 12/5/94
-
-
-
- * HISTORY
- * 22-Jan-98 radar 1669467 - ISO 9660 CD support - jwc
-
+ *
*/
#include <sys/param.h>
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/utfconv.h>
-#include <sys/paths.h>
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
struct buf *bp; /* a buffer of directory entries */
struct iso_directory_record *ep = NULL;/* the current directory entry */
int entryoffsetinblock; /* offset of ep in bp's buffer */
- int saveoffset = 0; /* offset of last directory entry in dir */
+ int saveoffset = 0; /* offset of last directory entry in dir */
int numdirpasses; /* strategy for directory search */
doff_t endsearch; /* offset to end directory search */
struct vnode *pdp; /* saved dp during symlink work */
u_long bmask; /* block offset mask */
int lockparent; /* 1 => lockparent flag is set */
int wantparent; /* 1 => wantparent or lockparent flag */
- int wantrsrc; /* 1 => looking for resource fork */
+ int wantassoc;
int error;
ino_t ino = 0;
int reclen;
u_short namelen;
+ int isoflags;
char altname[ISO_RRIP_NAMEMAX];
int res;
int len;
char *name;
struct vnode **vpp = ap->a_vpp;
struct componentname *cnp = ap->a_cnp;
- struct ucred *cred = cnp->cn_cred;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
struct proc *p = cnp->cn_proc;
int devBlockSize=0;
- long rsrcsize;
size_t altlen;
bp = NULL;
imp = dp->i_mnt;
lockparent = flags & LOCKPARENT;
wantparent = flags & (LOCKPARENT|WANTPARENT);
- wantrsrc = 0;
+ wantassoc = 0;
+
/*
* Check accessiblity of directory.
*/
if (vdp->v_type != VDIR)
return (ENOTDIR);
- if ( (error = VOP_ACCESS(vdp, VEXEC, cred, p)) )
+ if ( (error = VOP_ACCESS(vdp, VEXEC, cnp->cn_cred, p)) )
return (error);
- /*
- * Determine if we're looking for a resource fork
- * note: this could cause a read off the end of the
- * component name buffer in some rare cases.
- */
- if ((flags & ISLASTCN) == 0 &&
- bcmp(&cnp->cn_nameptr[cnp->cn_namelen],
- _PATH_RSRCFORKSPEC, sizeof(_PATH_RSRCFORKSPEC) - 1) == 0) {
- flags |= ISLASTCN;
- cnp->cn_consume = sizeof(_PATH_RSRCFORKSPEC) - 1;
- wantrsrc = 1;
- }
/*
* We now have a segment name to search for, and a directory to search.
*
* Before tediously performing a linear scan of the directory,
* check the name cache to see if the directory/name pair
* we are looking for is known already.
- * Note: resource forks are never in the name cache
*/
- if ((error = cache_lookup(vdp, vpp, cnp)) && !wantrsrc) {
+ if ((error = cache_lookup(vdp, vpp, cnp))) {
int vpid; /* capability number of vnode */
if (error == ENOENT)
return (error);
-#ifdef PARANOID
- if ((vdp->v_flag & VROOT) && (flags & ISDOTDOT))
- panic("cd9660_lookup: .. through root");
-#endif
/*
* Get the next vnode in the path.
* See comment below starting `Step through' for
len = cnp->cn_namelen;
name = cnp->cn_nameptr;
altname[0] = '\0';
- rsrcsize = 0;
-
+ /*
+ * A "._" prefix means, we are looking for an associated file
+ */
+ if (imp->iso_ftype != ISO_FTYPE_RRIP &&
+ *name == ASSOCCHAR1 && *(name+1) == ASSOCCHAR2) {
+ wantassoc = 1;
+ len -= 2;
+ name += 2;
+ }
/*
* Decode search name into UCS-2 (Unicode)
*/
* profiling time and hence has been removed in the interest
* of simplicity.
*/
- bmask = imp->im_bmask;
+ bmask = imp->im_sector_size - 1;
if (nameiop != LOOKUP || dp->i_diroff == 0 ||
dp->i_diroff > dp->i_size) {
entryoffsetinblock = 0;
dp->i_offset = dp->i_diroff;
if ((entryoffsetinblock = dp->i_offset & bmask) &&
- (error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)))
+ (error = VOP_BLKATOFF(vdp, SECTOFF(imp, dp->i_offset), NULL, &bp)))
return (error);
numdirpasses = 2;
iso_nchstats.ncs_2passes++;
if ((dp->i_offset & bmask) == 0) {
if (bp != NULL)
brelse(bp);
- if ( (error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)) )
+ if ( (error = VOP_BLKATOFF(vdp, SECTOFF(imp,dp->i_offset), NULL, &bp)) )
return (error);
entryoffsetinblock = 0;
}
if (reclen == 0) {
/* skip to next block, if any */
dp->i_offset =
- (dp->i_offset & ~bmask) + imp->logical_block_size;
+ (dp->i_offset & ~bmask) + imp->im_sector_size;
continue;
}
- if (reclen < ISO_DIRECTORY_RECORD_SIZE)
+ if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
/* illegal entry, stop */
break;
-
- if (entryoffsetinblock + reclen > imp->logical_block_size)
- /* entries are not allowed to cross boundaries */
+ }
+ if (entryoffsetinblock + reclen > imp->im_sector_size) {
+ /* entries are not allowed to cross sector boundaries */
break;
-
+ }
namelen = isonum_711(ep->name_len);
+ isoflags = isonum_711(ep->flags);
if (reclen < ISO_DIRECTORY_RECORD_SIZE + namelen)
/* illegal entry, stop */
break;
-
- /* remember the size of resource forks (associated files) */
- if ((isonum_711(ep->flags) & (directoryBit | associatedBit)) == associatedBit) {
- if (namelen < sizeof(altname) && ino == 0) {
- rsrcsize = isonum_733(ep->size);
- bcopy(ep->name, altname, namelen);
- altname[namelen] = '\0';
- altlen = namelen;
- }
- }
/*
* Check for a name match.
*/
if (imp->iso_ftype == ISO_FTYPE_RRIP) {
- if ( isonum_711(ep->flags) & directoryBit )
+ if (isoflags & directoryBit)
ino = isodirino(ep, imp);
else
ino = (bp->b_blkno << imp->im_bshift) + entryoffsetinblock;
goto found;
ino = 0;
} else {
- if ((!(isonum_711(ep->flags) & associatedBit)) == !wantrsrc) {
+ if ((!(isoflags & associatedBit)) == !wantassoc) {
if ((len == 1
&& *name == '.')
|| (flags & ISDOTDOT)) {
goto notfound;
} else if (imp->iso_ftype != ISO_FTYPE_JOLIET && !(res = isofncmp(name,len,
ep->name,namelen))) {
- if ( isonum_711(ep->flags) & directoryBit )
+ if ( isoflags & directoryBit )
ino = isodirino(ep, imp);
else
ino = (bp->b_blkno << imp->im_bshift) + entryoffsetinblock;
saveoffset = dp->i_offset;
} else if (imp->iso_ftype == ISO_FTYPE_JOLIET && !(res = ucsfncmp((u_int16_t*)name, len,
(u_int16_t*) ep->name, namelen))) {
- if ( isonum_711(ep->flags) & directoryBit )
+ if ( isoflags & directoryBit )
ino = isodirino(ep, imp);
else
ino = (bp->b_blkno << imp->im_bshift) + entryoffsetinblock;
lblkno(imp, saveoffset)) {
if (bp != NULL)
brelse(bp);
- if ( (error = VOP_BLKATOFF(vdp, (off_t)saveoffset, NULL, &bp)) )
+ if ( (error = VOP_BLKATOFF(vdp, SECTOFF(imp, saveoffset), NULL, &bp)) )
return (error);
}
entryoffsetinblock = saveoffset & bmask;
/*
* Insert name into cache (as non-existent) if appropriate.
*/
- if ((cnp->cn_flags & MAKEENTRY) && !wantrsrc)
+ if (cnp->cn_flags & MAKEENTRY)
cache_enter(vdp, *vpp, cnp);
if (nameiop == CREATE || nameiop == RENAME) {
/*
*/
return (EROFS);
}
-
- if (wantrsrc)
- return (ENOTDIR);
- else
- return (ENOENT);
+ return (ENOENT);
found:
if (numdirpasses == 2)
dp->i_ino != ino, ep, p);
/* save parent inode number */
VTOI(tdp)->i_parent = VTOI(pdp)->i_number;
- if (!wantrsrc && (tdp->v_type == VREG) && (rsrcsize > 0)) {
- if (bcmp(ep->name, altname, altlen) == 0)
- VTOI(tdp)->i_rsrcsize = rsrcsize;
- }
brelse(bp);
if (error)
return (error);
/*
* Insert name into cache if appropriate.
*/
- if ((cnp->cn_flags & MAKEENTRY) && !wantrsrc)
+ if (cnp->cn_flags & MAKEENTRY)
cache_enter(vdp, *vpp, cnp);
return (0);
imp = ip->i_mnt;
lbn = lblkno(imp, ap->a_offset);
bsize = blksize(imp, ip, lbn);
-
+ if ((bsize != imp->im_sector_size) &&
+ (ap->a_offset & (imp->im_sector_size - 1)) == 0) {
+ bsize = imp->im_sector_size;
+ }
+
if ( (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) ) {
brelse(bp);
*ap->a_bpp = NULL;