Annotation of src/sys/kern/sys_descrip.c, Revision 1.7.2.1
1.7.2.1 ! skrll 1: /* $NetBSD: sys_descrip.c,v 1.9 2009/01/11 02:45:52 christos Exp $ */
1.1 ad 2:
3: /*-
4: * Copyright (c) 2008 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26: * POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29: /*
30: * Copyright (c) 1982, 1986, 1989, 1991, 1993
31: * The Regents of the University of California. All rights reserved.
32: * (c) UNIX System Laboratories, Inc.
33: * All or some portions of this file are derived from material licensed
34: * to the University of California by American Telephone and Telegraph
35: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
36: * the permission of UNIX System Laboratories, Inc.
37: *
38: * Redistribution and use in source and binary forms, with or without
39: * modification, are permitted provided that the following conditions
40: * are met:
41: * 1. Redistributions of source code must retain the above copyright
42: * notice, this list of conditions and the following disclaimer.
43: * 2. Redistributions in binary form must reproduce the above copyright
44: * notice, this list of conditions and the following disclaimer in the
45: * documentation and/or other materials provided with the distribution.
46: * 3. Neither the name of the University nor the names of its contributors
47: * may be used to endorse or promote products derived from this software
48: * without specific prior written permission.
49: *
50: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60: * SUCH DAMAGE.
61: *
62: * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
63: */
64:
65: /*
66: * System calls on descriptors.
67: */
68:
69: #include <sys/cdefs.h>
1.7.2.1 ! skrll 70: __KERNEL_RCSID(0, "$NetBSD: sys_descrip.c,v 1.9 2009/01/11 02:45:52 christos Exp $");
1.1 ad 71:
72: #include <sys/param.h>
73: #include <sys/systm.h>
74: #include <sys/filedesc.h>
75: #include <sys/kernel.h>
76: #include <sys/vnode.h>
77: #include <sys/proc.h>
78: #include <sys/file.h>
79: #include <sys/namei.h>
80: #include <sys/socket.h>
81: #include <sys/socketvar.h>
82: #include <sys/stat.h>
83: #include <sys/ioctl.h>
84: #include <sys/fcntl.h>
85: #include <sys/malloc.h>
86: #include <sys/pool.h>
87: #include <sys/syslog.h>
88: #include <sys/unistd.h>
89: #include <sys/resourcevar.h>
90: #include <sys/conf.h>
91: #include <sys/event.h>
92: #include <sys/kauth.h>
93: #include <sys/atomic.h>
94: #include <sys/mount.h>
95: #include <sys/syscallargs.h>
96:
97: /*
98: * Duplicate a file descriptor.
99: */
100: int
101: sys_dup(struct lwp *l, const struct sys_dup_args *uap, register_t *retval)
102: {
103: /* {
104: syscallarg(int) fd;
105: } */
106: int new, error, old;
107: file_t *fp;
108:
109: old = SCARG(uap, fd);
110:
111: if ((fp = fd_getfile(old)) == NULL) {
112: return EBADF;
113: }
1.5 matt 114: error = fd_dup(fp, 0, &new, false);
1.1 ad 115: fd_putfile(old);
116: *retval = new;
117: return error;
118: }
119:
120: /*
121: * Duplicate a file descriptor to a particular value.
122: */
123: int
124: sys_dup2(struct lwp *l, const struct sys_dup2_args *uap, register_t *retval)
125: {
126: /* {
127: syscallarg(int) from;
128: syscallarg(int) to;
129: } */
130: int old, new, error;
131: file_t *fp;
132:
133: old = SCARG(uap, from);
134: new = SCARG(uap, to);
135:
136: if ((fp = fd_getfile(old)) == NULL) {
137: return EBADF;
138: }
1.7.2.1 ! skrll 139: mutex_enter(&fp->f_lock);
! 140: fp->f_count++;
! 141: mutex_exit(&fp->f_lock);
! 142: fd_putfile(old);
! 143:
1.1 ad 144: if ((u_int)new >= curproc->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
145: (u_int)new >= maxfiles) {
146: error = EBADF;
147: } else if (old == new) {
148: error = 0;
149: } else {
150: error = fd_dup2(fp, new);
151: }
1.7.2.1 ! skrll 152: closef(fp);
1.1 ad 153: *retval = new;
154:
1.6 njoly 155: return error;
1.1 ad 156: }
157:
158: /*
159: * fcntl call which is being passed to the file's fs.
160: */
161: static int
162: fcntl_forfs(int fd, file_t *fp, int cmd, void *arg)
163: {
164: int error;
165: u_int size;
166: void *data, *memp;
167: #define STK_PARAMS 128
168: char stkbuf[STK_PARAMS];
169:
170: if ((fp->f_flag & (FREAD | FWRITE)) == 0)
171: return (EBADF);
172:
173: /*
174: * Interpret high order word to find amount of data to be
175: * copied to/from the user's address space.
176: */
177: size = (size_t)F_PARAM_LEN(cmd);
178: if (size > F_PARAM_MAX)
179: return (EINVAL);
180: memp = NULL;
181: if (size > sizeof(stkbuf)) {
182: memp = kmem_alloc(size, KM_SLEEP);
183: data = memp;
184: } else
185: data = stkbuf;
186: if (cmd & F_FSIN) {
187: if (size) {
188: error = copyin(arg, data, size);
189: if (error) {
190: if (memp)
191: kmem_free(memp, size);
192: return (error);
193: }
194: } else
195: *(void **)data = arg;
196: } else if ((cmd & F_FSOUT) != 0 && size != 0) {
197: /*
198: * Zero the buffer so the user always
199: * gets back something deterministic.
200: */
201: memset(data, 0, size);
202: } else if (cmd & F_FSVOID)
203: *(void **)data = arg;
204:
205:
206: error = (*fp->f_ops->fo_fcntl)(fp, cmd, data);
207:
208: /*
209: * Copy any data to user, size was
210: * already set and checked above.
211: */
212: if (error == 0 && (cmd & F_FSOUT) && size)
213: error = copyout(data, arg, size);
214: if (memp)
215: kmem_free(memp, size);
216: return (error);
217: }
218:
219: int
220: do_fcntl_lock(int fd, int cmd, struct flock *fl)
221: {
222: file_t *fp;
223: vnode_t *vp;
224: proc_t *p;
225: int error, flg;
226:
227: if ((fp = fd_getfile(fd)) == NULL)
228: return EBADF;
229: if (fp->f_type != DTYPE_VNODE) {
230: fd_putfile(fd);
231: return EINVAL;
232: }
233: vp = fp->f_data;
234: if (fl->l_whence == SEEK_CUR)
235: fl->l_start += fp->f_offset;
236:
237: flg = F_POSIX;
238: p = curproc;
239:
240: switch (cmd) {
241: case F_SETLKW:
242: flg |= F_WAIT;
243: /* Fall into F_SETLK */
244:
245: case F_SETLK:
246: switch (fl->l_type) {
247: case F_RDLCK:
248: if ((fp->f_flag & FREAD) == 0) {
249: error = EBADF;
250: break;
251: }
252: if ((p->p_flag & PK_ADVLOCK) == 0) {
1.2 ad 253: mutex_enter(p->p_lock);
1.1 ad 254: p->p_flag |= PK_ADVLOCK;
1.2 ad 255: mutex_exit(p->p_lock);
1.1 ad 256: }
257: error = VOP_ADVLOCK(vp, p, F_SETLK, fl, flg);
258: break;
259:
260: case F_WRLCK:
261: if ((fp->f_flag & FWRITE) == 0) {
262: error = EBADF;
263: break;
264: }
265: if ((p->p_flag & PK_ADVLOCK) == 0) {
1.2 ad 266: mutex_enter(p->p_lock);
1.1 ad 267: p->p_flag |= PK_ADVLOCK;
1.2 ad 268: mutex_exit(p->p_lock);
1.1 ad 269: }
270: error = VOP_ADVLOCK(vp, p, F_SETLK, fl, flg);
271: break;
272:
273: case F_UNLCK:
274: error = VOP_ADVLOCK(vp, p, F_UNLCK, fl, F_POSIX);
275: break;
276:
277: default:
278: error = EINVAL;
279: break;
280: }
281: break;
282:
283: case F_GETLK:
284: if (fl->l_type != F_RDLCK &&
285: fl->l_type != F_WRLCK &&
286: fl->l_type != F_UNLCK) {
287: error = EINVAL;
288: break;
289: }
290: error = VOP_ADVLOCK(vp, p, F_GETLK, fl, F_POSIX);
291: break;
292:
293: default:
294: error = EINVAL;
295: break;
296: }
297:
298: fd_putfile(fd);
299: return error;
300: }
301:
302: /*
303: * The file control system call.
304: */
305: int
306: sys_fcntl(struct lwp *l, const struct sys_fcntl_args *uap, register_t *retval)
307: {
308: /* {
309: syscallarg(int) fd;
310: syscallarg(int) cmd;
311: syscallarg(void *) arg;
312: } */
313: int fd, i, tmp, error, cmd, newmin;
314: filedesc_t *fdp;
315: file_t *fp;
316: fdfile_t *ff;
317: struct flock fl;
318:
319: fd = SCARG(uap, fd);
320: cmd = SCARG(uap, cmd);
1.4 ad 321: fdp = l->l_fd;
1.1 ad 322: error = 0;
323:
324: switch (cmd) {
325: case F_CLOSEM:
326: if (fd < 0)
327: return EBADF;
328: while ((i = fdp->fd_lastfile) >= fd) {
329: if (fd_getfile(i) == NULL) {
330: /* Another thread has updated. */
331: continue;
332: }
333: fd_close(i);
334: }
335: return 0;
336:
337: case F_MAXFD:
338: *retval = fdp->fd_lastfile;
339: return 0;
340:
341: case F_SETLKW:
342: case F_SETLK:
343: case F_GETLK:
344: error = copyin(SCARG(uap, arg), &fl, sizeof(fl));
345: if (error)
346: return error;
347: error = do_fcntl_lock(fd, cmd, &fl);
348: if (cmd == F_GETLK && error == 0)
349: error = copyout(&fl, SCARG(uap, arg), sizeof(fl));
350: return error;
351:
352: default:
353: /* Handled below */
354: break;
355: }
356:
357: if ((fp = fd_getfile(fd)) == NULL)
358: return (EBADF);
359: ff = fdp->fd_ofiles[fd];
360:
361: if ((cmd & F_FSCTL)) {
362: error = fcntl_forfs(fd, fp, cmd, SCARG(uap, arg));
363: fd_putfile(fd);
364: return error;
365: }
366:
367: switch (cmd) {
368: case F_DUPFD:
369: newmin = (long)SCARG(uap, arg);
1.4 ad 370: if ((u_int)newmin >=
371: l->l_proc->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
1.1 ad 372: (u_int)newmin >= maxfiles) {
373: fd_putfile(fd);
374: return EINVAL;
375: }
1.5 matt 376: error = fd_dup(fp, newmin, &i, false);
1.1 ad 377: *retval = i;
378: break;
379:
380: case F_GETFD:
381: *retval = ff->ff_exclose;
382: break;
383:
384: case F_SETFD:
385: if ((long)SCARG(uap, arg) & 1) {
1.5 matt 386: ff->ff_exclose = true;
387: fdp->fd_exclose = true;
1.1 ad 388: } else {
1.5 matt 389: ff->ff_exclose = false;
1.1 ad 390: }
391: break;
392:
393: case F_GETFL:
394: *retval = OFLAGS(fp->f_flag);
395: break;
396:
397: case F_SETFL:
398: /* XXX not guaranteed to be atomic. */
399: tmp = FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
400: error = (*fp->f_ops->fo_fcntl)(fp, F_SETFL, &tmp);
401: if (error)
402: break;
403: i = tmp ^ fp->f_flag;
404: if (i & FNONBLOCK) {
405: int flgs = tmp & FNONBLOCK;
406: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, &flgs);
407: if (error) {
408: (*fp->f_ops->fo_fcntl)(fp, F_SETFL,
409: &fp->f_flag);
410: break;
411: }
412: }
413: if (i & FASYNC) {
414: int flgs = tmp & FASYNC;
415: error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, &flgs);
416: if (error) {
417: if (i & FNONBLOCK) {
418: tmp = fp->f_flag & FNONBLOCK;
419: (void)(*fp->f_ops->fo_ioctl)(fp,
420: FIONBIO, &tmp);
421: }
422: (*fp->f_ops->fo_fcntl)(fp, F_SETFL,
423: &fp->f_flag);
424: break;
425: }
426: }
427: fp->f_flag = (fp->f_flag & ~FCNTLFLAGS) | tmp;
428: break;
429:
430: case F_GETOWN:
431: error = (*fp->f_ops->fo_ioctl)(fp, FIOGETOWN, &tmp);
432: *retval = tmp;
433: break;
434:
435: case F_SETOWN:
1.7 rmind 436: tmp = (int)(uintptr_t) SCARG(uap, arg);
1.1 ad 437: error = (*fp->f_ops->fo_ioctl)(fp, FIOSETOWN, &tmp);
438: break;
439:
440: default:
441: error = EINVAL;
442: }
443:
444: fd_putfile(fd);
445: return (error);
446: }
447:
448: /*
449: * Close a file descriptor.
450: */
451: int
452: sys_close(struct lwp *l, const struct sys_close_args *uap, register_t *retval)
453: {
454: /* {
455: syscallarg(int) fd;
456: } */
457:
458: if (fd_getfile(SCARG(uap, fd)) == NULL) {
459: return EBADF;
460: }
461: return fd_close(SCARG(uap, fd));
462: }
463:
464: /*
465: * Return status information about a file descriptor.
466: * Common function for compat code.
467: */
468: int
469: do_sys_fstat(int fd, struct stat *sb)
470: {
471: file_t *fp;
472: int error;
473:
474: if ((fp = fd_getfile(fd)) == NULL) {
475: return EBADF;
476: }
477: error = (*fp->f_ops->fo_stat)(fp, sb);
478: fd_putfile(fd);
479:
480: return error;
481: }
482:
483: /*
484: * Return status information about a file descriptor.
485: */
486: int
1.7.2.1 ! skrll 487: sys___fstat50(struct lwp *l, const struct sys___fstat50_args *uap,
1.1 ad 488: register_t *retval)
489: {
490: /* {
491: syscallarg(int) fd;
492: syscallarg(struct stat *) sb;
493: } */
494: struct stat sb;
495: int error;
496:
497: error = do_sys_fstat(SCARG(uap, fd), &sb);
498: if (error == 0) {
499: error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
500: }
501: return error;
502: }
503:
504: /*
505: * Return pathconf information about a file descriptor.
506: */
507: int
508: sys_fpathconf(struct lwp *l, const struct sys_fpathconf_args *uap,
509: register_t *retval)
510: {
511: /* {
512: syscallarg(int) fd;
513: syscallarg(int) name;
514: } */
515: int fd, error;
516: file_t *fp;
517:
518: fd = SCARG(uap, fd);
519: error = 0;
520:
521: if ((fp = fd_getfile(fd)) == NULL) {
522: return (EBADF);
523: }
524: switch (fp->f_type) {
525: case DTYPE_SOCKET:
526: case DTYPE_PIPE:
527: if (SCARG(uap, name) != _PC_PIPE_BUF)
528: error = EINVAL;
529: else
530: *retval = PIPE_BUF;
531: break;
532:
533: case DTYPE_VNODE:
534: error = VOP_PATHCONF(fp->f_data, SCARG(uap, name), retval);
535: break;
536:
537: case DTYPE_KQUEUE:
538: error = EINVAL;
539: break;
540:
541: default:
542: error = EOPNOTSUPP;
543: break;
544: }
545:
546: fd_putfile(fd);
547: return (error);
548: }
549:
550: /*
551: * Apply an advisory lock on a file descriptor.
552: *
553: * Just attempt to get a record lock of the requested type on
554: * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
555: */
556: /* ARGSUSED */
557: int
558: sys_flock(struct lwp *l, const struct sys_flock_args *uap, register_t *retval)
559: {
560: /* {
561: syscallarg(int) fd;
562: syscallarg(int) how;
563: } */
564: int fd, how, error;
565: file_t *fp;
566: vnode_t *vp;
567: struct flock lf;
568: proc_t *p;
569:
570: fd = SCARG(uap, fd);
571: how = SCARG(uap, how);
572: error = 0;
573:
574: if ((fp = fd_getfile(fd)) == NULL) {
575: return EBADF;
576: }
577: if (fp->f_type != DTYPE_VNODE) {
578: fd_putfile(fd);
579: return EOPNOTSUPP;
580: }
581:
582: vp = fp->f_data;
583: lf.l_whence = SEEK_SET;
584: lf.l_start = 0;
585: lf.l_len = 0;
586: if (how & LOCK_UN) {
587: lf.l_type = F_UNLCK;
588: atomic_and_uint(&fp->f_flag, ~FHASLOCK);
589: error = VOP_ADVLOCK(vp, fp, F_UNLCK, &lf, F_FLOCK);
590: fd_putfile(fd);
591: return error;
592: }
593: if (how & LOCK_EX) {
594: lf.l_type = F_WRLCK;
595: } else if (how & LOCK_SH) {
596: lf.l_type = F_RDLCK;
597: } else {
598: fd_putfile(fd);
599: return EINVAL;
600: }
601: atomic_or_uint(&fp->f_flag, FHASLOCK);
602: p = curproc;
603: if (how & LOCK_NB) {
604: error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK);
605: } else {
606: error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK|F_WAIT);
607: }
608: fd_putfile(fd);
609: return error;
610: }
611:
612: int
613: do_posix_fadvise(int fd, off_t offset, off_t len, int advice)
614: {
615: file_t *fp;
616: int error;
617:
618: if ((fp = fd_getfile(fd)) == NULL) {
619: return EBADF;
620: }
621: if (fp->f_type != DTYPE_VNODE) {
622: if (fp->f_type == DTYPE_PIPE || fp->f_type == DTYPE_SOCKET) {
623: error = ESPIPE;
624: } else {
625: error = EOPNOTSUPP;
626: }
627: fd_putfile(fd);
628: return error;
629: }
630:
631: switch (advice) {
632: case POSIX_FADV_NORMAL:
633: case POSIX_FADV_RANDOM:
634: case POSIX_FADV_SEQUENTIAL:
635: KASSERT(POSIX_FADV_NORMAL == UVM_ADV_NORMAL);
636: KASSERT(POSIX_FADV_RANDOM == UVM_ADV_RANDOM);
637: KASSERT(POSIX_FADV_SEQUENTIAL == UVM_ADV_SEQUENTIAL);
638:
639: /*
640: * We ignore offset and size. must lock the file to
641: * do this, as f_advice is sub-word sized.
642: */
643: mutex_enter(&fp->f_lock);
644: fp->f_advice = (u_char)advice;
645: mutex_exit(&fp->f_lock);
646: error = 0;
647: break;
648:
649: case POSIX_FADV_WILLNEED:
650: case POSIX_FADV_DONTNEED:
651: case POSIX_FADV_NOREUSE:
652: /* Not implemented yet. */
653: error = 0;
654: break;
655: default:
656: error = EINVAL;
657: break;
658: }
659:
660: fd_putfile(fd);
661: return error;
662: }
663:
664: int
665: sys___posix_fadvise50(struct lwp *l,
666: const struct sys___posix_fadvise50_args *uap,
667: register_t *retval)
668: {
669: /* {
670: syscallarg(int) fd;
671: syscallarg(int) pad;
672: syscallarg(off_t) offset;
673: syscallarg(off_t) len;
674: syscallarg(int) advice;
675: } */
676:
677: return do_posix_fadvise(SCARG(uap, fd), SCARG(uap, offset),
678: SCARG(uap, len), SCARG(uap, advice));
679: }
CVSweb <webmaster@jp.NetBSD.org>