1987da915Sopenharmony_ci/*
2987da915Sopenharmony_ci    FUSE: Filesystem in Userspace
3987da915Sopenharmony_ci    Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
4987da915Sopenharmony_ci
5987da915Sopenharmony_ci    This program can be distributed under the terms of the GNU LGPLv2.
6987da915Sopenharmony_ci    See the file COPYING.LIB
7987da915Sopenharmony_ci*/
8987da915Sopenharmony_ci
9987da915Sopenharmony_ci#include "config.h"
10987da915Sopenharmony_ci#include "fuse_lowlevel.h"
11987da915Sopenharmony_ci#include "fuse_lowlevel_compat.h"
12987da915Sopenharmony_ci
13987da915Sopenharmony_ci#include <stdio.h>
14987da915Sopenharmony_ci#include <stdlib.h>
15987da915Sopenharmony_ci#include <string.h>
16987da915Sopenharmony_ci#include <assert.h>
17987da915Sopenharmony_ci#include <errno.h>
18987da915Sopenharmony_ci
19987da915Sopenharmony_cistruct fuse_session {
20987da915Sopenharmony_ci    struct fuse_session_ops op;
21987da915Sopenharmony_ci
22987da915Sopenharmony_ci    void *data;
23987da915Sopenharmony_ci
24987da915Sopenharmony_ci    volatile int exited;
25987da915Sopenharmony_ci
26987da915Sopenharmony_ci    struct fuse_chan *ch;
27987da915Sopenharmony_ci};
28987da915Sopenharmony_ci
29987da915Sopenharmony_cistruct fuse_chan {
30987da915Sopenharmony_ci    struct fuse_chan_ops op;
31987da915Sopenharmony_ci
32987da915Sopenharmony_ci    struct fuse_session *se;
33987da915Sopenharmony_ci
34987da915Sopenharmony_ci    int fd;
35987da915Sopenharmony_ci
36987da915Sopenharmony_ci    size_t bufsize;
37987da915Sopenharmony_ci
38987da915Sopenharmony_ci    void *data;
39987da915Sopenharmony_ci};
40987da915Sopenharmony_ci
41987da915Sopenharmony_cistruct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
42987da915Sopenharmony_ci{
43987da915Sopenharmony_ci    struct fuse_session *se = (struct fuse_session *) malloc(sizeof(*se));
44987da915Sopenharmony_ci    if (se == NULL) {
45987da915Sopenharmony_ci        fprintf(stderr, "fuse: failed to allocate session\n");
46987da915Sopenharmony_ci        return NULL;
47987da915Sopenharmony_ci    }
48987da915Sopenharmony_ci
49987da915Sopenharmony_ci    memset(se, 0, sizeof(*se));
50987da915Sopenharmony_ci    se->op = *op;
51987da915Sopenharmony_ci    se->data = data;
52987da915Sopenharmony_ci
53987da915Sopenharmony_ci    return se;
54987da915Sopenharmony_ci}
55987da915Sopenharmony_ci
56987da915Sopenharmony_civoid fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch)
57987da915Sopenharmony_ci{
58987da915Sopenharmony_ci    assert(se->ch == NULL);
59987da915Sopenharmony_ci    assert(ch->se == NULL);
60987da915Sopenharmony_ci    se->ch = ch;
61987da915Sopenharmony_ci    ch->se = se;
62987da915Sopenharmony_ci}
63987da915Sopenharmony_ci
64987da915Sopenharmony_civoid fuse_session_remove_chan(struct fuse_chan *ch)
65987da915Sopenharmony_ci{
66987da915Sopenharmony_ci    struct fuse_session *se = ch->se;
67987da915Sopenharmony_ci    if (se) {
68987da915Sopenharmony_ci        assert(se->ch == ch);
69987da915Sopenharmony_ci        se->ch = NULL;
70987da915Sopenharmony_ci        ch->se = NULL;
71987da915Sopenharmony_ci    }
72987da915Sopenharmony_ci}
73987da915Sopenharmony_ci
74987da915Sopenharmony_cistruct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
75987da915Sopenharmony_ci                                         struct fuse_chan *ch)
76987da915Sopenharmony_ci{
77987da915Sopenharmony_ci    assert(ch == NULL || ch == se->ch);
78987da915Sopenharmony_ci    if (ch == NULL)
79987da915Sopenharmony_ci        return se->ch;
80987da915Sopenharmony_ci    else
81987da915Sopenharmony_ci        return NULL;
82987da915Sopenharmony_ci}
83987da915Sopenharmony_ci
84987da915Sopenharmony_civoid fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
85987da915Sopenharmony_ci                          struct fuse_chan *ch)
86987da915Sopenharmony_ci{
87987da915Sopenharmony_ci    se->op.process(se->data, buf, len, ch);
88987da915Sopenharmony_ci}
89987da915Sopenharmony_ci
90987da915Sopenharmony_civoid fuse_session_destroy(struct fuse_session *se)
91987da915Sopenharmony_ci{
92987da915Sopenharmony_ci    if (se->op.destroy)
93987da915Sopenharmony_ci        se->op.destroy(se->data);
94987da915Sopenharmony_ci    if (se->ch != NULL)
95987da915Sopenharmony_ci        fuse_chan_destroy(se->ch);
96987da915Sopenharmony_ci    free(se);
97987da915Sopenharmony_ci}
98987da915Sopenharmony_ci
99987da915Sopenharmony_civoid fuse_session_exit(struct fuse_session *se)
100987da915Sopenharmony_ci{
101987da915Sopenharmony_ci    if (se->op.exit)
102987da915Sopenharmony_ci        se->op.exit(se->data, 1);
103987da915Sopenharmony_ci    se->exited = 1;
104987da915Sopenharmony_ci}
105987da915Sopenharmony_ci
106987da915Sopenharmony_civoid fuse_session_reset(struct fuse_session *se)
107987da915Sopenharmony_ci{
108987da915Sopenharmony_ci    if (se->op.exit)
109987da915Sopenharmony_ci        se->op.exit(se->data, 0);
110987da915Sopenharmony_ci    se->exited = 0;
111987da915Sopenharmony_ci}
112987da915Sopenharmony_ci
113987da915Sopenharmony_ciint fuse_session_exited(struct fuse_session *se)
114987da915Sopenharmony_ci{
115987da915Sopenharmony_ci    if (se->op.exited)
116987da915Sopenharmony_ci        return se->op.exited(se->data);
117987da915Sopenharmony_ci    else
118987da915Sopenharmony_ci        return se->exited;
119987da915Sopenharmony_ci}
120987da915Sopenharmony_ci
121987da915Sopenharmony_cistatic struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd,
122987da915Sopenharmony_ci                                size_t bufsize, void *data)
123987da915Sopenharmony_ci{
124987da915Sopenharmony_ci    struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch));
125987da915Sopenharmony_ci    if (ch == NULL) {
126987da915Sopenharmony_ci        fprintf(stderr, "fuse: failed to allocate channel\n");
127987da915Sopenharmony_ci        return NULL;
128987da915Sopenharmony_ci    }
129987da915Sopenharmony_ci
130987da915Sopenharmony_ci    memset(ch, 0, sizeof(*ch));
131987da915Sopenharmony_ci    ch->op = *op;
132987da915Sopenharmony_ci    ch->fd = fd;
133987da915Sopenharmony_ci    ch->bufsize = bufsize;
134987da915Sopenharmony_ci    ch->data = data;
135987da915Sopenharmony_ci
136987da915Sopenharmony_ci    return ch;
137987da915Sopenharmony_ci}
138987da915Sopenharmony_ci
139987da915Sopenharmony_cistruct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
140987da915Sopenharmony_ci                                size_t bufsize, void *data)
141987da915Sopenharmony_ci{
142987da915Sopenharmony_ci    return fuse_chan_new_common(op, fd, bufsize, data);
143987da915Sopenharmony_ci}
144987da915Sopenharmony_ci
145987da915Sopenharmony_ciint fuse_chan_fd(struct fuse_chan *ch)
146987da915Sopenharmony_ci{
147987da915Sopenharmony_ci    return ch->fd;
148987da915Sopenharmony_ci}
149987da915Sopenharmony_ci
150987da915Sopenharmony_cisize_t fuse_chan_bufsize(struct fuse_chan *ch)
151987da915Sopenharmony_ci{
152987da915Sopenharmony_ci    return ch->bufsize;
153987da915Sopenharmony_ci}
154987da915Sopenharmony_ci
155987da915Sopenharmony_civoid *fuse_chan_data(struct fuse_chan *ch)
156987da915Sopenharmony_ci{
157987da915Sopenharmony_ci    return ch->data;
158987da915Sopenharmony_ci}
159987da915Sopenharmony_ci
160987da915Sopenharmony_cistruct fuse_session *fuse_chan_session(struct fuse_chan *ch)
161987da915Sopenharmony_ci{
162987da915Sopenharmony_ci    return ch->se;
163987da915Sopenharmony_ci}
164987da915Sopenharmony_ci
165987da915Sopenharmony_ciint fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
166987da915Sopenharmony_ci{
167987da915Sopenharmony_ci    struct fuse_chan *ch = *chp;
168987da915Sopenharmony_ci
169987da915Sopenharmony_ci    return ch->op.receive(chp, buf, size);
170987da915Sopenharmony_ci}
171987da915Sopenharmony_ci
172987da915Sopenharmony_ci#ifdef __SOLARIS__
173987da915Sopenharmony_ciint fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
174987da915Sopenharmony_ci{
175987da915Sopenharmony_ci    int res;
176987da915Sopenharmony_ci
177987da915Sopenharmony_ci    res = fuse_chan_recv(&ch, buf, size);
178987da915Sopenharmony_ci    return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0;
179987da915Sopenharmony_ci}
180987da915Sopenharmony_ci#endif /* __SOLARIS__ */
181987da915Sopenharmony_ci
182987da915Sopenharmony_ciint fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count)
183987da915Sopenharmony_ci{
184987da915Sopenharmony_ci    return ch->op.send(ch, iov, count);
185987da915Sopenharmony_ci}
186987da915Sopenharmony_ci
187987da915Sopenharmony_civoid fuse_chan_destroy(struct fuse_chan *ch)
188987da915Sopenharmony_ci{
189987da915Sopenharmony_ci    fuse_session_remove_chan(ch);
190987da915Sopenharmony_ci    if (ch->op.destroy)
191987da915Sopenharmony_ci        ch->op.destroy(ch);
192987da915Sopenharmony_ci    free(ch);
193987da915Sopenharmony_ci}
194