X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/a937f8567ba9375553a85507f18042a6faaffaab..064062582a0f51f718f0e7be32705c4fa964a47c:/usr/src/sys/ufs/ffs/ufs_lookup.c diff --git a/usr/src/sys/ufs/ffs/ufs_lookup.c b/usr/src/sys/ufs/ffs/ufs_lookup.c index 0b37fdd273..7bb8f77c50 100644 --- a/usr/src/sys/ufs/ffs/ufs_lookup.c +++ b/usr/src/sys/ufs/ffs/ufs_lookup.c @@ -2,31 +2,27 @@ * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * %sccs.include.redist.c% * - * @(#)ufs_lookup.c 7.13 (Berkeley) %G% + * @(#)ufs_lookup.c 7.31 (Berkeley) %G% */ #include "param.h" -#include "user.h" +#include "namei.h" #include "buf.h" #include "file.h" #include "vnode.h" -#include "../ufs/inode.h" -#include "../ufs/fs.h" + +#include "quota.h" +#include "inode.h" +#include "fs.h" struct nchstats nchstats; +#ifdef DIAGNOSTIC int dirchk = 1; +#else +int dirchk = 0; +#endif /* * Convert a component of a pathname into a pointer to a locked inode. @@ -63,12 +59,12 @@ int dirchk = 1; * * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent inode unlocked. */ -ufs_lookup(vp, ndp) - struct vnode *vp; +ufs_lookup(vdp, ndp, p) + register struct vnode *vdp; register struct nameidata *ndp; + struct proc *p; { - register struct vnode *vdp; /* vnode copy of dp */ - register struct inode *dp = 0; /* the directory we are searching */ + register struct inode *dp; /* the directory we are searching */ register struct fs *fs; /* file system that directory is in */ struct buf *bp = 0; /* a buffer of directory entries */ register struct direct *ep; /* the current directory entry */ @@ -89,12 +85,12 @@ ufs_lookup(vp, ndp) int wantparent; /* 1 => wantparent or lockparent flag */ int error; - ndp->ni_dvp = vp; + ndp->ni_dvp = vdp; ndp->ni_vp = NULL; - dp = VTOI(vp); + dp = VTOI(vdp); fs = dp->i_fs; lockparent = ndp->ni_nameiop & LOCKPARENT; - flag = ndp->ni_nameiop & OPFLAG; + flag = ndp->ni_nameiop & OPMASK; wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT); /* @@ -102,7 +98,7 @@ ufs_lookup(vp, ndp) */ if ((dp->i_mode&IFMT) != IFDIR) return (ENOTDIR); - if (error = iaccess(dp, IEXEC, ndp->ni_cred)) + if (error = ufs_access(vdp, VEXEC, ndp->ni_cred, p)) return (error); /* @@ -117,34 +113,46 @@ ufs_lookup(vp, ndp) if (error == ENOENT) return (error); +#ifdef PARANOID + if (vdp == ndp->ni_rdir && ndp->ni_isdotdot) + panic("ufs_lookup: .. through root"); +#endif /* * Get the next vnode in the path. * See comment below starting `Step through' for * an explaination of the locking protocol. */ pdp = dp; - if (!(ndp->ni_vp == ndp->ni_rdir && ndp->ni_isdotdot)) - dp = VTOI(ndp->ni_vp); - vdp = ITOV(dp); + dp = VTOI(ndp->ni_vp); + vdp = ndp->ni_vp; vpid = vdp->v_id; if (pdp == dp) { VREF(vdp); + error = 0; } else if (ndp->ni_isdotdot) { IUNLOCK(pdp); - igrab(dp); + error = vget(vdp); + if (!error && lockparent && *ndp->ni_next == '\0') + ILOCK(pdp); } else { - igrab(dp); - IUNLOCK(pdp); + error = vget(vdp); + if (!lockparent || error || *ndp->ni_next != '\0') + IUNLOCK(pdp); } /* * Check that the capability number did not change * while we were waiting for the lock. */ - if (vpid == vdp->v_id) - return (0); - iput(dp); + if (!error) { + if (vpid == vdp->v_id) + return (0); + iput(dp); + if (lockparent && pdp != dp && *ndp->ni_next == '\0') + IUNLOCK(pdp); + } ILOCK(pdp); dp = pdp; + vdp = ITOV(dp); ndp->ni_vp = NULL; } @@ -309,7 +317,7 @@ searchloop: * Access for write is interpreted as allowing * creation of files in the directory. */ - if (error = iaccess(dp, IWRITE, ndp->ni_cred)) + if (error = ufs_access(vdp, VWRITE, ndp->ni_cred, p)) return (error); /* * Return an indication of where the new directory @@ -348,7 +356,7 @@ searchloop: /* * Insert name into cache (as non-existent) if appropriate. */ - if (ndp->ni_makeentry) + if (ndp->ni_makeentry && flag != CREATE) cache_enter(ndp); return (ENOENT); @@ -384,7 +392,7 @@ found: /* * Write access to directory required to delete files. */ - if (error = iaccess(dp, IWRITE, ndp->ni_cred)) + if (error = ufs_access(vdp, VWRITE, ndp->ni_cred, p)) return (error); /* * Return pointer to current entry in ndp->ni_offset, @@ -396,31 +404,29 @@ found: ndp->ni_count = 0; else ndp->ni_count = ndp->ni_offset - prevoff; - vdp = ITOV(dp); if (dp->i_number == ndp->ni_dent.d_ino) { VREF(vdp); - } else { - pdp = dp; - if (error = iget(dp, ndp->ni_dent.d_ino, &tdp)) - return (error); - vdp = ITOV(tdp); - /* - * If directory is "sticky", then user must own - * the directory, or the file in it, else he - * may not delete it (unless he's root). This - * implements append-only directories. - */ - if ((pdp->i_mode & ISVTX) && - ndp->ni_cred->cr_uid != 0 && - ndp->ni_cred->cr_uid != pdp->i_uid && - tdp->i_uid != ndp->ni_cred->cr_uid) { - iput(tdp); - return (EPERM); - } + ndp->ni_vp = vdp; + return (0); } - ndp->ni_vp = vdp; + if (error = iget(dp, ndp->ni_dent.d_ino, &tdp)) + return (error); + /* + * If directory is "sticky", then user must own + * the directory, or the file in it, else she + * may not delete it (unless she's root). This + * implements append-only directories. + */ + if ((dp->i_mode & ISVTX) && + ndp->ni_cred->cr_uid != 0 && + ndp->ni_cred->cr_uid != dp->i_uid && + tdp->i_uid != ndp->ni_cred->cr_uid) { + iput(tdp); + return (EPERM); + } + ndp->ni_vp = ITOV(tdp); if (!lockparent) - IUNLOCK(pdp); + IUNLOCK(dp); return (0); } @@ -431,7 +437,7 @@ found: * regular file, or empty directory. */ if (flag == RENAME && wantparent && *ndp->ni_next == 0) { - if (error = iaccess(dp, IWRITE, ndp->ni_cred)) + if (error = ufs_access(vdp, VWRITE, ndp->ni_cred, p)) return (error); /* * Careful about locking second inode. @@ -477,7 +483,6 @@ found: ILOCK(pdp); ndp->ni_vp = ITOV(tdp); } else if (dp->i_number == ndp->ni_dent.d_ino) { - vdp = ITOV(dp); VREF(vdp); /* we want ourself, ie "." */ ndp->ni_vp = vdp; } else { @@ -505,6 +510,8 @@ dirbad(ip, offset, how) printf("%s: bad dir ino %d at offset %d: %s\n", ip->i_fs->fs_fsmnt, ip->i_number, offset, how); + if (ip->i_fs->fs_ronly == 0) + panic("bad dir"); } /* @@ -566,12 +573,18 @@ direnter(ip, ndp) ndp->ni_count = newentrysize; ndp->ni_resid = newentrysize; ndp->ni_base = (caddr_t)&ndp->ni_dent; - error = writeip(dp, &ndp->ni_uio, ndp->ni_cred); - if (DIRBLKSIZ > dp->i_fs->fs_fsize) + ndp->ni_iov = &ndp->ni_nd.nd_iovec; + ndp->ni_iovcnt = 1; + ndp->ni_rw = UIO_WRITE; + ndp->ni_uioseg = UIO_SYSSPACE; + error = + ufs_write(ndp->ni_dvp, &ndp->ni_uio, IO_SYNC, ndp->ni_cred); + if (DIRBLKSIZ > dp->i_fs->fs_fsize) { panic("wdir: blksize"); /* XXX - should grow w/balloc */ - else + } else { dp->i_size = roundup(dp->i_size, DIRBLKSIZ); - iput(dp); + dp->i_flag |= ICHG; + } return (error); } @@ -596,10 +609,8 @@ direnter(ip, ndp) /* * Get the block containing the space for the new directory entry. */ - if (error = blkatoff(dp, ndp->ni_offset, (char **)&dirbuf, &bp)) { - iput(dp); + if (error = blkatoff(dp, ndp->ni_offset, (char **)&dirbuf, &bp)) return (error); - } /* * Find space for the new entry. In the simple case, the * entry at offset base will have the space. If it does @@ -642,9 +653,8 @@ direnter(ip, ndp) bcopy((caddr_t)&ndp->ni_dent, (caddr_t)ep, (u_int)newentrysize); error = bwrite(bp); dp->i_flag |= IUPD|ICHG; - if (ndp->ni_endoff && ndp->ni_endoff < dp->i_size) - error = itrunc(dp, (u_long)ndp->ni_endoff); - iput(dp); + if (!error && ndp->ni_endoff && ndp->ni_endoff < dp->i_size) + error = itrunc(dp, (u_long)ndp->ni_endoff, IO_SYNC); return (error); } @@ -675,7 +685,12 @@ dirremove(ndp) ndp->ni_dent.d_ino = 0; ndp->ni_count = ndp->ni_resid = DIRSIZ(&ndp->ni_dent); ndp->ni_base = (caddr_t)&ndp->ni_dent; - error = writeip(dp, &ndp->ni_uio, ndp->ni_cred); + ndp->ni_iov = &ndp->ni_nd.nd_iovec; + ndp->ni_iovcnt = 1; + ndp->ni_rw = UIO_WRITE; + ndp->ni_uioseg = UIO_SYSSPACE; + error = + ufs_write(ndp->ni_dvp, &ndp->ni_uio, IO_SYNC, ndp->ni_cred); } else { /* * Collapse new free space into previous entry. @@ -704,7 +719,11 @@ dirrewrite(dp, ip, ndp) ndp->ni_dent.d_ino = ip->i_number; ndp->ni_count = ndp->ni_resid = DIRSIZ(&ndp->ni_dent); ndp->ni_base = (caddr_t)&ndp->ni_dent; - return (writeip(dp, &ndp->ni_uio, ndp->ni_cred)); + ndp->ni_iov = &ndp->ni_nd.nd_iovec; + ndp->ni_iovcnt = 1; + ndp->ni_rw = UIO_WRITE; + ndp->ni_uioseg = UIO_SYSSPACE; + return (ufs_write(ITOV(dp), &ndp->ni_uio, IO_SYNC, ndp->ni_cred)); } /* @@ -727,17 +746,7 @@ blkatoff(ip, offset, res, bpp) int error; *bpp = 0; - if (error = bmap(ip, lbn, &bn, (daddr_t *)0, (int *)0)) - return (error); - if (bn == (daddr_t)-1) { - dirbad(ip, offset, "hole in dir"); - return (EIO); - } -#ifdef SECSIZE - bp = bread(ip->i_dev, fsbtodb(fs, bn), bsize, fs->fs_dbsize); -#else SECSIZE - error = bread(ip->i_devvp, bn, bsize, NOCRED, &bp); - if (error) { + if (error = bread(ITOV(ip), lbn, bsize, NOCRED, &bp)) { brelse(bp); return (error); } @@ -768,8 +777,8 @@ dirempty(ip, parentino, cred) #define MINDIRSIZ (sizeof (struct dirtemplate) / 2) for (off = 0; off < ip->i_size; off += dp->d_reclen) { - error = rdwri(UIO_READ, ip, (caddr_t)dp, MINDIRSIZ, off, - UIO_SYSSPACE, cred, &count); + error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, off, + UIO_SYSSPACE, IO_NODELOCKED, cred, &count, (struct proc *)0); /* * Since we read MINDIRSIZ, residual must * be 0 unless we're at end of file. @@ -827,9 +836,9 @@ checkpath(source, target, cred) error = ENOTDIR; break; } - error = rdwri(UIO_READ, ip, (caddr_t)&dirbuf, + error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)&dirbuf, sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, - cred, (int *)0); + IO_NODELOCKED, cred, (int *)0, (struct proc *)0); if (error != 0) break; if (dirbuf.dotdot_namlen != 2 ||