+ if ((error = copyin(argp, (caddr_t)&args, sizeof(args)))) {
+ goto outdrop;
+ }
+
+ if ((error = vnode_getwithref(vp))) {
+ goto outdrop;
+ }
+
+ error = VNOP_IOCTL(vp, F_TRIM_ACTIVE_FILE, (caddr_t)&args, 0, &context);
+ (void)vnode_put(vp);
+
+ goto outdrop;
+ }
+ case F_SPECULATIVE_READ: {
+ fspecread_t args;
+
+ if (fp->f_type != DTYPE_VNODE) {
+ error = EBADF;
+ goto out;
+ }
+
+ vp = (struct vnode *)fp->f_data;
+ proc_fdunlock(p);
+
+ if ((error = copyin(argp, (caddr_t)&args, sizeof(args)))) {
+ goto outdrop;
+ }
+
+ /* Discard invalid offsets or lengths */
+ if ((args.fsr_offset < 0) || (args.fsr_length < 0)) {
+ error = EINVAL;
+ goto outdrop;
+ }
+
+ /*
+ * Round the file offset down to a page-size boundary (or to 0).
+ * The filesystem will need to round the length up to the end of the page boundary
+ * or to the EOF of the file.
+ */
+ uint64_t foff = (((uint64_t)args.fsr_offset) & ~((uint64_t)PAGE_MASK));
+ uint64_t foff_delta = args.fsr_offset - foff;
+ args.fsr_offset = (off_t) foff;
+
+ /*
+ * Now add in the delta to the supplied length. Since we may have adjusted the
+ * offset, increase it by the amount that we adjusted.
+ */
+ args.fsr_length += foff_delta;
+
+ if ((error = vnode_getwithref(vp))) {
+ goto outdrop;
+ }
+ error = VNOP_IOCTL(vp, F_SPECULATIVE_READ, (caddr_t)&args, 0, &context);
+ (void)vnode_put(vp);
+
+ goto outdrop;
+ }
+ case F_SETSIZE:
+ if (fp->f_type != DTYPE_VNODE) {
+ error = EBADF;
+ goto out;
+ }
+ vp = (struct vnode *)fp->f_data;
+ proc_fdunlock(p);
+
+ error = copyin(argp, (caddr_t)&offset, sizeof(off_t));
+ if (error) {
+ goto outdrop;
+ }
+ AUDIT_ARG(value64, offset);
+
+ error = vnode_getwithref(vp);
+ if (error) {
+ goto outdrop;
+ }
+
+#if CONFIG_MACF
+ error = mac_vnode_check_truncate(&context,
+ fp->f_fglob->fg_cred, vp);
+ if (error) {
+ (void)vnode_put(vp);
+ goto outdrop;
+ }
+#endif
+ /*
+ * Make sure that we are root. Growing a file
+ * without zero filling the data is a security hole
+ * root would have access anyway so we'll allow it
+ */
+ if (!kauth_cred_issuser(kauth_cred_get())) {
+ error = EACCES;
+ } else {
+ /*
+ * set the file size
+ */
+ error = vnode_setsize(vp, offset, IO_NOZEROFILL,
+ &context);
+
+#if CONFIG_MACF
+ if (error == 0) {
+ mac_vnode_notify_truncate(&context, fp->f_fglob->fg_cred, vp);
+ }
+#endif
+ }
+
+ (void)vnode_put(vp);
+ goto outdrop;
+
+ case F_RDAHEAD:
+ if (fp->f_type != DTYPE_VNODE) {
+ error = EBADF;
+ goto out;
+ }
+ if (uap->arg) {
+ fp->f_fglob->fg_flag &= ~FNORDAHEAD;
+ } else {
+ fp->f_fglob->fg_flag |= FNORDAHEAD;
+ }
+
+ goto out;
+
+ case F_NOCACHE:
+ if (fp->f_type != DTYPE_VNODE) {
+ error = EBADF;
+ goto out;
+ }
+ if (uap->arg) {
+ fp->f_fglob->fg_flag |= FNOCACHE;
+ } else {
+ fp->f_fglob->fg_flag &= ~FNOCACHE;
+ }
+
+ goto out;
+
+ case F_NODIRECT:
+ if (fp->f_type != DTYPE_VNODE) {
+ error = EBADF;
+ goto out;
+ }
+ if (uap->arg) {
+ fp->f_fglob->fg_flag |= FNODIRECT;
+ } else {
+ fp->f_fglob->fg_flag &= ~FNODIRECT;
+ }
+
+ goto out;
+
+ case F_SINGLE_WRITER:
+ if (fp->f_type != DTYPE_VNODE) {
+ error = EBADF;
+ goto out;
+ }
+ if (uap->arg) {
+ fp->f_fglob->fg_flag |= FSINGLE_WRITER;
+ } else {
+ fp->f_fglob->fg_flag &= ~FSINGLE_WRITER;