Ejemplo n.º 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);
}
Ejemplo n.º 2
0
/*
 * Ok, time to get clever.  There are two possible cases: we are
 * opening a file or we are opening a directory.
 *
 * If it's a directory, don't bother opening it here, but rather
 * wait until readdir, since it's probable we need to be able to
 * open a directory there in any case.
 * 
 * If it's a regular file, open it here with whatever credentials
 * we happen to have.   Let the upper layers of the kernel worry
 * about permission control.
 */
int
puffs9p_node_open(struct puffs_usermount *pu, void *opc, int mode,
	const struct puffs_cred *pcr)
{
	struct puffs_cc *pcc = puffs_cc_getcc(pu);
	struct puffs9p *p9p = puffs_getspecific(pu);
	struct puffs_node *pn = opc;
	struct p9pnode *p9n = pn->pn_data;
	p9pfid_t nfid;
	int error = 0;

	puffs_setback(pcc, PUFFS_SETBACK_INACT_N1);
	if (pn->pn_va.va_type != VDIR) {
		if (mode & FREAD && p9n->fid_read == P9P_INVALFID) {
			nfid = NEXTFID(p9p);
			error = proto_cc_open(pu, p9n->fid_base, nfid,
			    P9PROTO_OMODE_READ);
			if (error)
				return error;
			p9n->fid_read = nfid;
		}
		if (mode & FWRITE && p9n->fid_write == P9P_INVALFID) {
			nfid = NEXTFID(p9p);
			error = proto_cc_open(pu, p9n->fid_base, nfid,
			    P9PROTO_OMODE_WRITE);
			if (error)
				return error;
			p9n->fid_write = nfid;
		}
	}

	return 0;
}
Ejemplo n.º 3
0
struct puffs_node *
allocnode(struct puffs_usermount *pu, struct puffs_node *parent,
	const char *entryname, const struct vattr *vap)
{
	struct psshfs_ctx *pctx = puffs_getspecific(pu);
	struct psshfs_dir *pd;
	struct puffs_node *pn;

	pd = direnter(parent, entryname);

	pd->va.va_fileid = pctx->nextino++;
	if (vap->va_type == VDIR) {
		pd->va.va_nlink = 2;
		parent->pn_va.va_nlink++;
	} else {
		pd->va.va_nlink = 1;
	}

	pn = makenode(pu, parent, pd, vap);
	if (pn) {
		pd->va.va_fileid = pn->pn_va.va_fileid;
		pd->entry = pn;
	}

	return pn;
}
Ejemplo n.º 4
0
void
closehandles(struct puffs_usermount *pu, struct psshfs_node *psn, int which)
{
	struct psshfs_ctx *pctx = puffs_getspecific(pu);
	struct puffs_framebuf *pb1, *pb2;
	uint32_t reqid;

	if (psn->fhand_r && (which & HANDLE_READ)) {
		assert(psn->lazyopen_r == NULL);

		pb1 = psbuf_makeout();
		reqid = NEXTREQ(pctx);
		psbuf_req_data(pb1, SSH_FXP_CLOSE, reqid,
		    psn->fhand_r, psn->fhand_r_len);
		puffs_framev_enqueue_justsend(pu, pctx->sshfd_data, pb1, 1, 0);
		free(psn->fhand_r);
		psn->fhand_r = NULL;
	}

	if (psn->fhand_w && (which & HANDLE_WRITE)) {
		assert(psn->lazyopen_w == NULL);

		pb2 = psbuf_makeout();
		reqid = NEXTREQ(pctx);
		psbuf_req_data(pb2, SSH_FXP_CLOSE, reqid,
		    psn->fhand_w, psn->fhand_w_len);
		puffs_framev_enqueue_justsend(pu, pctx->sshfd_data, pb2, 1, 0);
		free(psn->fhand_w);
		psn->fhand_w = NULL;
	}

	psn->stat |= PSN_HANDLECLOSE;
}
Ejemplo n.º 5
0
Archivo: fs.c Proyecto: 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;
}
Ejemplo n.º 6
0
void
perfuse_destroy_pn(struct puffs_usermount *pu, struct puffs_node *pn)
{
	struct perfuse_state *ps = puffs_getspecific(pu);
	struct perfuse_node_data *pnd;

	if ((pnd = puffs_pn_getpriv(pn)) != NULL) {
		if (pnd->pnd_all_fd != NULL)
			free(pnd->pnd_all_fd);

		if (pnd->pnd_dirent != NULL)
			free(pnd->pnd_dirent);
		
#ifdef PERFUSE_DEBUG
		if (pnd->pnd_flags & PND_OPEN)
			DERRX(EX_SOFTWARE, "%s: file open", __func__);

		if (!TAILQ_EMPTY(&pnd->pnd_pcq))
			DERRX(EX_SOFTWARE, "%s: non empty pnd_pcq", __func__);

		pnd->pnd_flags |= PND_INVALID;
#endif /* PERFUSE_DEBUG */

		free(pnd);
	}

	puffs_pn_put(pn);

	ps->ps_nodecount--;

	return;
}
Ejemplo n.º 7
0
static int
pssh_connect(struct puffs_usermount *pu, int which)
{
	struct psshfs_ctx *pctx = puffs_getspecific(pu);
	char * const *sshargs = pctx->sshargs;
	int fds[2];
	pid_t pid;
	int dnfd, x;
	int *sshfd;
	pid_t *sshpid;

	if (which == PSSHFD_META) {
		sshfd = &pctx->sshfd;
		sshpid = &pctx->sshpid;
	} else {
		assert(which == PSSHFD_DATA);
		sshfd = &pctx->sshfd_data;
		sshpid = &pctx->sshpid_data;
	}

	if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1)
		return -1;

	pid = fork();
	switch (pid) {
	case -1:
		return -1;
		/*NOTREACHED*/
	case 0: /* child */
		if (dup2(fds[0], STDIN_FILENO) == -1)
			err(1, "child dup2");
		if (dup2(fds[0], STDOUT_FILENO) == -1)
			err(1, "child dup2");
		close(fds[0]);
		close(fds[1]);

		dnfd = open(_PATH_DEVNULL, O_RDWR);
		if (dnfd != -1)
			dup2(dnfd, STDERR_FILENO);

		execvp(sshargs[0], sshargs);
		/*NOTREACHED*/
		break;
	default:
		*sshpid = pid;
		*sshfd = fds[1];
		close(fds[0]);
		break;
	}

	if (psshfs_handshake(pu, *sshfd) != 0)
		errx(1, "handshake failed, server does not support sftp?");
	x = 1;
	if (ioctl(*sshfd, FIONBIO, &x) == -1)
		err(1, "nonblocking descriptor %d", which);

	return *sshfd;
}
Ejemplo n.º 8
0
int
dtfs_node_mmap(struct puffs_usermount *pu, void *opc, vm_prot_t prot,
	const struct puffs_cred *pcr)
{
	struct dtfs_mount *dtm = puffs_getspecific(pu);

	if ((dtm->dtm_allowprot & prot) != prot)
		return EACCES;

	return 0;
}
Ejemplo n.º 9
0
Archivo: fs.c Proyecto: glk/puffs
int
psshfs_fs_unmount(struct puffs_usermount *pu, int flags)
{
	struct psshfs_ctx *pctx = puffs_getspecific(pu);

	kill(pctx->sshpid, SIGTERM);
	close(pctx->sshfd);
	if (pctx->numconnections == 2) {
		kill(pctx->sshpid_data, SIGTERM);
		close(pctx->sshfd_data);
	}

	return 0;
}
Ejemplo n.º 10
0
void
psshfs_notify(struct puffs_usermount *pu, int fd, int what)
{
	struct psshfs_ctx *pctx = puffs_getspecific(pu);
	int nretry, which, newfd, dummy;

	if (fd == pctx->sshfd) {
		which = PSSHFD_META;
	} else {
		assert(fd == pctx->sshfd_data);
		which = PSSHFD_DATA;
	}

	if (puffs_getstate(pu) != PUFFS_STATE_RUNNING)
		return;

	if (what != (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) {
		puffs_framev_removefd(pu, fd, ECONNRESET);
		return;
	}
	close(fd);

	/* deal with zmobies, beware of half-eaten brain */
	while (waitpid(-1, &dummy, WNOHANG) > 0)
		continue;

	for (nretry = 0;;nretry++) {
		if ((newfd = pssh_connect(pu, which)) == -1)
			goto retry2;

		if (puffs_framev_addfd(pu, newfd,
		    PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1)
			goto retry1;

		break;
 retry1:
		fprintf(stderr, "reconnect failed... ");
		close(newfd);
 retry2:
		if (nretry < RETRY_MAX) {
			fprintf(stderr, "retry (%d left)\n", RETRY_MAX-nretry);
			sleep(nretry);
		} else {
			fprintf(stderr, "retry count exceeded, going south\n");
			exit(1); /* XXXXXXX */
		}
	}
}
Ejemplo n.º 11
0
Archivo: fs.c Proyecto: glk/puffs
int
psshfs_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie,
	void *fid, size_t *fidsize)
{
	struct psshfs_ctx *pctx = puffs_getspecific(pu);
	struct puffs_node *pn = cookie;
	struct psshfs_node *psn = pn->pn_data;
	struct psshfs_fid *pf = fid;

	pf->mounttime = pctx->mounttime;
	pf->node = pn;

	psn->stat |= PSN_HASFH;

	return 0;
}
Ejemplo n.º 12
0
static void
loopfun(struct puffs_usermount *pu)
{
	struct dtfs_mount *dtm = puffs_getspecific(pu);
	struct dtfs_poll *dp;

	while (dtm->dtm_needwakeup) {
		dtm->dtm_needwakeup--;
		dp = LIST_FIRST(&dtm->dtm_pollent);
		if (dp == NULL)
			return;

		LIST_REMOVE(dp, dp_entries);
		puffs_cc_continue(dp->dp_pcc);
	}
}
Ejemplo n.º 13
0
int
getnodeattr(struct puffs_usermount *pu, struct puffs_node *pn, const char *path)
{
	struct psshfs_ctx *pctx = puffs_getspecific(pu);
	struct psshfs_node *psn = pn->pn_data;
	struct vattr va;
	int rv;

	if (!psn->attrread || REFRESHTIMEOUT(pctx, time(NULL)-psn->attrread)) {
		rv = getpathattr(pu, path ? path : PNPATH(pn), &va);
		if (rv)
			return rv;

		setpnva(pu, pn, &va);
	}

	return 0;
}
Ejemplo n.º 14
0
int
dtfs_node_poll(struct puffs_usermount *pu, void *opc, int *events)
{
	struct dtfs_mount *dtm = puffs_getspecific(pu);
	struct dtfs_poll dp;
	struct itimerval it;

	memset(&it, 0, sizeof(struct itimerval));
	it.it_value.tv_sec = 4;
	if (setitimer(ITIMER_REAL, &it, NULL) == -1)
		return errno;

	dp.dp_pcc = puffs_cc_getcc(pu);
	LIST_INSERT_HEAD(&dtm->dtm_pollent, &dp, dp_entries);
	puffs_cc_yield(dp.dp_pcc);

	*events = *events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM);
	return 0;
}
Ejemplo n.º 15
0
struct puffs_node *
perfuse_new_pn(struct puffs_usermount *pu, const char *name,
	struct puffs_node *parent)
{
	struct perfuse_state *ps = puffs_getspecific(pu);
	struct puffs_node *pn;
	struct perfuse_node_data *pnd;

