예제 #1
0
파일: dtfs_vnops.c 프로젝트: 2asoft/freebsd
int
dtfs_node_lookup(struct puffs_usermount *pu, void *opc,
	struct puffs_newinfo *pni, const struct puffs_cn *pcn)
{
	struct puffs_node *pn_dir = opc;
	struct dtfs_file *df = DTFS_CTOF(opc);
	struct dtfs_dirent *dfd;
	extern int straightflush;
	int rv;

	/* parent dir? */
	if (PCNISDOTDOT(pcn)) {
		if (df->df_dotdot == NULL)
			return ENOENT;

		assert(df->df_dotdot->pn_va.va_type == VDIR);
		puffs_newinfo_setcookie(pni, df->df_dotdot);
		puffs_newinfo_setvtype(pni, df->df_dotdot->pn_va.va_type);

		return 0;
	}

	dfd = dtfs_dirgetbyname(df, pcn->pcn_name, pcn->pcn_namelen);
	if (dfd) {
		if ((pcn->pcn_flags & NAMEI_ISLASTCN) &&
		    (pcn->pcn_nameiop == NAMEI_DELETE)) {
			rv = puffs_access(VDIR, pn_dir->pn_va.va_mode,
			    pn_dir->pn_va.va_uid, pn_dir->pn_va.va_gid,
			    PUFFS_VWRITE, pcn->pcn_cred);
			if (rv)
				return rv;
		}
		puffs_newinfo_setcookie(pni, dfd->dfd_node);
		puffs_newinfo_setvtype(pni, dfd->dfd_node->pn_va.va_type);
		puffs_newinfo_setsize(pni, dfd->dfd_node->pn_va.va_size);
		puffs_newinfo_setrdev(pni, dfd->dfd_node->pn_va.va_rdev);

		if (straightflush)
			puffs_flush_pagecache_node(pu, dfd->dfd_node);

		return 0;
	}

	if ((pcn->pcn_flags & NAMEI_ISLASTCN)
	    && (pcn->pcn_nameiop == NAMEI_CREATE ||
	        pcn->pcn_nameiop == NAMEI_RENAME)) {
		rv = puffs_access(VDIR, pn_dir->pn_va.va_mode,
		    pn_dir->pn_va.va_uid, pn_dir->pn_va.va_gid,
		    PUFFS_VWRITE, pcn->pcn_cred);
		if (rv)
			return rv;
	}

	return ENOENT;
}
예제 #2
0
int
sysctlfs_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize,
	struct puffs_newinfo *pni)
{
	struct puffs_pathobj po;
	struct puffs_node *pn;
	struct sfsnode *sfs;
	struct sfsfid *sfid;

	sfid = fid;

	po.po_len = sfid->len;
	po.po_path = &sfid->path;

	pn = getnode(pu, &po, 0);
	if (pn == NULL)
		return EINVAL;
	sfs = pn->pn_data;

	puffs_newinfo_setcookie(pni, pn);
	if (ISADIR(sfs))
		puffs_newinfo_setvtype(pni, VDIR);
	else
		puffs_newinfo_setvtype(pni, VREG);

	return 0;
}
예제 #3
0
파일: fs.c 프로젝트: glk/puffs
int
psshfs_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize,
	struct puffs_newinfo *pni)
{
	struct psshfs_ctx *pctx = puffs_getspecific(pu);
	struct psshfs_fid *pf = fid;
	struct puffs_node *pn = pf->node;
	struct psshfs_node *psn;
	int rv;

	if (pf->mounttime != pctx->mounttime)
		return EINVAL;
	if (pn == 0)
		return EINVAL;
	psn = pn->pn_data;
	if ((psn->stat & PSN_HASFH) == 0)
		return EINVAL;

	/* update node attributes */
	rv = getnodeattr(pu, pn);
	if (rv)
		return EINVAL;

	puffs_newinfo_setcookie(pni, pn);
	puffs_newinfo_setvtype(pni, pn->pn_va.va_type);
	puffs_newinfo_setsize(pni, pn->pn_va.va_size);

