/*
 * always call fuse_lowlevel_new_common() internally, to work around a
 * misfeature in the FreeBSD runtime linker, which links the old
 * version of a symbol to internal references.
 */
struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
					      const struct fuse_lowlevel_ops *op,
					      size_t op_size, void *userdata)
{
	struct fuse_ll *f;
	struct fuse_session *se;
	struct fuse_session_ops sop = {
		.process = fuse_ll_process,
		.destroy = fuse_ll_destroy,
	};

	if (sizeof(struct fuse_lowlevel_ops) < op_size) {
		fprintf(stderr, "fuse: warning: library too old, some operations may not work\n");
		op_size = sizeof(struct fuse_lowlevel_ops);
	}

	f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll));
	if (f == NULL) {
		fprintf(stderr, "fuse: failed to allocate fuse object\n");
		goto out;
	}

	f->conn.async_read = 1;
	f->conn.max_write = UINT_MAX;
	f->conn.max_readahead = UINT_MAX;
	f->atomic_o_trunc = 0;
	list_init_req(&f->list);
	list_init_req(&f->interrupts);
	fuse_mutex_init(&f->lock);

	if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
		goto out_free;

	if (f->debug)
		fprintf(stderr, "FUSE library version: %s\n", PACKAGE_VERSION);

	memcpy(&f->op, op, op_size);
	f->owner = getuid();
	f->userdata = userdata;

	se = fuse_session_new(&sop, f);
	if (!se)
		goto out_free;

	return se;

out_free:
	free(f);
out:
	return NULL;
}
Exemplo n.º 2
0
int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data)
{
    int res;
    struct procdata pd;
    struct fuse_session *prevse = fuse_get_session(f);
    struct fuse_session *se;
    struct fuse_chan *prevch = fuse_session_next_chan(prevse, NULL);
    struct fuse_chan *ch;
    struct fuse_session_ops sop = {
        .exit = mt_session_exit,
        .exited = mt_session_exited,
        .process = mt_session_proc,
    };
    struct fuse_chan_ops cop = {
        .receive = mt_chan_receive,
        .send = mt_chan_send,
    };

    pd.f = f;
    pd.prevch = prevch;
    pd.prevse = prevse;
    pd.proc = proc;
    pd.data = data;

    se = fuse_session_new(&sop, &pd);
    if (se == NULL)
        return -1;

    ch = fuse_chan_new(&cop, fuse_chan_fd(prevch), sizeof(struct fuse_cmd *),
                       &pd);
    if (ch == NULL) {
        fuse_session_destroy(se);
        return -1;
    }
    fuse_session_add_chan(se, ch);
    res = fuse_session_loop_mt(se);
    fuse_session_destroy(se);
    return res;
}