FreeBSD/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c
/*
 * 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(vnode_t *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(vnode_t *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.
 */
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.



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().



vp      - directory vnode
dp      - directory entry, sized according to maxlen given to
gfs_dir_create().

Return 0 on success, or error on failure.
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 . 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 () . vp - directory vnode dp - directory entry sized according to maxlen given to gfs_dir_create () . Return 0 on success or error on failure .
int
gfs_dir_readdir(vnode_t *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 = dvp->v_data;
	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 {
			eof = 1;
		}
	}
	return (gfs_readdir_fini(&gstate, error, eofp, eof));
}
int gfs_dir_readdir ( vnode_t * 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 = dvp -> v_data ; 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 { eof = 1 ; } } return ( gfs_readdir_fini ( & gstate , error , eofp , eof ) ) ; }
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
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
/*
			 * Offset is beyond the end of the static entries, and
			 * we have no dynamic entries.  Set EOF.
			 */