xref: /original-bsd/sys/kern/sys_generic.c (revision 62734ea8)
1 /*	sys_generic.c	5.22	82/11/13	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/dir.h"
6 #include "../h/user.h"
7 #include "../h/tty.h"
8 #include "../h/file.h"
9 #define	IDEBUG
10 #include "../h/inode.h"
11 #include "../h/buf.h"
12 #include "../h/proc.h"
13 #include "../h/conf.h"
14 #include "../h/socket.h"
15 #include "../h/socketvar.h"
16 #include "../h/fs.h"
17 #ifdef MUSH
18 #include "../h/quota.h"
19 #include "../h/share.h"
20 #else
21 #define	CHARGE(nothing)
22 #endif
23 #include "../h/descrip.h"
24 #include "../h/uio.h"
25 #include "../h/cmap.h"
26 
27 /*
28  * Read system call.
29  */
30 read()
31 {
32 	register struct a {
33 		int	fdes;
34 		char	*cbuf;
35 		unsigned count;
36 	} *uap = (struct a *)u.u_ap;
37 	struct uio auio;
38 	struct iovec aiov;
39 
40 	aiov.iov_base = (caddr_t)uap->cbuf;
41 	aiov.iov_len = uap->count;
42 	auio.uio_iov = &aiov;
43 	auio.uio_iovcnt = 1;
44 	rwuio(&auio, UIO_READ);
45 }
46 
47 readv()
48 {
49 	register struct a {
50 		int	fdes;
51 		struct	iovec *iovp;
52 		int	iovcnt;
53 	} *uap = (struct a *)u.u_ap;
54 	struct uio auio;
55 	struct iovec aiov[16];		/* XXX */
56 
57 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
58 		u.u_error = EINVAL;
59 		return;
60 	}
61 	auio.uio_iov = aiov;
62 	auio.uio_iovcnt = uap->iovcnt;
63 	if (copyin((caddr_t)uap->iovp, (caddr_t)aiov,
64 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)))) {
65 		u.u_error = EFAULT;
66 		return;
67 	}
68 	rwuio(&auio, UIO_READ);
69 }
70 
71 /*
72  * Write system call
73  */
74 write()
75 {
76 	register struct a {
77 		int	fdes;
78 		char	*cbuf;
79 		int	count;
80 	} *uap = (struct a *)u.u_ap;
81 	struct uio auio;
82 	struct iovec aiov;
83 
84 	auio.uio_iov = &aiov;
85 	auio.uio_iovcnt = 1;
86 	aiov.iov_base = uap->cbuf;
87 	aiov.iov_len = uap->count;
88 	rwuio(&auio, UIO_WRITE);
89 }
90 
91 writev()
92 {
93 	register struct a {
94 		int	fdes;
95 		struct	iovec *iovp;
96 		int	iovcnt;
97 	} *uap = (struct a *)u.u_ap;
98 	struct uio auio;
99 	struct iovec aiov[16];		/* XXX */
100 
101 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
102 		u.u_error = EINVAL;
103 		return;
104 	}
105 	auio.uio_iov = aiov;
106 	auio.uio_iovcnt = uap->iovcnt;
107 	if (copyin((caddr_t)uap->iovp, (caddr_t)aiov,
108 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)))) {
109 		u.u_error = EFAULT;
110 		return;
111 	}
112 	rwuio(&auio, UIO_WRITE);
113 }
114 
115 rwuio(uio, rw)
116 	register struct uio *uio;
117 	enum uio_rw rw;
118 {
119 	struct a {
120 		int	fdes;
121 	};
122 	register struct file *fp;
123 	register struct iovec *iov;
124 	register struct inode *ip;
125 	int i, count;
126 
127 	GETF(fp, ((struct a *)u.u_ap)->fdes);
128 	if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
129 		u.u_error = EBADF;
130 		return;
131 	}
132 	uio->uio_resid = 0;
133 	uio->uio_segflg = 0;
134 	iov = uio->uio_iov;
135 	for (i = 0; i < uio->uio_iovcnt; i++) {
136 		if (iov->iov_len < 0) {
137 			u.u_error = EINVAL;
138 			return;
139 		}
140 		uio->uio_resid += iov->iov_len;
141 		if (uio->uio_resid < 0) {
142 			u.u_error = EINVAL;
143 			return;
144 		}
145 	}
146 	count = uio->uio_resid;
147 	if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) {
148 		if (uio->uio_resid == count)
149 			u.u_eosys = RESTARTSYS;
150 	} else if (fp->f_type == DTYPE_SOCKET) {
151 		int sosend(), soreceive();
152 		u.u_error =
153 		    (*(rw==UIO_READ?soreceive:sosend))
154 		      (fp->f_socket, (struct sockaddr *)0, uio, 0);
155 	} else {
156 		ip = fp->f_inode;
157 		uio->uio_offset = fp->f_offset;
158 		if ((ip->i_mode&IFMT) == IFREG) {
159 			ILOCK(ip);
160 			u.u_error = rwip(ip, uio, rw);
161 			IUNLOCK(ip);
162 		} else
163 			u.u_error = rwip(ip, uio, rw);
164 		fp->f_offset += count - uio->uio_resid;
165 	}
166 	u.u_r.r_val1 = count - uio->uio_resid;
167 }
168 
169 rdwri(rw, ip, base, len, offset, segflg, aresid)
170 	struct inode *ip;
171 	caddr_t base;
172 	int len, offset, segflg;
173 	int *aresid;
174 	enum uio_rw rw;
175 {
176 	struct uio auio;
177 	struct iovec aiov;
178 	int error;
179 
180 	auio.uio_iov = &aiov;
181 	auio.uio_iovcnt = 1;
182 	aiov.iov_base = base;
183 	aiov.iov_len = len;
184 	auio.uio_resid = len;
185 	auio.uio_offset = offset;
186 	auio.uio_segflg = segflg;
187 	error = rwip(ip, &auio, rw);
188 	if (aresid)
189 		*aresid = auio.uio_resid;
190 	else
191 		if (auio.uio_resid)
192 			error = EIO;
193 	return (error);
194 }
195 
196 rwip(ip, uio, rw)
197 	register struct inode *ip;
198 	register struct uio *uio;
199 	enum uio_rw rw;
200 {
201 	dev_t dev = (dev_t)ip->i_rdev;
202 	struct buf *bp;
203 	struct fs *fs;
204 	daddr_t lbn, bn;
205 	register int n, on, type;
206 	int size;
207 	long bsize;
208 	extern int mem_no;
209 	int error = 0;
210 
211 	if (rw != UIO_READ && rw != UIO_WRITE)
212 		panic("rwip");
213 	if (uio->uio_offset < 0 &&
214 	    ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev)))
215 		return (EINVAL);
216 	if (rw == UIO_READ)
217 		ip->i_flag |= IACC;
218 	type = ip->i_mode&IFMT;
219 	if (type == IFCHR) {
220 #ifdef QUOTA
221 		register c = uio->uio_resid;
222 #endif
223 		if (rw == UIO_READ)
224 			u.u_error = (*cdevsw[major(dev)].d_read)(dev, uio);
225 		else {
226 			ip->i_flag |= IUPD|ICHG;
227 			u.u_error = (*cdevsw[major(dev)].d_write)(dev, uio);
228 		}
229 		CHARGE(sc_tio * (c - uio->uio_resid));
230 		return (u.u_error);
231 	}
232 	if (uio->uio_resid == 0)
233 		return;
234 	if (rw == UIO_WRITE && type == IFREG &&
235 	    uio->uio_offset + uio->uio_resid >
236 	      u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
237 		psignal(u.u_procp, SIGXFSZ);
238 		return (EMFILE);
239 	}
240 	if (type != IFBLK) {
241 		dev = ip->i_dev;
242 		fs = ip->i_fs;
243 		bsize = fs->fs_bsize;
244 	} else
245 		bsize = BLKDEV_IOSIZE;
246 	do {
247 		lbn = uio->uio_offset / bsize;
248 		on = uio->uio_offset % bsize;
249 		n = MIN((unsigned)(bsize - on), uio->uio_resid);
250 		if (type != IFBLK) {
251 			if (rw == UIO_READ) {
252 				int diff = ip->i_size - uio->uio_offset;
253 				if (diff <= 0)
254 					return (0);
255 				if (diff < n)
256 					n = diff;
257 			}
258 			bn = fsbtodb(fs,
259 			    bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n)));
260 			if (u.u_error || rw == UIO_WRITE && (long)bn<0)
261 				return (u.u_error);
262 			if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size &&
263 			   (type == IFDIR || type == IFREG || type == IFLNK))
264 				ip->i_size = uio->uio_offset + n;
265 			size = blksize(fs, ip, lbn);
266 		} else {
267 			bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE);
268 			rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE);
269 			rasize = size = bsize;
270 		}
271 		if (rw == UIO_READ) {
272 			if ((long)bn<0) {
273 				bp = geteblk(size);
274 				clrbuf(bp);
275 			} else if (ip->i_lastr + 1 == lbn)
276 				bp = breada(dev, bn, size, rablock, rasize);
277 			else
278 				bp = bread(dev, bn, size);
279 			ip->i_lastr = lbn;
280 		} else {
281 			int i, count;
282 			extern struct cmap *mfind();
283 
284 			count = howmany(size, DEV_BSIZE);
285 			for (i = 0; i < count; i += CLSIZE)
286 				if (mfind(dev, bn + i))
287 					munhash(dev, bn + i);
288 			if (n == bsize)
289 				bp = getblk(dev, bn, size);
290 			else
291 				bp = bread(dev, bn, size);
292 		}
293 		n = MIN(n, size - bp->b_resid);
294 		if (bp->b_flags & B_ERROR) {
295 			error = EIO;
296 			brelse(bp);
297 			goto bad;
298 		}
299 		u.u_error =
300 		    uiomove(bp->b_un.b_addr+on, n, rw, uio);
301 		if (rw == UIO_READ) {
302 			if (n + on == bsize || uio->uio_offset == ip->i_size)
303 				bp->b_flags |= B_AGE;
304 			brelse(bp);
305 		} else {
306 			if ((ip->i_mode&IFMT) == IFDIR)
307 				bwrite(bp);
308 			else if (n + on == bsize) {
309 				bp->b_flags |= B_AGE;
310 				bawrite(bp);
311 			} else
312 				bdwrite(bp);
313 			ip->i_flag |= IUPD|ICHG;
314 			if (u.u_ruid != 0)
315 				ip->i_mode &= ~(ISUID|ISGID);
316 		}
317 	} while (u.u_error == 0 && uio->uio_resid > 0 && n != 0);
318 bad:
319 	return (error);
320 }
321 
322 uiomove(cp, n, rw, uio)
323 	register caddr_t cp;
324 	register int n;
325 	enum uio_rw rw;
326 	register struct uio *uio;
327 {
328 	register struct iovec *iov;
329 	int error;
330 	u_int cnt;
331 
332 	while (n > 0 && uio->uio_resid) {
333 		iov = uio->uio_iov;
334 		cnt = iov->iov_len;
335 		if (cnt == 0) {
336 			uio->uio_iov++;
337 			uio->uio_iovcnt--;
338 			continue;
339 		}
340 		if (cnt > n)
341 			cnt = n;
342 		switch (uio->uio_segflg) {
343 
344 		case 0:
345 		case 2:
346 			if (rw == UIO_READ)
347 				error = copyout(cp, iov->iov_base, cnt);
348 			else
349 				error = copyin(iov->iov_base, cp, cnt);
350 			if (error)
351 				return (error);
352 			break;
353 
354 		case 1:
355 			if (rw == UIO_READ)
356 				bcopy((caddr_t)cp, iov->iov_base, cnt);
357 			else
358 				bcopy(iov->iov_base, (caddr_t)cp, cnt);
359 			break;
360 		}
361 		iov->iov_base += cnt;
362 		iov->iov_len -= cnt;
363 		uio->uio_resid -= cnt;
364 		uio->uio_offset += cnt;
365 		cp += cnt;
366 		n -= cnt;
367 	}
368 	return (error);
369 }
370 
371 /*
372  * Give next character to user as result of read.
373  */
374 ureadc(c, uio)
375 	register int c;
376 	register struct uio *uio;
377 {
378 	register struct iovec *iov;
379 
380 again:
381 	if (uio->uio_iovcnt == 0)
382 		panic("ureadc");
383 	iov = uio->uio_iov;
384 	if (iov->iov_len <= 0 || uio->uio_resid <= 0) {
385 		uio->uio_iovcnt--;
386 		uio->uio_iov++;
387 		goto again;
388 	}
389 	switch (uio->uio_segflg) {
390 
391 	case 0:
392 		if (subyte(iov->iov_base, c) < 0)
393 			return (EFAULT);
394 		break;
395 
396 	case 1:
397 		*iov->iov_base = c;
398 		break;
399 
400 	case 2:
401 		if (suibyte(iov->iov_base, c) < 0)
402 			return (EFAULT);
403 		break;
404 	}
405 	iov->iov_base++;
406 	iov->iov_len--;
407 	uio->uio_resid--;
408 	uio->uio_offset++;
409 	return (0);
410 }
411 
412 #ifdef notdef
413 /*
414  * Get next character written in by user from uio.
415  */
416 uwritec(uio)
417 	struct uio *uio;
418 {
419 	register struct iovec *iov;
420 	register int c;
421 
422 again:
423 	if (uio->uio_iovcnt <= 0 || uio->uio_resid <= 0)
424 		panic("uwritec");
425 	iov = uio->uio_iov;
426 	if (iov->iov_len == 0) {
427 		uio->uio_iovcnt--;
428 		uio->uio_iov++;
429 		goto again;
430 	}
431 	switch (uio->uio_segflg) {
432 
433 	case 0:
434 		c = fubyte(iov->iov_base);
435 		break;
436 
437 	case 1:
438 		c = *iov->iov_base & 0377;
439 		break;
440 
441 	case 2:
442 		c = fuibyte(iov->iov_base);
443 		break;
444 	}
445 	if (c < 0)
446 		return (-1);
447 	iov->iov_base++;
448 	iov->iov_len--;
449 	uio->uio_resid--;
450 	uio->uio_offset++;
451 	return (c & 0377);
452 }
453 #endif
454 
455 /*
456  * Ioctl system call
457  * Check legality, execute common code,
458  * and switch out to individual device routine.
459  */
460 ioctl()
461 {
462 	register struct file *fp;
463 	struct a {
464 		int	fdes;
465 		int	cmd;
466 		caddr_t	cmarg;
467 	} *uap;
468 	register int com;
469 	register u_int size;
470 	char data[IOCPARM_MASK+1];
471 
472 	uap = (struct a *)u.u_ap;
473 	if ((fp = getf(uap->fdes)) == NULL)
474 		return;
475 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
476 		u.u_error = EBADF;
477 		return;
478 	}
479 	com = uap->cmd;
480 
481 #ifndef NOCOMPAT
482 	/*
483 	 * Map old style ioctl's into new for the
484 	 * sake of backwards compatibility (sigh).
485 	 */
486 	if ((com&~0xffff) == 0) {
487 		com = mapioctl(com);
488 		if (com == 0) {
489 			u.u_error = EINVAL;
490 			return;
491 		}
492 	}
493 #endif
494 	if (com == FIOCLEX) {
495 		u.u_pofile[uap->fdes] |= EXCLOSE;
496 		return;
497 	}
498 	if (com == FIONCLEX) {
499 		u.u_pofile[uap->fdes] &= ~EXCLOSE;
500 		return;
501 	}
502 
503 	/*
504 	 * Interpret high order word to find
505 	 * amount of data to be copied to/from the
506 	 * user's address space.
507 	 */
508 	size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
509 	if (size > sizeof (data)) {
510 		u.u_error = EFAULT;
511 		return;
512 	}
513 	if (com&IOC_IN && size) {
514 		if (copyin(uap->cmarg, (caddr_t)data, (u_int)size)) {
515 			u.u_error = EFAULT;
516 			return;
517 		}
518 	} else
519 		*(caddr_t *)data = uap->cmarg;
520 	/*
521 	 * Zero the buffer on the stack so the user
522 	 * always gets back something deterministic.
523 	 */
524 	if ((com&IOC_OUT) && size)
525 		bzero((caddr_t)data, size);
526 
527 	if (fp->f_type == DTYPE_SOCKET)
528 		u.u_error = soioctl(fp->f_socket, com, data);
529 	else {
530 		register struct inode *ip = fp->f_inode;
531 		int fmt = ip->i_mode & IFMT;
532 		dev_t dev;
533 
534 		if (fmt != IFCHR) {
535 			if (com == FIONREAD && (fmt == IFREG || fmt == IFDIR)) {
536 				*(off_t *)data = ip->i_size - fp->f_offset;
537 				goto returndata;
538 			}
539 			if (com != FIONBIO && com != FIOASYNC)
540 				u.u_error = ENOTTY;
541 			return;
542 		}
543 		dev = ip->i_rdev;
544 		u.u_r.r_val1 = 0;
545 		if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) {
546 			u.u_eosys = RESTARTSYS;
547 			return;
548 		}
549 		u.u_error = (*cdevsw[major(dev)].d_ioctl)(dev, com, data, 0);
550 	}
551 
552 returndata:
553 	/*
554 	 * Copy any data to user, size was
555 	 * already set and checked above.
556 	 */
557 	if (u.u_error == 0 && (com&IOC_OUT))
558 		if (size && copyout(data, uap->cmarg, (u_int)size))
559 			u.u_error = EFAULT;
560 }
561 
562 /*
563  * Do nothing specific version of line
564  * discipline specific ioctl command.
565  */
566 /*ARGSUSED*/
567 nullioctl(tp, cmd, data, flags)
568 	struct tty *tp;
569 	char *data;
570 	int flags;
571 {
572 
573 #ifdef lint
574 	tp = tp; data = data; flags = flags;
575 #endif
576 	return (-1);
577 }
578 
579 ostty()
580 {
581 
582 }
583 
584 ogtty()
585 {
586 
587 }
588