Deleted Added
full compact
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 $
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
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}