FreeBSD/sys/fs/tmpfs/tmpfs_subr.c
/*
 * Helper function for tmpfs_readdir.  Returns as much directory entries
 * as can fit in the uio space.  The read starts at uio->uio_offset.
 * The function returns 0 on success, -1 if there was not enough space
 * in the uio structure to hold the directory entry or an appropriate
 * error code if another error happens.
 */
Helper function for tmpfs_readdir.  Returns as much directory entries
as can fit in the uio space.  The read starts at uio->uio_offset.
The function returns 0 on success, -1 if there was not enough space
in the uio structure to hold the directory entry or an appropriate
error code if another error happens.
Helper function for tmpfs_readdir . Returns as much directory entries as can fit in the uio space . The read starts at uio - > uio_offset . The function returns 0 on success - 1 if there was not enough space in the uio structure to hold the directory entry or an appropriate error code if another error happens .
int
tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int maxcookies,
    u_long *cookies, int *ncookies)
{
	struct tmpfs_dir_cursor dc;
	struct tmpfs_dirent *de;
	off_t off;
	int error;
	TMPFS_VALIDATE_DIR(node);
	off = 0;
	switch (uio->uio_offset) {
	case TMPFS_DIRCOOKIE_DOT:
		error = tmpfs_dir_getdotdent(node, uio);
		if (error != 0)
			return (error);
		uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT;
		if (cookies != NULL)
			cookies[(*ncookies)++] = off = uio->uio_offset;
	case TMPFS_DIRCOOKIE_DOTDOT:
		error = tmpfs_dir_getdotdotdent(node, uio);
		if (error != 0)
			return (error);
		de = tmpfs_dir_first(node, &dc);
		uio->uio_offset = tmpfs_dirent_cookie(de);
		if (cookies != NULL)
			cookies[(*ncookies)++] = off = uio->uio_offset;
		if (de == NULL)
			return (0);
		break;
	case TMPFS_DIRCOOKIE_EOF:
		return (0);
	default:
		de = tmpfs_dir_lookup_cookie(node, uio->uio_offset, &dc);
		if (de == NULL)
			return (EINVAL);
		if (cookies != NULL)
			off = tmpfs_dirent_cookie(de);
	}
	do {
		struct dirent d;
		if (de->td_node == NULL) {
			d.d_fileno = 1;
			d.d_type = DT_WHT;
		} else {
			d.d_fileno = de->td_node->tn_id;
			switch (de->td_node->tn_type) {
			case VBLK:
				d.d_type = DT_BLK;
				break;
			case VCHR:
				d.d_type = DT_CHR;
				break;
			case VDIR:
				d.d_type = DT_DIR;
				break;
			case VFIFO:
				d.d_type = DT_FIFO;
				break;
			case VLNK:
				d.d_type = DT_LNK;
				break;
			case VREG:
				d.d_type = DT_REG;
				break;
			case VSOCK:
				d.d_type = DT_SOCK;
				break;
			default:
				panic("tmpfs_dir_getdents: type %p %d",
				    de->td_node, (int)de->td_node->tn_type);
			}
		}
		d.d_namlen = de->td_namelen;
		MPASS(de->td_namelen < sizeof(d.d_name));
		(void)memcpy(d.d_name, de->ud.td_name, de->td_namelen);
		d.d_name[de->td_namelen] = '\0';
		d.d_reclen = GENERIC_DIRSIZ(&d);
		if (d.d_reclen > uio->uio_resid) {
			error = EJUSTRETURN;
			break;
		}
		error = uiomove(&d, d.d_reclen, uio);
		if (error == 0) {
			de = tmpfs_dir_next(node, &dc);
			if (cookies != NULL) {
				off = tmpfs_dirent_cookie(de);
				MPASS(*ncookies < maxcookies);
				cookies[(*ncookies)++] = off;
			}
		}
	} while (error == 0 && uio->uio_resid > 0 && de != NULL);
	if (cookies == NULL)
		off = tmpfs_dirent_cookie(de);
	uio->uio_offset = off;
	node->tn_dir.tn_readdir_lastn = off;
	node->tn_dir.tn_readdir_lastp = de;
	node->tn_status |= TMPFS_NODE_ACCESSED;
	return error;
}
int tmpfs_dir_getdents ( struct tmpfs_node * node , struct uio * uio , int maxcookies , u_long * cookies , int * ncookies ) { struct tmpfs_dir_cursor dc ; struct tmpfs_dirent * de ; off_t off ; int error ; TMPFS_VALIDATE_DIR ( node ) ; off = 0 ; switch ( uio -> uio_offset ) { case TMPFS_DIRCOOKIE_DOT : error = tmpfs_dir_getdotdent ( node , uio ) ; if ( error != 0 ) return ( error ) ; uio -> uio_offset = TMPFS_DIRCOOKIE_DOTDOT ; if ( cookies != NULL ) cookies [ ( * ncookies ) ++ ] = off = uio -> uio_offset ; case TMPFS_DIRCOOKIE_DOTDOT : error = tmpfs_dir_getdotdotdent ( node , uio ) ; if ( error != 0 ) return ( error ) ; de = tmpfs_dir_first ( node , & dc ) ; uio -> uio_offset = tmpfs_dirent_cookie ( de ) ; if ( cookies != NULL ) cookies [ ( * ncookies ) ++ ] = off = uio -> uio_offset ; if ( de == NULL ) return ( 0 ) ; break ; case TMPFS_DIRCOOKIE_EOF : return ( 0 ) ; default : de = tmpfs_dir_lookup_cookie ( node , uio -> uio_offset , & dc ) ; if ( de == NULL ) return ( EINVAL ) ; if ( cookies != NULL ) off = tmpfs_dirent_cookie ( de ) ; } do { struct dirent d ; if ( de -> td_node == NULL ) { d . d_fileno = 1 ; d . d_type = DT_WHT ; } else { d . d_fileno = de -> td_node -> tn_id ; switch ( de -> td_node -> tn_type ) { case VBLK : d . d_type = DT_BLK ; break ; case VCHR : d . d_type = DT_CHR ; break ; case VDIR : d . d_type = DT_DIR ; break ; case VFIFO : d . d_type = DT_FIFO ; break ; case VLNK : d . d_type = DT_LNK ; break ; case VREG : d . d_type = DT_REG ; break ; case VSOCK : d . d_type = DT_SOCK ; break ; default : panic ( " " , de -> td_node , ( int ) de -> td_node -> tn_type ) ; } } d . d_namlen = de -> td_namelen ; MPASS ( de -> td_namelen < sizeof ( d . d_name ) ) ; ( void ) memcpy ( d . d_name , de -> ud . td_name , de -> td_namelen ) ; d . d_name [ de -> td_namelen ] = ' \0 ' ; d . d_reclen = GENERIC_DIRSIZ ( & d ) ; if ( d . d_reclen > uio -> uio_resid ) { error = EJUSTRETURN ; break ; } error = uiomove ( & d , d . d_reclen , uio ) ; if ( error == 0 ) { de = tmpfs_dir_next ( node , & dc ) ; if ( cookies != NULL ) { off = tmpfs_dirent_cookie ( de ) ; MPASS ( * ncookies < maxcookies ) ; cookies [ ( * ncookies ) ++ ] = off ; } } } while ( error == 0 && uio -> uio_resid > 0 && de != NULL ) ; if ( cookies == NULL ) off = tmpfs_dirent_cookie ( de ) ; uio -> uio_offset = off ; node -> tn_dir . tn_readdir_lastn = off ; node -> tn_dir . tn_readdir_lastp = de ; node -> tn_status |= TMPFS_NODE_ACCESSED ; return error ; }
Helper function for tmpfs_readdir.
Helper function for tmpfs_readdir .
/*
	 * Lookup the node from the current offset.  The starting offset of
	 * 0 will lookup both '.' and '..', and then the first real entry,
	 * or EOF if there are none.  Then find all entries for the dir that
	 * fit into the buffer.  Once no more entries are found (de == NULL),
	 * the offset is set to TMPFS_DIRCOOKIE_EOF, which will cause the next
	 * call to return 0.
	 */ /* FALLTHROUGH */ /* EOF. */ /* Read as much entries as possible; i.e., until we reach the end of
	 * the directory or we exhaust uio space. */ /* Create a dirent structure representing the current
		 * tmpfs_node and fill it. */ /* Stop reading if the directory entry we are treating is
		 * bigger than the amount of data that can be returned. */ /* Copy the new dirent structure into the output buffer and
		 * advance pointers. */ /* Skip setting off when using cookies as it is already done above. */ /* Update the offset and cache. */