	return 0;
}
예제 #4
0
int
sysctlfs_node_lookup(struct puffs_usermount *pu, void *opc,
	struct puffs_newinfo *pni, const struct puffs_cn *pcn)
{
	struct puffs_cn *p2cn = __UNCONST(pcn); /* XXX: fix the interface */
	struct sysctlnode sn[SFS_NODEPERDIR];
	struct sysctlnode qnode;
	struct puffs_node *pn_dir = opc;
	struct puffs_node *pn_new;
	struct sfsnode *sfs_dir = pn_dir->pn_data, *sfs_new;
	SfsName *sname = PCNPATH(pcn);
	size_t sl, i;
	int nodetype;

	assert(ISADIR(sfs_dir));

	/*
	 * If we're looking for dotdot, we already have the entire pathname
	 * in sname, courtesy of pathbuild, so we can skip this step.
	 */
	if (!PCNISDOTDOT(pcn)) {
		memset(&qnode, 0, sizeof(qnode));
		sl = SFS_NODEPERDIR * sizeof(struct sysctlnode);
		qnode.sysctl_flags = SYSCTL_VERSION;
		(*sname)[PCNPLEN(pcn)] = CTL_QUERY;

		if (sysctl(*sname, PCNPLEN(pcn) + 1, sn, &sl,
		    &qnode, sizeof(qnode)) == -1)
			return ENOENT;

		for (i = 0; i < sl / sizeof(struct sysctlnode); i++)
			if (strcmp(sn[i].sysctl_name, pcn->pcn_name) == 0)
				break;
		if (i == sl / sizeof(struct sysctlnode))
			return ENOENT;

		(*sname)[PCNPLEN(pcn)] = sn[i].sysctl_num;
		p2cn->pcn_po_full.po_len++;
		nodetype = sn[i].sysctl_flags;
	} else
		nodetype = CTLTYPE_NODE;

	pn_new = getnode(pu, &p2cn->pcn_po_full, nodetype);
	sfs_new = pn_new->pn_data;

	puffs_newinfo_setcookie(pni, pn_new);
	if (ISADIR(sfs_new))
		puffs_newinfo_setvtype(pni, VDIR);
	else
		puffs_newinfo_setvtype(pni, VREG);

	return 0;
}
예제 #5
0
파일: dtfs_vnops.c 프로젝트: 2asoft/freebsd
int
dtfs_node_mkdir(struct puffs_usermount *pu, void *opc,
	struct puffs_newinfo *pni, const struct puffs_cn *pcn,
	const struct vattr *va)
{
	struct puffs_node *pn_parent = opc;
	struct puffs_node *pn_new;

	pn_new = dtfs_genfile(pn_parent, pcn, VDIR);
	puffs_setvattr(&pn_new->pn_va, va);

	puffs_newinfo_setcookie(pni, pn_new);

	return 0;
}
예제 #6
0
파일: dtfs_vnops.c 프로젝트: 2asoft/freebsd
/* create a new node in the parent directory specified by opc */
int
dtfs_node_create(struct puffs_usermount *pu, void *opc,
	struct puffs_newinfo *pni, const struct puffs_cn *pcn,
	const struct vattr *va)
{
	struct puffs_node *pn_parent = opc;
	struct puffs_node *pn_new;

	if (!(va->va_type == VREG || va->va_type == VSOCK))
		return ENODEV;

	pn_new = dtfs_genfile(pn_parent, pcn, va->va_type);
	puffs_setvattr(&pn_new->pn_va, va);

	puffs_newinfo_setcookie(pni, pn_new);

	return 0;
}
예제 #7
0
파일: null.c 프로젝트: glk/puffs
/*ARGSUSED*/
int
puffs_null_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize,
	struct puffs_newinfo *pni)
{
	struct puffs_node *pn_res;

	if (fidsize != sizeof(struct fid))
		return EINVAL;

	pn_res = puffs_pn_nodewalk(pu, fhcmp, fid);
	if (pn_res == NULL)
		return ENOENT;

