Example #1
0
static int 
dir_scopeiter(void *arg, psirp_id_t *idp)
{
    int error = 0;
    ps_pubi_t pi;
    enum ps_pub_type type;
    struct dir_iter *di = arg;
    struct uio *uio = di->di_uio;
    struct dirent dent;

    error = ps_pit_get(*idp, &pi);
    if (error)
	return error;
    error = ps_obj_get_type(pi, &type);
    if (error) {
	PS_OBJ_PUBI_UNLOCK(pi);
	return error;
    }
    switch (type) {
    case PS_PUB_SCOPE:
	break;
    case PS_PUB_DATA:
    case PS_PUB_UNKNOWN:
	if (di->di_only_sids) {
	    PS_OBJ_PUBI_UNLOCK(pi);
	    return 0;
	}
	break;
    default:
	/* XXX: May crash here on subscribe-before-publish.  If so, make a test case
	 *      and go to talk to Pekka. */
	panic("dir_scopeiter: bad publication type %d", type);
    }

    dent.d_fileno = pi->pi_ino + di->di_type;
    dent.d_type   = DT_DIR;
    dent.d_namlen = PSIRP_ID_LEN * 2;
    dent.d_reclen = GENERIC_DIRSIZ(&dent);
    PS_OBJ_PUBI_UNLOCK(pi);

    psfs_id2str(*idp, dent.d_name);

    di->di_count++;

    error = uiomove(&dent, dent.d_reclen, uio);
    if (di->di_cookies)
	*(di->di_cookies++) = uio->uio_offset;
    return error;
}
/*
 * Vnode op for readdir
 */
