adding GNU dc ("desk calculator")
[unix-history] / sys / kern / fifo_vnops.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)fifo_vnops.c 7.7 (Berkeley) 4/15/91
34 *
35 * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
36 * -------------------- ----- ----------------------
37 * CURRENT PATCH LEVEL: 1 00141
38 * -------------------- ----- ----------------------
39 *
40 * 20 Apr 93 Jay Fenlason 1. fi_{readers|fi_writers} of fifoinfo init to 0
41 * 2. fifo_open() was calling tsleep() without
42 * unlocking the inode of the fifo
43 */
44
45#include "param.h"
46#include "time.h"
47#include "namei.h"
48#include "vnode.h"
49#include "socket.h"
50#include "socketvar.h"
51#include "stat.h"
52#include "systm.h"
53#include "ioctl.h"
54#include "file.h"
55#include "fifo.h"
56#include "errno.h"
57#include "malloc.h"
58
59/*
60 * This structure is associated with the FIFO vnode and stores
61 * the state associated with the FIFO.
62 */
63struct fifoinfo {
64 struct socket *fi_readsock;
65 struct socket *fi_writesock;
66 long fi_readers;
67 long fi_writers;
68};
69
70struct vnodeops fifo_vnodeops = {
71 fifo_lookup, /* lookup */
72 fifo_create, /* create */
73 fifo_mknod, /* mknod */
74 fifo_open, /* open */
75 fifo_close, /* close */
76 fifo_access, /* access */
77 fifo_getattr, /* getattr */
78 fifo_setattr, /* setattr */
79 fifo_read, /* read */
80 fifo_write, /* write */
81 fifo_ioctl, /* ioctl */
82 fifo_select, /* select */
83 fifo_mmap, /* mmap */
84 fifo_fsync, /* fsync */
85 fifo_seek, /* seek */
86 fifo_remove, /* remove */
87 fifo_link, /* link */
88 fifo_rename, /* rename */
89 fifo_mkdir, /* mkdir */
90 fifo_rmdir, /* rmdir */
91 fifo_symlink, /* symlink */
92 fifo_readdir, /* readdir */
93 fifo_readlink, /* readlink */
94 fifo_abortop, /* abortop */
95 fifo_inactive, /* inactive */
96 fifo_reclaim, /* reclaim */
97 fifo_lock, /* lock */
98 fifo_unlock, /* unlock */
99 fifo_bmap, /* bmap */
100 fifo_strategy, /* strategy */
101 fifo_print, /* print */
102 fifo_islocked, /* islocked */
103 fifo_advlock, /* advlock */
104};
105
106/*
107 * Trivial lookup routine that always fails.
108 */
109/* ARGSUSED */
110fifo_lookup(vp, ndp, p)
111 struct vnode *vp;
112 struct nameidata *ndp;
113 struct proc *p;
114{
115
116 ndp->ni_dvp = vp;
117 ndp->ni_vp = NULL;
118 return (ENOTDIR);
119}
120
121/*
122 * Open called to set up a new instance of a fifo or
123 * to find an active instance of a fifo.
124 */
125/* ARGSUSED */
126fifo_open(vp, mode, cred, p)
127 register struct vnode *vp;
128 int mode;
129 struct ucred *cred;
130 struct proc *p;
131{
132 register struct fifoinfo *fip;
133 struct socket *rso, *wso;
134 int error;
135 static char openstr[] = "fifo";
136
137 if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE))
138 return (EINVAL);
139 if ((fip = vp->v_fifoinfo) == NULL) {
140 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
141 vp->v_fifoinfo = fip;
142 fip->fi_readers = fip->fi_writers = 0;
143 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) {
144 free(fip, M_VNODE);
145 vp->v_fifoinfo = NULL;
146 return (error);
147 }
148 fip->fi_readsock = rso;
149 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
150 (void)soclose(rso);
151 free(fip, M_VNODE);
152 vp->v_fifoinfo = NULL;
153 return (error);
154 }
155 fip->fi_writesock = wso;
156 if (error = unp_connect2(wso, rso)) {
157 (void)soclose(wso);
158 (void)soclose(rso);
159 free(fip, M_VNODE);
160 vp->v_fifoinfo = NULL;
161 return (error);
162 }
163 wso->so_state |= SS_CANTRCVMORE;
164 rso->so_state |= SS_CANTSENDMORE;
165 }
166 error = 0;
167 if (mode & FREAD) {
168 fip->fi_readers++;
169 if (fip->fi_readers == 1) {
170 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
171 if (fip->fi_writers > 0)
172 wakeup((caddr_t)&fip->fi_writers);
173 }
174 if (mode & O_NONBLOCK)
175 return (0);
176 while (fip->fi_writers == 0) {
177 VOP_UNLOCK(vp);
178 error = tsleep((caddr_t)&fip->fi_readers, PSOCK | PCATCH,
179 openstr, 0);
180 VOP_LOCK(vp);
181 if (error)
182 break;
183 }
184 } else {
185 fip->fi_writers++;
186 if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) {
187 error = ENXIO;
188 } else {
189 if (fip->fi_writers == 1) {
190 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
191 if (fip->fi_readers > 0)
192 wakeup((caddr_t)&fip->fi_readers);
193 }
194 while (fip->fi_readers == 0) {
195 VOP_UNLOCK(vp);
196 error = tsleep((caddr_t)&fip->fi_writers,
197 PSOCK | PCATCH, openstr, 0);
198 VOP_LOCK(vp);
199 if (error)
200 break;
201 }
202 }
203 }
204 if (error)
205 fifo_close(vp, mode, cred, p);
206 return (error);
207}
208
209/*
210 * Vnode op for read
211 */
212/* ARGSUSED */
213fifo_read(vp, uio, ioflag, cred)
214 struct vnode *vp;
215 register struct uio *uio;
216 int ioflag;
217 struct ucred *cred;
218{
219 register struct socket *rso = vp->v_fifoinfo->fi_readsock;
220 int error, startresid;
221
222#ifdef DIAGNOSTIC
223 if (uio->uio_rw != UIO_READ)
224 panic("fifo_read mode");
225#endif
226 if (uio->uio_resid == 0)
227 return (0);
228 if (ioflag & IO_NDELAY)
229 rso->so_state |= SS_NBIO;
230 startresid = uio->uio_resid;
231 VOP_UNLOCK(vp);
232 error = soreceive(rso, (struct mbuf **)0, uio, (int *)0,
233 (struct mbuf **)0, (struct mbuf **)0);
234 VOP_LOCK(vp);
235 /*
236 * Clear EOF indication after first such return.
237 */
238 if (uio->uio_resid == startresid)
239 rso->so_state &= ~SS_CANTRCVMORE;
240 if (ioflag & IO_NDELAY)
241 rso->so_state &= ~SS_NBIO;
242 return (error);
243}
244
245/*
246 * Vnode op for write
247 */
248/* ARGSUSED */
249fifo_write(vp, uio, ioflag, cred)
250 struct vnode *vp;
251 register struct uio *uio;
252 int ioflag;
253 struct ucred *cred;
254{
255 struct socket *wso = vp->v_fifoinfo->fi_writesock;
256 int error;
257
258#ifdef DIAGNOSTIC
259 if (uio->uio_rw != UIO_WRITE)
260 panic("fifo_write mode");
261#endif
262 if (ioflag & IO_NDELAY)
263 wso->so_state |= SS_NBIO;
264 VOP_UNLOCK(vp);
265 error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0);
266 VOP_LOCK(vp);
267 if (ioflag & IO_NDELAY)
268 wso->so_state &= ~SS_NBIO;
269 return (error);
270}
271
272/*
273 * Device ioctl operation.
274 */
275/* ARGSUSED */
276fifo_ioctl(vp, com, data, fflag, cred, p)
277 struct vnode *vp;
278 int com;
279 caddr_t data;
280 int fflag;
281 struct ucred *cred;
282 struct proc *p;
283{
284 struct file filetmp;
285 int error;
286
287 if (com == FIONBIO)
288 return (0);
289 if (fflag & FREAD)
290 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
291 else
292 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
293 return (soo_ioctl(&filetmp, com, data, p));
294}
295
296/* ARGSUSED */
297fifo_select(vp, which, fflag, cred, p)
298 struct vnode *vp;
299 int which, fflag;
300 struct ucred *cred;
301 struct proc *p;
302{
303 struct file filetmp;
304 int error;
305
306 if (fflag & FREAD)
307 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
308 else
309 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
310 return (soo_select(&filetmp, which, p));
311}
312
313/*
314 * This is a noop, simply returning what one has been given.
315 */
316fifo_bmap(vp, bn, vpp, bnp)
317 struct vnode *vp;
318 daddr_t bn;
319 struct vnode **vpp;
320 daddr_t *bnp;
321{
322
323 if (vpp != NULL)
324 *vpp = vp;
325 if (bnp != NULL)
326 *bnp = bn;
327 return (0);
328}
329
330/*
331 * At the moment we do not do any locking.
332 */
333/* ARGSUSED */
334fifo_lock(vp)
335 struct vnode *vp;
336{
337
338 return (0);
339}
340
341/* ARGSUSED */
342fifo_unlock(vp)
343 struct vnode *vp;
344{
345
346 return (0);
347}
348
349/*
350 * Device close routine
351 */
352/* ARGSUSED */
353fifo_close(vp, fflag, cred, p)
354 register struct vnode *vp;
355 int fflag;
356 struct ucred *cred;
357 struct proc *p;
358{
359 register struct fifoinfo *fip = vp->v_fifoinfo;
360 int error1, error2;
361
362 if (fflag & FWRITE) {
363 fip->fi_writers--;
364 if (fip->fi_writers == 0)
365 socantrcvmore(fip->fi_readsock);
366 } else {
367 fip->fi_readers--;
368 if (fip->fi_readers == 0)
369 socantsendmore(fip->fi_writesock);
370 }
371 if (vp->v_usecount > 1)
372 return (0);
373 error1 = soclose(fip->fi_readsock);
374 error2 = soclose(fip->fi_writesock);
375 FREE(fip, M_VNODE);
376 vp->v_fifoinfo = NULL;
377 if (error1)
378 return (error1);
379 return (error2);
380}
381
382/*
383 * Print out the contents of a fifo vnode.
384 */
385fifo_print(vp)
386 struct vnode *vp;
387{
388
389 printf("tag VT_NON");
390 fifo_printinfo(vp);
391 printf("\n");
392}
393
394/*
395 * Print out internal contents of a fifo vnode.
396 */
397fifo_printinfo(vp)
398 struct vnode *vp;
399{
400 register struct fifoinfo *fip = vp->v_fifoinfo;
401
402 printf(", fifo with %d readers and %d writers",
403 fip->fi_readers, fip->fi_writers);
404}
405
406/*
407 * Fifo failed operation
408 */
409fifo_ebadf()
410{
411
412 return (EBADF);
413}
414
415/*
416 * Fifo advisory byte-level locks.
417 */
418/* ARGSUSED */
419fifo_advlock(vp, id, op, fl, flags)
420 struct vnode *vp;
421 caddr_t id;
422 int op;
423 struct flock *fl;
424 int flags;
425{
426
427 return (EOPNOTSUPP);
428}
429
430/*
431 * Fifo bad operation
432 */
433fifo_badop()
434{
435
436 panic("fifo_badop called");
437 /* NOTREACHED */
438}