/* * Nfs server psuedo system call for the nfsd's * Based on the flag value it either: * - adds a socket to the selection list * - remains in the kernel as an nfsd * - remains in the kernel as an nfsiod * For INET6 we suppose that nfsd provides only IN6P_IPV6_V6ONLY sockets * and that mountd provides * - sockaddr with no IPv4-mapped addresses * - mask for both INET and INET6 families if there is IPv4-mapped overlap */ int nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap) { struct file *fp; struct nfsd_addsock_args addsockarg; struct nfsd_nfsd_args nfsdarg; int error; if (uap->flag & NFSSVC_ADDSOCK) { error = copyin(uap->argp, (caddr_t)&addsockarg, sizeof(addsockarg)); if (error) return (error); if ((error = fget(td, addsockarg.sock, CAP_SOCK_ALL, &fp)) != 0) return (error); if (fp->f_type != DTYPE_SOCKET) { fdrop(fp, td); return (error); /* XXXRW: Should be EINVAL? */ } error = nfssvc_addsock(fp, td); fdrop(fp, td); } else if (uap->flag & NFSSVC_OLDNFSD) error = nfssvc_nfsd(td, NULL); else if (uap->flag & NFSSVC_NFSD) { if (!uap->argp) return (EINVAL); error = copyin(uap->argp, (caddr_t)&nfsdarg, sizeof(nfsdarg)); if (error) return (error); error = nfssvc_nfsd(td, &nfsdarg); } else error = ENXIO; return (error); }
int sys_ksem_destroy(struct thread *td, struct ksem_destroy_args *uap) { struct file *fp; struct ksem *ks; int error; /* No capability rights required to close a semaphore. */ error = ksem_get(td, uap->id, 0, &fp); if (error) return (error); ks = fp->f_data; if (!(ks->ks_flags & KS_ANONYMOUS)) { fdrop(fp, td); return (EINVAL); } mtx_lock(&sem_lock); if (ks->ks_waiters != 0) { mtx_unlock(&sem_lock); error = EBUSY; goto err; } ks->ks_flags |= KS_DEAD; mtx_unlock(&sem_lock); error = kern_close(td, uap->id); err: fdrop(fp, td); return (error); }
int sys_posix_openpt(struct thread *td, struct posix_openpt_args *uap) { int error, fd; struct file *fp; /* * POSIX states it's unspecified when other flags are passed. We * don't allow this. */ if (uap->flags & ~(O_RDWR|O_NOCTTY|O_CLOEXEC)) return (EINVAL); error = falloc(td, &fp, &fd, uap->flags); if (error) return (error); /* Allocate the actual pseudo-TTY. */ error = pts_alloc(FFLAGS(uap->flags & O_ACCMODE), td, fp); if (error != 0) { fdclose(td, fp, fd); fdrop(fp, td); return (error); } /* Pass it back to userspace. */ td->td_retval[0] = fd; fdrop(fp, td); return (0); }
int sys_ksem_getvalue(struct thread *td, struct ksem_getvalue_args *uap) { struct file *fp; struct ksem *ks; int error, val; error = ksem_get(td, uap->id, CAP_SEM_GETVALUE, &fp); if (error) return (error); ks = fp->f_data; mtx_lock(&sem_lock); #ifdef MAC error = mac_posixsem_check_getvalue(td->td_ucred, fp->f_cred, ks); if (error) { mtx_unlock(&sem_lock); fdrop(fp, td); return (error); } #endif val = ks->ks_value; vfs_timestamp(&ks->ks_atime); mtx_unlock(&sem_lock); fdrop(fp, td); error = copyout(&val, uap->val, sizeof(val)); return (error); }
int freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap) { struct ioctl_args ap /*{ int fd; u_long com; caddr_t data; }*/ ; struct file *fp; cap_rights_t rights; int error; error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); if (error != 0) return (error); if ((fp->f_flag & (FREAD | FWRITE)) == 0) { fdrop(fp, td); return (EBADF); } switch (uap->com) { case MDIOCATTACH_32: /* FALLTHROUGH */ case MDIOCDETACH_32: /* FALLTHROUGH */ case MDIOCQUERY_32: /* FALLTHROUGH */ case MDIOCLIST_32: error = freebsd32_ioctl_md(td, uap, fp); break; case CDIOREADTOCENTRYS_32: error = freebsd32_ioctl_ioc_read_toc(td, uap, fp); break; case FIODGNAME_32: error = freebsd32_ioctl_fiodgname(td, uap, fp); break; case MEMRANGE_GET32: /* FALLTHROUGH */ case MEMRANGE_SET32: error = freebsd32_ioctl_memrange(td, uap, fp); break; case PCIOCGETCONF_32: error = freebsd32_ioctl_pciocgetconf(td, uap, fp); break; case SG_IO_32: error = freebsd32_ioctl_sg(td, uap, fp); break; default: fdrop(fp, td); ap.fd = uap->fd; ap.com = uap->com; PTRIN_CP(*uap, ap, data); return sys_ioctl(td, &ap); } fdrop(fp, td); return error; }
/* * File descriptors can be passed into an AF_NETGRAPH socket. * Note, that file descriptors cannot be passed OUT. * Only character device descriptors are accepted. * Character devices are useful to connect a graph to a device, * which after all is the purpose of this whole system. */ static int ng_internalize(struct mbuf *control, struct thread *td) { const struct cmsghdr *cm = mtod(control, const struct cmsghdr *); struct file *fp; struct vnode *vn; int oldfds; int fd; if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET || cm->cmsg_len != control->m_len) { TRAP_ERROR; return (EINVAL); } /* Check there is only one FD. XXX what would more than one signify? */ oldfds = ((caddr_t)cm + cm->cmsg_len - (caddr_t)data) / sizeof (int); if (oldfds != 1) { TRAP_ERROR; return (EINVAL); } /* Check that the FD given is legit. and change it to a pointer to a * struct file. */ fd = CMSG_DATA(cm); if ((error = fget(td, fd, &fp)) != 0) return (error); /* Depending on what kind of resource it is, act differently. For * devices, we treat it as a file. For an AF_NETGRAPH socket, * shortcut straight to the node. */ switch (fp->f_type) { case DTYPE_VNODE: vn = fp->f_data; if (vn && (vn->v_type == VCHR)) { /* for a VCHR, actually reference the FILE */ fhold(fp); /* XXX then what :) */ /* how to pass on to other modules? */ } else { fdrop(fp, td); TRAP_ERROR; return (EINVAL); } break; default: fdrop(fp, td); TRAP_ERROR; return (EINVAL); } fdrop(fp, td); return (0); }
static int kttcp_recv(struct thread *td, struct kttcp_io_args *kio) { struct file *fp; int error; struct timeval t0, t1; unsigned long long len = 0; struct uio auio; struct iovec aiov; bzero(&aiov, sizeof(aiov)); bzero(&auio, sizeof(auio)); auio.uio_iov = &aiov; auio.uio_segflg = UIO_NOCOPY; error = fget(td, kio->kio_socket, &fp); if (error != 0) return error; if ((fp->f_flag & FWRITE) == 0) { fdrop(fp, td); return EBADF; } if (fp->f_type == DTYPE_SOCKET) { len = kio->kio_totalsize; microtime(&t0); do { nbyte = MIN(len, (unsigned long long)nbyte); aiov.iov_len = nbyte; auio.uio_resid = nbyte; auio.uio_offset = 0; error = soreceive((struct socket *)fp->f_data, NULL, &auio, NULL, NULL, NULL); len -= auio.uio_offset; } while (error == 0 && len > 0 && auio.uio_offset != 0); microtime(&t1); if (error == EPIPE) error = 0; } else error = EFTYPE; fdrop(fp, td); if (error != 0) return error; timersub(&t1, &t0, &kio->kio_elapsed); kio->kio_bytesdone = kio->kio_totalsize - len; return 0; }
/* * Works similarly to nlookup_done() when nd initialized with * nlookup_init_at(). */ void nlookup_done_at(struct nlookupdata *nd, struct file *fp) { nlookup_done(nd); if (fp != NULL) fdrop(fp); }
/* * fp_open: * * Open a file as specified. Use O_* flags for flags. * * vn_open() asserts that the cred must match the process's cred. * * NOTE! when fp_open() is called from a pure thread, root creds are * used. */ int fp_open(const char *path, int flags, int mode, file_t *fpp) { struct nlookupdata nd; struct thread *td; struct file *fp; int error; if ((error = falloc(NULL, fpp, NULL)) != 0) return (error); fp = *fpp; td = curthread; if (td->td_proc) fsetcred(fp, td->td_proc->p_ucred); error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_LOCKVP); flags = FFLAGS(flags); if (error == 0) error = vn_open(&nd, fp, flags, mode); nlookup_done(&nd); if (error) { fdrop(fp); *fpp = NULL; } return(error); }
/* * The close() system call uses it's own audit call to capture the path/vnode * information because those pieces are not easily obtained within the system * call itself. */ void audit_sysclose(struct thread *td, int fd) { struct kaudit_record *ar; struct vnode *vp; struct file *fp; int vfslocked; KASSERT(td != NULL, ("audit_sysclose: td == NULL")); ar = currecord(); if (ar == NULL) return; audit_arg_fd(fd); if (getvnode(td->td_proc->p_fd, fd, &fp) != 0) return; vp = fp->f_vnode; vfslocked = VFS_LOCK_GIANT(vp->v_mount); vn_lock(vp, LK_SHARED | LK_RETRY); audit_arg_vnode1(vp); VOP_UNLOCK(vp, 0); VFS_UNLOCK_GIANT(vfslocked); fdrop(fp, td); }
int kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) { struct socket *so; struct file *fp; cap_rights_t rights; int error; AUDIT_ARG_FD(fd); AUDIT_ARG_SOCKADDR(td, dirfd, sa); error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND), &fp, NULL, NULL); if (error != 0) return (error); so = fp->f_data; #ifdef KTRACE if (KTRPOINT(td, KTR_STRUCT)) ktrsockaddr(sa); #endif #ifdef MAC error = mac_socket_check_bind(td->td_ucred, so, sa); if (error == 0) { #endif if (dirfd == AT_FDCWD) error = sobind(so, sa, td); else error = sobindat(dirfd, so, sa, td); #ifdef MAC } #endif fdrop(fp, td); return (error); }
static void filemon_dtr(void *data) { struct filemon *filemon = data; if (filemon != NULL) { struct file *fp = filemon->fp; /* Get exclusive write access. */ filemon_lock_write(); /* Remove from the in-use list. */ TAILQ_REMOVE(&filemons_inuse, filemon, link); filemon->fp = NULL; filemon->pid = -1; /* Add to the free list. */ TAILQ_INSERT_TAIL(&filemons_free, filemon, link); /* Give up write access. */ filemon_unlock_write(); if (fp != NULL) fdrop(fp, curthread); } }
int sys_ksem_post(struct thread *td, struct ksem_post_args *uap) { struct file *fp; struct ksem *ks; int error; error = ksem_get(td, uap->id, CAP_SEM_POST, &fp); if (error) return (error); ks = fp->f_data; mtx_lock(&sem_lock); #ifdef MAC error = mac_posixsem_check_post(td->td_ucred, fp->f_cred, ks); if (error) goto err; #endif if (ks->ks_value == SEM_VALUE_MAX) { error = EOVERFLOW; goto err; } ++ks->ks_value; if (ks->ks_waiters > 0) cv_signal(&ks->ks_cv); error = 0; vfs_timestamp(&ks->ks_ctime); err: mtx_unlock(&sem_lock); fdrop(fp, td); return (error); }
/* * Close out the log. */ static void filemon_close_log(struct filemon *filemon) { struct file *fp; struct timeval now; size_t len; sx_assert(&filemon->lock, SA_XLOCKED); if (filemon->fp == NULL) return; getmicrotime(&now); len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "# Stop %ju.%06ju\n# Bye bye\n", (uintmax_t)now.tv_sec, (uintmax_t)now.tv_usec); filemon_output(filemon, filemon->msgbufr, len); fp = filemon->fp; filemon->fp = NULL; sx_xunlock(&filemon->lock); fdrop(fp, curthread); sx_xlock(&filemon->lock); }
static void translate_fd_major_minor(struct thread *td, int fd, struct stat *buf) { struct file *fp; struct vnode *vp; int major, minor; /* * No capability rights required here. */ if ((!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) || fget(td, fd, 0, &fp) != 0) return; vp = fp->f_vnode; if (vp != NULL && vp->v_rdev != NULL && linux_driver_get_major_minor(devtoname(vp->v_rdev), &major, &minor) == 0) { buf->st_rdev = (major << 8 | minor); } else if (fp->f_type == DTYPE_PTS) { struct tty *tp = fp->f_data; /* Convert the numbers for the slave device. */ if (linux_driver_get_major_minor(devtoname(tp->t_dev), &major, &minor) == 0) { buf->st_rdev = (major << 8 | minor); } } fdrop(fp, td); }
int cloudabi_sys_fd_stat_get(struct thread *td, struct cloudabi_sys_fd_stat_get_args *uap) { cloudabi_fdstat_t fsb = {}; struct file *fp; cap_rights_t rights; struct filecaps fcaps; int error, oflags; /* Obtain file descriptor properties. */ error = fget_cap(td, uap->fd, cap_rights_init(&rights), &fp, &fcaps); if (error != 0) return (error); oflags = OFLAGS(fp->f_flag); fsb.fs_filetype = cloudabi_convert_filetype(fp); fdrop(fp, td); /* Convert file descriptor flags. */ if (oflags & O_APPEND) fsb.fs_flags |= CLOUDABI_FDFLAG_APPEND; if (oflags & O_NONBLOCK) fsb.fs_flags |= CLOUDABI_FDFLAG_NONBLOCK; if (oflags & O_SYNC) fsb.fs_flags |= CLOUDABI_FDFLAG_SYNC; /* Convert capabilities to CloudABI rights. */ convert_capabilities(&fcaps.fc_rights, fsb.fs_filetype, &fsb.fs_rights_base, &fsb.fs_rights_inheriting); filecaps_free(&fcaps); return (copyout(&fsb, (void *)uap->buf, sizeof(fsb))); }
static int aacraid_linux_ioctl(struct thread *td, struct linux_ioctl_args *args) { struct file *fp; #if __FreeBSD_version >= 900000 cap_rights_t rights; #endif u_long cmd; int error; if ((error = fget(td, args->fd, #if __FreeBSD_version >= 900000 cap_rights_init(&rights, CAP_IOCTL), #endif &fp)) != 0) { return (error); } cmd = args->cmd; /* * Pass the ioctl off to our standard handler. */ error = (fo_ioctl(fp, cmd, (caddr_t)args->arg, td->td_ucred, td)); fdrop(fp, td); return (error); }
static int ipmi_linux_ioctl(struct thread *td, struct linux_ioctl_args *args) { cap_rights_t rights; struct file *fp; u_long cmd; int error; error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); if (error != 0) return (error); cmd = args->cmd; switch(cmd) { case L_IPMICTL_GET_MY_ADDRESS_CMD: cmd = IPMICTL_GET_MY_ADDRESS_CMD; break; case L_IPMICTL_GET_MY_LUN_CMD: cmd = IPMICTL_GET_MY_LUN_CMD; break; } /* * Pass the ioctl off to our standard handler. */ error = (fo_ioctl(fp, cmd, (caddr_t)args->arg, td->td_ucred, td)); fdrop(fp, td); return (error); }
int cloudabi_sys_fd_stat_get(struct thread *td, struct cloudabi_sys_fd_stat_get_args *uap) { cloudabi_fdstat_t fsb = {}; struct filedesc *fdp; struct file *fp; seq_t seq; cap_rights_t rights; int error, oflags; bool modified; /* Obtain file descriptor properties. */ fdp = td->td_proc->p_fd; do { error = fget_unlocked(fdp, uap->fd, cap_rights_init(&rights), &fp, &seq); if (error != 0) return (error); if (fp->f_ops == &badfileops) { fdrop(fp, td); return (EBADF); } rights = *cap_rights(fdp, uap->fd); oflags = OFLAGS(fp->f_flag); fsb.fs_filetype = cloudabi_convert_filetype(fp); modified = fd_modified(fdp, uap->fd, seq); fdrop(fp, td); } while (modified); /* Convert file descriptor flags. */ if (oflags & O_APPEND) fsb.fs_flags |= CLOUDABI_FDFLAG_APPEND; if (oflags & O_NONBLOCK) fsb.fs_flags |= CLOUDABI_FDFLAG_NONBLOCK; if (oflags & O_SYNC) fsb.fs_flags |= CLOUDABI_FDFLAG_SYNC; /* Convert capabilities to CloudABI rights. */ convert_capabilities(&rights, fsb.fs_filetype, &fsb.fs_rights_base, &fsb.fs_rights_inheriting); return (copyout(&fsb, (void *)uap->buf, sizeof(fsb))); }
int ksem_close(struct thread *td, struct ksem_close_args *uap) { struct ksem *ks; struct file *fp; int error; error = ksem_get(td, uap->id, &fp); if (error) return (error); ks = fp->f_data; if (ks->ks_flags & KS_ANONYMOUS) { fdrop(fp, td); return (EINVAL); } error = kern_close(td, uap->id); fdrop(fp, td); return (error); }
static int linux_getdents_error(struct thread *td, int fd, int err) { struct vnode *vp; struct file *fp; int error; /* Linux return ENOTDIR in case when fd is not a directory. */ error = getvnode(td, fd, &cap_read_rights, &fp); if (error != 0) return (error); vp = fp->f_vnode; if (vp->v_type != VDIR) { fdrop(fp, td); return (ENOTDIR); } fdrop(fp, td); return (err); }
int pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd) { struct proc *p; cap_rights_t rights; int error; sx_assert(&pmc_sx, SA_XLOCKED); PMCDBG2(LOG,CFG,1, "config po=%p logfd=%d", po, logfd); p = po->po_owner; /* return EBUSY if a log file was already present */ if (po->po_flags & PMC_PO_OWNS_LOGFILE) return (EBUSY); KASSERT(po->po_file == NULL, ("[pmclog,%d] po=%p file (%p) already present", __LINE__, po, po->po_file)); /* get a reference to the file state */ error = fget_write(curthread, logfd, cap_rights_init(&rights, CAP_WRITE), &po->po_file); if (error) goto error; /* mark process as owning a log file */ po->po_flags |= PMC_PO_OWNS_LOGFILE; /* mark process as using HWPMCs */ PROC_LOCK(p); p->p_flag |= P_HWPMC; PROC_UNLOCK(p); /* create a log initialization entry */ PMCLOG_RESERVE_WITH_ERROR(po, INITIALIZE, sizeof(struct pmclog_initialize)); PMCLOG_EMIT32(PMC_VERSION); PMCLOG_EMIT32(md->pmd_cputype); PMCLOG_DESPATCH(po); return (0); error: KASSERT(po->po_kthread == NULL, ("[pmclog,%d] po=%p kthread not " "stopped", __LINE__, po)); if (po->po_file) (void) fdrop(po->po_file, curthread); po->po_file = NULL; /* clear file and error state */ po->po_error = 0; po->po_flags &= ~PMC_PO_OWNS_LOGFILE; return (error); }
static int sysvipc_install_fd(struct proc *p_from, struct proc *p_to, int fd) { struct filedesc *fdp_from = p_from->p_fd; struct filedesc *fdp_to = p_to->p_fd; struct file *fp; int error, newfd; int flags; /* * Get the file corresponding to fd from the process p_from. */ spin_lock(&fdp_from->fd_spin); if ((unsigned)fd >= fdp_from->fd_nfiles || fdp_from->fd_files[fd].fp == NULL) { spin_unlock(&fdp_from->fd_spin); return (EBADF); } fp = fdp_from->fd_files[fd].fp; flags = fdp_from->fd_files[fd].fileflags; fhold(fp); /* MPSAFE - can be called with a spinlock held */ spin_unlock(&fdp_from->fd_spin); /* * Reserve a fd in the process p_to. */ error = fdalloc(p_to, 1, &newfd); if (error) { fdrop(fp); return (error); } /* * Set fd for the fp file. */ fsetfd(fdp_to, fp, newfd); fdp_to->fd_files[newfd].fileflags = flags; fdrop(fp); return (newfd); }
int sys_ksem_close(struct thread *td, struct ksem_close_args *uap) { struct ksem *ks; struct file *fp; int error; /* No capability rights required to close a semaphore. */ error = ksem_get(td, uap->id, 0, &fp); if (error) return (error); ks = fp->f_data; if (ks->ks_flags & KS_ANONYMOUS) { fdrop(fp, td); return (EINVAL); } error = kern_close(td, uap->id); fdrop(fp, td); return (error); }
static int fdesc_get_ino_alloc(struct mount *mp, void *arg, int lkflags, struct vnode **rvp) { struct fdesc_get_ino_args *a; int error; a = arg; error = fdesc_allocvp(a->ftype, a->fd_fd, a->ix, mp, rvp); fdrop(a->fp, a->td); return (error); }
static int ksem_get(struct thread *td, semid_t id, cap_rights_t rights, struct file **fpp) { struct ksem *ks; struct file *fp; int error; error = fget(td, id, rights, &fp); if (error) return (EINVAL); if (fp->f_type != DTYPE_SEM) { fdrop(fp, td); return (EINVAL); } ks = fp->f_data; if (ks->ks_flags & KS_DEAD) { fdrop(fp, td); return (EINVAL); } *fpp = fp; return (0); }
static int amr_linux_ioctl(struct thread *p, struct linux_ioctl_args *args) { cap_rights_t rights; struct file *fp; int error; error = fget(p, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); if (error != 0) return (error); error = fo_ioctl(fp, args->cmd, (caddr_t)args->arg, p->td_ucred, p); fdrop(fp, p); return (error); }
int pmclog_deconfigure_log(struct pmc_owner *po) { int error; struct pmclog_buffer *lb; PMCDBG1(LOG,CFG,1, "de-config po=%p", po); if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0) return (EINVAL); KASSERT(po->po_sscount == 0, ("[pmclog,%d] po=%p still owning SS PMCs", __LINE__, po)); KASSERT(po->po_file != NULL, ("[pmclog,%d] po=%p no log file", __LINE__, po)); /* stop the kthread, this will reset the 'OWNS_LOGFILE' flag */ pmclog_stop_kthread(po); KASSERT(po->po_kthread == NULL, ("[pmclog,%d] po=%p kthread not stopped", __LINE__, po)); /* return all queued log buffers to the global pool */ while ((lb = TAILQ_FIRST(&po->po_logbuffers)) != NULL) { TAILQ_REMOVE(&po->po_logbuffers, lb, plb_next); PMCLOG_INIT_BUFFER_DESCRIPTOR(lb); mtx_lock_spin(&pmc_bufferlist_mtx); TAILQ_INSERT_HEAD(&pmc_bufferlist, lb, plb_next); mtx_unlock_spin(&pmc_bufferlist_mtx); } /* return the 'current' buffer to the global pool */ if ((lb = po->po_curbuf) != NULL) { PMCLOG_INIT_BUFFER_DESCRIPTOR(lb); mtx_lock_spin(&pmc_bufferlist_mtx); TAILQ_INSERT_HEAD(&pmc_bufferlist, lb, plb_next); mtx_unlock_spin(&pmc_bufferlist_mtx); } /* drop a reference to the fd */ if (po->po_file != NULL) { error = fdrop(po->po_file, curthread); po->po_file = NULL; } else error = 0; po->po_error = 0; return (error); }
static int fdesc_setattr(struct vop_setattr_args *ap) { struct vattr *vap = ap->a_vap; struct vnode *vp; struct mount *mp; struct file *fp; struct thread *td = curthread; cap_rights_t rights; unsigned fd; int error; /* * Can't mess with the root vnode */ if (VTOFDESC(ap->a_vp)->fd_type == Froot) return (EACCES); fd = VTOFDESC(ap->a_vp)->fd_fd; /* * Allow setattr where there is an underlying vnode. */ error = getvnode(td, fd, cap_rights_init(&rights, CAP_EXTATTR_SET), &fp); if (error) { /* * getvnode() returns EINVAL if the file descriptor is not * backed by a vnode. Silently drop all changes except * chflags(2) in this case. */ if (error == EINVAL) { if (vap->va_flags != VNOVAL) error = EOPNOTSUPP; else error = 0; } return (error); } vp = fp->f_vnode; if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) == 0) { vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); error = VOP_SETATTR(vp, ap->a_vap, ap->a_cred); VOP_UNLOCK(vp, 0); vn_finished_write(mp); } fdrop(fp, td); return (error); }
int smb_dev2share(int fd, int mode, struct smb_cred *scred, struct smb_share **sspp) { struct file *fp; struct vnode *vp; struct smb_dev *sdp; struct smb_share *ssp; struct cdev *dev; int error; fp = nsmb_getfp(scred->scr_td->td_proc->p_fd, fd, FREAD | FWRITE); if (fp == NULL) return EBADF; vp = fp->f_vnode; if (vp == NULL) { fdrop(fp, curthread); return EBADF; } if (vp->v_type != VCHR) { fdrop(fp, curthread); return EBADF; } dev = vp->v_rdev; SMB_CHECKMINOR(dev); ssp = sdp->sd_share; if (ssp == NULL) { fdrop(fp, curthread); return ENOTCONN; } error = smb_share_get(ssp, LK_EXCLUSIVE, scred); if (error == 0) *sspp = ssp; fdrop(fp, curthread); return error; }