static int
devfs_readdir(struct vnop_readdir_args *ap)
        /*struct vnop_readdir_args {
                struct vnode *a_vp;
                struct uio *a_uio;
		int a_flags;
		int *a_eofflag;
		int *a_numdirent;
		vfs_context_t a_context;
        } */
{
	struct vnode *vp = ap->a_vp;
	struct uio *uio = ap->a_uio;
	struct dirent dirent;
	devnode_t * dir_node;
	devdirent_t *	name_node;
	const char *name;
	int error = 0;
	int reclen;
	int nodenumber;
	int	startpos,pos;

	if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF))
		return (EINVAL);

	/*  set up refs to dir */
	dir_node = VTODN(vp);
	if (dir_node->dn_type != DEV_DIR)
		return(ENOTDIR);
	pos = 0;
	startpos = uio->uio_offset;

	DEVFS_LOCK();

	name_node = dir_node->dn_typeinfo.Dir.dirlist;
	nodenumber = 0;

	dir_node->dn_access = 1;

	while ((name_node || (nodenumber < 2)) && (uio_resid(uio) > 0))
	{
		switch(nodenumber)
		{
		case	0:
			dirent.d_fileno = (int32_t)(void *)dir_node;
			name = ".";
			dirent.d_namlen = 1;
			dirent.d_type = DT_DIR;
			break;
		case	1:
			if(dir_node->dn_typeinfo.Dir.parent)
			    dirent.d_fileno
				= (int32_t)dir_node->dn_typeinfo.Dir.parent;
			else
				dirent.d_fileno = (u_int32_t)dir_node;
			name = "..";
			dirent.d_namlen = 2;
			dirent.d_type = DT_DIR;
			break;
		default:
			dirent.d_fileno = (int32_t)(void *)name_node->de_dnp;
			dirent.d_namlen = strlen(name_node->de_name);
			name = name_node->de_name;
			switch(name_node->de_dnp->dn_type) {
			case DEV_BDEV:
				dirent.d_type = DT_BLK;
				break;
			case DEV_CDEV:
				dirent.d_type = DT_CHR;
				break;
			case DEV_DIR:
				dirent.d_type = DT_DIR;
				break;
			case DEV_SLNK:
				dirent.d_type = DT_LNK;
				break;
			default:
				dirent.d_type = DT_UNKNOWN;
			}
		}
#define	GENERIC_DIRSIZ(dp) \
    ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))

		reclen = dirent.d_reclen = GENERIC_DIRSIZ(&dirent);

		if(pos >= startpos)	/* made it to the offset yet? */
		{
			if (uio_resid(uio) < reclen) /* will it fit? */
				break;
			strlcpy(dirent.d_name, name, DEVMAXNAMESIZE);
			if ((error = uiomove ((caddr_t)&dirent,
					dirent.d_reclen, uio)) != 0)
				break;
		}
		pos += reclen;
		if((nodenumber >1) && name_node)
			name_node = name_node->de_next;
		nodenumber++;
	}
	DEVFS_UNLOCK();
	uio->uio_offset = pos;

	return (error);
}
Example #3
0
int
reiserfs_readdir(struct vop_readdir_args  /* {
		struct vnode *a_vp;
		struct uio *a_uio;
		struct ucred *a_cred;
		int *a_eofflag;
		int *a_ncookies;
		u_long **a_cookies;
	} */*ap)
{
	int error = 0;
	struct dirent dstdp;
	struct uio *uio = ap->a_uio;

	off_t next_pos;
	struct buf *bp;
	struct item_head *ih;
	struct cpu_key pos_key;
	const struct key *rkey;
	struct reiserfs_node *ip;
	struct reiserfs_dir_entry de;
	INITIALIZE_PATH(path_to_entry);
	int entry_num, item_num, search_res;

	/* The NFS part */
	int ncookies = 0;
	u_long *cookies = NULL;

	/*
	 * Form key for search the next directory entry using f_pos field of
	 * file structure
	 */
	ip = VTOI(ap->a_vp);
	make_cpu_key(&pos_key,
	    ip, uio->uio_offset ? uio->uio_offset : DOT_OFFSET,
	    TYPE_DIRENTRY, 3);
	next_pos = cpu_key_k_offset(&pos_key);

	reiserfs_log(LOG_DEBUG, "listing entries for "
	    "(objectid=%d, dirid=%d)\n",
	    pos_key.on_disk_key.k_objectid, pos_key.on_disk_key.k_dir_id);
	reiserfs_log(LOG_DEBUG, "uio_offset = %jd, uio_resid = %d\n",
	    (intmax_t)uio->uio_offset, uio->uio_resid);

	if (ap->a_ncookies && ap->a_cookies) {
		cookies = (u_long *)malloc(
		    uio->uio_resid / 16 * sizeof(u_long),
		    M_REISERFSCOOKIES, M_WAITOK);
	}

	while (1) {
		//research:
		/*
		 * Search the directory item, containing entry with
		 * specified key
		 */
		reiserfs_log(LOG_DEBUG, "search directory to read\n");
		search_res = search_by_entry_key(ip->i_reiserfs, &pos_key,
		    &path_to_entry, &de);
		if (search_res == IO_ERROR) {
			error = EIO;
			goto out;
		}

		entry_num = de.de_entry_num;
		item_num  = de.de_item_num;
		bp = de.de_bp;
		ih = de.de_ih;

		if (search_res == POSITION_FOUND ||
		    entry_num < I_ENTRY_COUNT(ih)) {
			/*
			 * Go through all entries in the directory item
			 * beginning from the entry, that has been found.
			 */
			struct reiserfs_de_head *deh = B_I_DEH(bp, ih) +
			    entry_num;

			if (ap->a_ncookies == NULL) {
				cookies = NULL;
			} else {
				//ncookies = 
			}

			reiserfs_log(LOG_DEBUG,
			    "walking through directory entries\n");
			for (; entry_num < I_ENTRY_COUNT(ih);
			    entry_num++, deh++) {
				int d_namlen;
				char *d_name;
				off_t d_off;
				ino_t d_ino;

				if (!de_visible(deh)) {
					/* It is hidden entry */
					continue;
				}

				d_namlen = entry_length(bp, ih, entry_num);
				d_name   = B_I_DEH_ENTRY_FILE_NAME(bp, ih, deh);
				if (!d_name[d_namlen - 1])
					d_namlen = strlen(d_name);
				reiserfs_log(LOG_DEBUG, "  - `%s' (len=%d)\n",
				    d_name, d_namlen);

				if (d_namlen > REISERFS_MAX_NAME(
				    ip->i_reiserfs->s_blocksize)) {
					/* Too big to send back to VFS */
					continue;
				}

#if 0
				/* Ignore the .reiserfs_priv entry */
				if (reiserfs_xattrs(ip->i_reiserfs) &&
				    !old_format_only(ip->i_reiserfs) &&
				    filp->f_dentry == ip->i_reiserfs->s_root &&
				    REISERFS_SB(ip->i_reiserfs)->priv_root &&
				    REISERFS_SB(ip->i_reiserfs)->priv_root->d_inode &&
				    deh_objectid(deh) ==
				    le32toh(INODE_PKEY(REISERFS_SB(
				    ip->i_reiserfs)->priv_root->d_inode)->k_objectid)) {
					continue;
				}
#endif

				d_off = deh_offset(deh);
				d_ino = deh_objectid(deh);
				uio->uio_offset = d_off;

				/* Copy to user land */
				dstdp.d_fileno = d_ino;
				dstdp.d_type   = DT_UNKNOWN;
				dstdp.d_namlen = d_namlen;
				dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp);
				bcopy(d_name, dstdp.d_name, dstdp.d_namlen);
				bzero(dstdp.d_name + dstdp.d_namlen,
				    dstdp.d_reclen -
				    offsetof(struct dirent, d_name) -
				    dstdp.d_namlen);

				if (d_namlen > 0) {
					if (dstdp.d_reclen <= uio->uio_resid) {
						reiserfs_log(LOG_DEBUG, "     copying to user land\n");
						error = uiomove(&dstdp,
						    dstdp.d_reclen, uio);
						if (error)
							goto end;
						if (cookies != NULL) {
							cookies[ncookies] =
							    d_off;
							ncookies++;
						}
					} else
						break;
				} else {
					error = EIO;
					break;
				}

				next_pos = deh_offset(deh) + 1;
			}
			reiserfs_log(LOG_DEBUG, "...done\n");
		}

		reiserfs_log(LOG_DEBUG, "checking item num (%d == %d ?)\n",
		    item_num, B_NR_ITEMS(bp) - 1);
		if (item_num != B_NR_ITEMS(bp) - 1) {
			/* End of directory has been reached */
			reiserfs_log(LOG_DEBUG, "end reached\n");
			if (ap->a_eofflag)
				*ap->a_eofflag = 1;
			goto end;
		}

		/*
		 * Item we went through is last item of node. Using right
		 * delimiting key check is it directory end
		 */
		reiserfs_log(LOG_DEBUG, "get right key\n");
		rkey = get_rkey(&path_to_entry, ip->i_reiserfs);
		reiserfs_log(LOG_DEBUG, "right key = (objectid=%d, dirid=%d)\n",
		    rkey->k_objectid, rkey->k_dir_id);

		reiserfs_log(LOG_DEBUG, "compare it to MIN_KEY\n");
		reiserfs_log(LOG_DEBUG, "MIN KEY = (objectid=%d, dirid=%d)\n",
		    MIN_KEY.k_objectid, MIN_KEY.k_dir_id);
		if (comp_le_keys(rkey, &MIN_KEY) == 0) {
			/* Set pos_key to key, that is the smallest and greater
			 * that key of the last entry in the item */
			reiserfs_log(LOG_DEBUG, "continuing on the right\n");
			set_cpu_key_k_offset(&pos_key, next_pos);
			continue;
		}

		reiserfs_log(LOG_DEBUG, "compare it to pos_key\n");
		reiserfs_log(LOG_DEBUG, "pos key = (objectid=%d, dirid=%d)\n",
		    pos_key.on_disk_key.k_objectid,
		    pos_key.on_disk_key.k_dir_id);
		if (COMP_SHORT_KEYS(rkey, &pos_key)) {
			/* End of directory has been reached */
			reiserfs_log(LOG_DEBUG, "end reached (right)\n");
			if (ap->a_eofflag)
				*ap->a_eofflag = 1;
			goto end;
		}

		/* Directory continues in the right neighboring block */
		reiserfs_log(LOG_DEBUG, "continuing with a new offset\n");
		set_cpu_key_k_offset(&pos_key,
		    le_key_k_offset(KEY_FORMAT_3_5, rkey));
		reiserfs_log(LOG_DEBUG,
		    "new pos key = (objectid=%d, dirid=%d)\n",
		    pos_key.on_disk_key.k_objectid,
		    pos_key.on_disk_key.k_dir_id);
	}

