/*
* Convert a component of a pathname into a pointer to a locked inode.
* This is a very central and rather complicated routine.
/*
* Convert a component of a pathname into a pointer to a locked inode.
* This is a very central and rather complicated routine.
* exists, lookup returns both the target and its parent directory locked.
* When creating or renaming and LOCKPARENT is specified, the target may
* not be ".". When deleting and LOCKPARENT is specified, the target may
* exists, lookup returns both the target and its parent directory locked.
* When creating or renaming and LOCKPARENT is specified, the target may
* not be ".". When deleting and LOCKPARENT is specified, the target may
- * be "."., but the caller must check to ensure it does an vrele and iput
- * instead of two iputs.
+ * be "."., but the caller must check to ensure it does an vrele and vput
+ * instead of two vputs.
-ufs_lookup(dvp, vpp, cnp)
- struct vnode *dvp;
- struct vnode **vpp;
- struct componentname *cnp;
+ufs_lookup(ap)
+ struct vop_lookup_args /* {
+ struct vnode *a_dvp;
+ struct vnode **a_vpp;
+ struct componentname *a_cnp;
+ } */ *ap;
struct buf *bp; /* a buffer of directory entries */
register struct direct *ep; /* the current directory entry */
int entryoffsetinblock; /* offset of ep in bp's buffer */
struct buf *bp; /* a buffer of directory entries */
register struct direct *ep; /* the current directory entry */
int entryoffsetinblock; /* offset of ep in bp's buffer */
int numdirpasses; /* strategy for directory search */
doff_t endsearch; /* offset to end directory search */
doff_t prevoff; /* prev entry dp->i_offset */
int numdirpasses; /* strategy for directory search */
doff_t endsearch; /* offset to end directory search */
doff_t prevoff; /* prev entry dp->i_offset */
- struct inode *pdp; /* saved dp during symlink work */
- struct vnode *tdp; /* returned by VOP_VGET */
+ struct vnode *pdp; /* saved dp during symlink work */
+ struct vnode *tdp; /* returned by VFS_VGET */
doff_t enduseful; /* pointer past last used dir slot */
u_long bmask; /* block offset mask */
int lockparent; /* 1 => lockparent flag is set */
int wantparent; /* 1 => wantparent or lockparent flag */
doff_t enduseful; /* pointer past last used dir slot */
u_long bmask; /* block offset mask */
int lockparent; /* 1 => lockparent flag is set */
int wantparent; /* 1 => wantparent or lockparent flag */
- int error;
- struct vnode *vdp = dvp; /* saved for one special case */
+ int namlen, error;
+ 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;
- if (error = ufs_access(dvp, VEXEC, cnp->cn_cred, cnp->cn_proc))
+ if (error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc))
/*
* Get the next vnode in the path.
* See comment below starting `Step through' for
* an explaination of the locking protocol.
*/
/*
* Get the next vnode in the path.
* See comment below starting `Step through' for
* an explaination of the locking protocol.
*/
- /*
- * The borrowing of variables
- * here is somewhat confusing. Usually, dvp/dp
- * is the directory being searched.
- * Here it's the target returned from the cache.
- */
- pdp = dp;
- bmask = VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
- if (cnp->cn_nameiop != LOOKUP || dp->i_diroff == 0 ||
+ bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
+ if (nameiop != LOOKUP || dp->i_diroff == 0 ||
- (error = VOP_BLKATOFF(dvp, (off_t)dp->i_offset, NULL, &bp)))
+ (error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)))
- VOP_BLKATOFF(dvp, (off_t)dp->i_offset, NULL, &bp))
+ VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp))
/*
* Save directory entry's inode number and
* reclen in ndp->ni_ufs area, and release
/*
* Save directory entry's inode number and
* reclen in ndp->ni_ufs area, and release
* directory has not been removed, then can consider
* allowing file to be created.
*/
* directory has not been removed, then can consider
* allowing file to be created.
*/
- if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
- (cnp->cn_flags & ISLASTCN) && dp->i_nlink != 0) {
+ if ((nameiop == CREATE || nameiop == RENAME) &&
+ (flags & ISLASTCN) && dp->i_nlink != 0) {
- if (error = ufs_access(dvp, VWRITE, cnp->cn_cred, cnp->cn_proc))
+ if (error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc))
- if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE)
- cache_enter(dvp, *vpp, cnp);
+ if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
+ cache_enter(vdp, *vpp, cnp);
* If the final component of path name, save information
* in the cache as to where the entry was found.
*/
* If the final component of path name, save information
* in the cache as to where the entry was found.
*/
* the directory (in ndp->ni_dvp), otherwise we go
* on and lock the inode, being careful with ".".
*/
* the directory (in ndp->ni_dvp), otherwise we go
* on and lock the inode, being careful with ".".
*/
- if (error = ufs_access(dvp, VWRITE, cnp->cn_cred, cnp->cn_proc))
+ if (error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc))
- cnp->cn_cred->cr_uid != 0 &&
- cnp->cn_cred->cr_uid != dp->i_uid &&
- VTOI(tdp)->i_uid != cnp->cn_cred->cr_uid) {
+ cred->cr_uid != 0 &&
+ cred->cr_uid != dp->i_uid &&
+ VTOI(tdp)->i_uid != cred->cr_uid) {
* Must get inode of directory entry to verify it's a
* regular file, or empty directory.
*/
* Must get inode of directory entry to verify it's a
* regular file, or empty directory.
*/
- if (cnp->cn_nameiop == RENAME && wantparent &&
- (cnp->cn_flags & ISLASTCN)) {
- if (error = ufs_access(dvp, VWRITE, cnp->cn_cred, cnp->cn_proc))
+ if (nameiop == RENAME && wantparent &&
+ (flags & ISLASTCN)) {
+ if (error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc))
* directory because we may need it again if a symbolic link
* is relative to the current directory. Instead we save it
* unlocked as "pdp". We must get the target inode before unlocking
* directory because we may need it again if a symbolic link
* is relative to the current directory. Instead we save it
* unlocked as "pdp". We must get the target inode before unlocking
* work if the file system has any hard links other than ".."
* that point backwards in the directory structure.
*/
* work if the file system has any hard links other than ".."
* that point backwards in the directory structure.
*/
- pdp = dp;
- if (cnp->cn_flags & ISDOTDOT) {
- IUNLOCK(pdp); /* race to get the inode */
- if (error = VOP_VGET(dvp, dp->i_ino, &tdp)) {
- ILOCK(pdp);
+ pdp = vdp;
+ if (flags & ISDOTDOT) {
+ VOP_UNLOCK(pdp); /* race to get the inode */
+ if (error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) {
+ VOP_LOCK(pdp);
+ return (error);
+ }
+ if (lockparent && (flags & ISLASTCN) &&
+ (error = VOP_LOCK(pdp))) {
+ vput(tdp);
if ((ep->d_reclen & 0x3) != 0 ||
ep->d_reclen > DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) ||
if ((ep->d_reclen & 0x3) != 0 ||
ep->d_reclen > DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) ||
newdir.d_ino = ip->i_number;
newdir.d_namlen = cnp->cn_namelen;
bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1);
newdir.d_ino = ip->i_number;
newdir.d_namlen = cnp->cn_namelen;
bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1);
- newentrysize = DIRSIZ(&newdir);
+ if (dvp->v_mount->mnt_maxsymlinklen > 0)
+ newdir.d_type = IFTODT(ip->i_mode);
+ else {
+ newdir.d_type = 0;
+# if (BYTE_ORDER == LITTLE_ENDIAN)
+ { u_char tmp = newdir.d_namlen;
+ newdir.d_namlen = newdir.d_type;
+ newdir.d_type = tmp; }
+# endif
+ }
+ newentrysize = DIRSIZ(FSFMT(dvp), &newdir);
spacefree = ep->d_reclen - dsize;
for (loc = ep->d_reclen; loc < dp->i_count; ) {
nep = (struct direct *)(dirbuf + loc);
spacefree = ep->d_reclen - dsize;
for (loc = ep->d_reclen; loc < dp->i_count; ) {
nep = (struct direct *)(dirbuf + loc);
spacefree += nep->d_reclen - dsize;
loc += nep->d_reclen;
bcopy((caddr_t)nep, (caddr_t)ep, dsize);
spacefree += nep->d_reclen - dsize;
loc += nep->d_reclen;
bcopy((caddr_t)nep, (caddr_t)ep, dsize);
- error = VOP_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, NOCRED);
+ error = VOP_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC,
+ cnp->cn_cred, cnp->cn_proc);
- if (error =
- VOP_BLKATOFF(ITOV(dp), (off_t)dp->i_offset, (char **)&ep, &bp))
+ if (error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, (char **)&ep, &bp))
#define MINDIRSIZ (sizeof (struct dirtemplate) / 2)
for (off = 0; off < ip->i_size; off += dp->d_reclen) {
#define MINDIRSIZ (sizeof (struct dirtemplate) / 2)
for (off = 0; off < ip->i_size; off += dp->d_reclen) {
/*
* Check if source directory is in the path of the target directory.
* Target is supplied locked, source is unlocked.
/*
* Check if source directory is in the path of the target directory.
* Target is supplied locked, source is unlocked.
*/
int
ufs_checkpath(source, target, cred)
struct inode *source, *target;
struct ucred *cred;
{
*/
int
ufs_checkpath(source, target, cred)
struct inode *source, *target;
struct ucred *cred;
{
error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf,
sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE,
IO_NODELOCKED, cred, (int *)0, (struct proc *)0);
if (error != 0)
break;
error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf,
sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE,
IO_NODELOCKED, cred, (int *)0, (struct proc *)0);
if (error != 0)
break;
- if (dirbuf.dotdot_namlen != 2 ||
+# if (BYTE_ORDER == LITTLE_ENDIAN)
+ if (vp->v_mount->mnt_maxsymlinklen > 0)
+ namlen = dirbuf.dotdot_namlen;
+ else
+ namlen = dirbuf.dotdot_type;
+# else
+ namlen = dirbuf.dotdot_namlen;
+# endif
+ if (namlen != 2 ||