]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/miscfs/fifofs/fifo_vnops.c
xnu-4903.241.1.tar.gz
[apple/xnu.git] / bsd / miscfs / fifofs / fifo_vnops.c
index caa874baf7f5e8ef0ab9673d6dd615574723dc19..6146bcbfa57b7a2a1f7c7f4081ccc135eb00fe0c 100644 (file)
@@ -1,14 +1,19 @@
 /*
- * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
@@ -18,7 +23,7 @@
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
 /*
@@ -74,9 +79,6 @@
 
 #define VOPFUNC int (*)(void *)
 
-extern int     soo_ioctl(struct fileproc *fp, u_long cmd, caddr_t data, struct proc *p);
-extern int     soo_select(struct fileproc *fp, int which, void * wql, struct proc *p);
-
 int (**fifo_vnodeop_p)(void *);
 struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
        { &vnop_default_desc, (VOPFUNC)vn_default_error },
@@ -115,7 +117,7 @@ struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
        { &vnop_blktooff_desc, (VOPFUNC)err_blktooff },         /* blktooff */
        { &vnop_offtoblk_desc, (VOPFUNC)err_offtoblk },         /* offtoblk */
        { &vnop_blockmap_desc, (VOPFUNC)err_blockmap },                 /* blockmap */
-       { (struct vnodeop_desc*)NULL, (int(*)())NULL }
+       { (struct vnodeop_desc*)NULL, (int(*)(void *))NULL }
 };
 struct vnodeopv_desc fifo_vnodeop_opv_desc =
        { &fifo_vnodeop_p, fifo_vnodeop_entries };
@@ -125,13 +127,7 @@ struct vnodeopv_desc fifo_vnodeop_opv_desc =
  */
 /* ARGSUSED */
 int
