static int tmpfs_open(struct vop_open_args *v) { struct vnode *vp = v->a_vp; int mode = v->a_mode; struct tmpfs_node *node; int error; node = VP_TO_TMPFS_NODE(vp); #if 0 /* The file is still active but all its names have been removed * (e.g. by a "rmdir $(pwd)"). It cannot be opened any more as * it is about to die. */ if (node->tn_links < 1) return (ENOENT); #endif /* If the file is marked append-only, deny write requests. */ if ((node->tn_flags & APPEND) && (mode & (FWRITE | O_APPEND)) == FWRITE) { error = EPERM; } else { error = (vop_stdopen(v)); } return (error); }
/* * set things up for doing i/o on * the pfsnode (vp). (vp) is locked * on entry, and should be left locked * on exit. * * for procfs we don't need to do anything * in particular for i/o. all that is done * is to support exclusive open on process * memory images. */ static int linprocfs_open(struct vop_open_args *ap) { struct pfsnode *pfs = VTOPFS(ap->a_vp); struct proc *p2; p2 = PFIND(pfs->pfs_pid); if (p2 == NULL) return (ENOENT); if (pfs->pfs_pid && !PRISON_CHECK(ap->a_cred, p2->p_ucred)) return (ENOENT); switch (pfs->pfs_type) { case Pmem: if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) || ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) return (EBUSY); if (p_trespass(ap->a_cred, p2->p_ucred)) return (EPERM); if (ap->a_mode & FWRITE) pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); break; default: break; } return (vop_stdopen(ap)); }
static int puffs_vnop_open(struct vop_open_args *ap) { PUFFS_MSG_VARS(vn, open); struct vnode *vp = ap->a_vp; struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); int mode = ap->a_mode; int error; DPRINTF(("puffs_open: vp %p, mode 0x%x\n", vp, mode)); if (vp->v_type == VREG && mode & FWRITE && !EXISTSOP(pmp, WRITE)) ERROUT(EROFS); if (!EXISTSOP(pmp, OPEN)) ERROUT(0); PUFFS_MSG_ALLOC(vn, open); open_msg->pvnr_mode = mode; puffs_credcvt(&open_msg->pvnr_cred, ap->a_cred); puffs_msg_setinfo(park_open, PUFFSOP_VN, PUFFS_VN_OPEN, VPTOPNC(vp)); PUFFS_MSG_ENQUEUEWAIT2(pmp, park_open, vp->v_data, NULL, error); error = checkerr(pmp, error, __func__); out: DPRINTF(("puffs_open: returning %d\n", error)); PUFFS_MSG_RELEASE(open); if (error) return error; return vop_stdopen(ap); }
/* * set things up for doing i/o on * the pfsnode (vp). (vp) is locked * on entry, and should be left locked * on exit. * * for procfs we don't need to do anything * in particular for i/o. all that is done * is to support exclusive open on process * memory images. * * procfs_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred, * struct file *a_fp) */ static int procfs_open(struct vop_open_args *ap) { struct pfsnode *pfs = VTOPFS(ap->a_vp); struct proc *p1, *p2; int error; p2 = pfs_pfind(pfs->pfs_pid); if (p2 == NULL) return (ENOENT); if (pfs->pfs_pid && !PRISON_CHECK(ap->a_cred, p2->p_ucred)) { error = ENOENT; goto done; } switch (pfs->pfs_type) { case Pmem: if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) || ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) { error = EBUSY; goto done; } p1 = curproc; KKASSERT(p1); /* Can't trace a process that's currently exec'ing. */ if ((p2->p_flags & P_INEXEC) != 0) { error = EAGAIN; goto done; } if (!CHECKIO(p1, p2) || p_trespass(ap->a_cred, p2->p_ucred)) { error = EPERM; goto done; } if (ap->a_mode & FWRITE) pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); break; default: break; } error = vop_stdopen(ap); done: pfs_pdone(p2); return error; }
/* * fdesc_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred, * struct file *a_fp) */ static int fdesc_open(struct vop_open_args *ap) { struct vnode *vp = ap->a_vp; struct lwp *lp = curthread->td_lwp; KKASSERT(lp); if (VTOFDESC(vp)->fd_type == Froot) return (vop_stdopen(ap)); /* * XXX Kludge: set lp->lwp_dupfd to contain the value of the the file * descriptor being sought for duplication. The error return ensures * that the vnode for this device will be released by vn_open. Open * will detect this special error and take the actions in dupfdopen. * Other callers of vn_open or VOP_OPEN will simply report the * error. */ lp->lwp_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ return (ENODEV); }
/* * portal_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred, * struct file *a_fp) */ static int portal_open(struct vop_open_args *ap) { struct socket *so = 0; struct portalnode *pt; struct thread *td = curthread; struct vnode *vp = ap->a_vp; struct uio auio; struct iovec aiov[2]; struct sockbuf sio; int res; struct mbuf *cm = 0; struct cmsghdr *cmsg; int newfds; int *ip; int fd; int error; int len; struct portalmount *fmp; struct file *fp; struct portal_cred pcred; /* * Nothing to do when opening the root node. */ if (vp->v_flag & VROOT) return (vop_stdopen(ap)); /* * Can't be opened unless the caller is set up * to deal with the side effects. Check for this * by testing whether the p_dupfd has been set. */ KKASSERT(td->td_proc); if (td->td_lwp->lwp_dupfd >= 0) return (ENODEV); pt = VTOPORTAL(vp); fmp = VFSTOPORTAL(vp->v_mount); /* * Create a new socket. */ error = socreate(AF_UNIX, &so, SOCK_STREAM, 0, td); if (error) goto bad; /* * Reserve some buffer space */ res = pt->pt_size + sizeof(pcred) + 512; /* XXX */ error = soreserve(so, res, res, &td->td_proc->p_rlimit[RLIMIT_SBSIZE]); if (error) goto bad; /* * Kick off connection */ error = portal_connect(so, (struct socket *)fmp->pm_server->f_data); if (error) goto bad; /* * Wait for connection to complete */ /* * XXX: Since the mount point is holding a reference on the * underlying server socket, it is not easy to find out whether * the server process is still running. To handle this problem * we loop waiting for the new socket to be connected (something * which will only happen if the server is still running) or for * the reference count on the server socket to drop to 1, which * will happen if the server dies. Sleep for 5 second intervals * and keep polling the reference count. XXX. */ crit_enter(); while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { if (fmp->pm_server->f_count == 1) { error = ECONNREFUSED; crit_exit(); goto bad; } (void) tsleep((caddr_t) &so->so_timeo, 0, "portalcon", 5 * hz); } crit_exit(); if (so->so_error) { error = so->so_error; goto bad; } /* * Set miscellaneous flags */ so->so_rcv.ssb_timeo = 0; so->so_snd.ssb_timeo = 0; atomic_set_int(&so->so_rcv.ssb_flags, SSB_NOINTR); atomic_set_int(&so->so_snd.ssb_flags, SSB_NOINTR); pcred.pcr_flag = ap->a_mode; pcred.pcr_uid = ap->a_cred->cr_uid; pcred.pcr_ngroups = ap->a_cred->cr_ngroups; bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t)); aiov[0].iov_base = (caddr_t) &pcred; aiov[0].iov_len = sizeof(pcred); aiov[1].iov_base = pt->pt_arg; aiov[1].iov_len = pt->pt_size; auio.uio_iov = aiov; auio.uio_iovcnt = 2; auio.uio_rw = UIO_WRITE; auio.uio_segflg = UIO_SYSSPACE; auio.uio_td = td; auio.uio_offset = 0; auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len; error = sosend(so, NULL, &auio, NULL, NULL, 0, td); if (error) goto bad; len = sizeof(int); sbinit(&sio, len); do { struct mbuf *m; int flags; flags = MSG_WAITALL; error = soreceive(so, NULL, NULL, &sio, &cm, &flags); if (error) goto bad; /* * Grab an error code from the mbuf. */ if ((m = sio.sb_mb) != NULL) { m = m_pullup(m, sizeof(int)); /* Needed? */ if (m) { error = *(mtod(m, int *)); m_freem(m); } else { error = EINVAL; } } else {
/* ARGSUSED */ static int nwfs_open(struct vop_open_args *ap) { thread_t td = curthread; /* XXX */ struct vnode *vp = ap->a_vp; int mode = ap->a_mode; struct nwnode *np = VTONW(vp); struct ncp_open_info no; struct nwmount *nmp = VTONWFS(vp); struct vattr vattr; int error, nwm; NCPVNDEBUG("%s,%d\n",np->n_name, np->opened); if (vp->v_type != VREG && vp->v_type != VDIR) { NCPFATAL("open vtype = %d\n", vp->v_type); return (EACCES); } if (vp->v_type == VDIR) return 0; /* nothing to do now */ if (np->n_flag & NMODIFIED) { if ((error = nwfs_vinvalbuf(vp, V_SAVE, 1)) == EINTR) return (error); np->n_atime = 0; error = VOP_GETATTR(vp, &vattr); if (error) return (error); np->n_mtime = vattr.va_mtime.tv_sec; } else { error = VOP_GETATTR(vp, &vattr); if (error) return (error); if (np->n_mtime != vattr.va_mtime.tv_sec) { if ((error = nwfs_vinvalbuf(vp, V_SAVE, 1)) == EINTR) return (error); np->n_mtime = vattr.va_mtime.tv_sec; } } if (np->opened) { np->opened++; return (vop_stdopen(ap)); } nwm = AR_READ; if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) nwm |= AR_WRITE; error = ncp_open_create_file_or_subdir(nmp, vp, 0, NULL, OC_MODE_OPEN, 0, nwm, &no, td, ap->a_cred); if (error) { if (mode & FWRITE) return EACCES; nwm = AR_READ; error = ncp_open_create_file_or_subdir(nmp, vp, 0, NULL, OC_MODE_OPEN, 0, nwm, &no, td, ap->a_cred); } np->n_atime = 0; if (error == 0) { np->opened++; np->n_fh = no.fh; np->n_origfh = no.origfh; error = vop_stdopen(ap); } return (error); }
static int devfs_spec_open(struct vop_open_args *ap) { struct vnode *vp = ap->a_vp; struct vnode *orig_vp = NULL; struct devfs_node *node = DEVFS_NODE(vp); struct devfs_node *newnode; cdev_t dev, ndev = NULL; int error = 0; if (node) { if (node->d_dev == NULL) return ENXIO; if (!devfs_node_is_accessible(node)) return ENOENT; } if ((dev = vp->v_rdev) == NULL) return ENXIO; vn_lock(vp, LK_UPGRADE | LK_RETRY); if (node && ap->a_fp) { devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_spec_open: -1.1-\n"); lockmgr(&devfs_lock, LK_EXCLUSIVE); ndev = devfs_clone(dev, node->d_dir.d_name, node->d_dir.d_namlen, ap->a_mode, ap->a_cred); if (ndev != NULL) { newnode = devfs_create_device_node( DEVFS_MNTDATA(vp->v_mount)->root_node, ndev, NULL, NULL); /* XXX: possibly destroy device if this happens */ if (newnode != NULL) { dev = ndev; devfs_link_dev(dev); devfs_debug(DEVFS_DEBUG_DEBUG, "parent here is: %s, node is: |%s|\n", ((node->parent->node_type == Nroot) ? "ROOT!" : node->parent->d_dir.d_name), newnode->d_dir.d_name); devfs_debug(DEVFS_DEBUG_DEBUG, "test: %s\n", ((struct devfs_node *)(TAILQ_LAST(DEVFS_DENODE_HEAD(node->parent), devfs_node_head)))->d_dir.d_name); /* * orig_vp is set to the original vp if we cloned. */ /* node->flags |= DEVFS_CLONED; */ devfs_allocv(&vp, newnode); orig_vp = ap->a_vp; ap->a_vp = vp; } } lockmgr(&devfs_lock, LK_RELEASE); } devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_spec_open() called on %s! \n", dev->si_name); /* * Make this field valid before any I/O in ->d_open */ if (!dev->si_iosize_max) /* XXX: old DFLTPHYS == 64KB dependency */ dev->si_iosize_max = min(MAXPHYS,64*1024); if (dev_dflags(dev) & D_TTY) vsetflags(vp, VISTTY); /* * Open underlying device */ vn_unlock(vp); error = dev_dopen(dev, ap->a_mode, S_IFCHR, ap->a_cred, ap->a_fp); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* * Clean up any cloned vp if we error out. */ if (error) { if (orig_vp) { vput(vp); ap->a_vp = orig_vp; /* orig_vp = NULL; */ } return error; } /* * This checks if the disk device is going to be opened for writing. * It will be only allowed in the cases where securelevel permits it * and it's not mounted R/W. */ if ((dev_dflags(dev) & D_DISK) && (ap->a_mode & FWRITE) && (ap->a_cred != FSCRED)) { /* Very secure mode. No open for writing allowed */ if (securelevel >= 2) return EPERM; /* * If it is mounted R/W, do not allow to open for writing. * In the case it's mounted read-only but securelevel * is >= 1, then do not allow opening for writing either. */ if (vfs_mountedon(vp)) { if (!(dev->si_mountpoint->mnt_flag & MNT_RDONLY)) return EBUSY; else if (securelevel >= 1) return EPERM; } } if (dev_dflags(dev) & D_TTY) { if (dev->si_tty) { struct tty *tp; tp = dev->si_tty; if (!tp->t_stop) { devfs_debug(DEVFS_DEBUG_DEBUG, "devfs: no t_stop\n"); tp->t_stop = nottystop; } } } if (vn_isdisk(vp, NULL)) { if (!dev->si_bsize_phys) dev->si_bsize_phys = DEV_BSIZE; vinitvmio(vp, IDX_TO_OFF(INT_MAX), PAGE_SIZE, -1); } vop_stdopen(ap); #if 0 if (node) nanotime(&node->atime); #endif /* * If we replaced the vp the vop_stdopen() call will have loaded * it into fp->f_data and vref()d the vp, giving us two refs. So * instead of just unlocking it here we have to vput() it. */ if (orig_vp) vput(vp); /* Ugly pty magic, to make pty devices appear once they are opened */ if (node && (node->flags & DEVFS_PTY) == DEVFS_PTY) node->flags &= ~DEVFS_INVISIBLE; if (ap->a_fp) { KKASSERT(ap->a_fp->f_type == DTYPE_VNODE); KKASSERT((ap->a_fp->f_flag & FMASK) == (ap->a_mode & FMASK)); ap->a_fp->f_ops = &devfs_dev_fileops; KKASSERT(ap->a_fp->f_data == (void *)vp); } return 0; }