end:
	uio->uio_offset = next_pos;
	pathrelse(&path_to_entry);
	reiserfs_check_path(&path_to_entry);
out:
	if (error && cookies != NULL) {
		free(cookies, M_REISERFSCOOKIES);
	} else if (ap->a_ncookies != NULL && ap->a_cookies != NULL) {
		*ap->a_ncookies = ncookies;
		*ap->a_cookies  = cookies;
	}
	return (error);
}
Example #4
0
/*
 * Vnode op for reading directories.
 *
 * This function has to convert directory entries from the on-disk
 * format to the format defined by <sys/dirent.h>.  Unfortunately, the
 * conversion will blow up some entries by four bytes, so it can't be
 * done in place.  Instead, the conversion is done entry by entry and
 * the converted entry is sent via uiomove.
 *
 * XXX allocate a buffer, convert as many entries as possible, then send
 * the whole buffer to uiomove
 */
int
ext2_readdir(struct vop_readdir_args *ap)
{
	struct uio *uio = ap->a_uio;
	int count, error;

	struct ext2fs_direct_2 *edp, *dp;
	int ncookies;
	struct dirent dstdp;
	struct uio auio;
	struct iovec aiov;
	caddr_t dirbuf;
	int DIRBLKSIZ = VTOI(ap->a_vp)->i_e2fs->e2fs_bsize;
	int readcnt;
	off_t startoffset = uio->uio_offset;

	count = uio->uio_resid;
	/*
	 * Avoid complications for partial directory entries by adjusting
	 * the i/o to end at a block boundary.  Don't give up (like ufs
	 * does) if the initial adjustment gives a negative count, since
	 * many callers don't supply a large enough buffer.  The correct
	 * size is a little larger than DIRBLKSIZ to allow for expansion
	 * of directory entries, but some callers just use 512.
	 */
	count -= (uio->uio_offset + count) & (DIRBLKSIZ -1);
	if (count <= 0)
		count += DIRBLKSIZ;
	auio = *uio;
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	auio.uio_resid = count;
	auio.uio_segflg = UIO_SYSSPACE;
	aiov.iov_len = count;
	dirbuf = malloc(count, M_TEMP, M_WAITOK);
	aiov.iov_base = dirbuf;
	error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred);
	if (error == 0) {
		readcnt = count - auio.uio_resid;
		edp = (struct ext2fs_direct_2 *)&dirbuf[readcnt];
		ncookies = 0;
		bzero(&dstdp, offsetof(struct dirent, d_name));
		for (dp = (struct ext2fs_direct_2 *)dirbuf;
		    !error && uio->uio_resid > 0 && dp < edp; ) {
			/*-
			 * "New" ext2fs directory entries differ in 3 ways
			 * from ufs on-disk ones:
			 * - the name is not necessarily NUL-terminated.
			 * - the file type field always exists and always
			 *   follows the name length field.
			 * - the file type is encoded in a different way.
			 *
			 * "Old" ext2fs directory entries need no special
			 * conversions, since they are binary compatible
			 * with "new" entries having a file type of 0 (i.e.,
			 * EXT2_FT_UNKNOWN).  Splitting the old name length
			 * field didn't make a mess like it did in ufs,
			 * because ext2fs uses a machine-independent disk
			 * layout.
			 */
			dstdp.d_fileno = dp->e2d_ino;
			dstdp.d_type = FTTODT(dp->e2d_type);
			dstdp.d_namlen = dp->e2d_namlen;
			dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp);
			bcopy(dp->e2d_name, dstdp.d_name, dstdp.d_namlen);
			bzero(dstdp.d_name + dstdp.d_namlen,
			    dstdp.d_reclen - offsetof(struct dirent, d_name) -
			    dstdp.d_namlen);

			if (dp->e2d_reclen > 0) {
				if(dstdp.d_reclen <= uio->uio_resid) {
					/* advance dp */
					dp = (struct ext2fs_direct_2 *)
					    ((char *)dp + dp->e2d_reclen);
					error =
					  uiomove(&dstdp, dstdp.d_reclen, uio);
					if (!error)
						ncookies++;
				} else
					break;
			} else {
				error = EIO;
				break;
			}
		}
		/* we need to correct uio_offset */
		uio->uio_offset = startoffset + (caddr_t)dp - dirbuf;

		if (!error && ap->a_ncookies != NULL) {
			u_long *cookiep, *cookies, *ecookies;
			off_t off;

			if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
				panic("ext2_readdir: unexpected uio from NFS server");
			cookies = malloc(ncookies * sizeof(u_long), M_TEMP,
			       M_WAITOK);
			off = startoffset;
			for (dp = (struct ext2fs_direct_2 *)dirbuf,
			     cookiep = cookies, ecookies = cookies + ncookies;
			     cookiep < ecookies;
			     dp = (struct ext2fs_direct_2 *)((caddr_t) dp + dp->e2d_reclen)) {
				off += dp->e2d_reclen;
				*cookiep++ = (u_long) off;
			}
			*ap->a_ncookies = ncookies;
			*ap->a_cookies = cookies;
		}
	}
