Example #1
0
/* ARGSUSED */
static int
fdread(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
{
	static struct fddirect dotbuf[] = {
		{ FDROOTINO, "."  },
		{ FDROOTINO, ".." }
	};
	struct fddirect dirbuf;
	int i, n;
	int minfd, maxfd, modoff, error = 0;
	int nentries;
	rctl_qty_t fdno_ctl;
	int endoff;

	if (vp->v_type != VDIR)
		return (ENOSYS);

	mutex_enter(&curproc->p_lock);
	fdno_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_NOFILE],
	    curproc->p_rctls, curproc);
	nentries = MIN(P_FINFO(curproc)->fi_nfiles, (int)fdno_ctl);
	mutex_exit(&curproc->p_lock);

	endoff = (nentries + 2) * FDSDSIZE;

	/*
	 * Fake up ".", "..", and the /dev/fd directory entries.
	 */
	if (uiop->uio_loffset < (offset_t)0 ||
	    uiop->uio_loffset >= (offset_t)endoff ||
	    uiop->uio_resid <= 0)
		return (0);
	ASSERT(uiop->uio_loffset <= MAXOFF_T);
	if (uiop->uio_offset < 2*FDSDSIZE) {
		error = uiomove((caddr_t)dotbuf + uiop->uio_offset,
		    MIN(uiop->uio_resid, 2*FDSDSIZE - uiop->uio_offset),
		    UIO_READ, uiop);
		if (uiop->uio_resid <= 0 || error)
			return (error);
	}
	minfd = (uiop->uio_offset - 2*FDSDSIZE)/FDSDSIZE;
	maxfd = (uiop->uio_offset + uiop->uio_resid - 1)/FDSDSIZE;
	modoff = uiop->uio_offset % FDSDSIZE;

	for (i = 0; i < FDDIRSIZE; i++)
		dirbuf.d_name[i] = '\0';
	for (i = minfd; i < MIN(maxfd, nentries); i++) {
		n = i;
		dirbuf.d_ino = fdtoi(n);
		numtos((ulong_t)n, dirbuf.d_name);
		error = uiomove((caddr_t)&dirbuf + modoff,
		    MIN(uiop->uio_resid, FDSDSIZE - modoff),
		    UIO_READ, uiop);
		if (uiop->uio_resid <= 0 || error)
			return (error);
		modoff = 0;
	}

	return (error);
}
/* ARGSUSED */
static int
ctfs_tdir_do_readdir(vnode_t *vp, void *dp, int *eofp,
    offset_t *offp, offset_t *nextp, void *data, int flags)
{
	uint64_t zuniqid;
	ctid_t next;
	ct_type_t *ty = ct_types[gfs_file_index(vp)];
	struct dirent64 *odp = dp;

	ASSERT(!(flags & V_RDDIR_ENTFLAGS));

	zuniqid = VTOZONE(vp)->zone_uniqid;
	next = contract_type_lookup(ty, zuniqid, *offp);

	if (next == -1) {
		*eofp = 1;
		return (0);
	}

	odp->d_ino = CTFS_INO_CT_DIR(next);
	numtos(next, odp->d_name);
	*offp = next;
	*nextp = next + 1;

	return (0);
}
Example #3
0
File: gfs.c Project: RJVB/zfs
/*
 * gfs_readdir_emitn: like gfs_readdir_emit(), but takes an integer
 * instead of a string for the entry's name.
 */
