2 * Copyright (c) 1998 Mark Newton
3 * Copyright (c) 1994, 1997 Christos Zoulas.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Christos Zoulas.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include <sys/param.h>
36 #include <sys/systm.h>
38 #include <sys/filedesc.h>
39 /*#include <sys/ioctl.h>*/
41 #include <sys/malloc.h>
42 #include <sys/mount.h>
43 #include <sys/mutex.h>
44 #include <sys/namei.h>
48 #include <sys/syscallsubr.h>
49 #include <sys/unistd.h>
50 #include <sys/vnode.h>
52 #include <sys/sysproto.h>
54 #include <compat/svr4/svr4.h>
55 #include <compat/svr4/svr4_types.h>
56 #include <compat/svr4/svr4_signal.h>
57 #include <compat/svr4/svr4_proto.h>
58 #include <compat/svr4/svr4_util.h>
59 #include <compat/svr4/svr4_fcntl.h>
61 #include <security/mac/mac_framework.h>
63 static int svr4_to_bsd_flags(int);
64 static u_long svr4_to_bsd_cmd(u_long);
65 static int fd_revoke(struct thread *, int);
66 static int fd_truncate(struct thread *, int, struct flock *);
67 static int bsd_to_svr4_flags(int);
68 static void bsd_to_svr4_flock(struct flock *, struct svr4_flock *);
69 static void svr4_to_bsd_flock(struct svr4_flock *, struct flock *);
70 static void bsd_to_svr4_flock64(struct flock *, struct svr4_flock64 *);
71 static void svr4_to_bsd_flock64(struct svr4_flock64 *, struct flock *);
106 r |= (l & SVR4_O_RDONLY) ? O_RDONLY : 0;
107 r |= (l & SVR4_O_WRONLY) ? O_WRONLY : 0;
108 r |= (l & SVR4_O_RDWR) ? O_RDWR : 0;
109 r |= (l & SVR4_O_NDELAY) ? O_NONBLOCK : 0;
110 r |= (l & SVR4_O_APPEND) ? O_APPEND : 0;
111 r |= (l & SVR4_O_SYNC) ? O_FSYNC : 0;
112 r |= (l & SVR4_O_NONBLOCK) ? O_NONBLOCK : 0;
113 r |= (l & SVR4_O_PRIV) ? O_EXLOCK : 0;
114 r |= (l & SVR4_O_CREAT) ? O_CREAT : 0;
115 r |= (l & SVR4_O_TRUNC) ? O_TRUNC : 0;
116 r |= (l & SVR4_O_EXCL) ? O_EXCL : 0;
117 r |= (l & SVR4_O_NOCTTY) ? O_NOCTTY : 0;
126 r |= (l & O_RDONLY) ? SVR4_O_RDONLY : 0;
127 r |= (l & O_WRONLY) ? SVR4_O_WRONLY : 0;
128 r |= (l & O_RDWR) ? SVR4_O_RDWR : 0;
129 r |= (l & O_NDELAY) ? SVR4_O_NONBLOCK : 0;
130 r |= (l & O_APPEND) ? SVR4_O_APPEND : 0;
131 r |= (l & O_FSYNC) ? SVR4_O_SYNC : 0;
132 r |= (l & O_NONBLOCK) ? SVR4_O_NONBLOCK : 0;
133 r |= (l & O_EXLOCK) ? SVR4_O_PRIV : 0;
134 r |= (l & O_CREAT) ? SVR4_O_CREAT : 0;
135 r |= (l & O_TRUNC) ? SVR4_O_TRUNC : 0;
136 r |= (l & O_EXCL) ? SVR4_O_EXCL : 0;
137 r |= (l & O_NOCTTY) ? SVR4_O_NOCTTY : 0;
143 bsd_to_svr4_flock(iflp, oflp)
145 struct svr4_flock *oflp;
147 switch (iflp->l_type) {
149 oflp->l_type = SVR4_F_RDLCK;
152 oflp->l_type = SVR4_F_WRLCK;
155 oflp->l_type = SVR4_F_UNLCK;
162 oflp->l_whence = (short) iflp->l_whence;
163 oflp->l_start = (svr4_off_t) iflp->l_start;
164 oflp->l_len = (svr4_off_t) iflp->l_len;
166 oflp->l_pid = (svr4_pid_t) iflp->l_pid;
171 svr4_to_bsd_flock(iflp, oflp)
172 struct svr4_flock *iflp;
175 switch (iflp->l_type) {
177 oflp->l_type = F_RDLCK;
180 oflp->l_type = F_WRLCK;
183 oflp->l_type = F_UNLCK;
190 oflp->l_whence = iflp->l_whence;
191 oflp->l_start = (off_t) iflp->l_start;
192 oflp->l_len = (off_t) iflp->l_len;
193 oflp->l_pid = (pid_t) iflp->l_pid;
194 oflp->l_sysid = iflp->l_sysid;
198 bsd_to_svr4_flock64(iflp, oflp)
200 struct svr4_flock64 *oflp;
202 switch (iflp->l_type) {
204 oflp->l_type = SVR4_F_RDLCK;
207 oflp->l_type = SVR4_F_WRLCK;
210 oflp->l_type = SVR4_F_UNLCK;
217 oflp->l_whence = (short) iflp->l_whence;
218 oflp->l_start = (svr4_off64_t) iflp->l_start;
219 oflp->l_len = (svr4_off64_t) iflp->l_len;
220 oflp->l_sysid = iflp->l_sysid;
221 oflp->l_pid = (svr4_pid_t) iflp->l_pid;
226 svr4_to_bsd_flock64(iflp, oflp)
227 struct svr4_flock64 *iflp;
230 switch (iflp->l_type) {
232 oflp->l_type = F_RDLCK;
235 oflp->l_type = F_WRLCK;
238 oflp->l_type = F_UNLCK;
245 oflp->l_whence = iflp->l_whence;
246 oflp->l_start = (off_t) iflp->l_start;
247 oflp->l_len = (off_t) iflp->l_len;
248 oflp->l_pid = (pid_t) iflp->l_pid;
263 retval = td->td_retval;
264 if ((error = fgetvp(td, fd, &vp)) != 0)
267 if (vp->v_type != VCHR && vp->v_type != VBLK) {
273 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
274 error = mac_vnode_check_revoke(td->td_ucred, vp);
280 if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred)) != 0)
283 if (td->td_ucred->cr_uid != vattr.va_uid &&
284 (error = priv_check(td, PRIV_VFS_ADMIN)) != 0)
287 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
290 VOP_REVOKE(vp, REVOKEALL);
291 vn_finished_write(mp);
299 fd_truncate(td, fd, flp)
309 struct ftruncate_args ft;
311 retval = td->td_retval;
314 * We only support truncating the file.
316 if ((error = fget(td, fd, &fp)) != 0)
321 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
326 if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred)) != 0) {
331 length = vattr.va_size;
333 switch (flp->l_whence) {
335 start = fp->f_offset + flp->l_start;
339 start = flp->l_start + length;
343 start = flp->l_start;
351 if (start + flp->l_len < length) {
352 /* We don't support free'ing in the middle of the file */
360 error = ftruncate(td, &ft);
367 svr4_sys_open(td, uap)
369 struct svr4_sys_open_args *uap;
371 struct proc *p = td->td_proc;
373 int bsd_flags, error, retval;
375 CHECKALTEXIST(td, uap->path, &newpath);
377 bsd_flags = svr4_to_bsd_flags(uap->flags);
378 error = kern_open(td, newpath, UIO_SYSSPACE, bsd_flags, uap->mode);
379 free(newpath, M_TEMP);
382 /* uprintf("svr4_open(%s, 0x%0x, 0%o): %d\n", uap->path,
383 uap->flags, uap->mode, error);*/
387 retval = td->td_retval[0];
390 if (!(bsd_flags & O_NOCTTY) && SESS_LEADER(p) &&
391 !(p->p_flag & P_CONTROLT)) {
395 error = fget(td, retval, &fp);
398 * we may have lost a race the above open() and
399 * another thread issuing a close()
402 return (EBADF); /* XXX: correct errno? */
403 /* ignore any error, just give it a try */
404 if (fp->f_type == DTYPE_VNODE)
405 fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred,
419 svr4_sys_open64(td, uap)
421 struct svr4_sys_open64_args *uap;
423 return svr4_sys_open(td, (struct svr4_sys_open_args *)uap);
427 svr4_sys_creat(td, uap)
429 struct svr4_sys_creat_args *uap;
434 CHECKALTEXIST(td, uap->path, &newpath);
436 error = kern_open(td, newpath, UIO_SYSSPACE, O_WRONLY | O_CREAT |
438 free(newpath, M_TEMP);
443 svr4_sys_creat64(td, uap)
445 struct svr4_sys_creat64_args *uap;
447 return svr4_sys_creat(td, (struct svr4_sys_creat_args *)uap);
451 svr4_sys_llseek(td, uap)
453 struct svr4_sys_llseek_args *uap;
455 struct lseek_args ap;
459 #if BYTE_ORDER == BIG_ENDIAN
460 ap.offset = (((u_int64_t) uap->offset1) << 32) |
463 ap.offset = (((u_int64_t) uap->offset2) << 32) |
466 ap.whence = uap->whence;
468 return lseek(td, &ap);
472 svr4_sys_access(td, uap)
474 struct svr4_sys_access_args *uap;
479 CHECKALTEXIST(td, uap->path, &newpath);
480 error = kern_access(td, newpath, UIO_SYSSPACE, uap->flags);
481 free(newpath, M_TEMP);
487 svr4_sys_pread(td, uap)
489 struct svr4_sys_pread_args *uap;
491 struct pread_args pra;
494 * Just translate the args structure and call the NetBSD
495 * pread(2) system call (offset type is 64-bit in NetBSD).
499 pra.nbyte = uap->nbyte;
500 pra.offset = uap->off;
502 return pread(td, &pra);
508 svr4_sys_pread64(td, v, retval)
514 struct svr4_sys_pread64_args *uap = v;
515 struct sys_pread_args pra;
518 * Just translate the args structure and call the NetBSD
519 * pread(2) system call (offset type is 64-bit in NetBSD).
523 pra.nbyte = uap->nbyte;
524 pra.offset = uap->off;
526 return (sys_pread(td, &pra, retval));
532 svr4_sys_pwrite(td, uap)
534 struct svr4_sys_pwrite_args *uap;
536 struct pwrite_args pwa;
539 * Just translate the args structure and call the NetBSD
540 * pwrite(2) system call (offset type is 64-bit in NetBSD).
544 pwa.nbyte = uap->nbyte;
545 pwa.offset = uap->off;
547 return pwrite(td, &pwa);
553 svr4_sys_pwrite64(td, v, retval)
558 struct svr4_sys_pwrite64_args *uap = v;
559 struct sys_pwrite_args pwa;
562 * Just translate the args structure and call the NetBSD
563 * pwrite(2) system call (offset type is 64-bit in NetBSD).
567 pwa.nbyte = uap->nbyte;
568 pwa.offset = uap->off;
570 return (sys_pwrite(td, &pwa, retval));
575 svr4_sys_fcntl(td, uap)
577 struct svr4_sys_fcntl_args *uap;
579 int cmd, error, *retval;
581 retval = td->td_retval;
583 cmd = svr4_to_bsd_cmd(uap->cmd);
590 return (kern_fcntl(td, uap->fd, cmd, (intptr_t)uap->arg));
593 error = kern_fcntl(td, uap->fd, cmd, (intptr_t)uap->arg);
596 *retval = bsd_to_svr4_flags(*retval);
602 * we must save the O_ASYNC flag, as that is
603 * handled by ioctl(_, I_SETSIG, _) emulation.
607 DPRINTF(("Setting flags %p\n", uap->arg));
609 error = kern_fcntl(td, uap->fd, F_GETFL, 0);
614 flags |= svr4_to_bsd_flags((u_long) uap->arg);
615 return (kern_fcntl(td, uap->fd, F_SETFL, flags));
622 struct svr4_flock ifl;
625 error = copyin(uap->arg, &ifl, sizeof (ifl));
629 svr4_to_bsd_flock(&ifl, &fl);
631 error = kern_fcntl(td, uap->fd, cmd, (intptr_t)&fl);
632 if (error || cmd != F_GETLK)
635 bsd_to_svr4_flock(&fl, &ifl);
637 return (copyout(&ifl, uap->arg, sizeof (ifl)));
643 struct svr4_flock ifl;
646 error = copyin(uap->arg, &ifl,
650 svr4_to_bsd_flock(&ifl, &fl);
651 return fd_truncate(td, uap->fd, &fl);
656 case SVR4_F_SETLKW64:
658 struct svr4_flock64 ifl;
668 case SVR4_F_SETLKW64:
672 error = copyin(uap->arg, &ifl,
677 svr4_to_bsd_flock64(&ifl, &fl);
679 error = kern_fcntl(td, uap->fd, cmd,
681 if (error || cmd != F_GETLK)
684 bsd_to_svr4_flock64(&fl, &ifl);
686 return (copyout(&ifl, uap->arg,
690 case SVR4_F_FREESP64:
692 struct svr4_flock64 ifl;
695 error = copyin(uap->arg, &ifl,
699 svr4_to_bsd_flock64(&ifl, &fl);
700 return fd_truncate(td, uap->fd, &fl);
704 return fd_revoke(td, uap->fd);