Example #1
0
/*
 * gfs_readdir_emit: emit a directory entry
 *   voff       - the virtual offset (obtained from gfs_readdir_pred)
 *   ino        - the entry's inode
 *   name       - the entry's name
 *   eflags	- value for ed_eflags (if processing edirent_t)
 *
 * Returns a 0 on success, a non-zero errno on failure, or -1 if the
 * readdir loop should terminate.  A non-zero result (either errno or
 * -1) from this function is typically passed directly to
 * gfs_readdir_fini().
 */
int
gfs_readdir_emit(gfs_readdir_state_t *st, uio_t *uiop, offset_t voff,
    ino64_t ino, const char *name, int eflags)
{
	offset_t off = (voff + 2) * st->grd_ureclen;

	if (st->grd_flags & V_RDDIR_ENTFLAGS) {
		edirent_t *edp = st->grd_dirent;

		edp->ed_ino = ino;
		(void) strncpy(edp->ed_name, name, st->grd_namlen);
		edp->ed_eflags = eflags;
	} else {
		dirent64_t *dp = st->grd_dirent;

		dp->d_ino = ino;
		(void) strncpy(dp->d_name, name, st->grd_namlen);
	}

	/*
	 * Inter-entry offsets are invalid, so we assume a record size of
	 * grd_ureclen and explicitly set the offset appropriately.
	 */
	return (gfs_readdir_emit_int(st, uiop, off + st->grd_ureclen));
}
Example #2
0
File: gfs.c Project: RJVB/zfs
/*
 * gfs_dir_readdir: does a readdir() on the given directory
 *
 *    dvp	- directory vnode
 *    uiop	- uio structure
 *    eofp	- eof pointer
 *    data	- arbitrary data passed to readdir callback
 *
 * This routine does all the readdir() dirty work.  Even so, the caller must
 * supply two callbacks in order to get full compatibility.
 *
 * If the directory contains static entries, an inode callback must be
 * specified.  This avoids having to create every vnode and call VOP_GETATTR()
 * when reading the directory.  This function has the following arguments:
 *
 *	ino_t gfs_inode_cb(struct vnode *vp, int index);
 *
 * 	vp	- vnode for the directory
 * 	index	- index in original gfs_dirent_t array
 *
 * 	Returns the inode number for the given entry.
 *
 * For directories with dynamic entries, a readdir callback must be provided.
 * This is significantly more complex, thanks to the particulars of
 * VOP_READDIR().
 *
 *	int gfs_readdir_cb(struct vnode *vp, void *dp, int *eofp,
 *	    offset_t *off, offset_t *nextoff, void *data, int flags)
 *
 *	vp	- directory vnode
 *	dp	- directory entry, sized according to maxlen given to
 *		  gfs_dir_create().  callback must fill in d_name and
 *		  d_ino (if a dirent64_t), or ed_name, ed_ino, and ed_eflags
 *		  (if an edirent_t). edirent_t is used if V_RDDIR_ENTFLAGS
 *		  is set in 'flags'.
 *	eofp	- callback must set to 1 when EOF has been reached
 *	off	- on entry, the last offset read from the directory.  Callback
 *		  must set to the offset of the current entry, typically left
 *		  untouched.
 *	nextoff	- callback must set to offset of next entry.  Typically
 *		  (off + 1)
 *	data	- caller-supplied data
 *	flags	- VOP_READDIR flags
 *
 *	Return 0 on success, or error on failure.
 */
int
gfs_dir_readdir(struct vnode *dvp, uio_t *uiop, int *eofp, int *ncookies,
    u_long **cookies, void *data, cred_t *cr, int flags)
{
	gfs_readdir_state_t gstate;
	int error, eof = 0;
	ino64_t ino, pino;
	offset_t off, next;
	gfs_dir_t *dp = vnode_fsnode(dvp);

	error = gfs_get_parent_ino(dvp, cr, NULL, &pino, &ino);
	if (error)
		return (error);

	if ((error = gfs_readdir_init(&gstate, dp->gfsd_maxlen, 1, uiop,
	    pino, ino, flags)) != 0)
		return (error);

	while ((error = gfs_readdir_pred(&gstate, uiop, &off, ncookies,
	    cookies)) == 0 && !eof) {

		if (off >= 0 && off < dp->gfsd_nstatic) {
			ino = dp->gfsd_inode(dvp, off);

			if ((error = gfs_readdir_emit(&gstate, uiop,
			    off, ino, dp->gfsd_static[off].gfse_name, 0,
			    ncookies, cookies)) != 0)
				break;

		} else if (dp->gfsd_readdir) {
			off -= dp->gfsd_nstatic;

			if ((error = dp->gfsd_readdir(dvp,
			    gstate.grd_dirent, &eof, &off, &next,
			    data, flags)) != 0 || eof)
				break;

			off += dp->gfsd_nstatic + 2;
			next += dp->gfsd_nstatic + 2;

			if ((error = gfs_readdir_emit_int(&gstate, uiop,
			    next, ncookies, cookies)) != 0)
				break;
		} else {
			/*
			 * Offset is beyond the end of the static entries, and
			 * we have no dynamic entries.  Set EOF.
			 */
			eof = 1;
		}
	}

	return (gfs_readdir_fini(&gstate, error, eofp, eof));
}
Example #3
0
File: gfs.c Project: RJVB/zfs
/*
 * gfs_readdir_emit: emit a directory entry
 *   voff       - the virtual offset (obtained from gfs_readdir_pred)
 *   ino        - the entry's inode
 *   name       - the entry's name
 *   eflags	- value for ed_eflags (if processing edirent_t)
 *
 * Returns a 0 on success, a non-zero errno on failure, or -1 if the
 * readdir loop should terminate.  A non-zero result (either errno or
 * -1) from this function is typically passed directly to
 * gfs_readdir_fini().
 */
int
gfs_readdir_emit(gfs_readdir_state_t *st, uio_t *uiop, offset_t voff,
    ino64_t ino, const char *name, int eflags, int *ncookies, u_long **cookies)
{
	offset_t off = (voff + 2) * st->grd_ureclen;
    //boolean_t   extended = (st->grd_flags & VNODE_READDIR_EXTENDED);
    dirent64_t *dp = st->grd_dirent;

    dp->d_ino = ino;
    dp->d_fileno = ino;
    (void) strncpy(dp->d_name, name, st->grd_namlen);

	/*
	 * Inter-entry offsets are invalid, so we assume a record size of
	 * grd_ureclen and explicitly set the offset appropriately.
	 */
	return (gfs_readdir_emit_int(st, uiop, off + st->grd_ureclen, ncookies,
	    cookies));
}