	if ((pnd = malloc(sizeof(*pnd))) == NULL)
		DERR(EX_OSERR, "%s: malloc failed", __func__);

	if ((pn = puffs_pn_new(pu, pnd)) == NULL)
		DERR(EX_SOFTWARE, "%s: puffs_pn_new failed", __func__);

	(void)memset(pnd, 0, sizeof(*pnd));
	pnd->pnd_rfh = FUSE_UNKNOWN_FH;
	pnd->pnd_wfh = FUSE_UNKNOWN_FH;
	pnd->pnd_nodeid = PERFUSE_UNKNOWN_NODEID;
	if (parent != NULL) {
		pnd->pnd_parent_nodeid = PERFUSE_NODE_DATA(parent)->pnd_nodeid;
	} else {
		pnd->pnd_parent_nodeid = FUSE_ROOT_ID;
	}
	pnd->pnd_fuse_nlookup = 0;
	pnd->pnd_puffs_nlookup = 0;
	pnd->pnd_pn = (puffs_cookie_t)pn;
	if (strcmp(name, "..") != 0)
		(void)strlcpy(pnd->pnd_name, name, MAXPATHLEN);
	else
		pnd->pnd_name[0] = 0; /* anonymous for now */
	TAILQ_INIT(&pnd->pnd_pcq);

	puffs_pn_setpriv(pn, pnd);

	ps->ps_nodecount++;

	return pn;
}
Ejemplo n.º 16
0
Archivo: fs.c Proyecto: 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;
}