- * A virgin directory (no blushing please).
- */
-struct dirtemplate mastertemplate = {
- 0, 12, 1, ".",
- 0, DIRBLKSIZ - 12, 2, ".."
-};
-
-/*
- * Mkdir system call
- */
-ufs_mkdir(ndp, vap)
- struct nameidata *ndp;
- struct vattr *vap;
-{
- register struct inode *ip, *dp;
- struct inode *tip;
- struct vnode *dvp;
- struct dirtemplate dirtemplate;
- int error;
- int dmode;
-
- dvp = ndp->ni_dvp;
- dp = VTOI(dvp);
- dmode = vap->va_mode&0777;
- dmode |= IFDIR;
- /*
- * Must simulate part of maknode here
- * in order to acquire the inode, but
- * not have it entered in the parent
- * directory. The entry is made later
- * after writing "." and ".." entries out.
- */
- error = ialloc(dp, dirpref(dp->i_fs), dmode, &tip);
- if (error) {
- iput(dp);
- return (error);
- }
- ip = tip;
-#ifdef QUOTA
- if (ip->i_dquot != NODQUOT)
- panic("mkdir: dquot");
-#endif
- ip->i_flag |= IACC|IUPD|ICHG;
- ip->i_mode = dmode;
- ITOV(ip)->v_type = VDIR; /* Rest init'd in iget() */
- ip->i_nlink = 2;
- ip->i_uid = ndp->ni_cred->cr_uid;
- ip->i_gid = dp->i_gid;
-#ifdef QUOTA
- ip->i_dquot = inoquota(ip);
-#endif
- error = iupdat(ip, &time, &time, 1);
-
- /*
- * Bump link count in parent directory
- * to reflect work done below. Should
- * be done before reference is created
- * so reparation is possible if we crash.
- */
- dp->i_nlink++;
- dp->i_flag |= ICHG;
- error = iupdat(dp, &time, &time, 1);
-
- /*
- * Initialize directory with "."
- * and ".." from static template.
- */
- dirtemplate = mastertemplate;
- dirtemplate.dot_ino = ip->i_number;
- dirtemplate.dotdot_ino = dp->i_number;
- error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate,
- sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
- ndp->ni_cred, (int *)0);
- if (error) {
- dp->i_nlink--;
- dp->i_flag |= ICHG;
- goto bad;
- }
- if (DIRBLKSIZ > dp->i_fs->fs_fsize)
- panic("mkdir: blksize"); /* XXX - should grow w/balloc() */
- else
- ip->i_size = DIRBLKSIZ;
- /*
- * Directory all set up, now
- * install the entry for it in
- * the parent directory.
- */
- error = direnter(ip, ndp);
- dp = NULL;
- if (error) {
- ndp->ni_nameiop = LOOKUP | NOCACHE;
- error = namei(ndp);
- if (!error) {
- dp = VTOI(ndp->ni_vp);
- dp->i_nlink--;
- dp->i_flag |= ICHG;
- }
- }
-bad:
- /*
- * No need to do an explicit itrunc here,
- * vrele will do this for us because we set
- * the link count to 0.
- */
- if (error) {
- ip->i_nlink = 0;
- ip->i_flag |= ICHG;
- }
- iput(ip);
- if (dp)
- iput(dp);
- return (error);
-}
-
-/*
- * Rmdir system call.
- */
-ufs_rmdir(ndp)
- register struct nameidata *ndp;
-{
- register struct inode *ip, *dp;
- int error = 0;
-
- ip = VTOI(ndp->ni_vp);
- dp = VTOI(ndp->ni_dvp);
- /*
- * No rmdir "." please.
- */
- if (dp == ip) {
- vrele(ITOV(dp));
- iput(ip);
- return (EINVAL);
- }
- /*
- * Verify the directory is empty (and valid).
- * (Rmdir ".." won't be valid since
- * ".." will contain a reference to
- * the current directory and thus be
- * non-empty.)
- */
- if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number, ndp->ni_cred)) {
- error = ENOTEMPTY;
- goto out;
- }
- /*
- * Delete reference to directory before purging
- * inode. If we crash in between, the directory
- * will be reattached to lost+found,
- */
- if (error = dirremove(ndp))
- goto out;
- dp->i_nlink--;
- dp->i_flag |= ICHG;
- cache_purge(ITOV(dp));
- iput(dp);
- ndp->ni_dvp = NULL;
- /*
- * Truncate inode. The only stuff left
- * in the directory is "." and "..". The
- * "." reference is inconsequential since
- * we're quashing it. The ".." reference
- * has already been adjusted above. We've
- * removed the "." reference and the reference
- * in the parent directory, but there may be
- * other hard links so decrement by 2 and
- * worry about them later.
- */
- ip->i_nlink -= 2;
- error = itrunc(ip, (u_long)0);
- cache_purge(ITOV(ip));
-out:
- if (ndp->ni_dvp)
- iput(dp);
- iput(ip);
- return (error);
-}
-
-/*
- * symlink -- make a symbolic link
- */
-ufs_symlink(ndp, vap, target)
- struct nameidata *ndp;
- struct vattr *vap;
- char *target;
-{
- struct inode *ip;
- int error;
-
- error = maknode(IFLNK | vap->va_mode, ndp, &ip);
- if (error)
- return (error);
- error = rdwri(UIO_WRITE, ip, target, strlen(target), (off_t)0,
- UIO_SYSSPACE, ndp->ni_cred, (int *)0);
- iput(ip);
- return (error);
-}
-
-/*
- * Vnode op for read and write
- */
-ufs_readdir(vp, uio, offp, cred)
- struct vnode *vp;
- register struct uio *uio;
- off_t *offp;
- struct ucred *cred;
-{
- register struct inode *ip = VTOI(vp);
- int count, error;
-
- ILOCK(ip);
- uio->uio_offset = *offp;
- count = uio->uio_resid;
- count &= ~(DIRBLKSIZ - 1);
- if (vp->v_type != VDIR || uio->uio_iovcnt != 1 ||
- (count < DIRBLKSIZ) || (uio->uio_offset & (DIRBLKSIZ -1))) {
- IUNLOCK(ip);
- return (EINVAL);
- }
- uio->uio_resid = count;
- uio->uio_iov->iov_len = count;
- error = readip(ip, uio, cred);
- *offp += count - uio->uio_resid;
- IUNLOCK(ip);
- return (error);
-}
-
-/*
- * Return target name of a symbolic link
- */
-ufs_readlink(vp, uiop, cred)
- struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
-{
-
- return (readip(VTOI(vp), uiop, cred));
-}
-
-/*
- * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
- * done. Iff ni_vp/ni_dvp not null and locked, unlock.
- */
-ufs_abortop(ndp)
- register struct nameidata *ndp;
-{
- register struct inode *ip;
-
- if (ndp->ni_vp) {
- ip = VTOI(ndp->ni_vp);
- if (ip->i_flag & ILOCKED)
- IUNLOCK(ip);
- vrele(ndp->ni_vp);
- }
- if (ndp->ni_dvp) {
- ip = VTOI(ndp->ni_dvp);
- if (ip->i_flag & ILOCKED)
- IUNLOCK(ip);
- vrele(ndp->ni_dvp);
- }
- return;
-}
-
-ufs_lock(vp)
- struct vnode *vp;
-{
- register struct inode *ip = VTOI(vp);
-
- ILOCK(ip);
- return (0);
-}
-
-ufs_unlock(vp)
- struct vnode *vp;
-{
- register struct inode *ip = VTOI(vp);
-
- if (!(ip->i_flag & ILOCKED))
- panic("ufs_unlock NOT LOCKED");
- IUNLOCK(ip);
- return (0);
-}
-
-/*
- * Get access to bmap