Exemplo n.º 1
0
static am_node *
amfs_direct_readlink(am_node *mp, int *error_return)
{
  am_node *xp;
  int rc = 0;

  xp = next_nonerror_node(mp->am_child);
  if (!xp) {
    if (!mp->am_al->al_mnt->mf_private)
      amfs_mkcacheref(mp->am_al->al_mnt);
    xp = amfs_generic_lookup_child(mp, mp->am_path + 1, &rc, VLOOK_CREATE);
    if (xp && rc < 0)
      xp = amfs_generic_mount_child(xp, &rc);
  }
  if (xp) {
    new_ttl(xp);		/* (7/12/89) from Rein Tollevik */
    return xp;
  }
  if (amd_state == Finishing)
    rc = ENOENT;
  *error_return = rc;
  return 0;
}
Exemplo n.º 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;
}
Exemplo n.º 3
0
static int
amfs_readdir3(am_node *mp, am_cookie3 cookie,
	      am_dirlist3 *dp, am_entry3 *ep, u_int count)
{
  uint64 gen = *(uint64 *) (uintptr_t) cookie;
  am_node *xp;

  if (amuDebug(D_READDIR))
    plog(XLOG_DEBUG, "amfs_readdir3 gen=%lu, count=%d", (long unsigned) gen, count);

  dp->eof = FALSE;		/* assume readdir not done */

  /* when gen is 0, we start reading from the beginning of the directory */
  if (gen == 0) {
    size_t needed = needroom3();
    /*
     * 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("%s: default search", __func__);

    if (count < needed) {
      dlog("%s: not enough room %u < %zu", __func__, count, needed);
      return EINVAL;
    }

    xp = next_nonerror_node(mp->am_child);
    dp->entries = ep;

    /* construct "." */
    ep[0].fileid = mp->am_gen;
    ep[0].name = ".";
    ep[0].cookie = 0;
    ep[0].nextentry = &ep[1];

    /* construct ".." */
    if (mp->am_parent)
      ep[1].fileid = mp->am_parent->am_gen;
    else
      ep[1].fileid = mp->am_gen;
    ep[1].name = "..";
    ep[1].nextentry = NULL;
    ep[1].cookie = (xp ? xp->am_gen : dotdotcookie);

    if (!xp)
      dp->eof = TRUE;	/* by default assume readdir done */

    if (amuDebug(D_READDIR)) {
      am_entry3 *ne;
      int j;
      for (j = 0, ne = ep; ne; ne = ne->nextentry) {
	plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%lu ck=%lu",
	     j++, ne->name, (long unsigned) ne->fileid, (long unsigned) ne->cookie);
      }
    }
    return 0;
  }
  dlog("%s: real child", __func__);

  if (gen == (uint64) DOT_DOT_COOKIE) {
    dlog("%s: End of readdir in %s", __func__, mp->am_path);
    dp->eof = TRUE;
    dp->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->entries = ep;
    do {
      am_node *xp_next = next_nonerror_node(xp->am_osib);

      if (xp_next) {
        ep->cookie = xp_next->am_gen;
      } else {
	ep->cookie = (uint64) dotdotcookie;
	dp->eof = TRUE;
      }

      ep->fileid = xp->am_gen;
      ep->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->nextentry = ep + 1;
	ep++;
	--todo;
      } else {
	todo = 0;
      }
    } while (todo > 0);

    ep->nextentry = NULL;

    if (amuDebug(D_READDIR)) {
      am_entry3 *ne;
      int j;
      for (j = 0, ne = ep; ne; ne = ne->nextentry) {
	plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%lu ck=%lu",
	     j++, ne->name, (long unsigned) ne->fileid, (long unsigned) ne->cookie);
      }
    }
    return 0;
  }
  return ESTALE;
}