/*
 * 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;
}
Ejemplo n.º 2
0
static void fuse_ll_process(void *data, const char *buf, size_t len,
                     struct fuse_chan *ch)
{
    struct fuse_ll *f = (struct fuse_ll *) data;
    struct fuse_in_header *in = (struct fuse_in_header *) buf;
    const void *inarg = buf + sizeof(struct fuse_in_header);
    struct fuse_req *req;

    /* Foxconn removed start pling 06/19/2009 */
#if 0
    if (f->debug)
        fprintf(stderr, "unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu\n",
                (unsigned long long) in->unique,
                opname((enum fuse_opcode) in->opcode), in->opcode,
                (unsigned long) in->nodeid, len);
#endif
    /* Foxconn removed end pling 06/19/2009 */

    req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
    if (req == NULL) {
        fprintf(stderr, "fuse: failed to allocate request\n");
        return;
    }

    req->f = f;
    req->unique = in->unique;
    req->ctx.uid = in->uid;
    req->ctx.gid = in->gid;
    req->ctx.pid = in->pid;
    req->ch = ch;
    req->ctr = 1;
    list_init_req(req);
    fuse_mutex_init(&req->lock);

    if (!f->got_init && in->opcode != FUSE_INIT)
        fuse_reply_err(req, EIO);
    else if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
             in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
             in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
             in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
             in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) {
        fuse_reply_err(req, EACCES);
    } else if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
        fuse_reply_err(req, ENOSYS);
    else {
        if (in->opcode != FUSE_INTERRUPT) {
            struct fuse_req *intr;
            pthread_mutex_lock(&f->lock);
            intr = check_interrupt(f, req);
            list_add_req(req, &f->list);
            pthread_mutex_unlock(&f->lock);
            if (intr)
                fuse_reply_err(intr, EAGAIN);
        }
        fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
    }
}
Ejemplo n.º 3
0
static struct fuse_req *check_interrupt(struct fuse_ll *f, struct fuse_req *req)
{
    struct fuse_req *curr;

    for (curr = f->interrupts.next; curr != &f->interrupts; curr = curr->next) {
        if (curr->u.i.unique == req->unique) {
            req->interrupted = 1;
            list_del_req(curr);
            free(curr);
            return NULL;
        }
    }
    curr = f->interrupts.next;
    if (curr != &f->interrupts) {
        list_del_req(curr);
        list_init_req(curr);
        return curr;
    } else
        return NULL;
}