1 /* $NetBSD: svr4_32_fcntl.c,v 1.33 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_32_fcntl.c,v 1.33 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_32/svr4_32_types.h>
52 #include <compat/svr4_32/svr4_32_signal.h>
53 #include <compat/svr4_32/svr4_32_ucontext.h>
54 #include <compat/svr4_32/svr4_32_lwp.h>
55 #include <compat/svr4_32/svr4_32_syscallargs.h>
56 #include <compat/svr4_32/svr4_32_util.h>
57 #include <compat/svr4_32/svr4_32_fcntl.h>
59 static int svr4_32_to_bsd_flags(int);
60 static int bsd_to_svr4_32_flags(int);
61 static void bsd_to_svr4_32_flock(struct flock
*, struct svr4_32_flock
*);
62 static void svr4_32_to_bsd_flock(struct svr4_32_flock
*, struct flock
*);
63 static void bsd_to_svr4_32_flock64(struct flock
*, struct svr4_32_flock64
*);
64 static void svr4_32_to_bsd_flock64(struct svr4_32_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_32_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_32_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_32_flock(struct flock
*iflp
, struct svr4_32_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_32_off_t
) iflp
->l_start
;
133 oflp
->l_len
= (svr4_32_off_t
) iflp
->l_len
;
135 oflp
->l_pid
= (svr4_32_pid_t
) iflp
->l_pid
;
140 svr4_32_to_bsd_flock(struct svr4_32_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_32_flock64(struct flock
*iflp
, struct svr4_32_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_32_off64_t
) iflp
->l_start
;
184 oflp
->l_len
= (svr4_32_off64_t
) iflp
->l_len
;
186 oflp
->l_pid
= (svr4_32_pid_t
) iflp
->l_pid
;
191 svr4_32_to_bsd_flock64(struct svr4_32_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
) {
232 if (vp
->v_type
!= VCHR
&& vp
->v_type
!= VBLK
) {
236 error
= dorevoke(vp
, l
->l_cred
);
245 fd_truncate(struct lwp
*l
, int fd
, struct flock
*flp
, register_t
*retval
)
252 struct sys_ftruncate_args ft
;
255 * We only support truncating the file.
257 if ((fp
= fd_getfile(fd
)) == NULL
)
260 if (fp
->f_type
!= DTYPE_VNODE
|| vp
->v_type
== VFIFO
) {
264 if ((error
= VOP_GETATTR(vp
, &vattr
, l
->l_cred
)) != 0) {
269 length
= vattr
.va_size
;
271 switch (flp
->l_whence
) {
273 start
= fp
->f_offset
+ flp
->l_start
;
277 start
= flp
->l_start
+ length
;
281 start
= flp
->l_start
;
289 if (start
+ flp
->l_len
< length
) {
290 /* We don't support free'ing in the middle of the file */
296 SCARG(&ft
, length
) = start
;
298 error
= sys_ftruncate(l
, &ft
, retval
);
305 svr4_32_sys_open(struct lwp
*l
, const struct svr4_32_sys_open_args
*uap
, register_t
*retval
)
308 struct sys_open_args cup
;
310 SCARG(&cup
, flags
) = svr4_32_to_bsd_flags(SCARG(uap
, flags
));
312 SCARG(&cup
, path
) = SCARG_P32(uap
, path
);
313 SCARG(&cup
, mode
) = SCARG(uap
, mode
);
314 error
= sys_open(l
, &cup
, retval
);
321 if (!(SCARG(&cup
, flags
) & O_NOCTTY
) && SESS_LEADER(l
->l_proc
) &&
322 !(l
->l_proc
->p_lflag
& PL_CONTROLT
)) {
329 /* ignore any error, just give it a try */
331 if (fp
->f_type
== DTYPE_VNODE
)
332 (fp
->f_ops
->fo_ioctl
)(fp
, TIOCSCTTY
, NULL
);
341 svr4_32_sys_creat(struct lwp
*l
, const struct svr4_32_sys_creat_args
*uap
, register_t
*retval
)
343 struct sys_open_args cup
;
345 SCARG(&cup
, path
) = SCARG_P32(uap
, path
);
346 SCARG(&cup
, mode
) = SCARG(uap
, mode
);
347 SCARG(&cup
, flags
) = O_WRONLY
| O_CREAT
| O_TRUNC
;
349 return sys_open(l
, &cup
, retval
);
354 svr4_32_sys_llseek(struct lwp
*l
, const struct svr4_32_sys_llseek_args
*uap
, register_t
*retval
)
356 struct sys_lseek_args ap
;
358 SCARG(&ap
, fd
) = SCARG(uap
, fd
);
360 #if BYTE_ORDER == BIG_ENDIAN
361 SCARG(&ap
, offset
) = (((long long) SCARG(uap
, offset1
)) << 32) |
364 SCARG(&ap
, offset
) = (((long long) SCARG(uap
, offset2
)) << 32) |
367 SCARG(&ap
, whence
) = SCARG(uap
, whence
);
369 return sys_lseek(l
, &ap
, retval
);
373 svr4_32_sys_access(struct lwp
*l
, const struct svr4_32_sys_access_args
*uap
, register_t
*retval
)
375 struct sys_access_args cup
;
377 SCARG(&cup
, path
) = SCARG_P32(uap
, path
);
378 SCARG(&cup
, flags
) = SCARG(uap
, flags
);
380 return sys_access(l
, &cup
, retval
);
385 svr4_32_sys_pread(struct lwp
*l
, const struct svr4_32_sys_pread_args
*uap
, register_t
*retval
)
387 struct sys_pread_args pra
;
390 * Just translate the args structure and call the NetBSD
391 * pread(2) system call (offset type is 64-bit in NetBSD).
393 SCARG(&pra
, fd
) = SCARG(uap
, fd
);
394 SCARG(&pra
, buf
) = SCARG_P32(uap
, buf
);
395 SCARG(&pra
, nbyte
) = SCARG(uap
, nbyte
);
396 SCARG(&pra
, offset
) = SCARG(uap
, off
);
398 return (sys_pread(l
, &pra
, retval
));
403 svr4_32_sys_pread64(struct lwp
*l
, const struct svr4_32_sys_pread64_args
*uap
, register_t
*retval
)
405 struct sys_pread_args pra
;
408 * Just translate the args structure and call the NetBSD
409 * pread(2) system call (offset type is 64-bit in NetBSD).
411 SCARG(&pra
, fd
) = SCARG(uap
, fd
);
412 SCARG(&pra
, buf
) = SCARG_P32(uap
, buf
);
413 SCARG(&pra
, nbyte
) = SCARG(uap
, nbyte
);
414 SCARG(&pra
, offset
) = SCARG(uap
, off
);
416 return (sys_pread(l
, &pra
, retval
));
421 svr4_32_sys_pwrite(struct lwp
*l
, const struct svr4_32_sys_pwrite_args
*uap
, register_t
*retval
)
423 struct sys_pwrite_args pwa
;
426 * Just translate the args structure and call the NetBSD
427 * pwrite(2) system call (offset type is 64-bit in NetBSD).
429 SCARG(&pwa
, fd
) = SCARG(uap
, fd
);
430 SCARG(&pwa
, buf
) = SCARG_P32(uap
, buf
);
431 SCARG(&pwa
, nbyte
) = SCARG(uap
, nbyte
);
432 SCARG(&pwa
, offset
) = SCARG(uap
, off
);
434 return (sys_pwrite(l
, &pwa
, retval
));
439 svr4_32_sys_pwrite64(struct lwp
*l
, const struct svr4_32_sys_pwrite64_args
*uap
, register_t
*retval
)
441 struct sys_pwrite_args pwa
;
444 * Just translate the args structure and call the NetBSD
445 * pwrite(2) system call (offset type is 64-bit in NetBSD).
447 SCARG(&pwa
, fd
) = SCARG(uap
, fd
);
448 SCARG(&pwa
, buf
) = SCARG_P32(uap
, buf
);
449 SCARG(&pwa
, nbyte
) = SCARG(uap
, nbyte
);
450 SCARG(&pwa
, offset
) = SCARG(uap
, off
);
452 return (sys_pwrite(l
, &pwa
, retval
));
457 svr4_32_sys_fcntl(struct lwp
*l
, const struct svr4_32_sys_fcntl_args
*uap
, register_t
*retval
)
459 struct sys_fcntl_args fa
;
461 struct svr4_32_flock64 ifl64
;
462 struct svr4_32_flock ifl
;
467 SCARG(&fa
, fd
) = SCARG(uap
, fd
);
468 SCARG(&fa
, arg
) = SCARG_P32(uap
, arg
);
470 switch (SCARG(uap
, cmd
)) {
487 * we must save the O_ASYNC flag, as that is
488 * handled by ioctl(_, I_SETSIG, _) emulation.
490 SCARG(&fa
, cmd
) = F_GETFL
;
491 if ((error
= sys_fcntl(l
, &fa
, &flags
)) != 0)
494 flags
|= svr4_32_to_bsd_flags((u_long
) SCARG_P32(uap
, arg
));
496 SCARG(&fa
, arg
) = (void *) flags
;
508 error
= copyin(SCARG_P32(uap
, arg
), &ifl
, sizeof ifl
);
511 svr4_32_to_bsd_flock(&ifl
, &fl
);
513 error
= do_fcntl_lock(SCARG(uap
, fd
), cmd
, &fl
);
514 if (cmd
!= F_GETLK
|| error
!= 0)
517 bsd_to_svr4_32_flock(&fl
, &ifl
);
518 return copyout(&ifl
, SCARG_P32(uap
, arg
), sizeof ifl
);
522 struct sys_dup2_args du
;
524 SCARG(&du
, from
) = SCARG(uap
, fd
);
525 SCARG(&du
, to
) = (int)(u_long
)SCARG_P32(uap
, arg
);
526 error
= sys_dup2(l
, &du
, retval
);
529 *retval
= SCARG(&du
, to
);
534 error
= copyin(SCARG_P32(uap
, arg
), &ifl
, sizeof ifl
);
537 svr4_32_to_bsd_flock(&ifl
, &fl
);
538 return fd_truncate(l
, SCARG(uap
, fd
), &fl
, retval
);
546 case SVR4_F_SETLKW64
:
549 error
= copyin(SCARG_P32(uap
, arg
), &ifl64
, sizeof ifl64
);
552 svr4_32_to_bsd_flock64(&ifl64
, &fl
);
554 error
= do_fcntl_lock(SCARG(uap
, fd
), cmd
, &fl
);
555 if (cmd
!= F_GETLK
|| error
!= 0)
558 bsd_to_svr4_32_flock64(&fl
, &ifl64
);
559 return copyout(&ifl64
, SCARG_P32(uap
, arg
), sizeof ifl64
);
561 case SVR4_F_FREESP64
:
562 error
= copyin(SCARG_P32(uap
, arg
), &ifl64
, sizeof ifl64
);
565 svr4_32_to_bsd_flock64(&ifl64
, &fl
);
566 return fd_truncate(l
, SCARG(uap
, fd
), &fl
, retval
);
569 return fd_revoke(l
, SCARG(uap
, fd
), retval
);
575 SCARG(&fa
, cmd
) = cmd
;
577 error
= sys_fcntl(l
, &fa
, retval
);
581 switch (SCARG(uap
, cmd
)) {
584 *retval
= bsd_to_svr4_32_flags(*retval
);