Beispiel #1
0
int
puffs_gendotdent(struct dirent **dent, ino_t id, int dotdot, size_t *reslen)
{
	const char *name;

	assert(dotdot == 0 || dotdot == 1);
	name = dotdot == 0 ? "." : "..";

	return puffs_nextdent(dent, name, id, DT_DIR, reslen);
}
Beispiel #2
0
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;
}
Beispiel #3
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;
}
Beispiel #4
0
/*
 * Problem is that 9P doesn't allow seeking into a directory.  So we
 * maintain a list of active fids for any given directory.  They
 * start living at the first read and exist either until the directory
 * is closed or until they reach the end.
 */
int
puffs9p_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)
{
	AUTOVAR(pu);
	struct puffs_node *pn = opc;
	struct p9pnode *p9n = pn->pn_data;
	struct vattr va;
	struct dirfid *dfp;
	char *name;
	uint32_t count;
	uint16_t statsize;

	rv = getdfwithoffset(pu, p9n, *readoff, &dfp);
	if (rv)
		goto out;

	tag = NEXTTAG(p9p);
	p9pbuf_put_1(pb, P9PROTO_T_READ);
	p9pbuf_put_2(pb, tag);
	p9pbuf_put_4(pb, dfp->fid);
	p9pbuf_put_8(pb, *readoff);
	p9pbuf_put_4(pb, *reslen); /* XXX */
	GETRESPONSE(pb);

	p9pbuf_get_4(pb, &count);

	/*
	 * if count is 0, assume we at end-of-dir.  dfp is no longer
	 * useful, so nuke it
	 */
	if (count == 0) {
		*eofflag = 1;
		releasedf(pu, dfp);
		goto out;
	}

	while (count > 0) {
		if ((rv = proto_getstat(pb, &va, &name, &statsize))) {
			/*
			 * If there was an error, it's unlikely we'll be
			 * coming back, so just nuke the dfp.  If we do
			 * come back for some strange reason, we'll just
			 * regen it.
			 */
			releasedf(pu, dfp);
			goto out;
		}

		puffs_nextdent(&dent, name, va.va_fileid,
		    puffs_vtype2dt(va.va_type), reslen);

		count -= statsize;
		*readoff += statsize;
		dfp->seekoff += statsize;
		free(name);
	}

	storedf(p9n, dfp);

 out:
	RETURN(rv);
}