]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/vfs/vfs_vnops.c
xnu-517.9.4.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_vnops.c
index e186fb48408a751e122d7e59d833bc97b3bd8e89..6e77308f8f5809489a87855000c95b17008313ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -90,9 +90,11 @@ static int vn_write __P((struct file *fp, struct uio *uio,
                struct ucred *cred, int flags, struct proc *p));
 static int vn_select __P(( struct file *fp, int which, void * wql,
                struct proc *p));
+static int vn_kqfilt_add __P((struct file *fp, struct knote *kn, struct proc *p));
+static int vn_kqfilt_remove __P((struct vnode *vp, uintptr_t ident, struct proc *p));
 
 struct         fileops vnops =
-       { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile };
+       { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile, vn_kqfilt_add };
 
 /*
  * Common code for vnode open operations.
@@ -102,6 +104,15 @@ int
 vn_open(ndp, fmode, cmode)
        register struct nameidata *ndp;
        int fmode, cmode;
+{
+       return vn_open_modflags(ndp,&fmode,cmode);
+}
+
+__private_extern__ int
+vn_open_modflags(ndp, fmodep, cmode)
+       register struct nameidata *ndp;
+       int *fmodep;
+       int cmode;
 {
        register struct vnode *vp;
        register struct proc *p = ndp->ni_cnd.cn_proc;
@@ -110,16 +121,22 @@ vn_open(ndp, fmode, cmode)
        struct vattr *vap = &vat;
        int error;
        int didhold = 0;
+       char *nameptr;
+       int fmode = *fmodep;
 
        if (fmode & O_CREAT) {
                ndp->ni_cnd.cn_nameiop = CREATE;
-               ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
+               ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | AUDITVNPATH1;
                if ((fmode & O_EXCL) == 0)
                        ndp->ni_cnd.cn_flags |= FOLLOW;
                bwillwrite();
                if (error = namei(ndp))
                        return (error);
                if (ndp->ni_vp == NULL) {
+                       nameptr = add_name(ndp->ni_cnd.cn_nameptr,
+                                          ndp->ni_cnd.cn_namelen,
+                                          ndp->ni_cnd.cn_hash, 0);
+
                        VATTR_NULL(vap);
                        vap->va_type = VREG;
                        vap->va_mode = cmode;
@@ -127,10 +144,17 @@ vn_open(ndp, fmode, cmode)
                                vap->va_vaflags |= VA_EXCLUSIVE;
                        VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE);
                        if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
-                           &ndp->ni_cnd, vap))
+                                              &ndp->ni_cnd, vap)) {
+                               remove_name(nameptr);
                                return (error);
+                       }
                        fmode &= ~O_TRUNC;
                        vp = ndp->ni_vp;
+                       
+                       VNAME(vp) = nameptr;
+                       if (vget(ndp->ni_dvp, 0, p) == 0) {
+                           VPARENT(vp) = ndp->ni_dvp;
+                       }
                } else {
                        VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
                        if (ndp->ni_dvp == ndp->ni_vp)
@@ -147,7 +171,7 @@ vn_open(ndp, fmode, cmode)
                }
        } else {
                ndp->ni_cnd.cn_nameiop = LOOKUP;
-               ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF;
+               ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF | AUDITVNPATH1;
                if (error = namei(ndp))
                        return (error);
                vp = ndp->ni_vp;
@@ -192,15 +216,6 @@ vn_open(ndp, fmode, cmode)
                                goto bad;
                }
        }
-       if (fmode & O_TRUNC) {
-               VOP_UNLOCK(vp, 0, p);                           /* XXX */
-               VOP_LEASE(vp, p, cred, LEASE_WRITE);
-               (void)vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);  /* XXX */
-               VATTR_NULL(vap);
-               vap->va_size = 0;
-               if (error = VOP_SETATTR(vp, vap, cred, p))
-                       goto bad;
-       }
 
        if (error = VOP_OPEN(vp, fmode, cred, p)) {
                goto bad;
@@ -209,12 +224,14 @@ vn_open(ndp, fmode, cmode)
        if (fmode & FWRITE)
                if (++vp->v_writecount <= 0)
                        panic("vn_open: v_writecount");
+       *fmodep = fmode;
        return (0);
 bad:
        VOP_UNLOCK(vp, 0, p);
        if (didhold)
                ubc_rele(vp);
        vrele(vp);
+       ndp->ni_vp = NULL;
        return (error);
 }
 
@@ -252,8 +269,17 @@ vn_close(vp, flags, cred, p)
 {
        int error;
 
-       if (flags & FWRITE)
+       if (flags & FWRITE) {
+               
                vp->v_writecount--;
+
+               {
+                       extern void notify_filemod_watchers(struct vnode *vp, struct proc *p);
+
+                       notify_filemod_watchers(vp, p);
+               }
+       }
+
        error = VOP_CLOSE(vp, flags, cred, p);
        ubc_rele(vp);
        vrele(vp);
@@ -555,7 +581,7 @@ vn_stat(vp, sb, p)
        sb->st_blksize = vap->va_blocksize;
        sb->st_flags = vap->va_flags;
        /* Do not give the generation number out to unpriviledged users */
-       if (suser(p->p_ucred, &p->p_acflag))
+       if (vap->va_gen && suser(p->p_ucred, &p->p_acflag))
                sb->st_gen = 0; 
        else
                sb->st_gen = vap->va_gen;
@@ -688,3 +714,34 @@ vn_closefile(fp, p)
        return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
                fp->f_cred, p));
 }
+
+static int
+vn_kqfilt_add(fp, kn, p)
+       struct file *fp;
+       struct knote *kn;
+       struct proc *p;
+{
+       struct vnode *vp = (struct vnode *)fp->f_data;
+       int error;
+       
+       error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+       if (error) return (error);
+       error = VOP_KQFILT_ADD(vp, kn, p);
+       (void)VOP_UNLOCK(vp, 0, p);
+       return (error);
+}
+
+static int
+vn_kqfilt_remove(vp, ident, p)
+       struct vnode *vp;
+       uintptr_t ident;
+       struct proc *p;
+{
+       int error;
+       
+       error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+       if (error) return (error);
+       error = VOP_KQFILT_REMOVE(vp, ident, p);
+       (void)VOP_UNLOCK(vp, 0, p);
+       return (error);
+}