/* * Helper function for tmpfs_readdir. Creates a '..' entry for the given * directory and returns it in the uio space. 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_getdotdotdent(struct tmpfs_mount *tmp, struct tmpfs_node *node, struct uio *uio) { int error; ino_t d_ino; TMPFS_VALIDATE_DIR(node); KKASSERT(uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT); if (node->tn_dir.tn_parent) { TMPFS_NODE_LOCK(node); if (node->tn_dir.tn_parent) d_ino = node->tn_dir.tn_parent->tn_id; else d_ino = tmp->tm_root->tn_id; TMPFS_NODE_UNLOCK(node); } else { d_ino = tmp->tm_root->tn_id; } if (vop_write_dirent(&error, uio, d_ino, DT_DIR, 2, "..")) return -1; if (error == 0) { struct tmpfs_dirent *de; de = RB_MIN(tmpfs_dirtree_cookie, &node->tn_dir.tn_cookietree); if (de == NULL) uio->uio_offset = TMPFS_DIRCOOKIE_EOF; else uio->uio_offset = tmpfs_dircookie(de); } return error; }
/* * Helper function for tmpfs_readdir. Creates a '.' entry for the given * directory and returns it in the uio space. 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_getdotdent(struct tmpfs_node *node, struct uio *uio) { int error; TMPFS_VALIDATE_DIR(node); KKASSERT(uio->uio_offset == TMPFS_DIRCOOKIE_DOT); if (vop_write_dirent(&error, uio, node->tn_id, DT_DIR, 1, ".")) return -1; if (error == 0) uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT; return error; }
static int procfs_readdir_proc(struct vop_readdir_args *ap) { struct pfsnode *pfs; int error, i, retval; struct proc *p; struct lwp *lp; struct proc_target *pt; struct uio *uio = ap->a_uio; pfs = VTOPFS(ap->a_vp); p = pfs_pfind(pfs->pfs_pid); if (p == NULL) return(0); if (!PRISON_CHECK(ap->a_cred, p->p_ucred)) { error = 0; goto done; } /* XXX lwp, not MPSAFE */ lp = FIRST_LWP_IN_PROC(p); error = 0; i = (int)uio->uio_offset; if (i < 0) { error = EINVAL; goto done; } for (pt = &proc_targets[i]; !error && uio->uio_resid > 0 && i < nproc_targets; pt++, i++) { if (pt->pt_valid && (*pt->pt_valid)(lp) == 0) continue; retval = vop_write_dirent(&error, uio, PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype), pt->pt_type, pt->pt_namlen, pt->pt_name); if (retval) break; } uio->uio_offset = (off_t)i; error = 0; done: PRELE(p); return error; }
static int hpfs_de_uiomove(int *error, struct hpfsmount *hpmp, struct hpfsdirent *dep, struct uio *uio) { char convname[HPFS_MAXFILENAME + 1]; int i, success; dprintf(("[no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x] ", dep->de_fnode, dep->de_size, dep->de_namelen, dep->de_namelen, dep->de_name, dep->de_flag)); /*strncpy(cde.d_name, dep->de_name, dep->de_namelen);*/ for (i=0; i<dep->de_namelen; i++) convname[i] = hpfs_d2u(hpmp, dep->de_name[i]); convname[dep->de_namelen] = '\0'; success = vop_write_dirent(error, uio, dep->de_fnode, (dep->de_flag & DE_DIR) ? DT_DIR : DT_REG, dep->de_namelen, convname); dprintf(("[0x%lx] ", uio->uio_resid)); return (success); }
static int nwfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred) { struct nwmount *nmp = VTONWFS(vp); int error, i; struct nwnode *np; struct nw_entry_info fattr; struct vnode *newvp; ncpfid fid; ino_t d_ino; size_t d_namlen; const char *d_name; uint8_t d_type; np = VTONW(vp); NCPVNDEBUG("dirname='%s'\n",np->n_name); if (uio->uio_offset < 0 || uio->uio_offset > INT_MAX) return (EINVAL); error = 0; i = (int)uio->uio_offset; /* offset in directory */ if (i == 0) { error = ncp_initsearch(vp, uio->uio_td, cred); if (error) { NCPVNDEBUG("cannot initialize search, error=%d",error); return( error ); } } for (; !error && uio->uio_resid > 0; i++) { switch (i) { case 0: /* `.' */ d_ino = np->n_fid.f_id; if (d_ino == 0) d_ino = NWFS_ROOT_INO; d_namlen = 1; d_name = "."; d_type = DT_DIR; break; case 1: /* `..' */ d_ino = np->n_parent.f_id; if (d_ino == 0) d_ino = NWFS_ROOT_INO; d_namlen = 2; d_name = ".."; d_type = DT_DIR; break; default: error = ncp_search_for_file_or_subdir(nmp, &np->n_seq, &fattr, uio->uio_td, cred); if (error && error < 0x80) goto done; d_ino = fattr.dirEntNum; d_type = (fattr.attributes & aDIR) ? DT_DIR : DT_REG; d_namlen = fattr.nameLen; d_name = fattr.entryName; #if 0 if (error && eofflag) { /* *eofflag = 1;*/ break; } #endif break; } if (nwfs_fastlookup && !error && i > 1) { fid.f_id = fattr.dirEntNum; fid.f_parent = np->n_fid.f_id; error = nwfs_nget(vp->v_mount, fid, &fattr, vp, &newvp); if (!error) { VTONW(newvp)->n_ctime = VTONW(newvp)->n_vattr.va_ctime.tv_sec; vput(newvp); } else error = 0; } if (error >= 0x80) { error = 0; break; } if (vop_write_dirent(&error, uio, d_ino, d_type, d_namlen, d_name)) break; } done: uio->uio_offset = i; return (error); }
/* * this is exactly what we do here - the problem is that the conversion * will blow up some entries by four bytes, so it can't be done in place. * This is too bad. Right now the conversion is done entry by entry, the * converted entry is sent via uiomove. * * XXX allocate a buffer, convert as many entries as possible, then send * the whole buffer to uiomove * * ext2_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred) */ int ext2_readdir(struct vop_readdir_args *ap) { struct uio *uio = ap->a_uio; int count, error; struct ext2_dir_entry_2 *edp, *dp; int ncookies; struct uio auio; struct iovec aiov; caddr_t dirbuf; int DIRBLKSIZ = VTOI(ap->a_vp)->i_e2fs->s_blocksize; int readcnt, retval; off_t startoffset = uio->uio_offset; if ((error = vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY)) != 0) return(error); 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; if (count > MAXBSIZE) /* limit to a reasonable size */ count = MAXBSIZE; #ifdef EXT2FS_DEBUG kprintf("ext2_readdir: uio_offset = %lld, uio_resid = %d, count = %d\n", uio->uio_offset, uio->uio_resid, count); #endif auio = *uio; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_resid = count; auio.uio_segflg = UIO_SYSSPACE; aiov.iov_len = count; dirbuf = kmalloc(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 ext2_dir_entry_2 *)&dirbuf[readcnt]; ncookies = 0; for (dp = (struct ext2_dir_entry_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 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-dependent disk * layout. */ if (dp->rec_len <= 0) { error = EIO; break; } retval = vop_write_dirent(&error, uio, dp->inode, FTTODT(dp->file_type), dp->name_len, dp->name); if (retval) break; /* advance dp */ dp = (struct ext2_dir_entry_2 *)((char *)dp + dp->rec_len); if (!error) ncookies++; } /* we need to correct uio_offset */ uio->uio_offset = startoffset + (caddr_t)dp - dirbuf; if (!error && ap->a_ncookies != NULL) { off_t *cookiep, *cookies, *ecookies; off_t off; if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) panic("ext2fs_readdir: unexpected uio from NFS server"); if (ncookies) { cookies = kmalloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK); } else { cookies = kmalloc(sizeof(off_t), M_TEMP, M_WAITOK); } off = startoffset; for (dp = (struct ext2_dir_entry_2 *)dirbuf, cookiep = cookies, ecookies = cookies + ncookies; cookiep < ecookies; dp = (struct ext2_dir_entry_2 *)((caddr_t) dp + dp->rec_len)) { off += dp->rec_len; *cookiep++ = off; } *ap->a_ncookies = ncookies; *ap->a_cookies = cookies; } } kfree(dirbuf, M_TEMP); if (ap->a_eofflag) *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset; vn_unlock(ap->a_vp); return (error); }
static int smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred) { struct smb_cred scred; struct smbfs_fctx *ctx; struct vnode *newvp; struct smbnode *np; int error, offset, retval; np = VTOSMB(vp); SMBVDEBUG("dirname='%s'\n", np->n_name); smb_makescred(&scred, uio->uio_td, cred); if (uio->uio_offset < 0 || uio->uio_offset > INT_MAX) return(EINVAL); error = 0; offset = uio->uio_offset; if (uio->uio_resid > 0 && offset < 1) { if (vop_write_dirent(&error, uio, np->n_ino, DT_DIR, 1, ".")) goto done; if (error) goto done; ++offset; } if (uio->uio_resid > 0 && offset < 2) { if (vop_write_dirent(&error, uio, np->n_parent ? VTOSMB(np->n_parent)->n_ino : 2, DT_DIR, 2, "..")) goto done; if (error) goto done; ++offset; } if (uio->uio_resid == 0) goto done; if (offset != np->n_dirofs || np->n_dirseq == NULL) { SMBVDEBUG("Reopening search %ld:%ld\n", offset, np->n_dirofs); if (np->n_dirseq) { smbfs_findclose(np->n_dirseq, &scred); np->n_dirseq = NULL; } np->n_dirofs = 2; error = smbfs_findopen(np, "*", 1, SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, &scred, &ctx); if (error) { SMBVDEBUG("can not open search, error = %d", error); return error; } np->n_dirseq = ctx; } else { ctx = np->n_dirseq; } while (np->n_dirofs < offset) { error = smbfs_findnext(ctx, offset - np->n_dirofs, &scred); ++np->n_dirofs; if (error) { smbfs_findclose(np->n_dirseq, &scred); np->n_dirseq = NULL; return error == ENOENT ? 0 : error; } } error = 0; while (uio->uio_resid > 0 && !error) { /* * Overestimate the size of a record a bit, doesn't really * hurt to be wrong here. */ error = smbfs_findnext(ctx, uio->uio_resid / _DIRENT_RECLEN(255) + 1, &scred); if (error) break; np->n_dirofs++; ++offset; retval = vop_write_dirent(&error, uio, ctx->f_attr.fa_ino, (ctx->f_attr.fa_attr & SMB_FA_DIR) ? DT_DIR : DT_REG, ctx->f_nmlen, ctx->f_name); if (retval) break; if (smbfs_fastlookup && !error) { error = smbfs_nget(vp->v_mount, vp, ctx->f_name, ctx->f_nmlen, &ctx->f_attr, &newvp); if (!error) vput(newvp); } } if (error == ENOENT) error = 0; done: uio->uio_offset = offset; return error; }
static int procfs_readdir_root_callback(struct proc *p, void *data) { struct procfs_readdir_root_info *info = data; struct uio *uio; int retval; ino_t d_ino; const char *d_name; char d_name_pid[20]; size_t d_namlen; uint8_t d_type; uio = info->uio; if (uio->uio_resid <= 0 || info->error) return(-1); switch (info->pcnt) { case 0: /* `.' */ d_ino = PROCFS_FILENO(0, Proot); d_name = "."; d_namlen = 1; d_type = DT_DIR; break; case 1: /* `..' */ d_ino = PROCFS_FILENO(0, Proot); d_name = ".."; d_namlen = 2; d_type = DT_DIR; break; case 2: d_ino = PROCFS_FILENO(0, Pcurproc); d_namlen = 7; d_name = "curproc"; d_type = DT_LNK; break; default: if (!PRISON_CHECK(info->cred, p->p_ucred)) return(0); if (ps_showallprocs == 0 && info->cred->cr_uid != 0 && info->cred->cr_uid != p->p_ucred->cr_uid) { return(0); } /* * Skip entries we have already returned (optimization) */ if (info->pcnt < info->i) { ++info->pcnt; return(0); } d_ino = PROCFS_FILENO(p->p_pid, Pproc); d_namlen = ksnprintf(d_name_pid, sizeof(d_name_pid), "%ld", (long)p->p_pid); d_name = d_name_pid; d_type = DT_DIR; break; } /* * Skip entries we have already returned (optimization) */ if (info->pcnt < info->i) { ++info->pcnt; return(0); } retval = vop_write_dirent(&info->error, uio, d_ino, d_type, d_namlen, d_name); if (retval) return(-1); ++info->pcnt; ++info->i; return(0); }
/* * hpfs_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred, * int *a_ncookies, off_t **cookies) */ int hpfs_readdir(struct vop_readdir_args *ap) { struct vnode *vp = ap->a_vp; struct hpfsnode *hp = VTOHP(vp); struct hpfsmount *hpmp = hp->h_hpmp; struct uio *uio = ap->a_uio; int ncookies = 0, i, num, cnum; int error = 0; struct buf *bp; struct dirblk *dp; struct hpfsdirent *dep; lsn_t olsn; lsn_t lsn; int level; dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%lx): ", hp->h_no, (u_int32_t)uio->uio_offset, uio->uio_resid)); /* * As we need to fake up . and .., and the remaining directory structure * can't be expressed in one off_t as well, we just increment uio_offset * by 1 for each entry. * * num is the entry we need to start reporting * cnum is the current entry */ if (uio->uio_offset < 0 || uio->uio_offset > INT_MAX) return(EINVAL); if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) return (error); num = uio->uio_offset; cnum = 0; if( num <= cnum ) { dprintf((". faked, ")); if (vop_write_dirent(&error, uio, hp->h_no, DT_DIR, 1, ".")) goto done; if (error) goto done; ncookies ++; } cnum++; if( num <= cnum ) { dprintf((".. faked, ")); if (vop_write_dirent(&error, uio, hp->h_fn.fn_parent, DT_DIR, 2, "..")) goto readdone; if (error) goto done; ncookies ++; } cnum++; lsn = ((alleaf_t *)hp->h_fn.fn_abd)->al_lsn; olsn = 0; level = 1; dive: dprintf(("[dive 0x%x] ", lsn)); error = bread(hp->h_devvp, dbtodoff(lsn), D_BSIZE, &bp); if (error) { brelse(bp); goto done; } dp = (struct dirblk *) bp->b_data; if (dp->d_magic != D_MAGIC) { kprintf("hpfs_readdir: MAGIC DOESN'T MATCH\n"); brelse(bp); error = EINVAL; goto done; } dep = D_DIRENT(dp); if (olsn) { dprintf(("[restore 0x%x] ", olsn)); while(!(dep->de_flag & DE_END) ) { if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) break; dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); } if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) { if (dep->de_flag & DE_END) goto blockdone; if (!(dep->de_flag & DE_SPECIAL)) { if (num <= cnum) { if (hpfs_de_uiomove(&error, hpmp, dep, uio)) { brelse(bp); dprintf(("[resid] ")); goto readdone; } if (error) { brelse (bp); goto done; } ncookies++; } cnum++; } dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); } else { kprintf("hpfs_readdir: ERROR! oLSN not found\n"); brelse(bp); error = EINVAL; goto done; } } olsn = 0; while(!(dep->de_flag & DE_END)) { if(dep->de_flag & DE_DOWN) { lsn = DE_DOWNLSN(dep); brelse(bp); level++; goto dive; } if (!(dep->de_flag & DE_SPECIAL)) { if (num <= cnum) { if (hpfs_de_uiomove(&error, hpmp, dep, uio)) { brelse(bp); dprintf(("[resid] ")); goto readdone; } if (error) { brelse (bp); goto done; } ncookies++; } cnum++; } dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); } if(dep->de_flag & DE_DOWN) { dprintf(("[enddive] ")); lsn = DE_DOWNLSN(dep); brelse(bp); level++; goto dive; } blockdone: dprintf(("[EOB] ")); olsn = lsn; lsn = dp->d_parent; brelse(bp); level--; dprintf(("[level %d] ", level)); if (level > 0) goto dive; /* undive really */ if (ap->a_eofflag) { dprintf(("[EOF] ")); *ap->a_eofflag = 1; } readdone: uio->uio_offset = cnum; dprintf(("[readdone]\n")); if (!error && ap->a_ncookies != NULL) { off_t *cookies; off_t *cookiep; dprintf(("%d cookies, ",ncookies)); if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) panic("hpfs_readdir: unexpected uio from NFS server"); cookies = kmalloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK); for (cookiep = cookies, i=0; i < ncookies; i++) *cookiep++ = ++num; *ap->a_ncookies = ncookies; *ap->a_cookies = cookies; } done: vn_unlock(ap->a_vp); return (error); }
static int devfs_vop_readdir(struct vop_readdir_args *ap) { struct devfs_node *dnode = DEVFS_NODE(ap->a_vp); struct devfs_node *node; int cookie_index; int ncookies; int error2; int error; int r; off_t *cookies; off_t saveoff; devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_readdir() called!\n"); if (ap->a_uio->uio_offset < 0 || ap->a_uio->uio_offset > INT_MAX) return (EINVAL); error = vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM); if (error) return (error); if (!devfs_node_is_accessible(dnode)) { vn_unlock(ap->a_vp); return ENOENT; } lockmgr(&devfs_lock, LK_EXCLUSIVE); saveoff = ap->a_uio->uio_offset; if (ap->a_ncookies) { ncookies = ap->a_uio->uio_resid / 16 + 1; /* Why / 16 ?? */ if (ncookies > 256) ncookies = 256; cookies = kmalloc(256 * sizeof(off_t), M_TEMP, M_WAITOK); cookie_index = 0; } else { ncookies = -1; cookies = NULL; cookie_index = 0; } nanotime(&dnode->atime); if (saveoff == 0) { r = vop_write_dirent(&error, ap->a_uio, dnode->d_dir.d_ino, DT_DIR, 1, "."); if (r) goto done; if (cookies) cookies[cookie_index] = saveoff; saveoff++; cookie_index++; if (cookie_index == ncookies) goto done; } if (saveoff == 1) { if (dnode->parent) { r = vop_write_dirent(&error, ap->a_uio, dnode->parent->d_dir.d_ino, DT_DIR, 2, ".."); } else { r = vop_write_dirent(&error, ap->a_uio, dnode->d_dir.d_ino, DT_DIR, 2, ".."); } if (r) goto done; if (cookies) cookies[cookie_index] = saveoff; saveoff++; cookie_index++; if (cookie_index == ncookies) goto done; } TAILQ_FOREACH(node, DEVFS_DENODE_HEAD(dnode), link) { if ((node->flags & DEVFS_HIDDEN) || (node->flags & DEVFS_INVISIBLE)) { continue; } /* * If the node type is a valid devfs alias, then we make * sure that the target isn't hidden. If it is, we don't * show the link in the directory listing. */ if ((node->node_type == Nlink) && (node->link_target != NULL) && (node->link_target->flags & DEVFS_HIDDEN)) continue; if (node->cookie < saveoff) continue; saveoff = node->cookie; error2 = vop_write_dirent(&error, ap->a_uio, node->d_dir.d_ino, node->d_dir.d_type, node->d_dir.d_namlen, node->d_dir.d_name); if (error2) break; saveoff++; if (cookies) cookies[cookie_index] = node->cookie; ++cookie_index; if (cookie_index == ncookies) break; } done: lockmgr(&devfs_lock, LK_RELEASE); vn_unlock(ap->a_vp); ap->a_uio->uio_offset = saveoff; if (error && cookie_index == 0) { if (cookies) { kfree(cookies, M_TEMP); *ap->a_ncookies = 0; *ap->a_cookies = NULL; } } else { if (cookies) { *ap->a_ncookies = cookie_index; *ap->a_cookies = cookies; } } return (error); }
/* * 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. * * Caller must hold the node locked (shared ok) */ int tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, off_t *cntp) { int error; off_t startcookie; struct tmpfs_dirent *de; TMPFS_VALIDATE_DIR(node); /* * Locate the first directory entry we have to return. We have cached * the last readdir in the node, so use those values if appropriate. * Otherwise do a linear scan to find the requested entry. */ startcookie = uio->uio_offset; KKASSERT(startcookie != TMPFS_DIRCOOKIE_DOT); KKASSERT(startcookie != TMPFS_DIRCOOKIE_DOTDOT); if (startcookie == TMPFS_DIRCOOKIE_EOF) return 0; de = tmpfs_dir_lookupbycookie(node, startcookie); if (de == NULL) return EINVAL; /* * Read as much entries as possible; i.e., until we reach the end of * the directory or we exhaust uio space. */ do { ino_t d_ino; uint8_t d_type; /* Create a dirent structure representing the current * tmpfs_node and fill it. */ d_ino = de->td_node->tn_id; switch (de->td_node->tn_type) { case VBLK: d_type = DT_BLK; break; case VCHR: d_type = DT_CHR; break; case VDIR: d_type = DT_DIR; break; case VFIFO: d_type = DT_FIFO; break; case VLNK: d_type = DT_LNK; break; case VREG: d_type = DT_REG; break; case VSOCK: d_type = DT_SOCK; break; default: panic("tmpfs_dir_getdents: type %p %d", de->td_node, (int)de->td_node->tn_type); } KKASSERT(de->td_namelen < 256); /* 255 + 1 */ if (vop_write_dirent(&error, uio, d_ino, d_type, de->td_namelen, de->td_name)) { error = -1; break; } (*cntp)++; de = RB_NEXT(tmpfs_dirtree_cookie, node->tn_dir.tn_cookietree, de); } while (error == 0 && uio->uio_resid > 0 && de != NULL); /* Update the offset and cache. */ if (de == NULL) { uio->uio_offset = TMPFS_DIRCOOKIE_EOF; } else { uio->uio_offset = tmpfs_dircookie(de); } return error; }