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); }
struct cfs_kern_file * kern_file_open(const char * filename, int uflags, int mode, int *err) { struct cfs_kern_file *fp; vnode_t vp; int error; fp = (struct cfs_kern_file *)_MALLOC(sizeof(struct cfs_kern_file), M_TEMP, M_WAITOK); if (fp == NULL) { if (err != NULL) *err = -ENOMEM; return NULL; } fp->f_flags = FFLAGS(uflags); fp->f_ctxt = vfs_context_create(NULL); if ((error = vnode_open(filename, fp->f_flags, mode, 0, &vp, fp->f_ctxt))){ if (err != NULL) *err = -error; _FREE(fp, M_TEMP); } else { if (err != NULL) *err = 0; fp->f_vp = vp; } return 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); }
cru2x(td->td_ucred, &msg.lm_cred); /* * Open the lock fifo. If for any reason we don't find the fifo, it * means that the lock daemon isn't running. Translate any missing * file error message for the user, otherwise the application will * complain that the user's file is missing, which isn't the case. * Note that we use proc0's cred, so the fifo is opened as root. * * XXX: Note that this behavior is relative to the root directory * of the current process, and this may result in a variety of * {functional, security} problems in chroot() environments. */ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, _PATH_LCKFIFO, td); fmode = FFLAGS(O_WRONLY); error = vn_open_cred(&nd, &fmode, 0, thread0.td_ucred); if (error != 0) { return (error == ENOENT ? EOPNOTSUPP : error); } wvp = nd.ni_vp; VOP_UNLOCK(wvp, 0, td); /* vn_open leaves it locked */ ioflg = IO_UNIT | IO_NOMACCHECK; for (;;) { VOP_LEASE(wvp, td, thread0.td_ucred, LEASE_WRITE); error = vn_rdwr(UIO_WRITE, wvp, (caddr_t)&msg, sizeof(msg), 0, UIO_SYSSPACE, ioflg, thread0.td_ucred, NOCRED, NULL, td);
int xfs_fhopen (d_thread_t *proc, struct xfs_fhandle_t *fhp, int user_flags, register_t *retval) { int error; struct vnode *vp; #ifdef HAVE_FREEBSD_THREAD struct ucred *cred = proc->td_proc->p_ucred; #else struct ucred *cred = proc->p_ucred; #endif int flags = FFLAGS(user_flags); int index; struct file *fp; int mode; struct xfs_fhandle_t fh; NNPFSDEB(XDEBVFOPS, ("xfs_fhopen: flags = %d\n", user_flags)); error = copyin (fhp, &fh, sizeof(fh)); if (error) return error; error = xfs_fhlookup (proc, &fh, &vp); NNPFSDEB(XDEBVFOPS, ("xfs_fhlookup returned %d\n", error)); if (error) return error; switch (vp->v_type) { case VDIR : case VREG : break; case VLNK : error = EMLINK; goto out; default : error = EOPNOTSUPP; goto out; } mode = 0; if (flags & FWRITE) { switch (vp->v_type) { case VREG : break; case VDIR : error = EISDIR; goto out; default : error = EOPNOTSUPP; goto out; } error = vn_writechk (vp); if (error) goto out; mode |= VWRITE; } if (flags & FREAD) mode |= VREAD; if (mode) { error = VOP_ACCESS(vp, mode, cred, proc); if (error) goto out; } error = VOP_OPEN(vp, flags, cred, proc); if (error) goto out; error = falloc(proc, &fp, &index); if (error) goto out; if (flags & FWRITE) vp->v_writecount++; #if defined(__FreeBSD_version) && __FreeBSD_version >= 300000 if (vp->v_type == VREG) { #ifdef HAVE_FREEBSD_THREAD error = xfs_vfs_object_create(vp, proc, proc->td_proc->p_ucred); #else error = xfs_vfs_object_create(vp, proc, proc->p_ucred); #endif if (error) goto out; } #endif fp->f_flag = flags & FMASK; fp->f_type = DTYPE_VNODE; fp->f_ops = &vnops; fp->f_data = (caddr_t)vp; xfs_vfs_unlock(vp, proc); *retval = index; #ifdef FILE_UNUSE FILE_UNUSE(fp, proc); #endif #ifdef __APPLE__ *fdflags(proc, index) &= ~UF_RESERVED; #endif return 0; out: NNPFSDEB(XDEBVFOPS, ("xfs_fhopen: error = %d\n", error)); vput(vp); return error; }
/* System calls. */ int sys_shm_open(struct thread *td, struct shm_open_args *uap) { struct filedesc *fdp; struct shmfd *shmfd; struct file *fp; char *path; Fnv32_t fnv; mode_t cmode; int fd, error; #ifdef CAPABILITY_MODE /* * shm_open(2) is only allowed for anonymous objects. */ if (IN_CAPABILITY_MODE(td) && (uap->path != SHM_ANON)) return (ECAPMODE); #endif if ((uap->flags & O_ACCMODE) != O_RDONLY && (uap->flags & O_ACCMODE) != O_RDWR) return (EINVAL); if ((uap->flags & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC)) != 0) return (EINVAL); fdp = td->td_proc->p_fd; cmode = (uap->mode & ~fdp->fd_cmask) & ACCESSPERMS; error = falloc(td, &fp, &fd, 0); if (error) return (error); /* A SHM_ANON path pointer creates an anonymous object. */ if (uap->path == SHM_ANON) { /* A read-only anonymous object is pointless. */ if ((uap->flags & O_ACCMODE) == O_RDONLY) { fdclose(fdp, fp, fd, td); fdrop(fp, td); return (EINVAL); } shmfd = shm_alloc(td->td_ucred, cmode); } else { path = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK); error = copyinstr(uap->path, path, MAXPATHLEN, NULL); /* Require paths to start with a '/' character. */ if (error == 0 && path[0] != '/') error = EINVAL; if (error) { fdclose(fdp, fp, fd, td); fdrop(fp, td); free(path, M_SHMFD); return (error); } fnv = fnv_32_str(path, FNV1_32_INIT); sx_xlock(&shm_dict_lock); shmfd = shm_lookup(path, fnv); if (shmfd == NULL) { /* Object does not yet exist, create it if requested. */ if (uap->flags & O_CREAT) { #ifdef MAC error = mac_posixshm_check_create(td->td_ucred, path); if (error == 0) { #endif shmfd = shm_alloc(td->td_ucred, cmode); shm_insert(path, fnv, shmfd); #ifdef MAC } #endif } else { free(path, M_SHMFD); error = ENOENT; } } else { /* * Object already exists, obtain a new * reference if requested and permitted. */ free(path, M_SHMFD); if ((uap->flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) error = EEXIST; else { #ifdef MAC error = mac_posixshm_check_open(td->td_ucred, shmfd, FFLAGS(uap->flags & O_ACCMODE)); if (error == 0) #endif error = shm_access(shmfd, td->td_ucred, FFLAGS(uap->flags & O_ACCMODE)); } /* * Truncate the file back to zero length if * O_TRUNC was specified and the object was * opened with read/write. */ if (error == 0 && (uap->flags & (O_ACCMODE | O_TRUNC)) == (O_RDWR | O_TRUNC)) { #ifdef MAC error = mac_posixshm_check_truncate( td->td_ucred, fp->f_cred, shmfd); if (error == 0) #endif shm_dotruncate(shmfd, 0); } if (error == 0) shm_hold(shmfd); } sx_xunlock(&shm_dict_lock); if (error) { fdclose(fdp, fp, fd, td); fdrop(fp, td); return (error); } } finit(fp, FFLAGS(uap->flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops); FILEDESC_XLOCK(fdp); if (fdp->fd_ofiles[fd] == fp) fdp->fd_ofileflags[fd] |= UF_EXCLOSE; FILEDESC_XUNLOCK(fdp); td->td_retval[0] = fd; fdrop(fp, td); return (0); }
/* * The file control system call. */ int sys_fcntl(struct lwp *l, const struct sys_fcntl_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(int) cmd; syscallarg(void *) arg; } */ int fd, i, tmp, error, cmd, newmin; filedesc_t *fdp; file_t *fp; struct flock fl; bool cloexec = false; fd = SCARG(uap, fd); cmd = SCARG(uap, cmd); fdp = l->l_fd; error = 0; switch (cmd) { case F_CLOSEM: if (fd < 0) return EBADF; while ((i = fdp->fd_lastfile) >= fd) { if (fd_getfile(i) == NULL) { /* Another thread has updated. */ continue; } fd_close(i); } return 0; case F_MAXFD: *retval = fdp->fd_lastfile; return 0; case F_SETLKW: case F_SETLK: case F_GETLK: error = copyin(SCARG(uap, arg), &fl, sizeof(fl)); if (error) return error; error = do_fcntl_lock(fd, cmd, &fl); if (cmd == F_GETLK && error == 0) error = copyout(&fl, SCARG(uap, arg), sizeof(fl)); return error; default: /* Handled below */ break; } if ((fp = fd_getfile(fd)) == NULL) return (EBADF); if ((cmd & F_FSCTL)) { error = fcntl_forfs(fd, fp, cmd, SCARG(uap, arg)); fd_putfile(fd); return error; } switch (cmd) { case F_DUPFD_CLOEXEC: cloexec = true; /*FALLTHROUGH*/ case F_DUPFD: newmin = (long)SCARG(uap, arg); if ((u_int)newmin >= l->l_proc->p_rlimit[RLIMIT_NOFILE].rlim_cur || (u_int)newmin >= maxfiles) { fd_putfile(fd); return EINVAL; } error = fd_dup(fp, newmin, &i, cloexec); *retval = i; break; case F_GETFD: *retval = fdp->fd_dt->dt_ff[fd]->ff_exclose; break; case F_SETFD: fd_set_exclose(l, fd, ((long)SCARG(uap, arg) & FD_CLOEXEC) != 0); break; case F_GETNOSIGPIPE: *retval = (fp->f_flag & FNOSIGPIPE) != 0; break; case F_SETNOSIGPIPE: if (SCARG(uap, arg)) atomic_or_uint(&fp->f_flag, FNOSIGPIPE); else atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE); *retval = 0; break; case F_GETFL: *retval = OFLAGS(fp->f_flag); break; case F_SETFL: /* XXX not guaranteed to be atomic. */ tmp = FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS; error = (*fp->f_ops->fo_fcntl)(fp, F_SETFL, &tmp); if (error) break; i = tmp ^ fp->f_flag; if (i & FNONBLOCK) { int flgs = tmp & FNONBLOCK; error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, &flgs); if (error) { (*fp->f_ops->fo_fcntl)(fp, F_SETFL, &fp->f_flag); break; } } if (i & FASYNC) { int flgs = tmp & FASYNC; error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, &flgs); if (error) { if (i & FNONBLOCK) { tmp = fp->f_flag & FNONBLOCK; (void)(*fp->f_ops->fo_ioctl)(fp, FIONBIO, &tmp); } (*fp->f_ops->fo_fcntl)(fp, F_SETFL, &fp->f_flag); break; } } fp->f_flag = (fp->f_flag & ~FCNTLFLAGS) | tmp; break; case F_GETOWN: error = (*fp->f_ops->fo_ioctl)(fp, FIOGETOWN, &tmp); *retval = tmp; break; case F_SETOWN: tmp = (int)(uintptr_t) SCARG(uap, arg); error = (*fp->f_ops->fo_ioctl)(fp, FIOSETOWN, &tmp); break; default: error = EINVAL; } fd_putfile(fd); return (error); }
/* * fp_vpopen(): convert a vnode to a file pointer, call VOP_OPEN() on the * the vnode. The vnode must be refd and locked. * * On success the vnode's ref is inherited by the file pointer and the caller * should not vrele() it, and the vnode is unlocked. * * On failure the vnode remains locked and refd and the caller is responsible * for vput()ing it. */ int fp_vpopen(struct vnode *vp, int flags, file_t *fpp) { struct thread *td; struct file *fp; int vmode; int error; td = curthread; /* * Vnode checks (from vn_open()) */ if (vp->v_type == VLNK) { error = EMLINK; goto bad2; } if (vp->v_type == VSOCK) { error = EOPNOTSUPP; goto bad2; } flags = FFLAGS(flags); vmode = 0; if (flags & (FWRITE | O_TRUNC)) { if (vp->v_type == VDIR) { error = EISDIR; goto bad2; } error = vn_writechk(vp, NULL); if (error) goto bad2; vmode |= VWRITE; } if (flags & FREAD) vmode |= VREAD; if (vmode) { error = VOP_ACCESS(vp, vmode, td->td_proc->p_ucred); if (error) goto bad2; } /* * File pointer setup */ if ((error = falloc(NULL, fpp, NULL)) != 0) goto bad2; fp = *fpp; if (td->td_proc) fsetcred(fp, td->td_proc->p_ucred); error = VOP_OPEN(vp, flags, td->td_proc->p_ucred, fp); if (error) goto bad1; vput(vp); return (0); bad1: fp->f_ops = &badfileops; /* open failed, don't close */ fp->f_data = NULL; fdrop(fp); /* leave the vnode intact, but fall through and unlock it anyway */ bad2: *fpp = NULL; return (error); }