Пример #1
0
int
sysctlfs_fs_nodetofh(struct puffs_usermount *pu, void *cookie,
	void *fid, size_t *fidsize)
{
	struct puffs_node *pn = cookie;
	struct sfsfid *sfid;

	sfid = fid;
	sfid->len = PNPLEN(pn);
	memcpy(&sfid->path, PNPATH(pn), sfid->len * sizeof(int));

	return 0;
}
Пример #2
0
/*
 * called from nodewalk, checks for exact match
 */
void *
puffs_path_walkcmp(struct puffs_usermount *pu, struct puffs_node *pn, void *arg)
{
	struct puffs_pathobj *po = arg;
	struct puffs_pathobj po2;

	if (po->po_len != PNPLEN(pn))
		return NULL;

	/*
	 * If hashing and the hash doesn't match, we know this is
	 * definitely not a match.  Otherwise check for collisions.
	 */
	if (pu->pu_flags & PUFFS_FLAG_HASHPATH)
		if (pn->pn_po.po_hash != po->po_hash)
			return NULL;

	po2.po_path = PNPATH(pn);
	po2.po_len = PNPLEN(pn);

	if (pu->pu_pathcmp(pu, po, &po2, PNPLEN(pn), 0) == 0)
		return pn;
	return NULL;
}
Пример #3
0
int
sysctlfs_node_write(struct puffs_usermount *pu, void *opc, uint8_t *buf,
	off_t offset, size_t *resid, const struct puffs_cred *cred,
	int ioflag)
{
	struct puffs_node *pn = opc;
	struct sfsnode *sfs = pn->pn_data;
	long long ll;
	int i, rv;
	bool b;

	/*
	 * I picked the wrong day to ... um, the wrong place to return errors
	 */

	/* easy to support, but just unavailable now */
	if (rflag)
		return EOPNOTSUPP;

	if (puffs_cred_isjuggernaut(cred) == 0)
		return EACCES;

	if (ISADIR(sfs))
		return EISDIR;

	if (offset != 0)
		return EINVAL;

	if (ioflag & PUFFS_IO_APPEND)
		return EINVAL;

	switch (SYSCTL_TYPE(sfs->sysctl_flags)) {
	case CTLTYPE_BOOL:
		if (strcasestr((const char *)buf, "true"))
			b = true;
		else if (strcasestr((const char *)buf, "false"))
			b = false;
		else
			return EINVAL;
		rv = sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL,
		    &b, sizeof(b));
		break;
	case CTLTYPE_INT:
		if (sscanf((const char *)buf, "%d", &i) != 1)
			return EINVAL;
		rv = sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL,
		    &i, sizeof(int));
		break;
	case CTLTYPE_QUAD:
		if (sscanf((const char *)buf, "%lld", &ll) != 1)
			return EINVAL;
		rv =  sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL,
		    &ll, sizeof(long long));
		break;
	case CTLTYPE_STRING:
		rv = sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL, buf, *resid);
		break;
	default:
		rv = EINVAL;
		break;
	}

	if (rv)
		return rv;

	*resid = 0;
	return 0;
}
Пример #4
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;
}