Example #5
0
static int 
dir_vers2dents(struct psfs_node *pnode, struct uio *uio, u_long *cookies, 
	       off_t maxcount, int *eofflag)
{
    int error = 0;
    off_t off;
    ps_pubi_t pi;
    ps_meta_t meta;
    int index, i;

    KASSERT(0 == uio->uio_offset % DIRSIZ_RID && uio->uio_offset >= DIRSIZ_RID,
	    ("Invalid uio_offset %ld", uio->uio_offset));

    off = uio->uio_offset;

    PS_PRINTF(PS_DEBUG_DIR, "off=%ld, maxcount=%ld, eofflag=%p\n", off, maxcount, eofflag);

    error = ps_pit_get(pnode->pn_rid, &pi);
    if (error)
	return error;

    error = ps_obj_get_page(pi, VMO_META, 0, (void **)&meta);
    if (error) {
	PS_OBJ_PUBI_UNLOCK(pi);
	return error;
    }
#ifdef INVARIANTS
    PS_PRINTF(PS_DEBUG_DIR, "meta->pm_interlock=%p:\n", meta->pm_interlock);
    if (ps_debug_mask & PS_DEBUG_DIR) {
	db_show_mtx(meta->pm_interlock);
    }
#endif
    PS_OBJ_META_LOCK(meta);
    PS_OBJ_PUBI_UNLOCK(pi);

    index = (uio->uio_offset / DIRSIZ_RID) - 1;
    for (i = index; i < meta->pm_vers_count; i++) {
	ps_pubi_t vpi;
	struct dirent dent;
	
	error = ps_pit_get(meta->pm_sub_object[i], &vpi);
	if (error) {
	    PS_PRINTF(PS_DEBUG_WARNING, "version %s not found in pit\n",
		      psfs_id2str(meta->pm_sub_object[i], NULL));
	    error = 0;
	    continue;
	}

	dent.d_fileno = vpi->pi_ino + IPUB;
	dent.d_type   = DT_DIR;
	dent.d_namlen = PSIRP_ID_LEN * 2;
	dent.d_reclen = GENERIC_DIRSIZ(&dent);
	PS_OBJ_PUBI_UNLOCK(vpi);

	psfs_id2str(meta->pm_sub_object[i], dent.d_name);

	error = uiomove(&dent, dent.d_reclen, uio);
	if (cookies)
	    *cookies++ = uio->uio_offset;
	if (error)
	    break;
    }
    if (eofflag && i >= meta->pm_vers_count)
	*eofflag = TRUE;
    /* 
     * Note that we have to unlock meta first, before locking pi,
     * as the locking order is always pi->meta->...
     */
    PS_OBJ_META_UNLOCK(meta);
    /* XXX: Is there any possibility for some race condition here? */
    PS_OBJ_PUBI_LOCK(pi);
    ps_obj_put_page(pi, VMO_META, FALSE);
    PS_OBJ_PUBI_UNLOCK(pi);
    if (error) 
	return error;


    PS_PRINTF(PS_DEBUG_DIR, "i=%d, *eofflag=%d -> %d\n", i, eofflag? *eofflag: 4077, error);

    KASSERT((0 == uio->uio_offset % DIRSIZ_RID && uio->uio_offset >= DIRSIZ_RID),
	    ("Invalid uio_offset %ld", uio->uio_offset));

    return error;
}
Example #6
0
int
fuse_internal_readdir_processdata(struct uio *uio,
    size_t reqsize,
    void *buf,
    size_t bufsize,
    void *param)
{
	int err = 0;
	int cou = 0;
	int bytesavail;
	size_t freclen;

	struct dirent *de;
	struct fuse_dirent *fudge;
	struct fuse_iov *cookediov = param;

	if (bufsize < FUSE_NAME_OFFSET) {
		return -1;
	}
	for (;;) {

		if (bufsize < FUSE_NAME_OFFSET) {
			err = -1;
			break;
		}
		fudge = (struct fuse_dirent *)buf;
		freclen = FUSE_DIRENT_SIZE(fudge);

		cou++;

		if (bufsize < freclen) {
			err = ((cou == 1) ? -1 : 0);
			break;
		}
#ifdef ZERO_PAD_INCOMPLETE_BUFS
		if (isbzero(buf, FUSE_NAME_OFFSET)) {
			err = -1;
			break;
		}
#endif

		if (!fudge->namelen || fudge->namelen > MAXNAMLEN) {
			err = EINVAL;
			break;
		}
		bytesavail = GENERIC_DIRSIZ((struct pseudo_dirent *)
					    &fudge->namelen);

		if (bytesavail > uio_resid(uio)) {
			err = -1;
			break;
		}
		fiov_refresh(cookediov);
		fiov_adjust(cookediov, bytesavail);

		de = (struct dirent *)cookediov->base;
		de->d_fileno = fudge->ino;	/* XXX: truncation */
		de->d_reclen = bytesavail;
		de->d_type = fudge->type;
		de->d_namlen = fudge->namelen;
		memcpy((char *)cookediov->base + sizeof(struct dirent) - 
		       MAXNAMLEN - 1,
		       (char *)buf + FUSE_NAME_OFFSET, fudge->namelen);
		((char *)cookediov->base)[bytesavail] = '\0';

		err = uiomove(cookediov->base, cookediov->len, uio);
		if (err) {
			break;
		}
		buf = (char *)buf + freclen;
		bufsize -= freclen;
		uio_setoffset(uio, fudge->off);
	}

	return err;
}
Example #7
0
__private_extern__
int
fuse_internal_readdir_processdata(vnode_t          vp,
                                  uio_t            uio,
                         __unused size_t           reqsize,
                                  void            *buf,
                                  size_t           bufsize,
                                  struct fuse_iov *cookediov,
                                  int             *numdirent)
{
    int err = 0;
    int cou = 0;
    int n   = 0;
    size_t bytesavail;
    size_t freclen;

    struct dirent      *de;
    struct fuse_dirent *fudge;

    if (bufsize < FUSE_NAME_OFFSET) {
        return -1;
    }

    for (;;) {

        if (bufsize < FUSE_NAME_OFFSET) {
            err = -1;
            break;
        }

        fudge = (struct fuse_dirent *)buf;
        freclen = FUSE_DIRENT_SIZE(fudge);

        cou++;

        if (bufsize < freclen) {
            err = ((cou == 1) ? -1 : 0);
            break;
        }

        /*
         * if (isbzero(buf, FUSE_NAME_OFFSET)) {
         *     // zero-pad incomplete buffer
         *     ...
         *     err = -1;
         *     break;
         * }
         */

        if (!fudge->namelen) { 
            err = EINVAL;
            break;
        }

        if (fudge->namelen > FUSE_MAXNAMLEN) {
            err = EIO;
            break;
        }

#define GENERIC_DIRSIZ(dp) \
  ((sizeof(struct dirent) - (FUSE_MAXNAMLEN + 1)) + \
   (((dp)->d_namlen + 1 + 3) & ~3))

        bytesavail = GENERIC_DIRSIZ((struct pseudo_dirent *)&fudge->namelen); 

        if (bytesavail > (size_t)uio_resid(uio)) {
            err = -1;
            break;
        }

        fiov_refresh(cookediov);
        fiov_adjust(cookediov, bytesavail);

        de = (struct dirent *)cookediov->base;
#if __DARWIN_64_BIT_INO_T
        de->d_fileno = fudge->ino;
#else
        de->d_fileno = (ino_t)fudge->ino; /* XXX: truncation */
#endif /* __DARWIN_64_BIT_INO_T */
        de->d_reclen = bytesavail;
        de->d_type   = fudge->type; 
        de->d_namlen = fudge->namelen;

        /* Filter out any ._* files if the mount is configured as such. */
        if (fuse_skip_apple_double_mp(vnode_mount(vp),
                                      fudge->name, fudge->namelen)) {
            de->d_fileno = 0;
            de->d_type = DT_WHT;
        }

        memcpy((char *)cookediov->base +
               sizeof(struct dirent) - FUSE_MAXNAMLEN - 1,
               (char *)buf + FUSE_NAME_OFFSET, fudge->namelen);
        ((char *)cookediov->base)[bytesavail] = '\0';

        err = uiomove(cookediov->base, (int)cookediov->len, uio);
        if (err) {
            break;
        }

        n++;

        buf = (char *)buf + freclen;
        bufsize -= freclen;
        uio_setoffset(uio, fudge->off);
    }

    if (!err && numdirent) {
        *numdirent = n;
    }

    return err;
}