Пример #1
0
/*
 * 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);
  }
}
Пример #2
0
/*
 * 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;
}