int dtfs_node_readdir(struct puffs_usermount *pu, void *opc, struct dirent *dent, off_t *readoff, size_t *reslen, const struct puffs_cred *pcr, int *eofflag, off_t *cookies, size_t *ncookies) { struct puffs_node *pn = opc; struct puffs_node *pn_nth; struct dtfs_dirent *dfd_nth; if (pn->pn_va.va_type != VDIR) return ENOTDIR; dtfs_updatetimes(pn, 1, 0, 0); *ncookies = 0; again: if (*readoff == DENT_DOT || *readoff == DENT_DOTDOT) { puffs_gendotdent(&dent, pn->pn_va.va_fileid, *readoff, reslen); (*readoff)++; PUFFS_STORE_DCOOKIE(cookies, ncookies, *readoff); goto again; } for (;;) { dfd_nth = dtfs_dirgetnth(pn->pn_data, DENT_ADJ(*readoff)); if (!dfd_nth) { *eofflag = 1; break; } pn_nth = dfd_nth->dfd_node; if (!puffs_nextdent(&dent, dfd_nth->dfd_name, pn_nth->pn_va.va_fileid, puffs_vtype2dt(pn_nth->pn_va.va_type), reslen)) break; (*readoff)++; PUFFS_STORE_DCOOKIE(cookies, ncookies, *readoff); } return 0; }
/*ARGSUSED*/ int puffs_null_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc, struct dirent *de, off_t *off, size_t *reslen, const struct puffs_cred *pcred, int *eofflag, off_t *cookies, size_t *ncookies) { struct puffs_node *pn = opc; struct dirent entry, *result; DIR *dp; off_t i; int rv; *ncookies = 0; dp = opendir(PNPATH(pn)); if (dp == NULL) return errno; rv = 0; i = *off; /* * XXX: need to do trickery here, telldir/seekdir would be nice, but * then we'd need to keep state, which I'm too lazy to keep */ while (i--) { rv = readdir_r(dp, &entry, &result); if (rv || !result) goto out; } for (;;) { rv = readdir_r(dp, &entry, &result); if (rv != 0) goto out; if (!result) { *eofflag = 1; goto out; } if (_DIRENT_SIZE(result) > *reslen) goto out; *de = *result; *reslen -= _DIRENT_SIZE(result); de = _DIRENT_NEXT(de); (*off)++; PUFFS_STORE_DCOOKIE(cookies, ncookies, *off); } out: closedir(dp); return 0; }
int sysctlfs_node_readdir(struct puffs_usermount *pu, void *opc, struct dirent *dent, off_t *readoff, size_t *reslen, const struct puffs_cred *pcr, int *eofflag, off_t *cookies, size_t *ncookies) { struct sysctlnode sn[SFS_NODEPERDIR]; struct sysctlnode qnode; struct puffs_node *pn_dir = opc; struct puffs_node *pn_res; struct puffs_pathobj po; struct sfsnode *sfs_dir = pn_dir->pn_data, *sfs_ent; SfsName *sname; size_t sl, i; enum vtype vt; ino_t id; *ncookies = 0; again: if (*readoff == DENT_DOT || *readoff == DENT_DOTDOT) { puffs_gendotdent(&dent, sfs_dir->myid, *readoff, reslen); (*readoff)++; PUFFS_STORE_DCOOKIE(cookies, ncookies, *readoff); goto again; } memset(&qnode, 0, sizeof(qnode)); sl = SFS_NODEPERDIR * sizeof(struct sysctlnode); qnode.sysctl_flags = SYSCTL_VERSION; sname = PNPATH(pn_dir); (*sname)[PNPLEN(pn_dir)] = CTL_QUERY; if (sysctl(*sname, PNPLEN(pn_dir) + 1, sn, &sl, &qnode, sizeof(qnode)) == -1) return ENOENT; po.po_path = sname; po.po_len = PNPLEN(pn_dir)+1; for (i = DENT_ADJ(*readoff); i < sl / sizeof(struct sysctlnode); i++) { if (SYSCTL_TYPE(sn[i].sysctl_flags) == CTLTYPE_NODE) vt = VDIR; else vt = VREG; /* * check if the node exists. if so, give it the real * inode number. otherwise just fake it. */ (*sname)[PNPLEN(pn_dir)] = sn[i].sysctl_num; pn_res = puffs_pn_nodewalk(pu, puffs_path_walkcmp, &po); if (pn_res) { sfs_ent = pn_res->pn_data; id = sfs_ent->myid; } else { id = nextid++; } if (!puffs_nextdent(&dent, sn[i].sysctl_name, id, puffs_vtype2dt(vt), reslen)) return 0; (*readoff)++; PUFFS_STORE_DCOOKIE(cookies, ncookies, *readoff); } *eofflag = 1; return 0; }