xref: /csrg-svn/sys/kern/sys_generic.c (revision 44444)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)sys_generic.c	7.22 (Berkeley) 06/28/90
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "user.h"
13 #include "ioctl.h"
14 #include "file.h"
15 #include "proc.h"
16 #include "uio.h"
17 #include "kernel.h"
18 #include "stat.h"
19 #include "malloc.h"
20 #ifdef KTRACE
21 #include "ktrace.h"
22 #endif
23 
24 /*
25  * Read system call.
26  */
27 read(p, uap, retval)
28 	struct proc *p;
29 	register struct args {
30 		int	fdes;
31 		char	*cbuf;
32 		unsigned count;
33 	} *uap;
34 	int *retval;
35 {
36 	register struct file *fp;
37 	struct uio auio;
38 	struct iovec aiov;
39 	long cnt, error = 0;
40 #ifdef KTRACE
41 	struct iovec ktriov;
42 #endif
43 
44 	if (((unsigned)uap->fdes) >= NOFILE ||
45 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
46 	    (fp->f_flag & FREAD) == 0)
47 		return (EBADF);
48 	aiov.iov_base = (caddr_t)uap->cbuf;
49 	aiov.iov_len = uap->count;
50 	auio.uio_iov = &aiov;
51 	auio.uio_iovcnt = 1;
52 	auio.uio_resid = uap->count;
53 	auio.uio_rw = UIO_READ;
54 	auio.uio_segflg = UIO_USERSPACE;
55 #ifdef KTRACE
56 	/*
57 	 * if tracing, save a copy of iovec
58 	 */
59 	if (KTRPOINT(p, KTR_GENIO))
60 		ktriov = aiov;
61 #endif
62 	cnt = uap->count;
63 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
64 		if (auio.uio_resid != cnt && (error == ERESTART ||
65 		    error == EINTR || error == EWOULDBLOCK))
66 			error = 0;
67 	cnt -= auio.uio_resid;
68 #ifdef KTRACE
69 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
70 		ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
71 #endif
72 	*retval = cnt;
73 	return (error);
74 }
75 
76 /*
77  * Scatter read system call.
78  */
79 readv(p, uap, retval)
80 	struct proc *p;
81 	register struct args {
82 		int	fdes;
83 		struct	iovec *iovp;
84 		unsigned iovcnt;
85 	} *uap;
86 	int *retval;
87 {
88 	register struct file *fp;
89 	struct uio auio;
90 	register struct iovec *iov;
91 	struct iovec aiov[UIO_SMALLIOV];
92 	long i, cnt, error = 0;
93 #ifdef KTRACE
94 	struct iovec *ktriov = NULL;
95 #endif
96 
97 	if (((unsigned)uap->fdes) >= NOFILE ||
98 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
99 	    (fp->f_flag & FREAD) == 0)
100 		return (EBADF);
101 	if (uap->iovcnt > UIO_SMALLIOV) {
102 		if (uap->iovcnt > UIO_MAXIOV)
103 			return (EINVAL);
104 		MALLOC(iov, struct iovec *,
105 		      sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
106 	} else
107 		iov = aiov;
108 	auio.uio_iov = iov;
109 	auio.uio_iovcnt = uap->iovcnt;
110 	auio.uio_rw = UIO_READ;
111 	auio.uio_segflg = UIO_USERSPACE;
112 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
113 	    uap->iovcnt * sizeof (struct iovec)))
114 		goto done;
115 	auio.uio_resid = 0;
116 	for (i = 0; i < uap->iovcnt; i++) {
117 		if (iov->iov_len < 0) {
118 			error = EINVAL;
119 			goto done;
120 		}
121 		auio.uio_resid += iov->iov_len;
122 		if (auio.uio_resid < 0) {
123 			error = EINVAL;
124 			goto done;
125 		}
126 		iov++;
127 	}
128 #ifdef KTRACE
129 	/*
130 	 * if tracing, save a copy of iovec
131 	 */
132 	if (KTRPOINT(p, KTR_GENIO))  {
133 		unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec);
134 
135 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
136 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
137 	}
138 #endif
139 	cnt = auio.uio_resid;
140 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
141 		if (auio.uio_resid != cnt && (error == ERESTART ||
142 		    error == EINTR || error == EWOULDBLOCK))
143 			error = 0;
144 	cnt -= auio.uio_resid;
145 #ifdef KTRACE
146 	if (ktriov != NULL) {
147 		if (error == 0)
148 			ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
149 			    cnt, error);
150 		FREE(ktriov, M_TEMP);
151 	}
152 #endif
153 	*retval = cnt;
154 done:
155 	if (uap->iovcnt > UIO_SMALLIOV)
156 		FREE(iov, M_IOV);
157 	return (error);
158 }
159 
160 /*
161  * Write system call
162  */
163 write(p, uap, retval)
164 	struct proc *p;
165 	register struct args {
166 		int	fdes;
167 		char	*cbuf;
168 		unsigned count;
169 	} *uap;
170 	int *retval;
171 {
172 	register struct file *fp;
173 	struct uio auio;
174 	struct iovec aiov;
175 	long cnt, error = 0;
176 #ifdef KTRACE
177 	struct iovec ktriov;
178 #endif
179 
180 	if (((unsigned)uap->fdes) >= NOFILE ||
181 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
182 	    (fp->f_flag & FWRITE) == 0)
183 		return (EBADF);
184 	aiov.iov_base = (caddr_t)uap->cbuf;
185 	aiov.iov_len = uap->count;
186 	auio.uio_iov = &aiov;
187 	auio.uio_iovcnt = 1;
188 	auio.uio_resid = uap->count;
189 	auio.uio_rw = UIO_WRITE;
190 	auio.uio_segflg = UIO_USERSPACE;
191 #ifdef KTRACE
192 	/*
193 	 * if tracing, save a copy of iovec
194 	 */
195 	if (KTRPOINT(p, KTR_GENIO))
196 		ktriov = aiov;
197 #endif
198 	cnt = uap->count;
199 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
200 		if (auio.uio_resid != cnt && (error == ERESTART ||
201 		    error == EINTR || error == EWOULDBLOCK))
202 			error = 0;
203 		if (error == EPIPE)
204 			psignal(p, SIGPIPE);
205 	}
206 	cnt -= auio.uio_resid;
207 #ifdef KTRACE
208 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
209 		ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
210 		    &ktriov, cnt, error);
211 #endif
212 	*retval = cnt;
213 	return (error);
214 }
215 
216 /*
217  * Gather write system call
218  */
219 writev(p, uap, retval)
220 	struct proc *p;
221 	register struct args {
222 		int	fdes;
223 		struct	iovec *iovp;
224 		unsigned iovcnt;
225 	} *uap;
226 	int *retval;
227 {
228 	register struct file *fp;
229 	struct uio auio;
230 	register struct iovec *iov;
231 	struct iovec aiov[UIO_SMALLIOV];
232 	long i, cnt, error = 0;
233 #ifdef KTRACE
234 	struct iovec *ktriov = NULL;
235 #endif
236 
237 	if (((unsigned)uap->fdes) >= NOFILE ||
238 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
239 	    (fp->f_flag & FWRITE) == 0)
240 		return (EBADF);
241 	if (uap->iovcnt > UIO_SMALLIOV) {
242 		if (uap->iovcnt > UIO_MAXIOV)
243 			return (EINVAL);
244 		MALLOC(iov, struct iovec *,
245 		      sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
246 	} else
247 		iov = aiov;
248 	auio.uio_iov = iov;
249 	auio.uio_iovcnt = uap->iovcnt;
250 	auio.uio_rw = UIO_WRITE;
251 	auio.uio_segflg = UIO_USERSPACE;
252 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
253 	    uap->iovcnt * sizeof (struct iovec)))
254 		goto done;
255 	auio.uio_resid = 0;
256 	for (i = 0; i < uap->iovcnt; i++) {
257 		if (iov->iov_len < 0) {
258 			error = EINVAL;
259 			goto done;
260 		}
261 		auio.uio_resid += iov->iov_len;
262 		if (auio.uio_resid < 0) {
263 			error = EINVAL;
264 			goto done;
265 		}
266 		iov++;
267 	}
268 #ifdef KTRACE
269 	/*
270 	 * if tracing, save a copy of iovec
271 	 */
272 	if (KTRPOINT(p, KTR_GENIO))  {
273 		unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec);
274 
275 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
276 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
277 	}
278 #endif
279 	cnt = auio.uio_resid;
280 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
281 		if (auio.uio_resid != cnt && (error == ERESTART ||
282 		    error == EINTR || error == EWOULDBLOCK))
283 			error = 0;
284 		if (error == EPIPE)
285 			psignal(p, SIGPIPE);
286 	}
287 	cnt -= auio.uio_resid;
288 #ifdef KTRACE
289 	if (ktriov != NULL) {
290 		if (error == 0)
291 			ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
292 				ktriov, cnt, error);
293 		FREE(ktriov, M_TEMP);
294 	}
295 #endif
296 	*retval = cnt;
297 done:
298 	if (uap->iovcnt > UIO_SMALLIOV)
299 		FREE(iov, M_IOV);
300 	return (error);
301 }
302 
303 /*
304  * Ioctl system call
305  */
306 /* ARGSUSED */
307 ioctl(p, uap, retval)
308 	struct proc *p;
309 	register struct args {
310 		int	fdes;
311 		int	cmd;
312 		caddr_t	cmarg;
313 	} *uap;
314 	int *retval;
315 {
316 	register struct file *fp;
317 	register int com, error;
318 	register u_int size;
319 	caddr_t memp = 0;
320 #define STK_PARAMS	128
321 	char stkbuf[STK_PARAMS];
322 	caddr_t data = stkbuf;
323 
324 	if ((unsigned)uap->fdes >= NOFILE ||
325 	    (fp = u.u_ofile[uap->fdes]) == NULL)
326 		return (EBADF);
327 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
328 		return (EBADF);
329 	com = uap->cmd;
330 
331 	if (com == FIOCLEX) {
332 		u.u_pofile[uap->fdes] |= UF_EXCLOSE;
333 		return (0);
334 	}
335 	if (com == FIONCLEX) {
336 		u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
337 		return (0);
338 	}
339 
340 	/*
341 	 * Interpret high order word to find
342 	 * amount of data to be copied to/from the
343 	 * user's address space.
344 	 */
345 	size = IOCPARM_LEN(com);
346 	if (size > IOCPARM_MAX)
347 		return (ENOTTY);
348 	if (size > sizeof (stkbuf)) {
349 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
350 		data = memp;
351 	}
352 	if (com&IOC_IN) {
353 		if (size) {
354 			error = copyin(uap->cmarg, data, (u_int)size);
355 			if (error) {
356 				if (memp)
357 					free(memp, M_IOCTLOPS);
358 				return (error);
359 			}
360 		} else
361 			*(caddr_t *)data = uap->cmarg;
362 	} else if ((com&IOC_OUT) && size)
363 		/*
364 		 * Zero the buffer so the user always
365 		 * gets back something deterministic.
366 		 */
367 		bzero(data, size);
368 	else if (com&IOC_VOID)
369 		*(caddr_t *)data = uap->cmarg;
370 
371 	switch (com) {
372 
373 	case FIONBIO:
374 		error = fset(fp, FNDELAY, *(int *)data);
375 		break;
376 
377 	case FIOASYNC:
378 		error = fset(fp, FASYNC, *(int *)data);
379 		break;
380 
381 	case FIOSETOWN:
382 		error = fsetown(fp, *(int *)data);
383 		break;
384 
385 	case FIOGETOWN:
386 		error = fgetown(fp, (int *)data);
387 		break;
388 	default:
389 		error = (*fp->f_ops->fo_ioctl)(fp, com, data);
390 		/*
391 		 * Copy any data to user, size was
392 		 * already set and checked above.
393 		 */
394 		if (error == 0 && (com&IOC_OUT) && size)
395 			error = copyout(data, uap->cmarg, (u_int)size);
396 		break;
397 	}
398 	if (memp)
399 		free(memp, M_IOCTLOPS);
400 	return (error);
401 }
402 
403 int	nselcoll;
404 
405 /*
406  * Select system call.
407  */
408 select(p, uap, retval)
409 	register struct proc *p;
410 	register struct args {
411 		int	nd;
412 		fd_set	*in, *ou, *ex;
413 		struct	timeval *tv;
414 	} *uap;
415 	int *retval;
416 {
417 	fd_set ibits[3], obits[3];
418 	struct timeval atv;
419 	int s, ncoll, ni, error = 0, timo;
420 
421 	bzero((caddr_t)ibits, sizeof(ibits));
422 	bzero((caddr_t)obits, sizeof(obits));
423 	if (uap->nd > NOFILE)
424 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
425 	ni = howmany(uap->nd, NFDBITS);
426 
427 #define	getbits(name, x) \
428 	if (uap->name) { \
429 		error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
430 		    (unsigned)(ni * sizeof(fd_mask))); \
431 		if (error) \
432 			goto done; \
433 	}
434 	getbits(in, 0);
435 	getbits(ou, 1);
436 	getbits(ex, 2);
437 #undef	getbits
438 
439 	if (uap->tv) {
440 		error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
441 			sizeof (atv));
442 		if (error)
443 			goto done;
444 		if (itimerfix(&atv)) {
445 			error = EINVAL;
446 			goto done;
447 		}
448 		s = splhigh(); timevaladd(&atv, &time); splx(s);
449 		timo = hzto(&atv);
450 	} else
451 		timo = 0;
452 retry:
453 	ncoll = nselcoll;
454 	p->p_flag |= SSEL;
455 	error = selscan(ibits, obits, uap->nd, retval);
456 	if (error || *retval)
457 		goto done;
458 	s = splhigh();
459 	/* this should be timercmp(&time, &atv, >=) */
460 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
461 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
462 		splx(s);
463 		goto done;
464 	}
465 	if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
466 		splx(s);
467 		goto retry;
468 	}
469 	p->p_flag &= ~SSEL;
470 	error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
471 	splx(s);
472 	if (error == 0)
473 		goto retry;
474 done:
475 	p->p_flag &= ~SSEL;
476 	/* select is not restarted after signals... */
477 	if (error == ERESTART)
478 		error = EINTR;
479 	if (error == EWOULDBLOCK)
480 		error = 0;
481 #define	putbits(name, x) \
482 	if (uap->name) { \
483 		int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
484 		    (unsigned)(ni * sizeof(fd_mask))); \
485 		if (error2) \
486 			error = error2; \
487 	}
488 	if (error == 0) {
489 		putbits(in, 0);
490 		putbits(ou, 1);
491 		putbits(ex, 2);
492 #undef putbits
493 	}
494 	return (error);
495 }
496 
497 selscan(ibits, obits, nfd, retval)
498 	fd_set *ibits, *obits;
499 	int nfd, *retval;
500 {
501 	register int which, i, j;
502 	register fd_mask bits;
503 	int flag;
504 	struct file *fp;
505 	int error = 0, n = 0;
506 
507 	for (which = 0; which < 3; which++) {
508 		switch (which) {
509 
510 		case 0:
511 			flag = FREAD; break;
512 
513 		case 1:
514 			flag = FWRITE; break;
515 
516 		case 2:
517 			flag = 0; break;
518 		}
519 		for (i = 0; i < nfd; i += NFDBITS) {
520 			bits = ibits[which].fds_bits[i/NFDBITS];
521 			while ((j = ffs(bits)) && i + --j < nfd) {
522 				bits &= ~(1 << j);
523 				fp = u.u_ofile[i + j];
524 				if (fp == NULL) {
525 					error = EBADF;
526 					break;
527 				}
528 				if ((*fp->f_ops->fo_select)(fp, flag)) {
529 					FD_SET(i + j, &obits[which]);
530 					n++;
531 				}
532 			}
533 		}
534 	}
535 	*retval = n;
536 	return (error);
537 }
538 
539 /*ARGSUSED*/
540 seltrue(dev, flag)
541 	dev_t dev;
542 	int flag;
543 {
544 
545 	return (1);
546 }
547 
548 selwakeup(p, coll)
549 	register struct proc *p;
550 	int coll;
551 {
552 
553 	if (coll) {
554 		nselcoll++;
555 		wakeup((caddr_t)&selwait);
556 	}
557 	if (p) {
558 		int s = splhigh();
559 		if (p->p_wchan == (caddr_t)&selwait) {
560 			if (p->p_stat == SSLEEP)
561 				setrun(p);
562 			else
563 				unsleep(p);
564 		} else if (p->p_flag & SSEL)
565 			p->p_flag &= ~SSEL;
566 		splx(s);
567 	}
568 }
569