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