blob: 3758627de4e627c3694a5ac08b974625e8b123f4 [file] [log] [blame]
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU LGPLv2.
6 See the file COPYING.LIB
7*/
8
9#include "fuse_i.h"
10#include "fuse_misc.h"
11#include "fuse_common_compat.h"
12#include "fuse_lowlevel_compat.h"
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <assert.h>
18#include <errno.h>
19
20struct fuse_chan {
21 struct fuse_chan_ops op;
22
23 struct fuse_session *se;
24
25 int fd;
26
27 size_t bufsize;
28
29 void *data;
30
31 int compat;
32};
33
34struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
35{
36 struct fuse_session *se = (struct fuse_session *) malloc(sizeof(*se));
37 if (se == NULL) {
38 fprintf(stderr, "fuse: failed to allocate session\n");
39 return NULL;
40 }
41
42 memset(se, 0, sizeof(*se));
43 se->op = *op;
44 se->data = data;
45
46 return se;
47}
48
49void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch)
50{
51 assert(se->ch == NULL);
52 assert(ch->se == NULL);
53 se->ch = ch;
54 ch->se = se;
55}
56
57void fuse_session_remove_chan(struct fuse_chan *ch)
58{
59 struct fuse_session *se = ch->se;
60 if (se) {
61 assert(se->ch == ch);
62 se->ch = NULL;
63 ch->se = NULL;
64 }
65}
66
67struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
68 struct fuse_chan *ch)
69{
70 assert(ch == NULL || ch == se->ch);
71 if (ch == NULL)
72 return se->ch;
73 else
74 return NULL;
75}
76
77void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
78 struct fuse_chan *ch)
79{
80 se->op.process(se->data, buf, len, ch);
81}
82
83void fuse_session_destroy(struct fuse_session *se)
84{
85 if (se->op.destroy)
86 se->op.destroy(se->data);
87 if (se->ch != NULL)
88 fuse_chan_destroy(se->ch);
89 free(se);
90}
91
92void fuse_session_exit(struct fuse_session *se)
93{
94 if (se->op.exit)
95 se->op.exit(se->data, 1);
96 se->exited = 1;
97}
98
99void fuse_session_reset(struct fuse_session *se)
100{
101 if (se->op.exit)
102 se->op.exit(se->data, 0);
103 se->exited = 0;
104}
105
106int fuse_session_exited(struct fuse_session *se)
107{
108 if (se->op.exited)
109 return se->op.exited(se->data);
110 else
111 return se->exited;
112}
113
114void *fuse_session_data(struct fuse_session *se)
115{
116 return se->data;
117}
118
119static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd,
120 size_t bufsize, void *data,
121 int compat)
122{
123 struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch));
124 if (ch == NULL) {
125 fprintf(stderr, "fuse: failed to allocate channel\n");
126 return NULL;
127 }
128
129 memset(ch, 0, sizeof(*ch));
130 ch->op = *op;
131 ch->fd = fd;
132 ch->bufsize = bufsize;
133 ch->data = data;
134 ch->compat = compat;
135
136 return ch;
137}
138
139struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
140 size_t bufsize, void *data)
141{
142 return fuse_chan_new_common(op, fd, bufsize, data, 0);
143}
144
145struct fuse_chan *fuse_chan_new_compat24(struct fuse_chan_ops_compat24 *op,
146 int fd, size_t bufsize, void *data)
147{
148 return fuse_chan_new_common((struct fuse_chan_ops *) op, fd, bufsize,
149 data, 24);
150}
151
152int fuse_chan_fd(struct fuse_chan *ch)
153{
154 return ch->fd;
155}
156
157size_t fuse_chan_bufsize(struct fuse_chan *ch)
158{
159 return ch->bufsize;
160}
161
162void *fuse_chan_data(struct fuse_chan *ch)
163{
164 return ch->data;
165}
166
167struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
168{
169 return ch->se;
170}
171
172int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
173{
174 struct fuse_chan *ch = *chp;
175 if (ch->compat)
176 return ((struct fuse_chan_ops_compat24 *) &ch->op)
177 ->receive(ch, buf, size);
178 else
179 return ch->op.receive(chp, buf, size);
180}
181
182int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
183{
184 int res;
185
186 res = fuse_chan_recv(&ch, buf, size);
187 return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0;
188}
189
190int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count)
191{
192 return ch->op.send(ch, iov, count);
193}
194
195void fuse_chan_destroy(struct fuse_chan *ch)
196{
197 fuse_session_remove_chan(ch);
198 if (ch->op.destroy)
199 ch->op.destroy(ch);
200 free(ch);
201}
202
203#ifndef __FreeBSD__
204FUSE_SYMVER(".symver fuse_chan_new_compat24,fuse_chan_new@FUSE_2.4");
205#endif