	puffs_newinfo_setcookie(pni, pn_res);
	puffs_newinfo_setvtype(pni, pn_res->pn_va.va_type);
	puffs_newinfo_setsize(pni, (off_t)pn_res->pn_va.va_size);
	puffs_newinfo_setrdev(pni, pn_res->pn_va.va_rdev);
	return 0;
}
예제 #8
0
파일: dtfs_vnops.c 프로젝트: 2asoft/freebsd
int
dtfs_node_mknod(struct puffs_usermount *pu, void *opc,
	struct puffs_newinfo *pni, const struct puffs_cn *pcn,
	const struct vattr *va)
{
	struct puffs_node *pn_parent = opc;
	struct puffs_node *pn_new;

	if (!(va->va_type == VBLK || va->va_type == VCHR
	    || va->va_type == VFIFO))
		return EINVAL;

	pn_new = dtfs_genfile(pn_parent, pcn, va->va_type);
	puffs_setvattr(&pn_new->pn_va, va);

	puffs_newinfo_setcookie(pni, pn_new);

	return 0;
}
예제 #9
0
파일: dtfs_vnops.c 프로젝트: 2asoft/freebsd
int
dtfs_node_symlink(struct puffs_usermount *pu, void *opc,
	struct puffs_newinfo *pni, const struct puffs_cn *pcn_src,
	const struct vattr *va, const char *link_target)
{
	struct puffs_node *pn_parent = opc;
	struct puffs_node *pn_new;
	struct dtfs_file *df_new;

	if (va->va_type != VLNK)
		return ENODEV;

	pn_new = dtfs_genfile(pn_parent, pcn_src, VLNK);
	puffs_setvattr(&pn_new->pn_va, va);
	df_new = DTFS_PTOF(pn_new);
	df_new->df_linktarget = estrdup(link_target);
	pn_new->pn_va.va_size = strlen(df_new->df_linktarget);

	puffs_newinfo_setcookie(pni, pn_new);

	return 0;
}
예제 #10
0
파일: null.c 프로젝트: glk/puffs
static int
makenode(struct puffs_usermount *pu, struct puffs_newinfo *pni,
	const struct puffs_cn *pcn, const struct vattr *va, int regular)
{
	struct puffs_node *pn;
	struct stat sb;
	int rv;

	if ((rv = processvattr(PCNPATH(pcn), va, regular)) != 0)
		return rv;

	pn = puffs_pn_new(pu, NULL);
	if (!pn)
		return ENOMEM;
	puffs_setvattr(&pn->pn_va, va);

	if (lstat(PCNPATH(pcn), &sb) == -1)
		return errno;
	puffs_stat2vattr(&pn->pn_va, &sb);

	puffs_newinfo_setcookie(pni, pn);
	return 0;
}
예제 #11
0
파일: null.c 프로젝트: glk/puffs
int
puffs_null_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc,
	struct puffs_newinfo *pni, const struct puffs_cn *pcn)
{
	struct puffs_node *pn = opc, *pn_res;
	struct stat sb;
	int rv;

	assert(pn->pn_va.va_type == VDIR);

	/*
	 * Note to whoever is copypasting this: you must first check
	 * if the node is there and only then do nodewalk.  Alternatively
	 * you could make sure that you don't return unlinked/rmdir'd
	 * nodes in some other fashion
	 */
	rv = lstat(PCNPATH(pcn), &sb);
	if (rv)
		return errno;

	/* XXX2: nodewalk is a bit too slow here */
	pn_res = puffs_pn_nodewalk(pu, inodecmp, &sb.st_ino);

	if (pn_res == NULL) {
		pn_res = puffs_pn_new(pu, NULL);
		if (pn_res == NULL)
			return ENOMEM;
		puffs_stat2vattr(&pn_res->pn_va, &sb);
	}

	puffs_newinfo_setcookie(pni, pn_res);
	puffs_newinfo_setvtype(pni, pn_res->pn_va.va_type);
	puffs_newinfo_setsize(pni, (off_t)pn_res->pn_va.va_size);
	puffs_newinfo_setrdev(pni, pn_res->pn_va.va_rdev);