int
gfs_readdir_emitn(gfs_readdir_state_t *st, uio_t *uiop, offset_t voff,
    ino64_t ino, unsigned long num)
{
	char buf[40];

	numtos(num, buf);
	return (gfs_readdir_emit(st, uiop, voff, ino, buf, 0));
}
Example #4
0
/* ARGSUSED */
static int
fdreaddir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp, caller_context_t *ct,
	int flags)
{
	/* bp holds one dirent structure */
	u_offset_t bp[DIRENT64_RECLEN(FDNSIZE) / sizeof (u_offset_t)];
	struct dirent64 *dirent = (struct dirent64 *)bp;
	int reclen, nentries;
	rctl_qty_t fdno_ctl;
	int  n;
	int oresid;
	off_t off;

	if (uiop->uio_offset < 0 || uiop->uio_resid <= 0 ||
	    (uiop->uio_offset % FDSDSIZE) != 0)
		return (ENOENT);

	ASSERT(uiop->uio_loffset <= MAXOFF_T);
	oresid = uiop->uio_resid;
	bzero(bp, sizeof (bp));

	mutex_enter(&curproc->p_lock);
	fdno_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_NOFILE],
	    curproc->p_rctls, curproc);
	nentries = MIN(P_FINFO(curproc)->fi_nfiles, (int)fdno_ctl);
	mutex_exit(&curproc->p_lock);

	while (uiop->uio_resid > 0) {
		if ((off = uiop->uio_offset) == 0) {	/* "." */
			dirent->d_ino = (ino64_t)FDROOTINO;
			dirent->d_name[0] = '.';
			dirent->d_name[1] = '\0';
			reclen = DIRENT64_RECLEN(1);
		} else if (off == FDSDSIZE) {		/* ".." */
			dirent->d_ino = (ino64_t)FDROOTINO;
			dirent->d_name[0] = '.';
			dirent->d_name[1] = '.';
			dirent->d_name[2] = '\0';
			reclen = DIRENT64_RECLEN(2);
		} else {
			/*
			 * Return entries corresponding to the allowable
			 * number of file descriptors for this process.
			 */
			if ((n = (off-2*FDSDSIZE)/FDSDSIZE) >= nentries)
				break;
			dirent->d_ino = (ino64_t)fdtoi(n);
			numtos((ulong_t)n, dirent->d_name);
			reclen = DIRENT64_RECLEN(strlen(dirent->d_name));
		}
		dirent->d_off = (offset_t)(uiop->uio_offset + FDSDSIZE);
		dirent->d_reclen = (ushort_t)reclen;

		if (reclen > uiop->uio_resid) {
			/*
			 * Error if no entries have been returned yet.
			 */
			if (uiop->uio_resid == oresid)
				return (EINVAL);
			break;
		}
		/*
		 * uiomove() updates both resid and offset by the same
		 * amount.  But we want offset to change in increments
		 * of FDSDSIZE, which is different from the number of bytes
		 * being returned to the user.  So we set uio_offset
		 * separately, ignoring what uiomove() does.
		 */
		if (uiomove((caddr_t)dirent, reclen, UIO_READ, uiop))
			return (EFAULT);
		uiop->uio_offset = off + FDSDSIZE;
	}
	if (eofp)
		*eofp = ((uiop->uio_offset-2*FDSDSIZE)/FDSDSIZE >= nentries);
	return (0);
}
Example #5
0
int
intpexec(
	struct vnode *vp,
	struct execa *uap,
	struct uarg *args,
	struct intpdata *idatap,
	int level,
	long *execsz,
	int setid,
	caddr_t exec_file,
	struct cred *cred,
	int brand_action)
{
	_NOTE(ARGUNUSED(brand_action))
	vnode_t *nvp;
	int error = 0;
	struct intpdata idata;
	struct pathname intppn;
	struct pathname resolvepn;
	char *opath;
	char devfd[19]; /* 32-bit int fits in 10 digits + 8 for "/dev/fd/" */
	int fd = -1;

	if (level) {		/* Can't recurse */
		error = ENOEXEC;
		goto bad;
	}

	ASSERT(idatap == (struct intpdata *)NULL);

	/*
	 * Allocate a buffer to read in the interpreter pathname.
	 */
	idata.intp = kmem_alloc(INTPSZ, KM_SLEEP);
	if (error = getintphead(vp, &idata))
		goto fail;

	/*
	 * Look the new vnode up.
	 */
	if (error = pn_get(idata.intp_name, UIO_SYSSPACE, &intppn))
		goto fail;
	pn_alloc(&resolvepn);
	if (error = lookuppn(&intppn, &resolvepn, FOLLOW, NULLVPP, &nvp)) {
		pn_free(&resolvepn);
		pn_free(&intppn);
		goto fail;
	}
	opath = args->pathname;
	args->pathname = resolvepn.pn_path;
	/* don't free resolvepn until we are done with args */
	pn_free(&intppn);

	/*
	 * When we're executing a set-uid script resulting in uids
	 * mismatching or when we execute with additional privileges,
	 * we close the "replace script between exec and open by shell"
	 * hole by passing the script as /dev/fd parameter.
	 */
	if ((setid & EXECSETID_PRIVS) != 0 ||
	    (setid & (EXECSETID_UGIDS|EXECSETID_SETID)) ==
	    (EXECSETID_UGIDS|EXECSETID_SETID)) {
		(void) strcpy(devfd, "/dev/fd/");
		if (error = execopen(&vp, &fd))
			goto done;
		numtos(fd, &devfd[8]);
		args->fname = devfd;
	}

	error = gexec(&nvp, uap, args, &idata, ++level, execsz, exec_file, cred,
	    EBA_NONE);
done:
	VN_RELE(nvp);
	args->pathname = opath;
	pn_free(&resolvepn);
fail:
	kmem_free(idata.intp, INTPSZ);
	if (error && fd != -1)
		(void) execclose(fd);
bad:
	return (error);
}