1 /* $NetBSD: sys_descrip.c,v 1.16 2009/06/10 23:48:10 yamt Exp $ */
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
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.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
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.
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
62 * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
66 * System calls on descriptors.
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: sys_descrip.c,v 1.16 2009/06/10 23:48:10 yamt Exp $");
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>
79 #include <sys/namei.h>
80 #include <sys/socket.h>
81 #include <sys/socketvar.h>
83 #include <sys/ioctl.h>
84 #include <sys/fcntl.h>
87 #include <sys/syslog.h>
88 #include <sys/unistd.h>
89 #include <sys/resourcevar.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>
97 #include <uvm/uvm_readahead.h>
100 * Duplicate a file descriptor.
103 sys_dup(struct lwp
*l
, const struct sys_dup_args
*uap
, register_t
*retval
)
111 old
= SCARG(uap
, fd
);
113 if ((fp
= fd_getfile(old
)) == NULL
) {
116 error
= fd_dup(fp
, 0, &new, false);
123 * Duplicate a file descriptor to a particular value.
126 sys_dup2(struct lwp
*l
, const struct sys_dup2_args
*uap
, register_t
*retval
)
129 syscallarg(int) from;
135 old
= SCARG(uap
, from
);
136 new = SCARG(uap
, to
);
138 if ((fp
= fd_getfile(old
)) == NULL
) {
141 mutex_enter(&fp
->f_lock
);
143 mutex_exit(&fp
->f_lock
);
146 if ((u_int
)new >= curproc
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
||
147 (u_int
)new >= maxfiles
) {
149 } else if (old
== new) {
152 error
= fd_dup2(fp
, new);
161 * fcntl call which is being passed to the file's fs.
164 fcntl_forfs(int fd
, file_t
*fp
, int cmd
, void *arg
)
169 #define STK_PARAMS 128
170 char stkbuf
[STK_PARAMS
];
172 if ((fp
->f_flag
& (FREAD
| FWRITE
)) == 0)
176 * Interpret high order word to find amount of data to be
177 * copied to/from the user's address space.
179 size
= (size_t)F_PARAM_LEN(cmd
);
180 if (size
> F_PARAM_MAX
)
183 if (size
> sizeof(stkbuf
)) {
184 memp
= kmem_alloc(size
, KM_SLEEP
);
190 error
= copyin(arg
, data
, size
);
193 kmem_free(memp
, size
);
197 *(void **)data
= arg
;
198 } else if ((cmd
& F_FSOUT
) != 0 && size
!= 0) {
200 * Zero the buffer so the user always
201 * gets back something deterministic.
203 memset(data
, 0, size
);
204 } else if (cmd
& F_FSVOID
)
205 *(void **)data
= arg
;
208 error
= (*fp
->f_ops
->fo_fcntl
)(fp
, cmd
, data
);
211 * Copy any data to user, size was
212 * already set and checked above.
214 if (error
== 0 && (cmd
& F_FSOUT
) && size
)
215 error
= copyout(data
, arg
, size
);
217 kmem_free(memp
, size
);
222 do_fcntl_lock(int fd
, int cmd
, struct flock
*fl
)
229 if ((fp
= fd_getfile(fd
)) == NULL
)
231 if (fp
->f_type
!= DTYPE_VNODE
) {
236 if (fl
->l_whence
== SEEK_CUR
)
237 fl
->l_start
+= fp
->f_offset
;
245 /* Fall into F_SETLK */
248 switch (fl
->l_type
) {
250 if ((fp
->f_flag
& FREAD
) == 0) {
254 if ((p
->p_flag
& PK_ADVLOCK
) == 0) {
255 mutex_enter(p
->p_lock
);
256 p
->p_flag
|= PK_ADVLOCK
;
257 mutex_exit(p
->p_lock
);
259 error
= VOP_ADVLOCK(vp
, p
, F_SETLK
, fl
, flg
);
263 if ((fp
->f_flag
& FWRITE
) == 0) {
267 if ((p
->p_flag
& PK_ADVLOCK
) == 0) {
268 mutex_enter(p
->p_lock
);
269 p
->p_flag
|= PK_ADVLOCK
;
270 mutex_exit(p
->p_lock
);
272 error
= VOP_ADVLOCK(vp
, p
, F_SETLK
, fl
, flg
);
276 error
= VOP_ADVLOCK(vp
, p
, F_UNLCK
, fl
, F_POSIX
);
286 if (fl
->l_type
!= F_RDLCK
&&
287 fl
->l_type
!= F_WRLCK
&&
288 fl
->l_type
!= F_UNLCK
) {
292 error
= VOP_ADVLOCK(vp
, p
, F_GETLK
, fl
, F_POSIX
);
305 * The file control system call.
308 sys_fcntl(struct lwp
*l
, const struct sys_fcntl_args
*uap
, register_t
*retval
)
313 syscallarg(void *) arg;
315 int fd
, i
, tmp
, error
, cmd
, newmin
;
322 cmd
= SCARG(uap
, cmd
);
330 while ((i
= fdp
->fd_lastfile
) >= fd
) {
331 if (fd_getfile(i
) == NULL
) {
332 /* Another thread has updated. */
340 *retval
= fdp
->fd_lastfile
;
346 error
= copyin(SCARG(uap
, arg
), &fl
, sizeof(fl
));
349 error
= do_fcntl_lock(fd
, cmd
, &fl
);
350 if (cmd
== F_GETLK
&& error
== 0)
351 error
= copyout(&fl
, SCARG(uap
, arg
), sizeof(fl
));
359 if ((fp
= fd_getfile(fd
)) == NULL
)
361 ff
= fdp
->fd_dt
->dt_ff
[fd
];
363 if ((cmd
& F_FSCTL
)) {
364 error
= fcntl_forfs(fd
, fp
, cmd
, SCARG(uap
, arg
));
371 newmin
= (long)SCARG(uap
, arg
);
373 l
->l_proc
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
||
374 (u_int
)newmin
>= maxfiles
) {
378 error
= fd_dup(fp
, newmin
, &i
, false);
383 *retval
= ff
->ff_exclose
;
387 if ((long)SCARG(uap
, arg
) & FD_CLOEXEC
) {
388 ff
->ff_exclose
= true;
389 fdp
->fd_exclose
= true;
391 ff
->ff_exclose
= false;
396 *retval
= OFLAGS(fp
->f_flag
);
400 /* XXX not guaranteed to be atomic. */
401 tmp
= FFLAGS((long)SCARG(uap
, arg
)) & FCNTLFLAGS
;
402 error
= (*fp
->f_ops
->fo_fcntl
)(fp
, F_SETFL
, &tmp
);
405 i
= tmp
^ fp
->f_flag
;
407 int flgs
= tmp
& FNONBLOCK
;
408 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, FIONBIO
, &flgs
);
410 (*fp
->f_ops
->fo_fcntl
)(fp
, F_SETFL
,
416 int flgs
= tmp
& FASYNC
;
417 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, FIOASYNC
, &flgs
);
420 tmp
= fp
->f_flag
& FNONBLOCK
;
421 (void)(*fp
->f_ops
->fo_ioctl
)(fp
,
424 (*fp
->f_ops
->fo_fcntl
)(fp
, F_SETFL
,
429 fp
->f_flag
= (fp
->f_flag
& ~FCNTLFLAGS
) | tmp
;
433 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, FIOGETOWN
, &tmp
);
438 tmp
= (int)(uintptr_t) SCARG(uap
, arg
);
439 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, FIOSETOWN
, &tmp
);
451 * Close a file descriptor.
454 sys_close(struct lwp
*l
, const struct sys_close_args
*uap
, register_t
*retval
)
460 if (fd_getfile(SCARG(uap
, fd
)) == NULL
) {
463 return fd_close(SCARG(uap
, fd
));
467 * Return status information about a file descriptor.
468 * Common function for compat code.
471 do_sys_fstat(int fd
, struct stat
*sb
)
476 if ((fp
= fd_getfile(fd
)) == NULL
) {
479 error
= (*fp
->f_ops
->fo_stat
)(fp
, sb
);
486 * Return status information about a file descriptor.
489 sys___fstat50(struct lwp
*l
, const struct sys___fstat50_args
*uap
,
494 syscallarg(struct stat *) sb;
499 error
= do_sys_fstat(SCARG(uap
, fd
), &sb
);
501 error
= copyout(&sb
, SCARG(uap
, sb
), sizeof(sb
));
507 * Return pathconf information about a file descriptor.
510 sys_fpathconf(struct lwp
*l
, const struct sys_fpathconf_args
*uap
,
515 syscallarg(int) name;
523 if ((fp
= fd_getfile(fd
)) == NULL
) {
526 switch (fp
->f_type
) {
529 if (SCARG(uap
, name
) != _PC_PIPE_BUF
)
536 error
= VOP_PATHCONF(fp
->f_data
, SCARG(uap
, name
), retval
);
553 * Apply an advisory lock on a file descriptor.
555 * Just attempt to get a record lock of the requested type on
556 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
560 sys_flock(struct lwp
*l
, const struct sys_flock_args
*uap
, register_t
*retval
)
573 how
= SCARG(uap
, how
);
576 if ((fp
= fd_getfile(fd
)) == NULL
) {
579 if (fp
->f_type
!= DTYPE_VNODE
) {
585 lf
.l_whence
= SEEK_SET
;
589 switch (how
& ~LOCK_NB
) {
592 atomic_and_uint(&fp
->f_flag
, ~FHASLOCK
);
593 error
= VOP_ADVLOCK(vp
, fp
, F_UNLCK
, &lf
, F_FLOCK
);
607 atomic_or_uint(&fp
->f_flag
, FHASLOCK
);
610 error
= VOP_ADVLOCK(vp
, fp
, F_SETLK
, &lf
, F_FLOCK
);
612 error
= VOP_ADVLOCK(vp
, fp
, F_SETLK
, &lf
, F_FLOCK
|F_WAIT
);
619 do_posix_fadvise(int fd
, off_t offset
, off_t len
, int advice
)
625 CTASSERT(POSIX_FADV_NORMAL
== UVM_ADV_NORMAL
);
626 CTASSERT(POSIX_FADV_RANDOM
== UVM_ADV_RANDOM
);
627 CTASSERT(POSIX_FADV_SEQUENTIAL
== UVM_ADV_SEQUENTIAL
);
630 endoffset
= INT64_MAX
;
631 } else if (INT64_MAX
- offset
>= len
) {
632 endoffset
= offset
+ len
;
636 if ((fp
= fd_getfile(fd
)) == NULL
) {
639 if (fp
->f_type
!= DTYPE_VNODE
) {
640 if (fp
->f_type
== DTYPE_PIPE
|| fp
->f_type
== DTYPE_SOCKET
) {
650 case POSIX_FADV_WILLNEED
:
651 case POSIX_FADV_DONTNEED
:
653 if (vp
->v_type
!= VREG
&& vp
->v_type
!= VBLK
) {
661 case POSIX_FADV_NORMAL
:
662 case POSIX_FADV_RANDOM
:
663 case POSIX_FADV_SEQUENTIAL
:
666 * We ignore offset and size. must lock the file to
667 * do this, as f_advice is sub-word sized.
669 mutex_enter(&fp
->f_lock
);
670 fp
->f_advice
= (u_char
)advice
;
671 mutex_exit(&fp
->f_lock
);
675 case POSIX_FADV_WILLNEED
:
677 error
= uvm_readahead(&vp
->v_uobj
, offset
, endoffset
- offset
);
680 case POSIX_FADV_DONTNEED
:
682 mutex_enter(&vp
->v_interlock
);
683 error
= VOP_PUTPAGES(vp
, round_page(offset
),
684 trunc_page(endoffset
), PGO_DEACTIVATE
| PGO_CLEANIT
);
687 case POSIX_FADV_NOREUSE
:
688 /* Not implemented yet. */
701 sys___posix_fadvise50(struct lwp
*l
,
702 const struct sys___posix_fadvise50_args
*uap
,
708 syscallarg(off_t) offset;
709 syscallarg(off_t) len;
710 syscallarg(int) advice;
713 *retval
= do_posix_fadvise(SCARG(uap
, fd
), SCARG(uap
, offset
),
714 SCARG(uap
, len
), SCARG(uap
, advice
));