No empty .Rs/.Re
[netbsd-mini2440.git] / sys / compat / svr4 / svr4_fcntl.c
blobe0cabb7053dc85e21751ca8dea743efce81c6b47
1 /* $NetBSD: svr4_fcntl.c,v 1.69 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_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>
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/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 *);
69 static int
70 svr4_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_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_flock(struct flock *iflp, struct svr4_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_off_t) iflp->l_start;
133 oflp->l_len = (svr4_off_t) iflp->l_len;
134 oflp->l_sysid = 0;
135 oflp->l_pid = (svr4_pid_t) iflp->l_pid;
139 static void
140 svr4_to_bsd_flock(struct svr4_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_flock64(struct flock *iflp, struct svr4_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_off64_t) iflp->l_start;
184 oflp->l_len = (svr4_off64_t) iflp->l_len;
185 oflp->l_sysid = 0;
186 oflp->l_pid = (svr4_pid_t) iflp->l_pid;
190 static void
191 svr4_to_bsd_flock64(struct svr4_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 vnode_t *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 = (vnode_t *) fp->f_data;
232 if (vp->v_type != VCHR && vp->v_type != VBLK) {
233 error = EINVAL;
234 goto out;
237 error = dorevoke(vp, l->l_cred);
238 out:
239 vrele(vp);
240 fd_putfile(fd);
241 return error;
245 static int
246 fd_truncate(struct lwp *l, int fd, struct flock *flp, register_t *retval)
248 file_t *fp;
249 off_t start, length;
250 vnode_t *vp;
251 struct vattr vattr;
252 int error;
253 struct sys_ftruncate_args ft;
256 * We only support truncating the file.
258 if ((fp = fd_getfile(fd)) == NULL)
259 return EBADF;
261 vp = fp->f_data;
262 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
263 fd_putfile(fd);
264 return ESPIPE;
266 if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0) {
267 fd_putfile(fd);
268 return error;
271 length = vattr.va_size;
273 switch (flp->l_whence) {
274 case SEEK_CUR:
275 start = fp->f_offset + flp->l_start;
276 break;
278 case SEEK_END:
279 start = flp->l_start + length;
280 break;
282 case SEEK_SET:
283 start = flp->l_start;
284 break;
286 default:
287 fd_putfile(fd);
288 return EINVAL;
291 if (start + flp->l_len < length) {
292 /* We don't support free'ing in the middle of the file */
293 fd_putfile(fd);
294 return EINVAL;
297 SCARG(&ft, fd) = fd;
298 SCARG(&ft, length) = start;
300 error = sys_ftruncate(l, &ft, retval);
301 fd_putfile(fd);
302 return error;
307 svr4_sys_open(struct lwp *l, const struct svr4_sys_open_args *uap, register_t *retval)
309 int error;
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);
318 if (error)
319 return error;
321 /* XXXAD locking */
323 if (!(SCARG(&cup, flags) & O_NOCTTY) && SESS_LEADER(l->l_proc) &&
324 !(l->l_proc->p_lflag & PL_CONTROLT)) {
325 file_t *fp;
326 fp = fd_getfile(*retval);
328 /* ignore any error, just give it a try */
329 if (fp != NULL) {
330 if (fp->f_type == DTYPE_VNODE)
331 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, NULL);
332 fd_putfile(*retval);
335 return 0;
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) |
375 SCARG(uap, offset2);
376 #else
377 SCARG(&ap, offset) = (((long long) SCARG(uap, offset2)) << 32) |
378 SCARG(uap, offset1);
379 #endif
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;
473 register_t flags;
474 struct svr4_flock64 ifl64;
475 struct svr4_flock ifl;
476 struct flock fl;
477 int error;
478 int cmd;
480 SCARG(&fa, fd) = SCARG(uap, fd);
481 SCARG(&fa, arg) = SCARG(uap, arg);
483 switch (SCARG(uap, cmd)) {
484 case SVR4_F_DUPFD:
485 cmd = F_DUPFD;
486 break;
487 case SVR4_F_GETFD:
488 cmd = F_GETFD;
489 break;
490 case SVR4_F_SETFD:
491 cmd = F_SETFD;
492 break;
494 case SVR4_F_GETFL:
495 cmd = F_GETFL;
496 break;
498 case SVR4_F_SETFL:
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)
505 return error;
506 flags &= O_ASYNC;
507 flags |= svr4_to_bsd_flags((u_long) SCARG(uap, arg));
508 cmd = F_SETFL;
509 SCARG(&fa, arg) = (void *) flags;
510 break;
512 case SVR4_F_GETLK:
513 cmd = F_GETLK;
514 goto lock32;
515 case SVR4_F_SETLK:
516 cmd = F_SETLK;
517 goto lock32;
518 case SVR4_F_SETLKW:
519 cmd = F_SETLKW;
520 lock32:
521 error = copyin(SCARG(uap, arg), &ifl, sizeof ifl);
522 if (error)
523 return error;
524 svr4_to_bsd_flock(&ifl, &fl);
526 error = do_fcntl_lock(SCARG(uap, fd), cmd, &fl);
527 if (cmd != F_GETLK || error != 0)
528 return error;
530 bsd_to_svr4_flock(&fl, &ifl);
531 return copyout(&ifl, SCARG(uap, arg), sizeof ifl);
533 case SVR4_F_DUP2FD:
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);
540 if (error)
541 return error;
542 *retval = SCARG(&du, to);
543 return 0;
546 case SVR4_F_FREESP:
547 error = copyin(SCARG(uap, arg), &ifl, sizeof ifl);
548 if (error)
549 return error;
550 svr4_to_bsd_flock(&ifl, &fl);
551 return fd_truncate(l, SCARG(uap, fd), &fl, retval);
553 case SVR4_F_GETLK64:
554 cmd = F_GETLK;
555 goto lock64;
556 case SVR4_F_SETLK64:
557 cmd = F_SETLK;
558 goto lock64;
559 case SVR4_F_SETLKW64:
560 cmd = F_SETLKW;
561 lock64:
562 error = copyin(SCARG(uap, arg), &ifl64, sizeof ifl64);
563 if (error)
564 return error;
565 svr4_to_bsd_flock64(&ifl64, &fl);
567 error = do_fcntl_lock(SCARG(uap, fd), cmd, &fl);
568 if (cmd != F_GETLK || error != 0)
569 return error;
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);
576 if (error)
577 return error;
578 svr4_to_bsd_flock64(&ifl64, &fl);
579 return fd_truncate(l, SCARG(uap, fd), &fl, retval);
581 case SVR4_F_REVOKE:
582 return fd_revoke(l, SCARG(uap, fd), retval);
584 default:
585 return ENOSYS;
588 SCARG(&fa, cmd) = cmd;
590 error = sys_fcntl(l, &fa, retval);
591 if (error != 0)
592 return error;
594 switch (SCARG(uap, cmd)) {
596 case SVR4_F_GETFL:
597 *retval = bsd_to_svr4_flags(*retval);
598 break;
601 return 0;