Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / emulation / 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: src/sys/svr4/svr4_fcntl.c,v 1.7 1999/12/12 10:27:04 newton Exp $
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 }