static int fd_revoke(struct lwp *l, int fd, register_t *retval) { file_t *fp; vnode_t *vp; int error; if ((fp = fd_getfile(fd)) == NULL) return EBADF; if (fp->f_type != DTYPE_VNODE) { fd_putfile(fd); return EINVAL; } vp = (vnode_t *) fp->f_data; if (vp->v_type != VCHR && vp->v_type != VBLK) { error = EINVAL; goto out; } error = dorevoke(vp, l->l_cred); out: vrele(vp); fd_putfile(fd); return error; }
static int fd_truncate(struct lwp *l, int fd, struct flock *flp, register_t *retval) { file_t *fp; off_t start, length; vnode_t *vp; struct vattr vattr; int error; struct sys_ftruncate_args ft; /* * We only support truncating the file. */ if ((fp = fd_getfile(fd)) == NULL) return EBADF; vp = fp->f_data; if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { fd_putfile(fd); return ESPIPE; } if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0) { fd_putfile(fd); return error; } length = vattr.va_size; switch (flp->l_whence) { case SEEK_CUR: start = fp->f_offset + flp->l_start; break; case SEEK_END: start = flp->l_start + length; break; case SEEK_SET: start = flp->l_start; break; default: fd_putfile(fd); return EINVAL; } if (start + flp->l_len < length) { /* We don't support free'ing in the middle of the file */ fd_putfile(fd); return EINVAL; } SCARG(&ft, fd) = fd; SCARG(&ft, length) = start; error = sys_ftruncate(l, &ft, retval); fd_putfile(fd); return error; }
/* ARGSUSED */ int sys_flock(struct lwp *l, const struct sys_flock_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(int) how; } */ int fd, how, error; file_t *fp; vnode_t *vp; struct flock lf; fd = SCARG(uap, fd); how = SCARG(uap, how); error = 0; if ((fp = fd_getfile(fd)) == NULL) { return EBADF; } if (fp->f_type != DTYPE_VNODE) { fd_putfile(fd); return EOPNOTSUPP; } vp = fp->f_vnode; lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; switch (how & ~LOCK_NB) { case LOCK_UN: lf.l_type = F_UNLCK; atomic_and_uint(&fp->f_flag, ~FHASLOCK); error = VOP_ADVLOCK(vp, fp, F_UNLCK, &lf, F_FLOCK); fd_putfile(fd); return error; case LOCK_EX: lf.l_type = F_WRLCK; break; case LOCK_SH: lf.l_type = F_RDLCK; break; default: fd_putfile(fd); return EINVAL; } atomic_or_uint(&fp->f_flag, FHASLOCK); if (how & LOCK_NB) { error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK); } else { error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK|F_WAIT); } fd_putfile(fd); return error; }
/* * Duplicate a file descriptor to a particular value. */ int dodup(struct lwp *l, int from, int to, int flags, register_t *retval) { int error; file_t *fp; if ((fp = fd_getfile(from)) == NULL) return EBADF; mutex_enter(&fp->f_lock); fp->f_count++; mutex_exit(&fp->f_lock); fd_putfile(from); if ((u_int)to >= curproc->p_rlimit[RLIMIT_NOFILE].rlim_cur || (u_int)to >= maxfiles) error = EBADF; else if (from == to) error = 0; else error = fd_dup2(fp, to, flags); closef(fp); *retval = to; return error; }
/* * Read a block of directory entries in a file system independent format. */ int compat_12_sys_getdirentries(struct lwp *l, const struct compat_12_sys_getdirentries_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(char *) buf; syscallarg(u_int) count; syscallarg(long *) basep; } */ struct file *fp; int error, done; long loff; /* fd_getvnode() will use the descriptor for us */ if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) return error; if ((fp->f_flag & FREAD) == 0) { error = EBADF; goto out; } loff = fp->f_offset; error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE, SCARG(uap, count), &done, l, 0, 0); error = copyout(&loff, SCARG(uap, basep), sizeof(long)); *retval = done; out: fd_putfile(SCARG(uap, fd)); return error; }
int compat_50_netbsd32_futimes(struct lwp *l, const struct compat_50_netbsd32_futimes_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(const netbsd32_timeval50p_t) tptr; } */ int error; file_t *fp; struct timeval tv[2], *tvp; error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp); if (error != 0) return error; /* fd_getvnode() will use the descriptor for us */ if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) return error; error = do_sys_utimes(l, fp->f_data, NULL, 0, tvp, UIO_SYSSPACE); fd_putfile(SCARG(uap, fd)); return error; }
/* * Get peer socket name. */ int do_sys_getpeername(int fd, struct mbuf **nam) { struct socket *so; struct mbuf *m; int error; if ((error = fd_getsock(fd, &so)) != 0) return error; m = m_getclr(M_WAIT, MT_SONAME); MCLAIM(m, so->so_mowner); solock(so); if ((so->so_state & SS_ISCONNECTED) == 0) error = ENOTCONN; else { *nam = m; error = (*so->so_proto->pr_usrreqs->pr_peeraddr)(so, m); } sounlock(so); if (error != 0) m_free(m); fd_putfile(fd); return error; }
int svr4_sys_open(struct lwp *l, const struct svr4_sys_open_args *uap, register_t *retval) { int error; struct sys_open_args cup; SCARG(&cup, flags) = svr4_to_bsd_flags(SCARG(uap, flags)); SCARG(&cup, path) = SCARG(uap, path); SCARG(&cup, mode) = SCARG(uap, mode); error = sys_open(l, &cup, retval); if (error) return error; /* XXXAD locking */ if (!(SCARG(&cup, flags) & O_NOCTTY) && SESS_LEADER(l->l_proc) && !(l->l_proc->p_lflag & PL_CONTROLT)) { file_t *fp; fp = fd_getfile(*retval); /* ignore any error, just give it a try */ if (fp != NULL) { if (fp->f_type == DTYPE_VNODE) (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, NULL); fd_putfile(*retval); } } return 0; }
int compat_30_netbsd32_getdents(struct lwp *l, const struct compat_30_netbsd32_getdents_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(netbsd32_charp) buf; syscallarg(netbsd32_size_t) count; } */ file_t *fp; int error, done; char *buf; netbsd32_size_t count; /* Limit the size on any kernel buffers used by VOP_READDIR */ count = min(MAXBSIZE, SCARG(uap, count)); /* fd_getvnode() will use the descriptor for us */ if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) return (error); if ((fp->f_flag & FREAD) == 0) { error = EBADF; goto out; } buf = kmem_alloc(count, KM_SLEEP); error = vn_readdir(fp, buf, UIO_SYSSPACE, count, &done, l, 0, 0); if (error == 0) { *retval = netbsd32_to_dirent12(buf, done); error = copyout(buf, SCARG_P32(uap, buf), *retval); } kmem_free(buf, count); out: fd_putfile(SCARG(uap, fd)); return (error); }
int ibcs2_sys_open(struct lwp *l, const struct ibcs2_sys_open_args *uap, register_t *retval) { /* { syscallarg(char *) path; syscallarg(int) flags; syscallarg(int) mode; } */ struct proc *p = l->l_proc; struct sys_open_args bsd_ua; int noctty = SCARG(uap, flags) & IBCS2_O_NOCTTY; int ret; SCARG(&bsd_ua, path) = SCARG(uap, path); SCARG(&bsd_ua, flags) = cvt_o_flags(SCARG(uap, flags)); SCARG(&bsd_ua, mode) = SCARG(uap, mode); ret = sys_open(l, &bsd_ua, retval); if (!ret && !noctty && SESS_LEADER(p) && !(p->p_lflag & PL_CONTROLT)) { file_t *fp; if ((fp = fd_getfile(*retval)) != NULL) { /* ignore any error, just give it a try */ if (fp->f_type == DTYPE_VNODE) (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, NULL); fd_putfile(*retval); } } return ret; }
int compat_20_netbsd32_fstatfs(struct lwp *l, const struct compat_20_netbsd32_fstatfs_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(netbsd32_statfsp_t) buf; } */ file_t *fp; struct mount *mp; struct statvfs *sp; struct netbsd32_statfs s32; int error; /* fd_getvnode() will use the descriptor for us */ if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) return (error); mp = ((struct vnode *)fp->f_data)->v_mount; sp = &mp->mnt_stat; if ((error = VFS_STATVFS(mp, sp)) != 0) goto out; sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; compat_20_netbsd32_from_statvfs(sp, &s32); error = copyout(&s32, SCARG_P32(uap, buf), sizeof(s32)); out: fd_putfile(SCARG(uap, fd)); return (error); }
static void linux_open_ctty(struct lwp *l, int flags, int fd) { struct proc *p = l->l_proc; /* * this bit from sunos_misc.c (and svr4_fcntl.c). * If we are a session leader, and we don't have a controlling * terminal yet, and the O_NOCTTY flag is not set, try to make * this the controlling terminal. */ if (!(flags & O_NOCTTY) && SESS_LEADER(p) && !(p->p_lflag & PL_CONTROLT)) { file_t *fp; fp = fd_getfile(fd); /* ignore any error, just give it a try */ if (fp != NULL) { if (fp->f_type == DTYPE_VNODE) { (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, NULL); } fd_putfile(fd); } } }
static int kttcp_recv(struct lwp *l, struct kttcp_io_args *kio) { struct socket *so; int error; struct timeval t0, t1; unsigned long long len, done; done = 0; /* XXX gcc */ if (kio->kio_totalsize > KTTCP_MAX_XMIT) return EINVAL; if ((error = fd_getsock(kio->kio_socket, &so)) != 0) return error; len = kio->kio_totalsize; microtime(&t0); do { error = kttcp_soreceive(so, len, &done, l, NULL); len -= done; } while (error == 0 && len > 0 && done > 0); fd_putfile(kio->kio_socket); microtime(&t1); if (error == EPIPE) error = 0; if (error != 0) return error; timersub(&t1, &t0, &kio->kio_elapsed); kio->kio_bytesdone = kio->kio_totalsize - len; return 0; }
int ibcs2_sys_fstatvfs(struct lwp *l, const struct ibcs2_sys_fstatvfs_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(struct ibcs2_statvfs *) buf; } */ file_t *fp; struct mount *mp; struct statvfs *sp; int error; /* fd_getvnode() will use the descriptor for us */ if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) return (error); mp = ((struct vnode *)fp->f_data)->v_mount; sp = &mp->mnt_stat; if ((error = VFS_STATVFS(mp, sp)) != 0) goto out; sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; error = cvt_statvfs(sp, SCARG(uap, buf), sizeof(struct ibcs2_statvfs)); out: fd_putfile(SCARG(uap, fd)); return (error); }
int do_sys_connect(struct lwp *l, int fd, struct mbuf *nam) { struct socket *so; int error; int interrupted = 0; if ((error = fd_getsock(fd, &so)) != 0) { m_freem(nam); return (error); } solock(so); MCLAIM(nam, so->so_mowner); if ((so->so_state & SS_ISCONNECTING) != 0) { error = EALREADY; goto out; } error = soconnect(so, nam, l); if (error) goto bad; if ((so->so_state & (SS_NBIO|SS_ISCONNECTING)) == (SS_NBIO|SS_ISCONNECTING)) { error = EINPROGRESS; goto out; } while ((so->so_state & SS_ISCONNECTING) != 0 && so->so_error == 0) { error = sowait(so, true, 0); if (__predict_false((so->so_state & SS_ISABORTING) != 0)) { error = EPIPE; interrupted = 1; break; } if (error) { if (error == EINTR || error == ERESTART) interrupted = 1; break; } } if (error == 0) { error = so->so_error; so->so_error = 0; } bad: if (!interrupted) so->so_state &= ~SS_ISCONNECTING; if (error == ERESTART) error = EINTR; out: sounlock(so); fd_putfile(fd); m_freem(nam); return error; }
int sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(int) level; syscallarg(int) name; syscallarg(void *) val; syscallarg(unsigned int *) avalsize; } */ struct sockopt sopt; struct socket *so; file_t *fp; unsigned int valsize, len; int error; if (SCARG(uap, val) != NULL) { error = copyin(SCARG(uap, avalsize), &valsize, sizeof(valsize)); if (error) return error; } else valsize = 0; if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0) return (error); sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), 0); if (fp->f_flag & FNOSIGPIPE) so->so_options |= SO_NOSIGPIPE; else so->so_options &= ~SO_NOSIGPIPE; error = sogetopt(so, &sopt); if (error) goto out; if (valsize > 0) { len = min(valsize, sopt.sopt_size); error = copyout(sopt.sopt_data, SCARG(uap, val), len); if (error) goto out; error = copyout(&len, SCARG(uap, avalsize), sizeof(len)); if (error) goto out; } out: sockopt_destroy(&sopt); fd_putfile(SCARG(uap, s)); return error; }
int do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from, struct mbuf **control, register_t *retsize) { int error; struct socket *so; if ((error = fd_getsock(s, &so)) != 0) return error; error = do_sys_recvmsg_so(l, s, so, mp, from, control, retsize); fd_putfile(s); return error; }
int do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags, register_t *retsize) { int error; struct socket *so; file_t *fp; if ((error = fd_getsock1(s, &so, &fp)) != 0) return error; error = do_sys_sendmsg_so(l, s, so, fp, mp, flags, retsize); fd_putfile(s); return error; }
int netbsd32_mq_setattr(struct lwp *l, const struct netbsd32_mq_setattr_args *uap, register_t *retval) { /* { syscallarg(mqd_t) mqdes; syscallarg(const netbsd32_mq_attrp_t) mqstat; syscallarg(netbsd32_mq_attrp_t) omqstat; } */ struct mqueue *mq; struct netbsd32_mq_attr attr32; struct mq_attr attr; int error, nonblock; error = copyin(SCARG_P32(uap, mqstat), &attr32, sizeof(attr32)); if (error) return error; netbsd32_to_mq_attr(&attr32, &attr); nonblock = (attr.mq_flags & O_NONBLOCK); error = mqueue_get(SCARG(uap, mqdes), 0, &mq); if (error) return error; /* Copy the old attributes, if needed */ if (SCARG_P32(uap, omqstat)) memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr)); /* Ignore everything, except O_NONBLOCK */ if (nonblock) mq->mq_attrib.mq_flags |= O_NONBLOCK; else mq->mq_attrib.mq_flags &= ~O_NONBLOCK; mutex_exit(&mq->mq_mtx); fd_putfile((int)SCARG(uap, mqdes)); /* * Copy the data to the user-space. * Note: According to POSIX, the new attributes should not be set in * case of fail - this would be violated. */ if (SCARG_P32(uap, omqstat)) { netbsd32_from_mq_attr(&attr, &attr32); error = copyout(&attr32, SCARG_P32(uap, omqstat), sizeof(attr32)); } return error; }
/* * Return status information about a file descriptor. * Common function for compat code. */ int do_sys_fstat(int fd, struct stat *sb) { file_t *fp; int error; if ((fp = fd_getfile(fd)) == NULL) { return EBADF; } error = (*fp->f_ops->fo_stat)(fp, sb); fd_putfile(fd); return error; }
int do_sys_bind(struct lwp *l, int fd, struct mbuf *nam) { struct socket *so; int error; if ((error = fd_getsock(fd, &so)) != 0) { m_freem(nam); return (error); } MCLAIM(nam, so->so_mowner); error = sobind(so, nam, l); m_freem(nam); fd_putfile(fd); return error; }
int sys_listen(struct lwp *l, const struct sys_listen_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(int) backlog; } */ struct socket *so; int error; if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) return (error); error = solisten(so, SCARG(uap, backlog), l); fd_putfile(SCARG(uap, s)); return error; }
int sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(int) level; syscallarg(int) name; syscallarg(const void *) val; syscallarg(unsigned int) valsize; } */ struct sockopt sopt; struct socket *so; file_t *fp; int error; unsigned int len; len = SCARG(uap, valsize); if (len > 0 && SCARG(uap, val) == NULL) return EINVAL; if (len > MCLBYTES) return EINVAL; if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0) return (error); sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len); if (len > 0) { error = copyin(SCARG(uap, val), sopt.sopt_data, len); if (error) goto out; } error = sosetopt(so, &sopt); if (so->so_options & SO_NOSIGPIPE) atomic_or_uint(&fp->f_flag, FNOSIGPIPE); else atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE); out: sockopt_destroy(&sopt); fd_putfile(SCARG(uap, s)); return error; }
int netbsd32_mq_notify(struct lwp *l, const struct netbsd32_mq_notify_args *uap, register_t *result) { /* { syscallarg(mqd_t) mqdes; syscallarg(const netbsd32_sigeventp_t) notification; } */ struct mqueue *mq; struct netbsd32_sigevent sig32; int error; if (SCARG_P32(uap, notification)) { /* Get the signal from user-space */ error = copyin(SCARG_P32(uap, notification), &sig32, sizeof(sig32)); if (error) return error; if (sig32.sigev_notify == SIGEV_SIGNAL && (sig32.sigev_signo <=0 || sig32.sigev_signo >= NSIG)) return EINVAL; } error = mqueue_get(SCARG(uap, mqdes), 0, &mq); if (error) { return error; } if (SCARG_P32(uap, notification)) { /* Register notification: set the signal and target process */ if (mq->mq_notify_proc == NULL) { netbsd32_to_sigevent(&sig32, &mq->mq_sig_notify); mq->mq_notify_proc = l->l_proc; } else { /* Fail if someone else already registered */ error = EBUSY; } } else { /* Unregister the notification */ mq->mq_notify_proc = NULL; } mutex_exit(&mq->mq_mtx); fd_putfile((int)SCARG(uap, mqdes)); return error; }
int darwin_sys_ioctl(struct lwp *l, const struct darwin_sys_ioctl_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(u_long) com; syscallarg(void *) data; } */ struct sys_ioctl_args cup; int error; switch (SCARG(uap, com)) { case DARWIN_FIODTYPE: { /* Get file d_type */ file_t *fp; struct vnode *vp; int *data = SCARG(uap, data); int type; /* fd_getvnode() will use the descriptor for us */ if ((error = fd_getvnode(SCARG(uap, fd), &fp))) return (error); vp = fp->f_data; type = vtype_to_dtype(vp->v_type); fd_putfile(SCARG(uap, fd)); error = copyout(&type, data, sizeof(*data)); return error; break; } default: /* Try native ioctl */ break; } SCARG(&cup, fd) = SCARG(uap, fd); SCARG(&cup, com) = SCARG(uap, com); SCARG(&cup, data) = SCARG(uap, data); error = sys_ioctl(l, &cup, retval); return error; }
/* * Duplicate a file descriptor. */ int sys_dup(struct lwp *l, const struct sys_dup_args *uap, register_t *retval) { /* { syscallarg(int) fd; } */ int error, newfd, oldfd; file_t *fp; oldfd = SCARG(uap, fd); if ((fp = fd_getfile(oldfd)) == NULL) { return EBADF; } error = fd_dup(fp, 0, &newfd, false); fd_putfile(oldfd); *retval = newfd; return error; }
int sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(int) how; } */ struct socket *so; int error; if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) return error; solock(so); error = soshutdown(so, SCARG(uap, how)); sounlock(so); fd_putfile(SCARG(uap, s)); return error; }
/* * Return pathconf information about a file descriptor. */ int sys_fpathconf(struct lwp *l, const struct sys_fpathconf_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(int) name; } */ int fd, error; file_t *fp; fd = SCARG(uap, fd); error = 0; if ((fp = fd_getfile(fd)) == NULL) { return (EBADF); } switch (fp->f_type) { case DTYPE_SOCKET: case DTYPE_PIPE: if (SCARG(uap, name) != _PC_PIPE_BUF) error = EINVAL; else *retval = PIPE_BUF; break; case DTYPE_VNODE: error = VOP_PATHCONF(fp->f_vnode, SCARG(uap, name), retval); break; case DTYPE_KQUEUE: error = EINVAL; break; default: error = EOPNOTSUPP; break; } fd_putfile(fd); return (error); }
int ultrix_sys_open(struct lwp *l, const struct ultrix_sys_open_args *uap, register_t *retval) { struct proc *p = l->l_proc; int q, r; int noctty; int ret; struct sys_open_args ap; /* convert open flags into NetBSD flags */ q = SCARG(uap, flags); noctty = q & 0x8000; r = (q & (0x0001 | 0x0002 | 0x0008 | 0x0040 | 0x0200 | 0x0400 | 0x0800)); r |= ((q & (0x0004 | 0x1000 | 0x4000)) ? O_NONBLOCK : 0); r |= ((q & 0x0080) ? O_SHLOCK : 0); r |= ((q & 0x0100) ? O_EXLOCK : 0); r |= ((q & 0x2000) ? O_FSYNC : 0); SCARG(&ap, path) = SCARG(uap, path); SCARG(&ap, flags) = r; SCARG(&ap, mode) = SCARG(uap, mode); ret = sys_open(l, &ap, retval); /* XXXSMP */ if (!ret && !noctty && SESS_LEADER(p) && !(p->p_lflag & PL_CONTROLT)) { file_t *fp; int fd; fd = (int)*retval; fp = fd_getfile(fd); /* ignore any error, just give it a try */ if (fp != NULL) { if (fp->f_type == DTYPE_VNODE) (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, NULL); fd_putfile(fd); } } return ret; }
/* * sys_fstatfs() takes an fd, not a path, and so needs no emul * pathname processing; but it's similar enough to sys_statvfs() that * it goes here anyway. */ int ultrix_sys_fstatfs(struct lwp *l, const struct ultrix_sys_fstatfs_args *uap, register_t *retval) { file_t *fp; struct mount *mp; struct statvfs *sp; int error; /* fd_getvnode() will use the descriptor for us */ if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) return error; mp = ((struct vnode *)fp->f_data)->v_mount; sp = &mp->mnt_stat; if ((error = VFS_STATVFS(mp, sp)) != 0) goto out; sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; error = ultrixstatfs(sp, (void *)SCARG(uap, buf)); out: fd_putfile(SCARG(uap, fd)); return error; }