Sync usage with man page.
[netbsd-mini2440.git] / sys / compat / svr4_32 / svr4_32_fcntl.c
bloba481c667fead01f6bce82c3a4b391cd1c7db01b2
1 /* $NetBSD: svr4_32_fcntl.c,v 1.33 2008/03/21 21:54:59 ad Exp $ */
3 /*-
4 * Copyright (c) 1994, 1997, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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>
38 #include <sys/proc.h>
39 #include <sys/file.h>
40 #include <sys/stat.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 *);
69 static int
70 svr4_32_to_bsd_flags(int l)
72 int r = 0;
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;
87 return r;
91 static int
92 bsd_to_svr4_32_flags(int l)
94 int r = 0;
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;
109 return r;
113 static void
114 bsd_to_svr4_32_flock(struct flock *iflp, struct svr4_32_flock *oflp)
116 switch (iflp->l_type) {
117 case F_RDLCK:
118 oflp->l_type = SVR4_F_RDLCK;
119 break;
120 case F_WRLCK:
121 oflp->l_type = SVR4_F_WRLCK;
122 break;
123 case F_UNLCK:
124 oflp->l_type = SVR4_F_UNLCK;
125 break;
126 default:
127 oflp->l_type = -1;
128 break;
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;
134 oflp->l_sysid = 0;
135 oflp->l_pid = (svr4_32_pid_t) iflp->l_pid;
139 static void
140 svr4_32_to_bsd_flock(struct svr4_32_flock *iflp, struct flock *oflp)
142 switch (iflp->l_type) {
143 case SVR4_F_RDLCK:
144 oflp->l_type = F_RDLCK;
145 break;
146 case SVR4_F_WRLCK:
147 oflp->l_type = F_WRLCK;
148 break;
149 case SVR4_F_UNLCK:
150 oflp->l_type = F_UNLCK;
151 break;
152 default:
153 oflp->l_type = -1;
154 break;
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;
164 static void
165 bsd_to_svr4_32_flock64(struct flock *iflp, struct svr4_32_flock64 *oflp)
167 switch (iflp->l_type) {
168 case F_RDLCK:
169 oflp->l_type = SVR4_F_RDLCK;
170 break;
171 case F_WRLCK:
172 oflp->l_type = SVR4_F_WRLCK;
173 break;
174 case F_UNLCK:
175 oflp->l_type = SVR4_F_UNLCK;
176 break;
177 default:
178 oflp->l_type = -1;
179 break;
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;
185 oflp->l_sysid = 0;
186 oflp->l_pid = (svr4_32_pid_t) iflp->l_pid;
190 static void
191 svr4_32_to_bsd_flock64(struct svr4_32_flock64 *iflp, struct flock *oflp)
193 switch (iflp->l_type) {
194 case SVR4_F_RDLCK:
195 oflp->l_type = F_RDLCK;
196 break;
197 case SVR4_F_WRLCK:
198 oflp->l_type = F_WRLCK;
199 break;
200 case SVR4_F_UNLCK:
201 oflp->l_type = F_UNLCK;
202 break;
203 default:
204 oflp->l_type = -1;
205 break;
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;
216 static int
217 fd_revoke(struct lwp *l, int fd, register_t *retval)
219 file_t *fp;
220 struct vnode *vp;
221 int error;
223 if ((fp = fd_getfile(fd)) == NULL)
224 return EBADF;
226 if (fp->f_type != DTYPE_VNODE) {
227 fd_putfile(fd);
228 return EINVAL;
231 vp = fp->f_data;
232 if (vp->v_type != VCHR && vp->v_type != VBLK) {
233 error = EINVAL;
234 goto out;
236 error = dorevoke(vp, l->l_cred);
237 out:
238 vrele(vp);
239 fd_putfile(fd);
240 return error;
244 static int
245 fd_truncate(struct lwp *l, int fd, struct flock *flp, register_t *retval)
247 file_t *fp;
248 off_t start, length;
249 struct vnode *vp;
250 struct vattr vattr;
251 int error;
252 struct sys_ftruncate_args ft;
255 * We only support truncating the file.
257 if ((fp = fd_getfile(fd)) == NULL)
258 return EBADF;
259 vp = fp->f_data;
260 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
261 fd_putfile(fd);
262 return ESPIPE;
264 if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0) {
265 fd_putfile(fd);
266 return error;
269 length = vattr.va_size;
271 switch (flp->l_whence) {
272 case SEEK_CUR:
273 start = fp->f_offset + flp->l_start;
274 break;
276 case SEEK_END:
277 start = flp->l_start + length;
278 break;
280 case SEEK_SET:
281 start = flp->l_start;
282 break;
284 default:
285 fd_putfile(fd);
286 return EINVAL;
289 if (start + flp->l_len < length) {
290 /* We don't support free'ing in the middle of the file */
291 fd_putfile(fd);
292 return EINVAL;
295 SCARG(&ft, fd) = fd;
296 SCARG(&ft, length) = start;
298 error = sys_ftruncate(l, &ft, retval);
299 fd_putfile(fd);
300 return error;
305 svr4_32_sys_open(struct lwp *l, const struct svr4_32_sys_open_args *uap, register_t *retval)
307 int error;
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);
316 if (error)
317 return error;
319 /* XXXAD locking */
321 if (!(SCARG(&cup, flags) & O_NOCTTY) && SESS_LEADER(l->l_proc) &&
322 !(l->l_proc->p_lflag & PL_CONTROLT)) {
323 file_t *fp;
324 int fd;
326 fd = *retval;
327 fp = fd_getfile(fd);
329 /* ignore any error, just give it a try */
330 if (fp != NULL) {
331 if (fp->f_type == DTYPE_VNODE)
332 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, NULL);
333 fd_putfile(fd);
336 return 0;
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) |
362 SCARG(uap, offset2);
363 #else
364 SCARG(&ap, offset) = (((long long) SCARG(uap, offset2)) << 32) |
365 SCARG(uap, offset1);
366 #endif
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;
460 register_t flags;
461 struct svr4_32_flock64 ifl64;
462 struct svr4_32_flock ifl;
463 struct flock fl;
464 int error;
465 int cmd;
467 SCARG(&fa, fd) = SCARG(uap, fd);
468 SCARG(&fa, arg) = SCARG_P32(uap, arg);
470 switch (SCARG(uap, cmd)) {
471 case SVR4_F_DUPFD:
472 cmd = F_DUPFD;
473 break;
474 case SVR4_F_GETFD:
475 cmd = F_GETFD;
476 break;
477 case SVR4_F_SETFD:
478 cmd = F_SETFD;
479 break;
481 case SVR4_F_GETFL:
482 cmd = F_GETFL;
483 break;
485 case SVR4_F_SETFL:
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)
492 return error;
493 flags &= O_ASYNC;
494 flags |= svr4_32_to_bsd_flags((u_long) SCARG_P32(uap, arg));
495 cmd = F_SETFL;
496 SCARG(&fa, arg) = (void *) flags;
497 break;
499 case SVR4_F_GETLK:
500 cmd = F_GETLK;
501 goto lock32;
502 case SVR4_F_SETLK:
503 cmd = F_SETLK;
504 goto lock32;
505 case SVR4_F_SETLKW:
506 cmd = F_SETLKW;
507 lock32:
508 error = copyin(SCARG_P32(uap, arg), &ifl, sizeof ifl);
509 if (error)
510 return error;
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)
515 return error;
517 bsd_to_svr4_32_flock(&fl, &ifl);
518 return copyout(&ifl, SCARG_P32(uap, arg), sizeof ifl);
520 case SVR4_F_DUP2FD:
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);
527 if (error)
528 return error;
529 *retval = SCARG(&du, to);
530 return 0;
533 case SVR4_F_FREESP:
534 error = copyin(SCARG_P32(uap, arg), &ifl, sizeof ifl);
535 if (error)
536 return error;
537 svr4_32_to_bsd_flock(&ifl, &fl);
538 return fd_truncate(l, SCARG(uap, fd), &fl, retval);
540 case SVR4_F_GETLK64:
541 cmd = F_GETLK;
542 goto lock64;
543 case SVR4_F_SETLK64:
544 cmd = F_SETLK;
545 goto lock64;
546 case SVR4_F_SETLKW64:
547 cmd = F_SETLKW;
548 lock64:
549 error = copyin(SCARG_P32(uap, arg), &ifl64, sizeof ifl64);
550 if (error)
551 return error;
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)
556 return error;
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);
563 if (error)
564 return error;
565 svr4_32_to_bsd_flock64(&ifl64, &fl);
566 return fd_truncate(l, SCARG(uap, fd), &fl, retval);
568 case SVR4_F_REVOKE:
569 return fd_revoke(l, SCARG(uap, fd), retval);
571 default:
572 return ENOSYS;
575 SCARG(&fa, cmd) = cmd;
577 error = sys_fcntl(l, &fa, retval);
578 if (error != 0)
579 return error;
581 switch (SCARG(uap, cmd)) {
583 case SVR4_F_GETFL:
584 *retval = bsd_to_svr4_32_flags(*retval);
585 break;
588 return 0;