-fifo_lookup(ap)
-       struct vnop_lookup_args /* {
-               struct vnode * a_dvp;
-               struct vnode ** a_vpp;
-               struct componentname * a_cnp;
-               vfs_context_t a_context;
-       } */ *ap;
+fifo_lookup(struct vnop_lookup_args *ap)
 {
        
        *ap->a_vpp = NULL;
@@ -144,12 +140,7 @@ fifo_lookup(ap)
  */
 /* ARGSUSED */
 int
-fifo_open(ap)
-       struct vnop_open_args /* {
-               struct vnode *a_vp;
-               int  a_mode;
-               vfs_context_t a_context;
-       } */ *ap;
+fifo_open(struct vnop_open_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct fifoinfo *fip;
@@ -168,7 +159,7 @@ retry:
        if ((fip->fi_flags & FIFO_CREATED) == 0) {
                if (fip->fi_flags & FIFO_INCREATE) {
                        fip->fi_flags |= FIFO_CREATEWAIT;       
-                       error = msleep(&fip->fi_flags, &vp->v_lock, PRIBIO | PCATCH, "fifocreatewait", 0);
+                       error = msleep(&fip->fi_flags, &vp->v_lock, PRIBIO | PCATCH, "fifocreatewait", NULL);
                        if (error) {
                                vnode_unlock(vp);
                                return(error);
@@ -180,13 +171,11 @@ retry:
                        if ( (error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) ) {
                                goto bad1;
                        }
-                       fip->fi_readsock = rso;
 
                        if ( (error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) ) {
                                (void)soclose(rso);
                                goto bad1;
                        }
-                       fip->fi_writesock = wso;
 
                        if ( (error = soconnect2(wso, rso)) ) {
                                (void)soclose(wso);
@@ -195,22 +184,22 @@ retry:
                        }
                        fip->fi_readers = fip->fi_writers = 0;
 
-               socket_lock(wso, 1);
+                       /* Lock ordering between wso and rso does not matter here 
+                        * because they are just created and no one has a reference to them
+                        */
+                       socket_lock(wso, 1);
                        wso->so_state |= SS_CANTRCVMORE;
                        wso->so_snd.sb_lowat = PIPE_BUF;
-#if 0
-                       /* Because all the unp is protected by single mutex 
-                        * doing it in two step may actually cause problems
-                        * as it opens up window between the drop and acquire
-                        */
-               socket_unlock(wso, 1);
+                       socket_unlock(wso, 1);
 
-               socket_lock(rso, 1);
-#endif
+                       socket_lock(rso, 1);
                        rso->so_state |= SS_CANTSENDMORE;
-               socket_unlock(wso, 1);
+                       socket_unlock(rso, 1);
 
                        vnode_lock(vp);
+                       fip->fi_readsock = rso;
+                       fip->fi_writesock = wso;
+
                        fip->fi_flags |= FIFO_CREATED;
                        fip->fi_flags &= ~FIFO_INCREATE;
                        
@@ -249,7 +238,7 @@ retry:
        if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
                if (fip->fi_writers == 0) {
                        error = msleep((caddr_t)&fip->fi_readers, &vp->v_lock,
-                                       PCATCH | PSOCK, "fifoor", 0);
+                                       PCATCH | PSOCK, "fifoor", NULL);
                        if (error)
                                goto bad;
                        if (fip->fi_readers == 1) {
@@ -267,7 +256,7 @@ retry:
                } else {
                        if (fip->fi_readers == 0) {
                                error = msleep((caddr_t)&fip->fi_writers,&vp->v_lock,
-                                               PCATCH | PSOCK, "fifoow", 0);
+                                               PCATCH | PSOCK, "fifoow", NULL);
                                if (error)
                                        goto bad;
                                if (fip->fi_writers == 1) {
@@ -303,17 +292,12 @@ bad1:
  * Vnode op for read
  */
 int
-fifo_read(ap)
-       struct vnop_read_args /* {
-               struct vnode *a_vp;
-               struct uio *a_uio;
-               int  a_ioflag;
-               vfs_context_t a_context;
-       } */ *ap;
+fifo_read(struct vnop_read_args *ap)
 {
        struct uio *uio = ap->a_uio;
        struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
-       int error, startresid;
+       user_ssize_t startresid;
+       int error;
        int rflags;
 
 #if DIAGNOSTIC
@@ -325,7 +309,6 @@ fifo_read(ap)
 
        rflags = (ap->a_ioflag & IO_NDELAY) ? MSG_NBIO : 0;
 
-       // LP64todo - fix this!
        startresid = uio_resid(uio);
 
        /* fifo conformance - if we have a reader open on the fifo but no 
@@ -343,7 +326,9 @@ fifo_read(ap)
        /* skip soreceive to avoid blocking when we have no writers */
        if (error != EWOULDBLOCK) {
                error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0,
-                                               (struct mbuf **)0, &rflags);
+                                               (struct mbuf **)0, &rflags);
+               if (error == 0)
+                       lock_vnode_and_post(ap->a_vp, 0);
        }
        else {
                /* clear EWOULDBLOCK and return EOF (zero) */
@@ -364,13 +349,7 @@ fifo_read(ap)
  * Vnode op for write
  */
 int
-fifo_write(ap)
-       struct vnop_write_args /* {
-               struct vnode *a_vp;
-               struct uio *a_uio;
-               int  a_ioflag;
-               vfs_context_t a_context;
-       } */ *ap;
+fifo_write(struct vnop_write_args *ap)
 {
        struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
        int error;
@@ -379,8 +358,10 @@ fifo_write(ap)
        if (ap->a_uio->uio_rw != UIO_WRITE)
                panic("fifo_write mode");
 #endif
-       error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0,
+       error = sosend(wso, (struct sockaddr *)0, ap->a_uio, NULL,
                       (struct mbuf *)0, (ap->a_ioflag & IO_NDELAY) ? MSG_NBIO : 0);
+       if (error == 0)
+               lock_vnode_and_post(ap->a_vp, 0);
 
        return (error);
 }
@@ -389,16 +370,8 @@ fifo_write(ap)
  * Device ioctl operation.
  */
 int
-fifo_ioctl(ap)
-       struct vnop_ioctl_args /* {
-               struct vnode *a_vp;
-               int  a_command;
-               caddr_t  a_data;
-               int  a_fflag;
-               vfs_context_t a_context;
-       } */ *ap;
+fifo_ioctl(struct vnop_ioctl_args *ap)
 {
-       struct proc *p = vfs_context_proc(ap->a_context);
        struct fileproc filetmp;
        struct fileglob filefg;
        int error;
@@ -409,13 +382,13 @@ fifo_ioctl(ap)
        filetmp.f_fglob = &filefg;
        if (ap->a_fflag & FREAD) {
                filetmp.f_fglob->fg_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
-               error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, p);
+               error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_context);
                if (error)
                        return (error);
        }
        if (ap->a_fflag & FWRITE) {
                filetmp.f_fglob->fg_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
-               error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, p);
+               error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_context);
                if (error)
                        return (error);
        }
@@ -423,16 +396,8 @@ fifo_ioctl(ap)
 }
 
 int
-fifo_select(ap)
-       struct vnop_select_args /* {
-               struct vnode *a_vp;
-               int  a_which;
-               int  a_fflags;
-               void * a_wql;
-               vfs_context_t a_context;
-       } */ *ap;
+fifo_select(struct vnop_select_args *ap)
 {
-       struct proc *p = vfs_context_proc(ap->a_context);
        struct fileproc filetmp;
        struct fileglob filefg;
        int ready;
@@ -441,13 +406,13 @@ fifo_select(ap)
        filetmp.f_fglob = &filefg;
        if (ap->a_which & FREAD) {
                filetmp.f_fglob->fg_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
-               ready = soo_select(&filetmp, ap->a_which, ap->a_wql, p);
+               ready = soo_select(&filetmp, ap->a_which, ap->a_wql, ap->a_context);
                if (ready)
                        return (ready);
        }
        if (ap->a_which & FWRITE) {
                filetmp.f_fglob->fg_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
-               ready = soo_select(&filetmp, ap->a_which, ap->a_wql, p);
+               ready = soo_select(&filetmp, ap->a_which, ap->a_wql, ap->a_context);
                if (ready)
                        return (ready);
        }
@@ -465,12 +430,7 @@ fifo_inactive(__unused struct vnop_inactive_args *ap)
  * Device close routine
  */
 int
-fifo_close(ap)
-       struct vnop_close_args /* {
-               struct vnode *a_vp;
-               int  a_fflag;
-               vfs_context_t a_context;
-       } */ *ap;
+fifo_close(struct vnop_close_args *ap)
 {
        return fifo_close_internal(ap->a_vp, ap->a_fflag, ap->a_context, 0);
 }
@@ -478,7 +438,7 @@ fifo_close(ap)
 int
 fifo_close_internal(vnode_t vp, int fflag, __unused vfs_context_t context, int locked)
 {
-       register struct fifoinfo *fip = vp->v_fifoinfo;
+       struct fifoinfo *fip = vp->v_fifoinfo;
        int error1, error2;
        struct socket *rso;
        struct socket *wso;
@@ -526,8 +486,8 @@ fifo_close_internal(vnode_t vp, int fflag, __unused vfs_context_t context, int l
 
        wso = fip->fi_writesock;
        rso = fip->fi_readsock;
-       fip->fi_readsock = 0;
-       fip->fi_writesock = 0;
+       fip->fi_readsock = NULL;
+       fip->fi_writesock = NULL;
        fip->fi_flags &= ~FIFO_CREATED;
        if (!locked)
                vnode_unlock(vp);
@@ -539,17 +499,15 @@ fifo_close_internal(vnode_t vp, int fflag, __unused vfs_context_t context, int l
        return (error2);
 }
 
-
 /*
  * Print out internal contents of a fifo vnode.
  */
 void
-fifo_printinfo(vp)
-       struct vnode *vp;
+fifo_printinfo(struct vnode *vp)
 {
-       register struct fifoinfo *fip = vp->v_fifoinfo;
+       struct fifoinfo *fip = vp->v_fifoinfo;
 
-       printf(", fifo with %d readers and %d writers",
+       printf(", fifo with %ld readers and %ld writers",
                fip->fi_readers, fip->fi_writers);
 }
 
@@ -557,15 +515,8 @@ fifo_printinfo(vp)
  * Return POSIX pathconf information applicable to fifo's.
  */
 int
-fifo_pathconf(ap)
-       struct vnop_pathconf_args /* {
-               struct vnode *a_vp;
-               int a_name;
-               int *a_retval;
-               vfs_context_t a_context;
-       } */ *ap;
+fifo_pathconf(struct vnop_pathconf_args *ap)
 {
-
        switch (ap->a_name) {
        case _PC_LINK_MAX:
                *ap->a_retval = LINK_MAX;
@@ -574,7 +525,7 @@ fifo_pathconf(ap)
                *ap->a_retval = PIPE_BUF;
                return (0);
        case _PC_CHOWN_RESTRICTED:
-               *ap->a_retval = 1;
+               *ap->a_retval = 200112;         /* _POSIX_CHOWN_RESTRICTED */
                return (0);
        default:
                return (EINVAL);
@@ -602,3 +553,26 @@ fifo_advlock(__unused struct vnop_advlock_args *ap)
        return (ENOTSUP);
 }
 
+
+/* You'd certainly better have an iocount on the vnode! */
+int
+fifo_freespace(struct vnode *vp, long *count) 
+{
+       struct socket *rsock;
+       rsock = vp->v_fifoinfo->fi_readsock;
+       socket_lock(rsock, 1);
+       *count = sbspace(&rsock->so_rcv);
+       socket_unlock(rsock, 1);
+       return 0;
+}
+
+int
+fifo_charcount(struct vnode *vp, int *count) 
+{
+       int mcount;
+       int err = sock_ioctl(vp->v_fifoinfo->fi_readsock, FIONREAD, (void*)&mcount);
+       if (err == 0) {
+               *count = mcount;
+       }
+       return err;
+}