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