1 /* $NetBSD: svr4_fcntl.c,v 1.69 2008/03/21 21:54:59 ad Exp $ */
4 * Copyright (c) 1994, 1997, 2008 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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: svr4_fcntl.c,v 1.69 2008/03/21 21:54:59 ad Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/namei.h>
41 #include <sys/filedesc.h>
42 #include <sys/ioctl.h>
43 #include <sys/kernel.h>
44 #include <sys/mount.h>
45 #include <sys/malloc.h>
46 #include <sys/vnode.h>
47 #include <sys/kauth.h>
49 #include <sys/syscallargs.h>
51 #include <compat/svr4/svr4_types.h>
52 #include <compat/svr4/svr4_signal.h>
53 #include <compat/svr4/svr4_ucontext.h>
54 #include <compat/svr4/svr4_lwp.h>
55 #include <compat/svr4/svr4_syscallargs.h>
56 #include <compat/svr4/svr4_util.h>
57 #include <compat/svr4/svr4_fcntl.h>
59 static int svr4_to_bsd_flags(int);
60 static int bsd_to_svr4_flags(int);
61 static void bsd_to_svr4_flock(struct flock
*, struct svr4_flock
*);
62 static void svr4_to_bsd_flock(struct svr4_flock
*, struct flock
*);
63 static void bsd_to_svr4_flock64(struct flock
*, struct svr4_flock64
*);
64 static void svr4_to_bsd_flock64(struct svr4_flock64
*, struct flock
*);
65 static int fd_revoke(struct lwp
*, int, register_t
*);
66 static int fd_truncate(struct lwp
*, int, struct flock
*, register_t
*);
70 svr4_to_bsd_flags(int l
)
73 r
|= (l
& SVR4_O_RDONLY
) ? O_RDONLY
: 0;
74 r
|= (l
& SVR4_O_WRONLY
) ? O_WRONLY
: 0;
75 r
|= (l
& SVR4_O_RDWR
) ? O_RDWR
: 0;
76 r
|= (l
& SVR4_O_NDELAY
) ? O_NDELAY
: 0;
77 r
|= (l
& SVR4_O_APPEND
) ? O_APPEND
: 0;
78 r
|= (l
& SVR4_O_SYNC
) ? O_FSYNC
: 0;
79 r
|= (l
& SVR4_O_RSYNC
) ? O_RSYNC
: 0;
80 r
|= (l
& SVR4_O_DSYNC
) ? O_DSYNC
: 0;
81 r
|= (l
& SVR4_O_NONBLOCK
) ? O_NONBLOCK
: 0;
82 r
|= (l
& SVR4_O_PRIV
) ? O_EXLOCK
: 0;
83 r
|= (l
& SVR4_O_CREAT
) ? O_CREAT
: 0;
84 r
|= (l
& SVR4_O_TRUNC
) ? O_TRUNC
: 0;
85 r
|= (l
& SVR4_O_EXCL
) ? O_EXCL
: 0;
86 r
|= (l
& SVR4_O_NOCTTY
) ? O_NOCTTY
: 0;
92 bsd_to_svr4_flags(int l
)
95 r
|= (l
& O_RDONLY
) ? SVR4_O_RDONLY
: 0;
96 r
|= (l
& O_WRONLY
) ? SVR4_O_WRONLY
: 0;
97 r
|= (l
& O_RDWR
) ? SVR4_O_RDWR
: 0;
98 r
|= (l
& O_NDELAY
) ? SVR4_O_NDELAY
: 0;
99 r
|= (l
& O_APPEND
) ? SVR4_O_APPEND
: 0;
100 r
|= (l
& O_FSYNC
) ? SVR4_O_SYNC
: 0;
101 r
|= (l
& O_RSYNC
) ? SVR4_O_RSYNC
: 0;
102 r
|= (l
& O_DSYNC
) ? SVR4_O_DSYNC
: 0;
103 r
|= (l
& O_NONBLOCK
) ? SVR4_O_NONBLOCK
: 0;
104 r
|= (l
& O_EXLOCK
) ? SVR4_O_PRIV
: 0;
105 r
|= (l
& O_CREAT
) ? SVR4_O_CREAT
: 0;
106 r
|= (l
& O_TRUNC
) ? SVR4_O_TRUNC
: 0;
107 r
|= (l
& O_EXCL
) ? SVR4_O_EXCL
: 0;
108 r
|= (l
& O_NOCTTY
) ? SVR4_O_NOCTTY
: 0;
114 bsd_to_svr4_flock(struct flock
*iflp
, struct svr4_flock
*oflp
)
116 switch (iflp
->l_type
) {
118 oflp
->l_type
= SVR4_F_RDLCK
;
121 oflp
->l_type
= SVR4_F_WRLCK
;
124 oflp
->l_type
= SVR4_F_UNLCK
;
131 oflp
->l_whence
= (short) iflp
->l_whence
;
132 oflp
->l_start
= (svr4_off_t
) iflp
->l_start
;
133 oflp
->l_len
= (svr4_off_t
) iflp
->l_len
;
135 oflp
->l_pid
= (svr4_pid_t
) iflp
->l_pid
;
140 svr4_to_bsd_flock(struct svr4_flock
*iflp
, struct flock
*oflp
)
142 switch (iflp
->l_type
) {
144 oflp
->l_type
= F_RDLCK
;
147 oflp
->l_type
= F_WRLCK
;
150 oflp
->l_type
= F_UNLCK
;
157 oflp
->l_whence
= iflp
->l_whence
;
158 oflp
->l_start
= (off_t
) iflp
->l_start
;
159 oflp
->l_len
= (off_t
) iflp
->l_len
;
160 oflp
->l_pid
= (pid_t
) iflp
->l_pid
;
165 bsd_to_svr4_flock64(struct flock
*iflp
, struct svr4_flock64
*oflp
)
167 switch (iflp
->l_type
) {
169 oflp
->l_type
= SVR4_F_RDLCK
;
172 oflp
->l_type
= SVR4_F_WRLCK
;
175 oflp
->l_type
= SVR4_F_UNLCK
;
182 oflp
->l_whence
= (short) iflp
->l_whence
;
183 oflp
->l_start
= (svr4_off64_t
) iflp
->l_start
;
184 oflp
->l_len
= (svr4_off64_t
) iflp
->l_len
;
186 oflp
->l_pid
= (svr4_pid_t
) iflp
->l_pid
;
191 svr4_to_bsd_flock64(struct svr4_flock64
*iflp
, struct flock
*oflp
)
193 switch (iflp
->l_type
) {
195 oflp
->l_type
= F_RDLCK
;
198 oflp
->l_type
= F_WRLCK
;
201 oflp
->l_type
= F_UNLCK
;
208 oflp
->l_whence
= iflp
->l_whence
;
209 oflp
->l_start
= (off_t
) iflp
->l_start
;
210 oflp
->l_len
= (off_t
) iflp
->l_len
;
211 oflp
->l_pid
= (pid_t
) iflp
->l_pid
;
217 fd_revoke(struct lwp
*l
, int fd
, register_t
*retval
)
223 if ((fp
= fd_getfile(fd
)) == NULL
)
226 if (fp
->f_type
!= DTYPE_VNODE
) {
231 vp
= (vnode_t
*) fp
->f_data
;
232 if (vp
->v_type
!= VCHR
&& vp
->v_type
!= VBLK
) {
237 error
= dorevoke(vp
, l
->l_cred
);
246 fd_truncate(struct lwp
*l
, int fd
, struct flock
*flp
, register_t
*retval
)
253 struct sys_ftruncate_args ft
;
256 * We only support truncating the file.
258 if ((fp
= fd_getfile(fd
)) == NULL
)
262 if (fp
->f_type
!= DTYPE_VNODE
|| vp
->v_type
== VFIFO
) {
266 if ((error
= VOP_GETATTR(vp
, &vattr
, l
->l_cred
)) != 0) {
271 length
= vattr
.va_size
;
273 switch (flp
->l_whence
) {
275 start
= fp
->f_offset
+ flp
->l_start
;
279 start
= flp
->l_start
+ length
;
283 start
= flp
->l_start
;
291 if (start
+ flp
->l_len
< length
) {
292 /* We don't support free'ing in the middle of the file */
298 SCARG(&ft
, length
) = start
;
300 error
= sys_ftruncate(l
, &ft
, retval
);
307 svr4_sys_open(struct lwp
*l
, const struct svr4_sys_open_args
*uap
, register_t
*retval
)
310 struct sys_open_args cup
;
312 SCARG(&cup
, flags
) = svr4_to_bsd_flags(SCARG(uap
, flags
));
314 SCARG(&cup
, path
) = SCARG(uap
, path
);
315 SCARG(&cup
, mode
) = SCARG(uap
, mode
);
316 error
= sys_open(l
, &cup
, retval
);
323 if (!(SCARG(&cup
, flags
) & O_NOCTTY
) && SESS_LEADER(l
->l_proc
) &&
324 !(l
->l_proc
->p_lflag
& PL_CONTROLT
)) {
326 fp
= fd_getfile(*retval
);
328 /* ignore any error, just give it a try */
330 if (fp
->f_type
== DTYPE_VNODE
)
331 (fp
->f_ops
->fo_ioctl
)(fp
, TIOCSCTTY
, NULL
);
340 svr4_sys_open64(struct lwp
*l
, const struct svr4_sys_open64_args
*uap
, register_t
*retval
)
342 return svr4_sys_open(l
, (const void *)uap
, retval
);
347 svr4_sys_creat(struct lwp
*l
, const struct svr4_sys_creat_args
*uap
, register_t
*retval
)
349 struct sys_open_args cup
;
351 SCARG(&cup
, path
) = SCARG(uap
, path
);
352 SCARG(&cup
, mode
) = SCARG(uap
, mode
);
353 SCARG(&cup
, flags
) = O_WRONLY
| O_CREAT
| O_TRUNC
;
355 return sys_open(l
, &cup
, retval
);
360 svr4_sys_creat64(struct lwp
*l
, const struct svr4_sys_creat64_args
*uap
, register_t
*retval
)
362 return svr4_sys_creat(l
, (const void *)uap
, retval
);
367 svr4_sys_llseek(struct lwp
*l
, const struct svr4_sys_llseek_args
*uap
, register_t
*retval
)
369 struct sys_lseek_args ap
;
371 SCARG(&ap
, fd
) = SCARG(uap
, fd
);
373 #if BYTE_ORDER == BIG_ENDIAN
374 SCARG(&ap
, offset
) = (((long long) SCARG(uap
, offset1
)) << 32) |
377 SCARG(&ap
, offset
) = (((long long) SCARG(uap
, offset2
)) << 32) |
380 SCARG(&ap
, whence
) = SCARG(uap
, whence
);
382 return sys_lseek(l
, &ap
, retval
);
386 svr4_sys_access(struct lwp
*l
, const struct svr4_sys_access_args
*uap
, register_t
*retval
)
388 struct sys_access_args cup
;
390 SCARG(&cup
, path
) = SCARG(uap
, path
);
391 SCARG(&cup
, flags
) = SCARG(uap
, flags
);
393 return sys_access(l
, &cup
, retval
);
398 svr4_sys_pread(struct lwp
*l
, const struct svr4_sys_pread_args
*uap
, register_t
*retval
)
400 struct sys_pread_args pra
;
403 * Just translate the args structure and call the NetBSD
404 * pread(2) system call (offset type is 64-bit in NetBSD).
406 SCARG(&pra
, fd
) = SCARG(uap
, fd
);
407 SCARG(&pra
, buf
) = SCARG(uap
, buf
);
408 SCARG(&pra
, nbyte
) = SCARG(uap
, nbyte
);
409 SCARG(&pra
, offset
) = SCARG(uap
, off
);
411 return (sys_pread(l
, &pra
, retval
));
416 svr4_sys_pread64(struct lwp
*l
, const struct svr4_sys_pread64_args
*uap
, register_t
*retval
)
418 struct sys_pread_args pra
;
421 * Just translate the args structure and call the NetBSD
422 * pread(2) system call (offset type is 64-bit in NetBSD).
424 SCARG(&pra
, fd
) = SCARG(uap
, fd
);
425 SCARG(&pra
, buf
) = SCARG(uap
, buf
);
426 SCARG(&pra
, nbyte
) = SCARG(uap
, nbyte
);
427 SCARG(&pra
, offset
) = SCARG(uap
, off
);
429 return (sys_pread(l
, &pra
, retval
));
434 svr4_sys_pwrite(struct lwp
*l
, const struct svr4_sys_pwrite_args
*uap
, register_t
*retval
)
436 struct sys_pwrite_args pwa
;
439 * Just translate the args structure and call the NetBSD
440 * pwrite(2) system call (offset type is 64-bit in NetBSD).
442 SCARG(&pwa
, fd
) = SCARG(uap
, fd
);
443 SCARG(&pwa
, buf
) = SCARG(uap
, buf
);
444 SCARG(&pwa
, nbyte
) = SCARG(uap
, nbyte
);
445 SCARG(&pwa
, offset
) = SCARG(uap
, off
);
447 return (sys_pwrite(l
, &pwa
, retval
));
452 svr4_sys_pwrite64(struct lwp
*l
, const struct svr4_sys_pwrite64_args
*uap
, register_t
*retval
)
454 struct sys_pwrite_args pwa
;
457 * Just translate the args structure and call the NetBSD
458 * pwrite(2) system call (offset type is 64-bit in NetBSD).
460 SCARG(&pwa
, fd
) = SCARG(uap
, fd
);
461 SCARG(&pwa
, buf
) = SCARG(uap
, buf
);
462 SCARG(&pwa
, nbyte
) = SCARG(uap
, nbyte
);
463 SCARG(&pwa
, offset
) = SCARG(uap
, off
);
465 return (sys_pwrite(l
, &pwa
, retval
));
470 svr4_sys_fcntl(struct lwp
*l
, const struct svr4_sys_fcntl_args
*uap
, register_t
*retval
)
472 struct sys_fcntl_args fa
;
474 struct svr4_flock64 ifl64
;
475 struct svr4_flock ifl
;
480 SCARG(&fa
, fd
) = SCARG(uap
, fd
);
481 SCARG(&fa
, arg
) = SCARG(uap
, arg
);
483 switch (SCARG(uap
, cmd
)) {
500 * we must save the O_ASYNC flag, as that is
501 * handled by ioctl(_, I_SETSIG, _) emulation.
503 SCARG(&fa
, cmd
) = F_GETFL
;
504 if ((error
= sys_fcntl(l
, &fa
, &flags
)) != 0)
507 flags
|= svr4_to_bsd_flags((u_long
) SCARG(uap
, arg
));
509 SCARG(&fa
, arg
) = (void *) flags
;
521 error
= copyin(SCARG(uap
, arg
), &ifl
, sizeof ifl
);
524 svr4_to_bsd_flock(&ifl
, &fl
);
526 error
= do_fcntl_lock(SCARG(uap
, fd
), cmd
, &fl
);
527 if (cmd
!= F_GETLK
|| error
!= 0)
530 bsd_to_svr4_flock(&fl
, &ifl
);
531 return copyout(&ifl
, SCARG(uap
, arg
), sizeof ifl
);
535 struct sys_dup2_args du
;
537 SCARG(&du
, from
) = SCARG(uap
, fd
);
538 SCARG(&du
, to
) = (int)(u_long
)SCARG(uap
, arg
);
539 error
= sys_dup2(l
, &du
, retval
);
542 *retval
= SCARG(&du
, to
);
547 error
= copyin(SCARG(uap
, arg
), &ifl
, sizeof ifl
);
550 svr4_to_bsd_flock(&ifl
, &fl
);
551 return fd_truncate(l
, SCARG(uap
, fd
), &fl
, retval
);
559 case SVR4_F_SETLKW64
:
562 error
= copyin(SCARG(uap
, arg
), &ifl64
, sizeof ifl64
);
565 svr4_to_bsd_flock64(&ifl64
, &fl
);
567 error
= do_fcntl_lock(SCARG(uap
, fd
), cmd
, &fl
);
568 if (cmd
!= F_GETLK
|| error
!= 0)
571 bsd_to_svr4_flock64(&fl
, &ifl64
);
572 return copyout(&ifl64
, SCARG(uap
, arg
), sizeof ifl64
);
574 case SVR4_F_FREESP64
:
575 error
= copyin(SCARG(uap
, arg
), &ifl64
, sizeof ifl64
);
578 svr4_to_bsd_flock64(&ifl64
, &fl
);
579 return fd_truncate(l
, SCARG(uap
, fd
), &fl
, retval
);
582 return fd_revoke(l
, SCARG(uap
, fd
), retval
);
588 SCARG(&fa
, cmd
) = cmd
;
590 error
= sys_fcntl(l
, &fa
, retval
);
594 switch (SCARG(uap
, cmd
)) {
597 *retval
= bsd_to_svr4_flags(*retval
);