+ register struct filedesc *fdp = p->p_fd;
+ register struct file *fp;
+ register char *pop;
+ struct vnode *vp;
+ int i, error, flags = F_POSIX;
+ struct flock fl;
+
+ if ((unsigned)uap->fd >= fdp->fd_nfiles ||
+ (fp = OFILE(fdp, uap->fd)) == NULL)
+ return (EBADF);
+ pop = &OFILEFLAGS(fdp, uap->fd);
+ switch(uap->cmd) {
+ case F_DUPFD:
+ if ((unsigned)uap->arg >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
+ return (EINVAL);
+ if (error = fdalloc(p, uap->arg, &i))
+ return (error);
+ OFILE(fdp, i) = fp;
+ OFILEFLAGS(fdp, i) = *pop &~ UF_EXCLOSE;
+ fp->f_count++;
+ if (i > fdp->fd_lastfile)
+ fdp->fd_lastfile = i;
+ *retval = i;
+ return (0);
+
+ case F_GETFD:
+ *retval = *pop & 1;
+ return (0);
+
+ case F_SETFD:
+ *pop = (*pop &~ 1) | (uap->arg & 1);
+ return (0);
+
+ case F_GETFL:
+ *retval = OFLAGS(fp->f_flag);
+ return (0);
+
+ case F_SETFL:
+ fp->f_flag &= ~FCNTLFLAGS;
+ fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS;
+ if (error = fset(fp, FNDELAY, fp->f_flag & FNDELAY))
+ return (error);
+ if (error = fset(fp, FASYNC, fp->f_flag & FASYNC))
+ (void) fset(fp, FNDELAY, 0);
+ return (error);
+
+ case F_GETOWN:
+ return (fgetown(fp, retval));
+
+ case F_SETOWN:
+ return (fsetown(fp, uap->arg));
+
+ case F_SETLKW:
+ flags |= F_WAIT;
+ /* Fall into F_SETLK */
+
+ case F_SETLK:
+ if (fp->f_type != DTYPE_VNODE)
+ return (EBADF);
+ vp = (struct vnode *)fp->f_data;
+ /* Copy in the lock structure */
+ error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
+ if (error)
+ return (error);
+ if (fl.l_whence == SEEK_CUR)
+ fl.l_start += fp->f_offset;
+ switch (fl.l_type) {
+
+ case F_RDLCK:
+ if ((fp->f_flag & FREAD) == 0)
+ return (EBADF);
+ return (VOP_ADVLOCK(vp, p, F_SETLK, &fl, flags));
+
+ case F_WRLCK:
+ if ((fp->f_flag & FWRITE) == 0)
+ return (EBADF);
+ return (VOP_ADVLOCK(vp, p, F_SETLK, &fl, flags));
+
+ case F_UNLCK:
+ return (VOP_ADVLOCK(vp, p, F_UNLCK, &fl, F_POSIX));
+
+ default:
+ return (EINVAL);
+ }