need a semi-colon before the done
[unix-history] / usr / src / sys / miscfs / fifofs / fifo_vnops.c
CommitLineData
cc6b488e
KM
1/*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
dbf0c423 5 * %sccs.include.redist.c%
cc6b488e 6 *
dbf0c423 7 * @(#)fifo_vnops.c 7.4 (Berkeley) %G%
cc6b488e
KM
8 */
9
10#include "param.h"
11#include "time.h"
12#include "namei.h"
13#include "vnode.h"
14#include "socket.h"
15#include "socketvar.h"
16#include "stat.h"
17#include "ioctl.h"
18#include "file.h"
19#include "errno.h"
20#include "malloc.h"
21
22/*
23 * This structure is associated with the FIFO vnode and stores
24 * the state associated with the FIFO.
25 */
26struct fifoinfo {
27 struct socket *fi_readsock;
28 struct socket *fi_writesock;
29 long fi_readers;
30 long fi_writers;
31};
32
33int fifo_lookup(),
34 fifo_open(),
35 fifo_read(),
36 fifo_write(),
37 fifo_strategy(),
38 fifo_bmap(),
39 fifo_ioctl(),
40 fifo_select(),
41 fifo_lock(),
42 fifo_unlock(),
43 fifo_close(),
44 fifo_print(),
45 fifo_ebadf(),
46 fifo_badop(),
47 fifo_nullop();
48
49struct vnodeops fifo_vnodeops = {
50 fifo_lookup, /* lookup */
51 fifo_badop, /* create */
52 fifo_badop, /* mknod */
53 fifo_open, /* open */
54 fifo_close, /* close */
55 fifo_ebadf, /* access */
56 fifo_ebadf, /* getattr */
57 fifo_ebadf, /* setattr */
58 fifo_read, /* read */
59 fifo_write, /* write */
60 fifo_ioctl, /* ioctl */
61 fifo_select, /* select */
62 fifo_badop, /* mmap */
63 fifo_nullop, /* fsync */
64 fifo_badop, /* seek */
65 fifo_badop, /* remove */
66 fifo_badop, /* link */
67 fifo_badop, /* rename */
68 fifo_badop, /* mkdir */
69 fifo_badop, /* rmdir */
70 fifo_badop, /* symlink */
71 fifo_badop, /* readdir */
72 fifo_badop, /* readlink */
73 fifo_badop, /* abortop */
74 fifo_nullop, /* inactive */
75 fifo_nullop, /* reclaim */
76 fifo_lock, /* lock */
77 fifo_unlock, /* unlock */
78 fifo_bmap, /* bmap */
79 fifo_badop, /* strategy */
80 fifo_print, /* print */
81 fifo_nullop, /* islocked */
82};
83
84/*
85 * Trivial lookup routine that always fails.
86 */
87fifo_lookup(vp, ndp)
88 struct vnode *vp;
89 struct nameidata *ndp;
90{
91
92 ndp->ni_dvp = vp;
93 ndp->ni_vp = NULL;
94 return (ENOTDIR);
95}
96
97/*
98 * Open called to set up a new instance of a fifo or
99 * to find an active instance of a fifo.
100 */
101/* ARGSUSED */
102fifo_open(vp, mode, cred)
103 register struct vnode *vp;
104 int mode;
105 struct ucred *cred;
106{
107 register struct fifoinfo *fip;
108 struct socket *rso, *wso;
109 int error;
bcc829cc 110 static char openstr[] = "fifo";
cc6b488e
KM
111
112 if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE))
113 return (EINVAL);
114 if ((fip = vp->v_fifoinfo) == NULL) {
115 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
116 vp->v_fifoinfo = fip;
ed89f575
KM
117 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) {
118 free(fip, M_VNODE);
119 vp->v_fifoinfo = NULL;
cc6b488e 120 return (error);
ed89f575 121 }
cc6b488e
KM
122 fip->fi_readsock = rso;
123 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
124 (void)soclose(rso);
ed89f575
KM
125 free(fip, M_VNODE);
126 vp->v_fifoinfo = NULL;
cc6b488e
KM
127 return (error);
128 }
129 fip->fi_writesock = wso;
130 if (error = unp_connect2(wso, rso)) {
131 (void)soclose(wso);
132 (void)soclose(rso);
ed89f575
KM
133 free(fip, M_VNODE);
134 vp->v_fifoinfo = NULL;
cc6b488e
KM
135 return (error);
136 }
137 wso->so_state |= SS_CANTRCVMORE;
138 rso->so_state |= SS_CANTSENDMORE;
139 }
140 error = 0;
141 if (mode & FREAD) {
142 fip->fi_readers++;
143 if (fip->fi_readers == 1) {
144 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
145 if (fip->fi_writers > 0)
146 wakeup((caddr_t)&fip->fi_writers);
147 }
148 if (mode & O_NONBLOCK)
149 return (0);
150 while (fip->fi_writers == 0)
bcc829cc
MK
151 if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK,
152 openstr, 0))
cc6b488e
KM
153 break;
154 } else {
155 fip->fi_writers++;
156 if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) {
157 error = ENXIO;
158 } else {
159 if (fip->fi_writers == 1) {
160 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
161 if (fip->fi_readers > 0)
162 wakeup((caddr_t)&fip->fi_readers);
163 }
164 while (fip->fi_readers == 0)
bcc829cc
MK
165 if (error = tsleep((caddr_t)&fip->fi_writers,
166 PSOCK, openstr, 0))
cc6b488e
KM
167 break;
168 }
169 }
170 if (error)
171 fifo_close(vp, mode, cred);
172 return (error);
173}
174
175/*
176 * Vnode op for read
177 */
178/* ARGSUSED */
179fifo_read(vp, uio, ioflag, cred)
180 struct vnode *vp;
181 register struct uio *uio;
182 int ioflag;
183 struct ucred *cred;
184{
185 register struct socket *rso = vp->v_fifoinfo->fi_readsock;
186 int error, startresid;
187
188 if (uio->uio_rw != UIO_READ)
189 panic("fifo_read mode");
190 if (uio->uio_resid == 0)
191 return (0);
192 if (ioflag & IO_NDELAY)
193 rso->so_state |= SS_NBIO;
194 startresid = uio->uio_resid;
195 VOP_UNLOCK(vp);
196 error = soreceive(rso, (struct mbuf **)0, uio, (int *)0,
197 (struct mbuf **)0, (struct mbuf **)0);
198 VOP_LOCK(vp);
199 /*
200 * Clear EOF indication after first such return.
201 */
202 if (uio->uio_resid == startresid)
203 rso->so_state &= ~SS_CANTRCVMORE;
204 if (ioflag & IO_NDELAY)
205 rso->so_state &= ~SS_NBIO;
206 return (error);
207}
208
209/*
210 * Vnode op for write
211 */
212/* ARGSUSED */
213fifo_write(vp, uio, ioflag, cred)
214 struct vnode *vp;
215 register struct uio *uio;
216 int ioflag;
217 struct ucred *cred;
218{
219 struct socket *wso = vp->v_fifoinfo->fi_writesock;
220 int error;
221
222 if (uio->uio_rw != UIO_WRITE)
223 panic("fifo_write mode");
224 if (ioflag & IO_NDELAY)
225 wso->so_state |= SS_NBIO;
226 VOP_UNLOCK(vp);
227 error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0);
228 VOP_LOCK(vp);
229 if (ioflag & IO_NDELAY)
230 wso->so_state &= ~SS_NBIO;
231 return (error);
232}
233
234/*
235 * Device ioctl operation.
236 */
237/* ARGSUSED */
238fifo_ioctl(vp, com, data, fflag, cred)
239 struct vnode *vp;
240 int com;
241 caddr_t data;
242 int fflag;
243 struct ucred *cred;
244{
245 struct file filetmp;
246 int error;
247
248 if (com == FIONBIO)
249 return (0);
250 if (fflag & FREAD)
251 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
252 else
253 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
254 return (soo_ioctl(&filetmp, com, data));
255}
256
257/* ARGSUSED */
258fifo_select(vp, which, fflag, cred)
259 struct vnode *vp;
260 int which, fflag;
261 struct ucred *cred;
262{
263 struct file filetmp;
264 int error;
265
266 if (fflag & FREAD)
267 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
268 else
269 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
270 return (soo_select(&filetmp, which));
271}
272
273/*
274 * This is a noop, simply returning what one has been given.
275 */
276fifo_bmap(vp, bn, vpp, bnp)
277 struct vnode *vp;
278 daddr_t bn;
279 struct vnode **vpp;
280 daddr_t *bnp;
281{
282
283 if (vpp != NULL)
284 *vpp = vp;
285 if (bnp != NULL)
286 *bnp = bn;
287 return (0);
288}
289
290/*
291 * At the moment we do not do any locking.
292 */
293/* ARGSUSED */
294fifo_lock(vp)
295 struct vnode *vp;
296{
297
298 return (0);
299}
300
301/* ARGSUSED */
302fifo_unlock(vp)
303 struct vnode *vp;
304{
305
306 return (0);
307}
308
309/*
310 * Device close routine
311 */
312/* ARGSUSED */
313fifo_close(vp, fflag, cred)
314 register struct vnode *vp;
315 int fflag;
316 struct ucred *cred;
317{
318 register struct fifoinfo *fip = vp->v_fifoinfo;
319 int error1, error2;
320
321 if (fflag & FWRITE) {
322 fip->fi_writers--;
323 if (fip->fi_writers == 0)
324 socantrcvmore(fip->fi_readsock);
325 } else {
326 fip->fi_readers--;
327 if (fip->fi_readers == 0)
328 socantsendmore(fip->fi_writesock);
329 }
330 if (vp->v_usecount > 1)
331 return (0);
332 error1 = soclose(fip->fi_readsock);
333 error2 = soclose(fip->fi_writesock);
334 FREE(fip, M_VNODE);
335 vp->v_fifoinfo = NULL;
336 if (error1)
337 return (error1);
338 return (error2);
339}
340
341/*
342 * Print out the contents of a fifo vnode.
343 */
344fifo_print(vp)
345 struct vnode *vp;
346{
347
348 printf("tag VT_NON");
349 fifo_printinfo(vp);
350 printf("\n");
351}
352
353/*
354 * Print out internal contents of a fifo vnode.
355 */
356fifo_printinfo(vp)
357 struct vnode *vp;
358{
359 register struct fifoinfo *fip = vp->v_fifoinfo;
360
361 printf(", fifo with %d readers and %d writers",
362 fip->fi_readers, fip->fi_writers);
363}
364
365/*
366 * Fifo failed operation
367 */
368fifo_ebadf()
369{
370
371 return (EBADF);
372}
373
374/*
375 * Fifo bad operation
376 */
377fifo_badop()
378{
379
380 panic("fifo_badop called");
381 /* NOTREACHED */
382}
383
384/*
385 * Fifo null operation
386 */
387fifo_nullop()
388{
389
390 return (0);
391}