Deleted Added
full compact
svr4_fcntl.c (109153) svr4_fcntl.c (116174)
1/*
2 * Copyright (c) 1998 Mark Newton
3 * Copyright (c) 1994, 1997 Christos Zoulas.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
19 *
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.
1/*
2 * Copyright (c) 1998 Mark Newton
3 * Copyright (c) 1994, 1997 Christos Zoulas.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
19 *
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.
30 *
31 * $FreeBSD: head/sys/compat/svr4/svr4_fcntl.c 109153 2003-01-13 00:33:17Z dillon $
32 */
33
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/compat/svr4/svr4_fcntl.c 116174 2003-06-10 21:44:29Z obrien $");
34
34#include "opt_mac.h"
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/file.h>
39#include <sys/filedesc.h>
40/*#include <sys/ioctl.h>*/
41#include <sys/lock.h>
42#include <sys/mac.h>
43#include <sys/mount.h>
44#include <sys/mutex.h>
45#include <sys/namei.h>
46#include <sys/proc.h>
47#include <sys/stat.h>
48#include <sys/unistd.h>
49#include <sys/vnode.h>
50
51#include <sys/sysproto.h>
52
53#include <compat/svr4/svr4.h>
54#include <compat/svr4/svr4_types.h>
55#include <compat/svr4/svr4_signal.h>
56#include <compat/svr4/svr4_proto.h>
57#include <compat/svr4/svr4_util.h>
58#include <compat/svr4/svr4_fcntl.h>
59
60static int svr4_to_bsd_flags(int);
61static u_long svr4_to_bsd_cmd(u_long);
62static int fd_revoke(struct thread *, int);
63static int fd_truncate(struct thread *, int, struct flock *);
64static int bsd_to_svr4_flags(int);
65static void bsd_to_svr4_flock(struct flock *, struct svr4_flock *);
66static void svr4_to_bsd_flock(struct svr4_flock *, struct flock *);
67static void bsd_to_svr4_flock64(struct flock *, struct svr4_flock64 *);
68static void svr4_to_bsd_flock64(struct svr4_flock64 *, struct flock *);
69
70static u_long
71svr4_to_bsd_cmd(cmd)
72 u_long cmd;
73{
74 switch (cmd) {
75 case SVR4_F_DUPFD:
76 return F_DUPFD;
77 case SVR4_F_GETFD:
78 return F_GETFD;
79 case SVR4_F_SETFD:
80 return F_SETFD;
81 case SVR4_F_GETFL:
82 return F_GETFL;
83 case SVR4_F_SETFL:
84 return F_SETFL;
85 case SVR4_F_GETLK:
86 return F_GETLK;
87 case SVR4_F_SETLK:
88 return F_SETLK;
89 case SVR4_F_SETLKW:
90 return F_SETLKW;
91 default:
92 return -1;
93 }
94}
95
96static int
97svr4_to_bsd_flags(l)
98 int l;
99{
100 int r = 0;
101 r |= (l & SVR4_O_RDONLY) ? O_RDONLY : 0;
102 r |= (l & SVR4_O_WRONLY) ? O_WRONLY : 0;
103 r |= (l & SVR4_O_RDWR) ? O_RDWR : 0;
104 r |= (l & SVR4_O_NDELAY) ? O_NONBLOCK : 0;
105 r |= (l & SVR4_O_APPEND) ? O_APPEND : 0;
106 r |= (l & SVR4_O_SYNC) ? O_FSYNC : 0;
107 r |= (l & SVR4_O_NONBLOCK) ? O_NONBLOCK : 0;
108 r |= (l & SVR4_O_PRIV) ? O_EXLOCK : 0;
109 r |= (l & SVR4_O_CREAT) ? O_CREAT : 0;
110 r |= (l & SVR4_O_TRUNC) ? O_TRUNC : 0;
111 r |= (l & SVR4_O_EXCL) ? O_EXCL : 0;
112 r |= (l & SVR4_O_NOCTTY) ? O_NOCTTY : 0;
113 return r;
114}
115
116static int
117bsd_to_svr4_flags(l)
118 int l;
119{
120 int r = 0;
121 r |= (l & O_RDONLY) ? SVR4_O_RDONLY : 0;
122 r |= (l & O_WRONLY) ? SVR4_O_WRONLY : 0;
123 r |= (l & O_RDWR) ? SVR4_O_RDWR : 0;
124 r |= (l & O_NDELAY) ? SVR4_O_NONBLOCK : 0;
125 r |= (l & O_APPEND) ? SVR4_O_APPEND : 0;
126 r |= (l & O_FSYNC) ? SVR4_O_SYNC : 0;
127 r |= (l & O_NONBLOCK) ? SVR4_O_NONBLOCK : 0;
128 r |= (l & O_EXLOCK) ? SVR4_O_PRIV : 0;
129 r |= (l & O_CREAT) ? SVR4_O_CREAT : 0;
130 r |= (l & O_TRUNC) ? SVR4_O_TRUNC : 0;
131 r |= (l & O_EXCL) ? SVR4_O_EXCL : 0;
132 r |= (l & O_NOCTTY) ? SVR4_O_NOCTTY : 0;
133 return r;
134}
135
136
137static void
138bsd_to_svr4_flock(iflp, oflp)
139 struct flock *iflp;
140 struct svr4_flock *oflp;
141{
142 switch (iflp->l_type) {
143 case F_RDLCK:
144 oflp->l_type = SVR4_F_RDLCK;
145 break;
146 case F_WRLCK:
147 oflp->l_type = SVR4_F_WRLCK;
148 break;
149 case F_UNLCK:
150 oflp->l_type = SVR4_F_UNLCK;
151 break;
152 default:
153 oflp->l_type = -1;
154 break;
155 }
156
157 oflp->l_whence = (short) iflp->l_whence;
158 oflp->l_start = (svr4_off_t) iflp->l_start;
159 oflp->l_len = (svr4_off_t) iflp->l_len;
160 oflp->l_sysid = 0;
161 oflp->l_pid = (svr4_pid_t) iflp->l_pid;
162}
163
164
165static void
166svr4_to_bsd_flock(iflp, oflp)
167 struct svr4_flock *iflp;
168 struct flock *oflp;
169{
170 switch (iflp->l_type) {
171 case SVR4_F_RDLCK:
172 oflp->l_type = F_RDLCK;
173 break;
174 case SVR4_F_WRLCK:
175 oflp->l_type = F_WRLCK;
176 break;
177 case SVR4_F_UNLCK:
178 oflp->l_type = F_UNLCK;
179 break;
180 default:
181 oflp->l_type = -1;
182 break;
183 }
184
185 oflp->l_whence = iflp->l_whence;
186 oflp->l_start = (off_t) iflp->l_start;
187 oflp->l_len = (off_t) iflp->l_len;
188 oflp->l_pid = (pid_t) iflp->l_pid;
189
190}
191
192static void
193bsd_to_svr4_flock64(iflp, oflp)
194 struct flock *iflp;
195 struct svr4_flock64 *oflp;
196{
197 switch (iflp->l_type) {
198 case F_RDLCK:
199 oflp->l_type = SVR4_F_RDLCK;
200 break;
201 case F_WRLCK:
202 oflp->l_type = SVR4_F_WRLCK;
203 break;
204 case F_UNLCK:
205 oflp->l_type = SVR4_F_UNLCK;
206 break;
207 default:
208 oflp->l_type = -1;
209 break;
210 }
211
212 oflp->l_whence = (short) iflp->l_whence;
213 oflp->l_start = (svr4_off64_t) iflp->l_start;
214 oflp->l_len = (svr4_off64_t) iflp->l_len;
215 oflp->l_sysid = 0;
216 oflp->l_pid = (svr4_pid_t) iflp->l_pid;
217}
218
219
220static void
221svr4_to_bsd_flock64(iflp, oflp)
222 struct svr4_flock64 *iflp;
223 struct flock *oflp;
224{
225 switch (iflp->l_type) {
226 case SVR4_F_RDLCK:
227 oflp->l_type = F_RDLCK;
228 break;
229 case SVR4_F_WRLCK:
230 oflp->l_type = F_WRLCK;
231 break;
232 case SVR4_F_UNLCK:
233 oflp->l_type = F_UNLCK;
234 break;
235 default:
236 oflp->l_type = -1;
237 break;
238 }
239
240 oflp->l_whence = iflp->l_whence;
241 oflp->l_start = (off_t) iflp->l_start;
242 oflp->l_len = (off_t) iflp->l_len;
243 oflp->l_pid = (pid_t) iflp->l_pid;
244
245}
246
247
248static int
249fd_revoke(td, fd)
250 struct thread *td;
251 int fd;
252{
253 struct vnode *vp;
254 struct mount *mp;
255 struct vattr vattr;
256 int error, *retval;
257
258 retval = td->td_retval;
259 if ((error = fgetvp(td, fd, &vp)) != 0)
260 return (error);
261
262 if (vp->v_type != VCHR && vp->v_type != VBLK) {
263 error = EINVAL;
264 goto out;
265 }
266
267#ifdef MAC
268 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
269 error = mac_check_vnode_revoke(td->td_ucred, vp);
270 VOP_UNLOCK(vp, 0, td);
271 if (error)
272 goto out;
273#endif
274
275 if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred, td)) != 0)
276 goto out;
277
278 if (td->td_ucred->cr_uid != vattr.va_uid &&
279 (error = suser(td)) != 0)
280 goto out;
281
282 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
283 goto out;
284 if (vcount(vp) > 1)
285 VOP_REVOKE(vp, REVOKEALL);
286 vn_finished_write(mp);
287out:
288 vrele(vp);
289 return error;
290}
291
292
293static int
294fd_truncate(td, fd, flp)
295 struct thread *td;
296 int fd;
297 struct flock *flp;
298{
299 off_t start, length;
300 struct file *fp;
301 struct vnode *vp;
302 struct vattr vattr;
303 int error, *retval;
304 struct ftruncate_args ft;
305
306 retval = td->td_retval;
307
308 /*
309 * We only support truncating the file.
310 */
311 if ((error = fget(td, fd, &fp)) != 0)
312 return (error);
313
314 vp = fp->f_data;
315
316 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
317 fdrop(fp, td);
318 return ESPIPE;
319 }
320
321 if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred, td)) != 0) {
322 fdrop(fp, td);
323 return error;
324 }
325
326 length = vattr.va_size;
327
328 switch (flp->l_whence) {
329 case SEEK_CUR:
330 start = fp->f_offset + flp->l_start;
331 break;
332
333 case SEEK_END:
334 start = flp->l_start + length;
335 break;
336
337 case SEEK_SET:
338 start = flp->l_start;
339 break;
340
341 default:
342 fdrop(fp, td);
343 return EINVAL;
344 }
345
346 if (start + flp->l_len < length) {
347 /* We don't support free'ing in the middle of the file */
348 fdrop(fp, td);
349 return EINVAL;
350 }
351
352 ft.fd = fd;
353 ft.length = start;
354
355 error = ftruncate(td, &ft);
356
357 fdrop(fp, td);
358 return (error);
359}
360
361int
362svr4_sys_open(td, uap)
363 register struct thread *td;
364 struct svr4_sys_open_args *uap;
365{
366 struct proc *p = td->td_proc;
367 int error, retval;
368 struct open_args cup;
369
370 caddr_t sg = stackgap_init();
371 CHECKALTEXIST(td, &sg, uap->path);
372
373 (&cup)->path = uap->path;
374 (&cup)->flags = svr4_to_bsd_flags(uap->flags);
375 (&cup)->mode = uap->mode;
376 error = open(td, &cup);
377
378 if (error) {
379 /* uprintf("svr4_open(%s, 0x%0x, 0%o): %d\n", uap->path,
380 uap->flags, uap->mode, error);*/
381 return error;
382 }
383
384 retval = td->td_retval[0];
385
386 PROC_LOCK(p);
387 if (!(cup.flags & O_NOCTTY) && SESS_LEADER(p) &&
388 !(td->td_proc->p_flag & P_CONTROLT)) {
389#if defined(NOTYET)
390 struct file *fp;
391
392 error = fget(td, retval, &fp);
393 PROC_UNLOCK(p);
394 /*
395 * we may have lost a race the above open() and
396 * another thread issuing a close()
397 */
398 if (error)
399 return (EBADF); /* XXX: correct errno? */
400 /* ignore any error, just give it a try */
401 if (fp->f_type == DTYPE_VNODE)
402 fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred,
403 td);
404 fdrop(fp, td);
405 } else {
406 PROC_UNLOCK(p);
407 }
408#else
409 }
410 PROC_UNLOCK(p);
411#endif
412 return error;
413}
414
415int
416svr4_sys_open64(td, uap)
417 register struct thread *td;
418 struct svr4_sys_open64_args *uap;
419{
420 return svr4_sys_open(td, (struct svr4_sys_open_args *)uap);
421}
422
423int
424svr4_sys_creat(td, uap)
425 register struct thread *td;
426 struct svr4_sys_creat_args *uap;
427{
428 struct open_args cup;
429
430 caddr_t sg = stackgap_init();
431 CHECKALTEXIST(td, &sg, uap->path);
432
433 cup.path = uap->path;
434 cup.mode = uap->mode;
435 cup.flags = O_WRONLY | O_CREAT | O_TRUNC;
436
437 return open(td, &cup);
438}
439
440int
441svr4_sys_creat64(td, uap)
442 register struct thread *td;
443 struct svr4_sys_creat64_args *uap;
444{
445 return svr4_sys_creat(td, (struct svr4_sys_creat_args *)uap);
446}
447
448int
449svr4_sys_llseek(td, uap)
450 register struct thread *td;
451 struct svr4_sys_llseek_args *uap;
452{
453 struct lseek_args ap;
454
455 ap.fd = uap->fd;
456
457#if BYTE_ORDER == BIG_ENDIAN
458 ap.offset = (((u_int64_t) uap->offset1) << 32) |
459 uap->offset2;
460#else
461 ap.offset = (((u_int64_t) uap->offset2) << 32) |
462 uap->offset1;
463#endif
464 ap.whence = uap->whence;
465
466 return lseek(td, &ap);
467}
468
469int
470svr4_sys_access(td, uap)
471 register struct thread *td;
472 struct svr4_sys_access_args *uap;
473{
474 struct access_args cup;
475 int *retval;
476
477 caddr_t sg = stackgap_init();
478 CHECKALTEXIST(td, &sg, uap->path);
479
480 retval = td->td_retval;
481
482 cup.path = uap->path;
483 cup.flags = uap->flags;
484
485 return access(td, &cup);
486}
487
488#if defined(NOTYET)
489int
490svr4_sys_pread(td, uap)
491 register struct thread *td;
492 struct svr4_sys_pread_args *uap;
493{
494 struct pread_args pra;
495
496 /*
497 * Just translate the args structure and call the NetBSD
498 * pread(2) system call (offset type is 64-bit in NetBSD).
499 */
500 pra.fd = uap->fd;
501 pra.buf = uap->buf;
502 pra.nbyte = uap->nbyte;
503 pra.offset = uap->off;
504
505 return pread(td, &pra);
506}
507#endif
508
509#if defined(NOTYET)
510int
511svr4_sys_pread64(td, v, retval)
512 register struct thread *td;
513 void *v;
514 register_t *retval;
515{
516
517 struct svr4_sys_pread64_args *uap = v;
518 struct sys_pread_args pra;
519
520 /*
521 * Just translate the args structure and call the NetBSD
522 * pread(2) system call (offset type is 64-bit in NetBSD).
523 */
524 pra.fd = uap->fd;
525 pra.buf = uap->buf;
526 pra.nbyte = uap->nbyte;
527 pra.offset = uap->off;
528
529 return (sys_pread(td, &pra, retval));
530}
531#endif /* NOTYET */
532
533#if defined(NOTYET)
534int
535svr4_sys_pwrite(td, uap)
536 register struct thread *td;
537 struct svr4_sys_pwrite_args *uap;
538{
539 struct pwrite_args pwa;
540
541 /*
542 * Just translate the args structure and call the NetBSD
543 * pwrite(2) system call (offset type is 64-bit in NetBSD).
544 */
545 pwa.fd = uap->fd;
546 pwa.buf = uap->buf;
547 pwa.nbyte = uap->nbyte;
548 pwa.offset = uap->off;
549
550 return pwrite(td, &pwa);
551}
552#endif
553
554#if defined(NOTYET)
555int
556svr4_sys_pwrite64(td, v, retval)
557 register struct thread *td;
558 void *v;
559 register_t *retval;
560{
561 struct svr4_sys_pwrite64_args *uap = v;
562 struct sys_pwrite_args pwa;
563
564 /*
565 * Just translate the args structure and call the NetBSD
566 * pwrite(2) system call (offset type is 64-bit in NetBSD).
567 */
568 pwa.fd = uap->fd;
569 pwa.buf = uap->buf;
570 pwa.nbyte = uap->nbyte;
571 pwa.offset = uap->off;
572
573 return (sys_pwrite(td, &pwa, retval));
574}
575#endif /* NOTYET */
576
577int
578svr4_sys_fcntl(td, uap)
579 register struct thread *td;
580 struct svr4_sys_fcntl_args *uap;
581{
582 int error;
583 struct fcntl_args fa;
584 int *retval;
585
586 retval = td->td_retval;
587
588 fa.fd = uap->fd;
589 fa.cmd = svr4_to_bsd_cmd(uap->cmd);
590
591 switch (fa.cmd) {
592 case F_DUPFD:
593 case F_GETFD:
594 case F_SETFD:
595 fa.arg = (long) uap->arg;
596 return fcntl(td, &fa);
597
598 case F_GETFL:
599 fa.arg = (long) uap->arg;
600 error = fcntl(td, &fa);
601 if (error)
602 return error;
603 *retval = bsd_to_svr4_flags(*retval);
604 return error;
605
606 case F_SETFL:
607 {
608 /*
609 * we must save the O_ASYNC flag, as that is
610 * handled by ioctl(_, I_SETSIG, _) emulation.
611 */
612 long cmd;
613 int flags;
614
615 DPRINTF(("Setting flags %p\n", uap->arg));
616 cmd = fa.cmd; /* save it for a while */
617
618 fa.cmd = F_GETFL;
619 if ((error = fcntl(td, &fa)) != 0)
620 return error;
621 flags = *retval;
622 flags &= O_ASYNC;
623 flags |= svr4_to_bsd_flags((u_long) uap->arg);
624 fa.cmd = cmd;
625 fa.arg = (long) flags;
626 return fcntl(td, &fa);
627 }
628
629 case F_GETLK:
630 case F_SETLK:
631 case F_SETLKW:
632 {
633 struct svr4_flock ifl;
634 struct flock *flp, fl;
635 caddr_t sg = stackgap_init();
636
637 flp = stackgap_alloc(&sg, sizeof(struct flock));
638 fa.arg = (long) flp;
639
640 error = copyin(uap->arg, &ifl, sizeof ifl);
641 if (error)
642 return error;
643
644 svr4_to_bsd_flock(&ifl, &fl);
645
646 error = copyout(&fl, flp, sizeof fl);
647 if (error)
648 return error;
649
650 error = fcntl(td, &fa);
651 if (error || fa.cmd != F_GETLK)
652 return error;
653
654 error = copyin(flp, &fl, sizeof fl);
655 if (error)
656 return error;
657
658 bsd_to_svr4_flock(&fl, &ifl);
659
660 return copyout(&ifl, uap->arg, sizeof ifl);
661 }
662 case -1:
663 switch (uap->cmd) {
664 case SVR4_F_DUP2FD:
665 {
666 struct dup2_args du;
667
668 du.from = uap->fd;
669 du.to = (int)uap->arg;
670 error = dup2(td, &du);
671 if (error)
672 return error;
673 *retval = du.to;
674 return 0;
675 }
676
677 case SVR4_F_FREESP:
678 {
679 struct svr4_flock ifl;
680 struct flock fl;
681
682 error = copyin(uap->arg, &ifl,
683 sizeof ifl);
684 if (error)
685 return error;
686 svr4_to_bsd_flock(&ifl, &fl);
687 return fd_truncate(td, uap->fd, &fl);
688 }
689
690 case SVR4_F_GETLK64:
691 case SVR4_F_SETLK64:
692 case SVR4_F_SETLKW64:
693 {
694 struct svr4_flock64 ifl;
695 struct flock *flp, fl;
696 caddr_t sg = stackgap_init();
697
698 flp = stackgap_alloc(&sg, sizeof(struct flock));
699 fa.arg = (long) flp;
700
701 error = copyin(uap->arg, &ifl,
702 sizeof ifl);
703 if (error)
704 return error;
705
706 svr4_to_bsd_flock64(&ifl, &fl);
707
708 error = copyout(&fl, flp, sizeof fl);
709 if (error)
710 return error;
711
712 error = fcntl(td, &fa);
713 if (error || fa.cmd != F_GETLK)
714 return error;
715
716 error = copyin(flp, &fl, sizeof fl);
717 if (error)
718 return error;
719
720 bsd_to_svr4_flock64(&fl, &ifl);
721
722 return copyout(&ifl, uap->arg,
723 sizeof ifl);
724 }
725
726 case SVR4_F_FREESP64:
727 {
728 struct svr4_flock64 ifl;
729 struct flock fl;
730
731 error = copyin(uap->arg, &ifl,
732 sizeof ifl);
733 if (error)
734 return error;
735 svr4_to_bsd_flock64(&ifl, &fl);
736 return fd_truncate(td, uap->fd, &fl);
737 }
738
739 case SVR4_F_REVOKE:
740 return fd_revoke(td, uap->fd);
741
742 default:
743 return ENOSYS;
744 }
745
746 default:
747 return ENOSYS;
748 }
749}
35#include "opt_mac.h"
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/file.h>
40#include <sys/filedesc.h>
41/*#include <sys/ioctl.h>*/
42#include <sys/lock.h>
43#include <sys/mac.h>
44#include <sys/mount.h>
45#include <sys/mutex.h>
46#include <sys/namei.h>
47#include <sys/proc.h>
48#include <sys/stat.h>
49#include <sys/unistd.h>
50#include <sys/vnode.h>
51
52#include <sys/sysproto.h>
53
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>
60
61static int svr4_to_bsd_flags(int);
62static u_long svr4_to_bsd_cmd(u_long);
63static int fd_revoke(struct thread *, int);
64static int fd_truncate(struct thread *, int, struct flock *);
65static int bsd_to_svr4_flags(int);
66static void bsd_to_svr4_flock(struct flock *, struct svr4_flock *);
67static void svr4_to_bsd_flock(struct svr4_flock *, struct flock *);
68static void bsd_to_svr4_flock64(struct flock *, struct svr4_flock64 *);
69static void svr4_to_bsd_flock64(struct svr4_flock64 *, struct flock *);
70
71static u_long
72svr4_to_bsd_cmd(cmd)
73 u_long cmd;
74{
75 switch (cmd) {
76 case SVR4_F_DUPFD:
77 return F_DUPFD;
78 case SVR4_F_GETFD:
79 return F_GETFD;
80 case SVR4_F_SETFD:
81 return F_SETFD;
82 case SVR4_F_GETFL:
83 return F_GETFL;
84 case SVR4_F_SETFL:
85 return F_SETFL;
86 case SVR4_F_GETLK:
87 return F_GETLK;
88 case SVR4_F_SETLK:
89 return F_SETLK;
90 case SVR4_F_SETLKW:
91 return F_SETLKW;
92 default:
93 return -1;
94 }
95}
96
97static int
98svr4_to_bsd_flags(l)
99 int l;
100{
101 int r = 0;
102 r |= (l & SVR4_O_RDONLY) ? O_RDONLY : 0;
103 r |= (l & SVR4_O_WRONLY) ? O_WRONLY : 0;
104 r |= (l & SVR4_O_RDWR) ? O_RDWR : 0;
105 r |= (l & SVR4_O_NDELAY) ? O_NONBLOCK : 0;
106 r |= (l & SVR4_O_APPEND) ? O_APPEND : 0;
107 r |= (l & SVR4_O_SYNC) ? O_FSYNC : 0;
108 r |= (l & SVR4_O_NONBLOCK) ? O_NONBLOCK : 0;
109 r |= (l & SVR4_O_PRIV) ? O_EXLOCK : 0;
110 r |= (l & SVR4_O_CREAT) ? O_CREAT : 0;
111 r |= (l & SVR4_O_TRUNC) ? O_TRUNC : 0;
112 r |= (l & SVR4_O_EXCL) ? O_EXCL : 0;
113 r |= (l & SVR4_O_NOCTTY) ? O_NOCTTY : 0;
114 return r;
115}
116
117static int
118bsd_to_svr4_flags(l)
119 int l;
120{
121 int r = 0;
122 r |= (l & O_RDONLY) ? SVR4_O_RDONLY : 0;
123 r |= (l & O_WRONLY) ? SVR4_O_WRONLY : 0;
124 r |= (l & O_RDWR) ? SVR4_O_RDWR : 0;
125 r |= (l & O_NDELAY) ? SVR4_O_NONBLOCK : 0;
126 r |= (l & O_APPEND) ? SVR4_O_APPEND : 0;
127 r |= (l & O_FSYNC) ? SVR4_O_SYNC : 0;
128 r |= (l & O_NONBLOCK) ? SVR4_O_NONBLOCK : 0;
129 r |= (l & O_EXLOCK) ? SVR4_O_PRIV : 0;
130 r |= (l & O_CREAT) ? SVR4_O_CREAT : 0;
131 r |= (l & O_TRUNC) ? SVR4_O_TRUNC : 0;
132 r |= (l & O_EXCL) ? SVR4_O_EXCL : 0;
133 r |= (l & O_NOCTTY) ? SVR4_O_NOCTTY : 0;
134 return r;
135}
136
137
138static void
139bsd_to_svr4_flock(iflp, oflp)
140 struct flock *iflp;
141 struct svr4_flock *oflp;
142{
143 switch (iflp->l_type) {
144 case F_RDLCK:
145 oflp->l_type = SVR4_F_RDLCK;
146 break;
147 case F_WRLCK:
148 oflp->l_type = SVR4_F_WRLCK;
149 break;
150 case F_UNLCK:
151 oflp->l_type = SVR4_F_UNLCK;
152 break;
153 default:
154 oflp->l_type = -1;
155 break;
156 }
157
158 oflp->l_whence = (short) iflp->l_whence;
159 oflp->l_start = (svr4_off_t) iflp->l_start;
160 oflp->l_len = (svr4_off_t) iflp->l_len;
161 oflp->l_sysid = 0;
162 oflp->l_pid = (svr4_pid_t) iflp->l_pid;
163}
164
165
166static void
167svr4_to_bsd_flock(iflp, oflp)
168 struct svr4_flock *iflp;
169 struct flock *oflp;
170{
171 switch (iflp->l_type) {
172 case SVR4_F_RDLCK:
173 oflp->l_type = F_RDLCK;
174 break;
175 case SVR4_F_WRLCK:
176 oflp->l_type = F_WRLCK;
177 break;
178 case SVR4_F_UNLCK:
179 oflp->l_type = F_UNLCK;
180 break;
181 default:
182 oflp->l_type = -1;
183 break;
184 }
185
186 oflp->l_whence = iflp->l_whence;
187 oflp->l_start = (off_t) iflp->l_start;
188 oflp->l_len = (off_t) iflp->l_len;
189 oflp->l_pid = (pid_t) iflp->l_pid;
190
191}
192
193static void
194bsd_to_svr4_flock64(iflp, oflp)
195 struct flock *iflp;
196 struct svr4_flock64 *oflp;
197{
198 switch (iflp->l_type) {
199 case F_RDLCK:
200 oflp->l_type = SVR4_F_RDLCK;
201 break;
202 case F_WRLCK:
203 oflp->l_type = SVR4_F_WRLCK;
204 break;
205 case F_UNLCK:
206 oflp->l_type = SVR4_F_UNLCK;
207 break;
208 default:
209 oflp->l_type = -1;
210 break;
211 }
212
213 oflp->l_whence = (short) iflp->l_whence;
214 oflp->l_start = (svr4_off64_t) iflp->l_start;
215 oflp->l_len = (svr4_off64_t) iflp->l_len;
216 oflp->l_sysid = 0;
217 oflp->l_pid = (svr4_pid_t) iflp->l_pid;
218}
219
220
221static void
222svr4_to_bsd_flock64(iflp, oflp)
223 struct svr4_flock64 *iflp;
224 struct flock *oflp;
225{
226 switch (iflp->l_type) {
227 case SVR4_F_RDLCK:
228 oflp->l_type = F_RDLCK;
229 break;
230 case SVR4_F_WRLCK:
231 oflp->l_type = F_WRLCK;
232 break;
233 case SVR4_F_UNLCK:
234 oflp->l_type = F_UNLCK;
235 break;
236 default:
237 oflp->l_type = -1;
238 break;
239 }
240
241 oflp->l_whence = iflp->l_whence;
242 oflp->l_start = (off_t) iflp->l_start;
243 oflp->l_len = (off_t) iflp->l_len;
244 oflp->l_pid = (pid_t) iflp->l_pid;
245
246}
247
248
249static int
250fd_revoke(td, fd)
251 struct thread *td;
252 int fd;
253{
254 struct vnode *vp;
255 struct mount *mp;
256 struct vattr vattr;
257 int error, *retval;
258
259 retval = td->td_retval;
260 if ((error = fgetvp(td, fd, &vp)) != 0)
261 return (error);
262
263 if (vp->v_type != VCHR && vp->v_type != VBLK) {
264 error = EINVAL;
265 goto out;
266 }
267
268#ifdef MAC
269 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
270 error = mac_check_vnode_revoke(td->td_ucred, vp);
271 VOP_UNLOCK(vp, 0, td);
272 if (error)
273 goto out;
274#endif
275
276 if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred, td)) != 0)
277 goto out;
278
279 if (td->td_ucred->cr_uid != vattr.va_uid &&
280 (error = suser(td)) != 0)
281 goto out;
282
283 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
284 goto out;
285 if (vcount(vp) > 1)
286 VOP_REVOKE(vp, REVOKEALL);
287 vn_finished_write(mp);
288out:
289 vrele(vp);
290 return error;
291}
292
293
294static int
295fd_truncate(td, fd, flp)
296 struct thread *td;
297 int fd;
298 struct flock *flp;
299{
300 off_t start, length;
301 struct file *fp;
302 struct vnode *vp;
303 struct vattr vattr;
304 int error, *retval;
305 struct ftruncate_args ft;
306
307 retval = td->td_retval;
308
309 /*
310 * We only support truncating the file.
311 */
312 if ((error = fget(td, fd, &fp)) != 0)
313 return (error);
314
315 vp = fp->f_data;
316
317 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
318 fdrop(fp, td);
319 return ESPIPE;
320 }
321
322 if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred, td)) != 0) {
323 fdrop(fp, td);
324 return error;
325 }
326
327 length = vattr.va_size;
328
329 switch (flp->l_whence) {
330 case SEEK_CUR:
331 start = fp->f_offset + flp->l_start;
332 break;
333
334 case SEEK_END:
335 start = flp->l_start + length;
336 break;
337
338 case SEEK_SET:
339 start = flp->l_start;
340 break;
341
342 default:
343 fdrop(fp, td);
344 return EINVAL;
345 }
346
347 if (start + flp->l_len < length) {
348 /* We don't support free'ing in the middle of the file */
349 fdrop(fp, td);
350 return EINVAL;
351 }
352
353 ft.fd = fd;
354 ft.length = start;
355
356 error = ftruncate(td, &ft);
357
358 fdrop(fp, td);
359 return (error);
360}
361
362int
363svr4_sys_open(td, uap)
364 register struct thread *td;
365 struct svr4_sys_open_args *uap;
366{
367 struct proc *p = td->td_proc;
368 int error, retval;
369 struct open_args cup;
370
371 caddr_t sg = stackgap_init();
372 CHECKALTEXIST(td, &sg, uap->path);
373
374 (&cup)->path = uap->path;
375 (&cup)->flags = svr4_to_bsd_flags(uap->flags);
376 (&cup)->mode = uap->mode;
377 error = open(td, &cup);
378
379 if (error) {
380 /* uprintf("svr4_open(%s, 0x%0x, 0%o): %d\n", uap->path,
381 uap->flags, uap->mode, error);*/
382 return error;
383 }
384
385 retval = td->td_retval[0];
386
387 PROC_LOCK(p);
388 if (!(cup.flags & O_NOCTTY) && SESS_LEADER(p) &&
389 !(td->td_proc->p_flag & P_CONTROLT)) {
390#if defined(NOTYET)
391 struct file *fp;
392
393 error = fget(td, retval, &fp);
394 PROC_UNLOCK(p);
395 /*
396 * we may have lost a race the above open() and
397 * another thread issuing a close()
398 */
399 if (error)
400 return (EBADF); /* XXX: correct errno? */
401 /* ignore any error, just give it a try */
402 if (fp->f_type == DTYPE_VNODE)
403 fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred,
404 td);
405 fdrop(fp, td);
406 } else {
407 PROC_UNLOCK(p);
408 }
409#else
410 }
411 PROC_UNLOCK(p);
412#endif
413 return error;
414}
415
416int
417svr4_sys_open64(td, uap)
418 register struct thread *td;
419 struct svr4_sys_open64_args *uap;
420{
421 return svr4_sys_open(td, (struct svr4_sys_open_args *)uap);
422}
423
424int
425svr4_sys_creat(td, uap)
426 register struct thread *td;
427 struct svr4_sys_creat_args *uap;
428{
429 struct open_args cup;
430
431 caddr_t sg = stackgap_init();
432 CHECKALTEXIST(td, &sg, uap->path);
433
434 cup.path = uap->path;
435 cup.mode = uap->mode;
436 cup.flags = O_WRONLY | O_CREAT | O_TRUNC;
437
438 return open(td, &cup);
439}
440
441int
442svr4_sys_creat64(td, uap)
443 register struct thread *td;
444 struct svr4_sys_creat64_args *uap;
445{
446 return svr4_sys_creat(td, (struct svr4_sys_creat_args *)uap);
447}
448
449int
450svr4_sys_llseek(td, uap)
451 register struct thread *td;
452 struct svr4_sys_llseek_args *uap;
453{
454 struct lseek_args ap;
455
456 ap.fd = uap->fd;
457
458#if BYTE_ORDER == BIG_ENDIAN
459 ap.offset = (((u_int64_t) uap->offset1) << 32) |
460 uap->offset2;
461#else
462 ap.offset = (((u_int64_t) uap->offset2) << 32) |
463 uap->offset1;
464#endif
465 ap.whence = uap->whence;
466
467 return lseek(td, &ap);
468}
469
470int
471svr4_sys_access(td, uap)
472 register struct thread *td;
473 struct svr4_sys_access_args *uap;
474{
475 struct access_args cup;
476 int *retval;
477
478 caddr_t sg = stackgap_init();
479 CHECKALTEXIST(td, &sg, uap->path);
480
481 retval = td->td_retval;
482
483 cup.path = uap->path;
484 cup.flags = uap->flags;
485
486 return access(td, &cup);
487}
488
489#if defined(NOTYET)
490int
491svr4_sys_pread(td, uap)
492 register struct thread *td;
493 struct svr4_sys_pread_args *uap;
494{
495 struct pread_args pra;
496
497 /*
498 * Just translate the args structure and call the NetBSD
499 * pread(2) system call (offset type is 64-bit in NetBSD).
500 */
501 pra.fd = uap->fd;
502 pra.buf = uap->buf;
503 pra.nbyte = uap->nbyte;
504 pra.offset = uap->off;
505
506 return pread(td, &pra);
507}
508#endif
509
510#if defined(NOTYET)
511int
512svr4_sys_pread64(td, v, retval)
513 register struct thread *td;
514 void *v;
515 register_t *retval;
516{
517
518 struct svr4_sys_pread64_args *uap = v;
519 struct sys_pread_args pra;
520
521 /*
522 * Just translate the args structure and call the NetBSD
523 * pread(2) system call (offset type is 64-bit in NetBSD).
524 */
525 pra.fd = uap->fd;
526 pra.buf = uap->buf;
527 pra.nbyte = uap->nbyte;
528 pra.offset = uap->off;
529
530 return (sys_pread(td, &pra, retval));
531}
532#endif /* NOTYET */
533
534#if defined(NOTYET)
535int
536svr4_sys_pwrite(td, uap)
537 register struct thread *td;
538 struct svr4_sys_pwrite_args *uap;
539{
540 struct pwrite_args pwa;
541
542 /*
543 * Just translate the args structure and call the NetBSD
544 * pwrite(2) system call (offset type is 64-bit in NetBSD).
545 */
546 pwa.fd = uap->fd;
547 pwa.buf = uap->buf;
548 pwa.nbyte = uap->nbyte;
549 pwa.offset = uap->off;
550
551 return pwrite(td, &pwa);
552}
553#endif
554
555#if defined(NOTYET)
556int
557svr4_sys_pwrite64(td, v, retval)
558 register struct thread *td;
559 void *v;
560 register_t *retval;
561{
562 struct svr4_sys_pwrite64_args *uap = v;
563 struct sys_pwrite_args pwa;
564
565 /*
566 * Just translate the args structure and call the NetBSD
567 * pwrite(2) system call (offset type is 64-bit in NetBSD).
568 */
569 pwa.fd = uap->fd;
570 pwa.buf = uap->buf;
571 pwa.nbyte = uap->nbyte;
572 pwa.offset = uap->off;
573
574 return (sys_pwrite(td, &pwa, retval));
575}
576#endif /* NOTYET */
577
578int
579svr4_sys_fcntl(td, uap)
580 register struct thread *td;
581 struct svr4_sys_fcntl_args *uap;
582{
583 int error;
584 struct fcntl_args fa;
585 int *retval;
586
587 retval = td->td_retval;
588
589 fa.fd = uap->fd;
590 fa.cmd = svr4_to_bsd_cmd(uap->cmd);
591
592 switch (fa.cmd) {
593 case F_DUPFD:
594 case F_GETFD:
595 case F_SETFD:
596 fa.arg = (long) uap->arg;
597 return fcntl(td, &fa);
598
599 case F_GETFL:
600 fa.arg = (long) uap->arg;
601 error = fcntl(td, &fa);
602 if (error)
603 return error;
604 *retval = bsd_to_svr4_flags(*retval);
605 return error;
606
607 case F_SETFL:
608 {
609 /*
610 * we must save the O_ASYNC flag, as that is
611 * handled by ioctl(_, I_SETSIG, _) emulation.
612 */
613 long cmd;
614 int flags;
615
616 DPRINTF(("Setting flags %p\n", uap->arg));
617 cmd = fa.cmd; /* save it for a while */
618
619 fa.cmd = F_GETFL;
620 if ((error = fcntl(td, &fa)) != 0)
621 return error;
622 flags = *retval;
623 flags &= O_ASYNC;
624 flags |= svr4_to_bsd_flags((u_long) uap->arg);
625 fa.cmd = cmd;
626 fa.arg = (long) flags;
627 return fcntl(td, &fa);
628 }
629
630 case F_GETLK:
631 case F_SETLK:
632 case F_SETLKW:
633 {
634 struct svr4_flock ifl;
635 struct flock *flp, fl;
636 caddr_t sg = stackgap_init();
637
638 flp = stackgap_alloc(&sg, sizeof(struct flock));
639 fa.arg = (long) flp;
640
641 error = copyin(uap->arg, &ifl, sizeof ifl);
642 if (error)
643 return error;
644
645 svr4_to_bsd_flock(&ifl, &fl);
646
647 error = copyout(&fl, flp, sizeof fl);
648 if (error)
649 return error;
650
651 error = fcntl(td, &fa);
652 if (error || fa.cmd != F_GETLK)
653 return error;
654
655 error = copyin(flp, &fl, sizeof fl);
656 if (error)
657 return error;
658
659 bsd_to_svr4_flock(&fl, &ifl);
660
661 return copyout(&ifl, uap->arg, sizeof ifl);
662 }
663 case -1:
664 switch (uap->cmd) {
665 case SVR4_F_DUP2FD:
666 {
667 struct dup2_args du;
668
669 du.from = uap->fd;
670 du.to = (int)uap->arg;
671 error = dup2(td, &du);
672 if (error)
673 return error;
674 *retval = du.to;
675 return 0;
676 }
677
678 case SVR4_F_FREESP:
679 {
680 struct svr4_flock ifl;
681 struct flock fl;
682
683 error = copyin(uap->arg, &ifl,
684 sizeof ifl);
685 if (error)
686 return error;
687 svr4_to_bsd_flock(&ifl, &fl);
688 return fd_truncate(td, uap->fd, &fl);
689 }
690
691 case SVR4_F_GETLK64:
692 case SVR4_F_SETLK64:
693 case SVR4_F_SETLKW64:
694 {
695 struct svr4_flock64 ifl;
696 struct flock *flp, fl;
697 caddr_t sg = stackgap_init();
698
699 flp = stackgap_alloc(&sg, sizeof(struct flock));
700 fa.arg = (long) flp;
701
702 error = copyin(uap->arg, &ifl,
703 sizeof ifl);
704 if (error)
705 return error;
706
707 svr4_to_bsd_flock64(&ifl, &fl);
708
709 error = copyout(&fl, flp, sizeof fl);
710 if (error)
711 return error;
712
713 error = fcntl(td, &fa);
714 if (error || fa.cmd != F_GETLK)
715 return error;
716
717 error = copyin(flp, &fl, sizeof fl);
718 if (error)
719 return error;
720
721 bsd_to_svr4_flock64(&fl, &ifl);
722
723 return copyout(&ifl, uap->arg,
724 sizeof ifl);
725 }
726
727 case SVR4_F_FREESP64:
728 {
729 struct svr4_flock64 ifl;
730 struct flock fl;
731
732 error = copyin(uap->arg, &ifl,
733 sizeof ifl);
734 if (error)
735 return error;
736 svr4_to_bsd_flock64(&ifl, &fl);
737 return fd_truncate(td, uap->fd, &fl);
738 }
739
740 case SVR4_F_REVOKE:
741 return fd_revoke(td, uap->fd);
742
743 default:
744 return ENOSYS;
745 }
746
747 default:
748 return ENOSYS;
749 }
750}