	return 0;
}
예제 #12
0
파일: node.c 프로젝트: ryo/netbsd-src
int
puffs9p_node_lookup(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni,
	const struct puffs_cn *pcn)
{
	AUTOVAR(pu);
	struct vattr va;
	struct puffs_node *pn, *pn_dir = opc;
	struct p9pnode *p9n_dir = pn_dir->pn_data;
	p9ptag_t tfid = NEXTFID(p9p);
	struct qid9p newqid;
	uint16_t nqid;

	p9pbuf_put_1(pb, P9PROTO_T_WALK);
	p9pbuf_put_2(pb, tag);
	p9pbuf_put_4(pb, p9n_dir->fid_base);
	p9pbuf_put_4(pb, tfid);
	p9pbuf_put_2(pb, 1);
	p9pbuf_put_str(pb, pcn->pcn_name);
	GETRESPONSE(pb);

	rv = proto_expect_walk_nqids(pb, &nqid);
	if (rv) {
		rv = ENOENT;
		goto out;
	}
	if (nqid != 1) {
		rv = EPROTO;
		goto out;
	}
	if ((rv = proto_getqid(pb, &newqid)))
		goto out;

	/* we get the parent vers in walk(?)  compensate */
	p9pbuf_recycleout(pb);
	tag = NEXTTAG(p9p);
	p9pbuf_put_1(pb, P9PROTO_T_STAT);
	p9pbuf_put_2(pb, tag);
	p9pbuf_put_4(pb, tfid);
	GETRESPONSE(pb);
	if ((rv = proto_expect_stat(pb, &va)) != 0) {
		proto_cc_clunkfid(pu, tfid, 0);
		rv = ENOENT;
		goto out;
	}
	if (newqid.qidpath != va.va_fileid) {
		proto_cc_clunkfid(pu, tfid, 0);
		rv = EPROTO;
		goto out;
	}
	newqid.qidvers = va.va_gen;

	pn = puffs_pn_nodewalk(pu, nodecmp, &newqid);
	if (pn == NULL)
		pn = newp9pnode_qid(pu, &newqid, tfid);
	else
		proto_cc_clunkfid(pu, tfid, 0);
	/* assert pn */
	memcpy(&pn->pn_va, &va, sizeof(va));

	puffs_newinfo_setcookie(pni, pn);
	puffs_newinfo_setvtype(pni, pn->pn_va.va_type);
	puffs_newinfo_setsize(pni, pn->pn_va.va_size);
	puffs_newinfo_setrdev(pni, pn->pn_va.va_rdev);

 out:
	RETURN(rv);
}
예제 #13
0
파일: node.c 프로젝트: ryo/netbsd-src
static int
nodecreate(struct puffs_usermount *pu, struct puffs_node *pn,
	struct puffs_newinfo *pni, const char *name,
	const struct vattr *vap, uint32_t dirbit)
{
	AUTOVAR(pu);
	struct puffs_node *pn_new;
	struct p9pnode *p9n = pn->pn_data;
	p9pfid_t nfid = NEXTFID(p9p);
	struct qid9p nqid;
	int tries = 0;

 again:
	if (++tries > 5) {
		rv = EPROTO;
		goto out;
	}

	rv = proto_cc_dupfid(pu, p9n->fid_base, nfid);
	if (rv)
		goto out;

	p9pbuf_put_1(pb, P9PROTO_T_CREATE);
	p9pbuf_put_2(pb, tag);
	p9pbuf_put_4(pb, nfid);
	p9pbuf_put_str(pb, name);
	p9pbuf_put_4(pb, dirbit | (vap->va_mode & 0777));
	p9pbuf_put_1(pb, 0);
	GETRESPONSE(pb);

	rv = proto_expect_qid(pb, P9PROTO_R_CREATE, &nqid);
	if (rv)
		goto out;

	/*
	 * Now, little problem here: create returns an *open* fid.
	 * So, clunk it and walk the parent directory to get a fid
	 * which is not open for I/O yet.
	 */
	proto_cc_clunkfid(pu, nfid, 0);
	nfid = NEXTFID(p9p);

	p9pbuf_recycleout(pb);
	p9pbuf_put_1(pb, P9PROTO_T_WALK);
	p9pbuf_put_2(pb, tag);
	p9pbuf_put_4(pb, p9n->fid_base);
	p9pbuf_put_4(pb, nfid);
	p9pbuf_put_2(pb, 1);
	p9pbuf_put_str(pb, name);
	GETRESPONSE(pb);

	/*
	 * someone removed it already? try again
	 * note: this is kind of lose/lose
	 */
	if (p9pbuf_get_type(pb) != P9PROTO_R_WALK)
		goto again;

	pn_new = newp9pnode_va(pu, vap, nfid);
	qid2vattr(&pn_new->pn_va, &nqid);
	puffs_newinfo_setcookie(pni, pn_new);

 out:
	RETURN(rv);
}