1 /* $NetBSD: sys_generic.c,v 1.123 2009/05/24 21:41:26 ad Exp $ */
4 * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1982, 1986, 1989, 1993
34 * The Regents of the University of California. All rights reserved.
35 * (c) UNIX System Laboratories, Inc.
36 * All or some portions of this file are derived from material licensed
37 * to the University of California by American Telephone and Telegraph
38 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
39 * the permission of UNIX System Laboratories, Inc.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * @(#)sys_generic.c 8.9 (Berkeley) 2/14/95
69 * System calls relating to files.
72 #include <sys/cdefs.h>
73 __KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.123 2009/05/24 21:41:26 ad Exp $");
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/filedesc.h>
78 #include <sys/ioctl.h>
81 #include <sys/socketvar.h>
82 #include <sys/signalvar.h>
84 #include <sys/kernel.h>
88 #include <sys/vnode.h>
89 #include <sys/mount.h>
90 #include <sys/syscallargs.h>
91 #include <sys/ktrace.h>
92 #include <sys/atomic.h>
94 #include <uvm/uvm_extern.h>
101 sys_read(struct lwp
*l
, const struct sys_read_args
*uap
, register_t
*retval
)
105 syscallarg(void *) buf;
106 syscallarg(size_t) nbyte;
113 if ((fp
= fd_getfile(fd
)) == NULL
)
116 if ((fp
->f_flag
& FREAD
) == 0) {
121 /* dofileread() will unuse the descriptor for us */
122 return (dofileread(fd
, fp
, SCARG(uap
, buf
), SCARG(uap
, nbyte
),
123 &fp
->f_offset
, FOF_UPDATE_OFFSET
, retval
));
127 dofileread(int fd
, struct file
*fp
, void *buf
, size_t nbyte
,
128 off_t
*offset
, int flags
, register_t
*retval
)
138 aiov
.iov_base
= (void *)buf
;
139 aiov
.iov_len
= nbyte
;
140 auio
.uio_iov
= &aiov
;
142 auio
.uio_resid
= nbyte
;
143 auio
.uio_rw
= UIO_READ
;
144 auio
.uio_vmspace
= l
->l_proc
->p_vmspace
;
147 * Reads return ssize_t because -1 is returned on error. Therefore
148 * we must restrict the length to SSIZE_MAX to avoid garbage return
151 if (auio
.uio_resid
> SSIZE_MAX
) {
156 cnt
= auio
.uio_resid
;
157 error
= (*fp
->f_ops
->fo_read
)(fp
, offset
, &auio
, fp
->f_cred
, flags
);
159 if (auio
.uio_resid
!= cnt
&& (error
== ERESTART
||
160 error
== EINTR
|| error
== EWOULDBLOCK
))
162 cnt
-= auio
.uio_resid
;
163 ktrgenio(fd
, UIO_READ
, buf
, cnt
, error
);
171 * Scatter read system call.
174 sys_readv(struct lwp
*l
, const struct sys_readv_args
*uap
, register_t
*retval
)
178 syscallarg(const struct iovec *) iovp;
179 syscallarg(int) iovcnt;
182 return do_filereadv(SCARG(uap
, fd
), SCARG(uap
, iovp
),
183 SCARG(uap
, iovcnt
), NULL
, FOF_UPDATE_OFFSET
, retval
);
187 do_filereadv(int fd
, const struct iovec
*iovp
, int iovcnt
,
188 off_t
*offset
, int flags
, register_t
*retval
)
191 struct iovec
*iov
, *needfree
= NULL
, aiov
[UIO_SMALLIOV
];
196 struct iovec
*ktriov
= NULL
;
201 if ((fp
= fd_getfile(fd
)) == NULL
)
204 if ((fp
->f_flag
& FREAD
) == 0) {
210 offset
= &fp
->f_offset
;
212 struct vnode
*vp
= fp
->f_data
;
213 if (fp
->f_type
!= DTYPE_VNODE
|| vp
->v_type
== VFIFO
) {
218 * Test that the device is seekable ?
219 * XXX This works because no file systems actually
220 * XXX take any action on the seek operation.
222 error
= VOP_SEEK(vp
, fp
->f_offset
, *offset
, fp
->f_cred
);
227 iovlen
= iovcnt
* sizeof(struct iovec
);
228 if (flags
& FOF_IOV_SYSSPACE
)
229 iov
= __UNCONST(iovp
);
232 if ((u_int
)iovcnt
> UIO_SMALLIOV
) {
233 if ((u_int
)iovcnt
> IOV_MAX
) {
237 iov
= kmem_alloc(iovlen
, KM_SLEEP
);
244 error
= copyin(iovp
, iov
, iovlen
);
250 auio
.uio_iovcnt
= iovcnt
;
251 auio
.uio_rw
= UIO_READ
;
252 auio
.uio_vmspace
= curproc
->p_vmspace
;
255 for (i
= 0; i
< iovcnt
; i
++, iov
++) {
256 auio
.uio_resid
+= iov
->iov_len
;
258 * Reads return ssize_t because -1 is returned on error.
259 * Therefore we must restrict the length to SSIZE_MAX to
260 * avoid garbage return values.
262 if (iov
->iov_len
> SSIZE_MAX
|| auio
.uio_resid
> SSIZE_MAX
) {
269 * if tracing, save a copy of iovec
271 if (ktrpoint(KTR_GENIO
)) {
272 ktriov
= kmem_alloc(iovlen
, KM_SLEEP
);
274 memcpy(ktriov
, auio
.uio_iov
, iovlen
);
277 cnt
= auio
.uio_resid
;
278 error
= (*fp
->f_ops
->fo_read
)(fp
, offset
, &auio
, fp
->f_cred
, flags
);
280 if (auio
.uio_resid
!= cnt
&& (error
== ERESTART
||
281 error
== EINTR
|| error
== EWOULDBLOCK
))
283 cnt
-= auio
.uio_resid
;
286 if (ktriov
!= NULL
) {
287 ktrgeniov(fd
, UIO_READ
, ktriov
, cnt
, error
);
288 kmem_free(ktriov
, iovlen
);
293 kmem_free(needfree
, iovlen
);
303 sys_write(struct lwp
*l
, const struct sys_write_args
*uap
, register_t
*retval
)
307 syscallarg(const void *) buf;
308 syscallarg(size_t) nbyte;
315 if ((fp
= fd_getfile(fd
)) == NULL
)
318 if ((fp
->f_flag
& FWRITE
) == 0) {
323 /* dofilewrite() will unuse the descriptor for us */
324 return (dofilewrite(fd
, fp
, SCARG(uap
, buf
), SCARG(uap
, nbyte
),
325 &fp
->f_offset
, FOF_UPDATE_OFFSET
, retval
));
329 dofilewrite(int fd
, struct file
*fp
, const void *buf
,
330 size_t nbyte
, off_t
*offset
, int flags
, register_t
*retval
)
337 aiov
.iov_base
= __UNCONST(buf
); /* XXXUNCONST kills const */
338 aiov
.iov_len
= nbyte
;
339 auio
.uio_iov
= &aiov
;
341 auio
.uio_resid
= nbyte
;
342 auio
.uio_rw
= UIO_WRITE
;
343 auio
.uio_vmspace
= curproc
->p_vmspace
;
346 * Writes return ssize_t because -1 is returned on error. Therefore
347 * we must restrict the length to SSIZE_MAX to avoid garbage return
350 if (auio
.uio_resid
> SSIZE_MAX
) {
355 cnt
= auio
.uio_resid
;
356 error
= (*fp
->f_ops
->fo_write
)(fp
, offset
, &auio
, fp
->f_cred
, flags
);
358 if (auio
.uio_resid
!= cnt
&& (error
== ERESTART
||
359 error
== EINTR
|| error
== EWOULDBLOCK
))
361 if (error
== EPIPE
) {
362 mutex_enter(proc_lock
);
363 psignal(curproc
, SIGPIPE
);
364 mutex_exit(proc_lock
);
367 cnt
-= auio
.uio_resid
;
368 ktrgenio(fd
, UIO_WRITE
, buf
, cnt
, error
);
376 * Gather write system call
379 sys_writev(struct lwp
*l
, const struct sys_writev_args
*uap
, register_t
*retval
)
383 syscallarg(const struct iovec *) iovp;
384 syscallarg(int) iovcnt;
387 return do_filewritev(SCARG(uap
, fd
), SCARG(uap
, iovp
),
388 SCARG(uap
, iovcnt
), NULL
, FOF_UPDATE_OFFSET
, retval
);
392 do_filewritev(int fd
, const struct iovec
*iovp
, int iovcnt
,
393 off_t
*offset
, int flags
, register_t
*retval
)
396 struct iovec
*iov
, *needfree
= NULL
, aiov
[UIO_SMALLIOV
];
401 struct iovec
*ktriov
= NULL
;
406 if ((fp
= fd_getfile(fd
)) == NULL
)
409 if ((fp
->f_flag
& FWRITE
) == 0) {
415 offset
= &fp
->f_offset
;
417 struct vnode
*vp
= fp
->f_data
;
418 if (fp
->f_type
!= DTYPE_VNODE
|| vp
->v_type
== VFIFO
) {
423 * Test that the device is seekable ?
424 * XXX This works because no file systems actually
425 * XXX take any action on the seek operation.
427 error
= VOP_SEEK(vp
, fp
->f_offset
, *offset
, fp
->f_cred
);
432 iovlen
= iovcnt
* sizeof(struct iovec
);
433 if (flags
& FOF_IOV_SYSSPACE
)
434 iov
= __UNCONST(iovp
);
437 if ((u_int
)iovcnt
> UIO_SMALLIOV
) {
438 if ((u_int
)iovcnt
> IOV_MAX
) {
442 iov
= kmem_alloc(iovlen
, KM_SLEEP
);
449 error
= copyin(iovp
, iov
, iovlen
);
455 auio
.uio_iovcnt
= iovcnt
;
456 auio
.uio_rw
= UIO_WRITE
;
457 auio
.uio_vmspace
= curproc
->p_vmspace
;
460 for (i
= 0; i
< iovcnt
; i
++, iov
++) {
461 auio
.uio_resid
+= iov
->iov_len
;
463 * Writes return ssize_t because -1 is returned on error.
464 * Therefore we must restrict the length to SSIZE_MAX to
465 * avoid garbage return values.
467 if (iov
->iov_len
> SSIZE_MAX
|| auio
.uio_resid
> SSIZE_MAX
) {
474 * if tracing, save a copy of iovec
476 if (ktrpoint(KTR_GENIO
)) {
477 ktriov
= kmem_alloc(iovlen
, KM_SLEEP
);
479 memcpy(ktriov
, auio
.uio_iov
, iovlen
);
482 cnt
= auio
.uio_resid
;
483 error
= (*fp
->f_ops
->fo_write
)(fp
, offset
, &auio
, fp
->f_cred
, flags
);
485 if (auio
.uio_resid
!= cnt
&& (error
== ERESTART
||
486 error
== EINTR
|| error
== EWOULDBLOCK
))
488 if (error
== EPIPE
) {
489 mutex_enter(proc_lock
);
490 psignal(curproc
, SIGPIPE
);
491 mutex_exit(proc_lock
);
494 cnt
-= auio
.uio_resid
;
497 if (ktriov
!= NULL
) {
498 ktrgeniov(fd
, UIO_WRITE
, ktriov
, cnt
, error
);
499 kmem_free(ktriov
, iovlen
);
504 kmem_free(needfree
, iovlen
);
515 sys_ioctl(struct lwp
*l
, const struct sys_ioctl_args
*uap
, register_t
*retval
)
519 syscallarg(u_long) com;
520 syscallarg(void *) data;
524 struct filedesc
*fdp
;
529 #define STK_PARAMS 128
530 u_long stkbuf
[STK_PARAMS
/sizeof(u_long
)];
537 if ((fp
= fd_getfile(SCARG(uap
, fd
))) == NULL
)
540 if ((fp
->f_flag
& (FREAD
| FWRITE
)) == 0) {
546 ff
= fdp
->fd_dt
->dt_ff
[SCARG(uap
, fd
)];
547 switch (com
= SCARG(uap
, com
)) {
549 ff
->ff_exclose
= false;
553 ff
->ff_exclose
= true;
554 fdp
->fd_exclose
= true;
559 * Interpret high order word to find amount of data to be
560 * copied to/from the user's address space.
562 size
= IOCPARM_LEN(com
);
563 if (size
> IOCPARM_MAX
) {
568 if ((com
>> IOCPARM_SHIFT
) == 0) {
569 /* UNIX-style ioctl. */
570 data
= SCARG(uap
, data
);
572 if (size
> sizeof(stkbuf
)) {
573 memp
= kmem_alloc(size
, KM_SLEEP
);
576 data
= (void *)stkbuf
;
580 error
= copyin(SCARG(uap
, data
), data
, size
);
583 kmem_free(memp
, size
);
587 ktrgenio(SCARG(uap
, fd
), UIO_WRITE
,
588 SCARG(uap
, data
), size
, 0);
590 *(void **)data
= SCARG(uap
, data
);
592 } else if ((com
&IOC_OUT
) && size
) {
594 * Zero the buffer so the user always
595 * gets back something deterministic.
597 memset(data
, 0, size
);
598 } else if (com
&IOC_VOID
) {
599 *(void **)data
= SCARG(uap
, data
);
606 /* XXX Code block is not atomic */
607 if (*(int *)data
!= 0)
608 atomic_or_uint(&fp
->f_flag
, FNONBLOCK
);
610 atomic_and_uint(&fp
->f_flag
, ~FNONBLOCK
);
611 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, FIONBIO
, data
);
615 /* XXX Code block is not atomic */
616 if (*(int *)data
!= 0)
617 atomic_or_uint(&fp
->f_flag
, FASYNC
);
619 atomic_and_uint(&fp
->f_flag
, ~FASYNC
);
620 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, FIOASYNC
, data
);
624 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, com
, data
);
626 * Copy any data to user, size was
627 * already set and checked above.
629 if (error
== 0 && (com
&IOC_OUT
) && size
) {
630 error
= copyout(data
, SCARG(uap
, data
), size
);
631 ktrgenio(SCARG(uap
, fd
), UIO_READ
, SCARG(uap
, data
),
637 kmem_free(memp
, size
);
639 fd_putfile(SCARG(uap
, fd
));
642 printf("sys_ioctl: _IO%s%s('%c', %lu, %lu) returned -1: "
644 (com
& IOC_IN
) ? "W" : "", (com
& IOC_OUT
) ? "R" : "",
645 (char)IOCGROUP(com
), (com
& 0xff), IOCPARM_LEN(com
),
646 p
->p_pid
, p
->p_comm
);