/* * This readdir function which call a special version of it that allows * browsing if browsable_dirs=yes was set on the map. */ int amfs_generic_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count) { int browsable, full; /* check if map is browsable */ browsable = 0; if (mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) { mntent_t mnt; mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts; if (amu_hasmntopt(&mnt, "fullybrowsable")) browsable = 2; else if (amu_hasmntopt(&mnt, "browsable")) browsable = 1; } full = (browsable == 2); if (nfs_dispatcher == nfs_program_2) { if (browsable) return amfs_readdir_browsable(mp, cookie, dp, ep, count, full); else return amfs_readdir(mp, cookie, dp, ep, count); } else { if (browsable) return amfs_readdir3_browsable(mp, (am_cookie3) (uintptr_t) cookie, dp, ep, count, full); else return amfs_readdir3(mp, (am_cookie3) (uintptr_t) cookie, dp, ep, count); } }
/* * This readdir function which call a special version of it that allows * browsing if browsable_dirs=yes was set on the map. */ int amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count) { u_int gen = *(u_int *) cookie; am_node *xp; mntent_t mnt; dp->dl_eof = FALSE; /* assume readdir not done */ /* check if map is browsable */ if (mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) { mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts; if (amu_hasmntopt(&mnt, "fullybrowsable")) return amfs_readdir_browsable(mp, cookie, dp, ep, count, TRUE); if (amu_hasmntopt(&mnt, "browsable")) return amfs_readdir_browsable(mp, cookie, dp, ep, count, FALSE); } /* when gen is 0, we start reading from the beginning of the directory */ if (gen == 0) { /* * In the default instance (which is used to start a search) we return * "." and "..". * * This assumes that the count is big enough to allow both "." and ".." * to be returned in a single packet. If it isn't (which would be * fairly unbelievable) then tough. */ dlog("amfs_generic_readdir: default search"); /* * Check for enough room. This is extremely approximate but is more * than enough space. Really need 2 times: * 4byte fileid * 4byte cookie * 4byte name length * 4byte name * plus the dirlist structure */ if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp)))) return EINVAL; xp = next_nonerror_node(mp->am_child); dp->dl_entries = ep; /* construct "." */ ep[0].ne_fileid = mp->am_gen; ep[0].ne_name = "."; ep[0].ne_nextentry = &ep[1]; (void)memset(ep[0].ne_cookie, 0, sizeof(u_int)); /* construct ".." */ if (mp->am_parent) ep[1].ne_fileid = mp->am_parent->am_gen; else ep[1].ne_fileid = mp->am_gen; ep[1].ne_name = ".."; ep[1].ne_nextentry = NULL; (void)memcpy(ep[1].ne_cookie, (xp ? &xp->am_gen : &dotdotcookie), sizeof(dotdotcookie)); if (!xp) dp->dl_eof = TRUE; /* by default assume readdir done */ if (amuDebug(D_READDIR)) { nfsentry *ne; int j; for (j = 0, ne = ep; ne; ne = ne->ne_nextentry) { u_int cookie; (void)memcpy(&cookie, ne->ne_cookie, sizeof(cookie)); plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%d ck=%d", j++, ne->ne_name, ne->ne_fileid, cookie); } } return 0; } dlog("amfs_generic_readdir: real child"); if (gen == DOT_DOT_COOKIE) { dlog("amfs_generic_readdir: End of readdir in %s", mp->am_path); dp->dl_eof = TRUE; dp->dl_entries = NULL; if (amuDebug(D_READDIR)) plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n"); return 0; } /* non-browsable directories code */ xp = mp->am_child; while (xp && xp->am_gen != gen) xp = xp->am_osib; if (xp) { int nbytes = count / 2; /* conservative */ int todo = MAX_READDIR_ENTRIES; dp->dl_entries = ep; do { am_node *xp_next = next_nonerror_node(xp->am_osib); if (xp_next) { (void)memcpy(ep->ne_cookie, &xp_next->am_gen, sizeof(xp_next->am_gen)); } else { (void)memcpy(ep->ne_cookie, &dotdotcookie, sizeof(dotdotcookie)); dp->dl_eof = TRUE; } ep->ne_fileid = xp->am_gen; ep->ne_name = xp->am_name; nbytes -= sizeof(*ep) + 1; if (xp->am_name) nbytes -= strlen(xp->am_name); xp = xp_next; if (nbytes > 0 && !dp->dl_eof && todo > 1) { ep->ne_nextentry = ep + 1; ep++; --todo; } else { todo = 0; } } while (todo > 0); ep->ne_nextentry = NULL; if (amuDebug(D_READDIR)) { nfsentry *ne; int j; for (j=0,ne=ep; ne; ne=ne->ne_nextentry) { u_int cookie; (void)memcpy(&cookie, ne->ne_cookie, sizeof(cookie)); plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%d ck=%d", j++, ne->ne_name, ne->ne_fileid, cookie); } } return 0; } return ESTALE; }