예제 #1
0
static void
setpnva(struct puffs_usermount *pu, struct puffs_node *pn,
	const struct vattr *vap)
{
	struct psshfs_ctx *pctx = puffs_getspecific(pu);
	struct psshfs_node *psn = pn->pn_data;
	struct vattr modva;

	/*
	 * Check if the file was modified from below us.
	 * If so, invalidate page cache.  This is the only
	 * sensible place we can do this in.
	 */
	if (pn->pn_va.va_mtime.tv_sec != PUFFS_VNOVAL)
		if (pn->pn_va.va_mtime.tv_sec != vap->va_mtime.tv_sec
		    && pn->pn_va.va_type == VREG)
			puffs_inval_pagecache_node(pu, pn);

	modva = *vap;
	if (pctx->domangleuid && modva.va_uid == pctx->mangleuid)
		modva.va_uid = pctx->myuid;
	if (pctx->domanglegid && modva.va_gid == pctx->manglegid)
		modva.va_gid = pctx->mygid;

	puffs_setvattr(&pn->pn_va, &modva);
	psn->attrread = time(NULL);
}
예제 #2
0
파일: dtfs_vnops.c 프로젝트: 2asoft/freebsd
int
dtfs_node_setattr(struct puffs_usermount *pu, void *opc,
	const struct vattr *va, const struct puffs_cred *pcr)
{
	struct puffs_node *pn = opc;
	int rv;

	/* check permissions */
	if (va->va_flags != PUFFS_VNOVAL)
		return EOPNOTSUPP;

	if (va->va_uid != PUFFS_VNOVAL || va->va_gid != PUFFS_VNOVAL) {
		rv = puffs_access_chown(pn->pn_va.va_uid, pn->pn_va.va_gid,
		    va->va_uid, va->va_gid, pcr);
		if (rv)
			return rv;
	}

	if (va->va_mode != PUFFS_VNOVAL) {
		rv = puffs_access_chmod(pn->pn_va.va_uid, pn->pn_va.va_gid,
		    pn->pn_va.va_type, va->va_mode, pcr);
		if (rv)
			return rv;
	}

	if ((va->va_atime.tv_sec != PUFFS_VNOVAL
	      && va->va_atime.tv_nsec != PUFFS_VNOVAL)
	    || (va->va_mtime.tv_sec != PUFFS_VNOVAL
	      && va->va_mtime.tv_nsec != PUFFS_VNOVAL)) {
		rv = puffs_access_times(pn->pn_va.va_uid, pn->pn_va.va_gid,
		    pn->pn_va.va_mode, va->va_vaflags & VA_UTIMES_NULL, pcr);
		if (rv)
			return rv;
	}

	if (va->va_size != PUFFS_VNOVAL) {
		switch (pn->pn_va.va_type) {
		case VREG:
			dtfs_setsize(pn, va->va_size);
			pn->pn_va.va_bytes = va->va_size;
			break;
		case VBLK:
		case VCHR:
		case VFIFO:
			break;
		case VDIR:
			return EISDIR;
		default:
			return EOPNOTSUPP;
		}
	}

	puffs_setvattr(&pn->pn_va, va);

	return 0;
}
예제 #3
0
파일: null.c 프로젝트: glk/puffs
/*ARGSUSED*/
int
puffs_null_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc,
	const struct vattr *va, const struct puffs_cred *pcred)
{
	struct puffs_node *pn = opc;
	int rv;

	rv = processvattr(PNPATH(pn), va, pn->pn_va.va_type == VREG);
	if (rv)
		return rv;

	puffs_setvattr(&pn->pn_va, va);

	return 0;
}
예제 #4
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;
}
예제 #5
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;
}
예제 #6
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;
}
예제 #7
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;
}
예제 #8
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;
}
예제 #9
0
파일: fs.c 프로젝트: glk/puffs
int
psshfs_handshake(struct puffs_usermount *pu, int fd)
{
	struct psshfs_ctx *pctx = puffs_getspecific(pu);
	struct puffs_framebuf *pb;
	struct puffs_pathobj *po_root;
	struct puffs_node *pn_root;
	struct vattr va, *rva;
	const struct extunit *extu;
	char *rootpath;
	char *ext, *val;
	uint32_t count;
	int rv, done;

	pb = psbuf_makeout();
	psbuf_put_1(pb, SSH_FXP_INIT);
	psbuf_put_4(pb, SFTP_PROTOVERSION);
	DO_IO(psbuf_write, pu, pb, fd, &done, rv);

	puffs_framebuf_recycle(pb);
	DO_IO(psbuf_read, pu, pb, fd, &done, rv);
	if (psbuf_get_type(pb) != SSH_FXP_VERSION)
		reterr((stderr, "invalid server response: %d",
		    psbuf_get_type(pb)), EPROTO);
	pctx->protover = psbuf_get_reqid(pb);

	/*
	 * Check out which extensions are available.  Currently
	 * we are only interested in the openssh statvfs extension.
	 */
	for (;;) {
		if (psbuf_get_str(pb, &ext, NULL) != 0)
			break;
		if (psbuf_get_str(pb, &val, NULL) != 0)
			break;

		for (extu = exttable; extu->ext; extu++)
			if (strcmp(ext, extu->ext) == 0
			    && strcmp(val, extu->val) == 0)
				pctx->extensions |= extu->extflag;
	}

	/* scope out our rootpath */
	psbuf_recycleout(pb);
	psbuf_put_1(pb, SSH_FXP_REALPATH);
	psbuf_put_4(pb, NEXTREQ(pctx));
	psbuf_put_str(pb, pctx->mountpath);
	DO_IO(psbuf_write, pu, pb, fd, &done, rv);

	puffs_framebuf_recycle(pb);
	DO_IO(psbuf_read, pu, pb, fd, &done, rv);
	if (psbuf_get_type(pb) != SSH_FXP_NAME)
		reterr((stderr, "invalid server realpath response for \"%s\"",
		    pctx->mountpath), EPROTO);
	if (psbuf_get_4(pb, &count) == -1)
		reterr((stderr, "invalid realpath response: count"), EPROTO);
	if (psbuf_get_str(pb, &rootpath, NULL) == -1)
		reterr((stderr, "invalid realpath response: rootpath"), EPROTO);

	/* stat the rootdir so that we know it's a dir */
	psbuf_recycleout(pb);
	psbuf_req_str(pb, SSH_FXP_LSTAT, NEXTREQ(pctx), rootpath);
	DO_IO(psbuf_write, pu, pb, fd, &done, rv);

	puffs_framebuf_recycle(pb);
	DO_IO(psbuf_read, pu, pb, fd, &done, rv);

	rv = psbuf_expect_attrs(pb, &va);
	if (rv)
		reterr((stderr, "couldn't stat rootpath"), rv);
	puffs_framebuf_destroy(pb);

	if (puffs_mode2vt(va.va_mode) != VDIR)
		reterr((stderr, "remote path (%s) not a directory", rootpath),
		    ENOTDIR);

	pn_root = puffs_getroot(pu);
	rva = &pn_root->pn_va;
	puffs_setvattr(rva, &va);

	po_root = puffs_getrootpathobj(pu);
	if (po_root == NULL)
		err(1, "getrootpathobj");
	po_root->po_path = rootpath;
	po_root->po_len = strlen(rootpath);

	return 0;
}