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