• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "config.h"
10 #include "fuse_lowlevel.h"
11 #include "fuse_lowlevel_compat.h"
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <assert.h>
17 #include <errno.h>
18 
19 struct fuse_session {
20     struct fuse_session_ops op;
21 
22     void *data;
23 
24     volatile int exited;
25 
26     struct fuse_chan *ch;
27 };
28 
29 struct fuse_chan {
30     struct fuse_chan_ops op;
31 
32     struct fuse_session *se;
33 
34     int fd;
35 
36     size_t bufsize;
37 
38     void *data;
39 };
40 
fuse_session_new(struct fuse_session_ops * op,void * data)41 struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
42 {
43     struct fuse_session *se = (struct fuse_session *) malloc(sizeof(*se));
44     if (se == NULL) {
45         fprintf(stderr, "fuse: failed to allocate session\n");
46         return NULL;
47     }
48 
49     memset(se, 0, sizeof(*se));
50     se->op = *op;
51     se->data = data;
52 
53     return se;
54 }
55 
fuse_session_add_chan(struct fuse_session * se,struct fuse_chan * ch)56 void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch)
57 {
58     assert(se->ch == NULL);
59     assert(ch->se == NULL);
60     se->ch = ch;
61     ch->se = se;
62 }
63 
fuse_session_remove_chan(struct fuse_chan * ch)64 void fuse_session_remove_chan(struct fuse_chan *ch)
65 {
66     struct fuse_session *se = ch->se;
67     if (se) {
68         assert(se->ch == ch);
69         se->ch = NULL;
70         ch->se = NULL;
71     }
72 }
73 
fuse_session_next_chan(struct fuse_session * se,struct fuse_chan * ch)74 struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
75                                          struct fuse_chan *ch)
76 {
77     assert(ch == NULL || ch == se->ch);
78     if (ch == NULL)
79         return se->ch;
80     else
81         return NULL;
82 }
83 
fuse_session_process(struct fuse_session * se,const char * buf,size_t len,struct fuse_chan * ch)84 void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
85                           struct fuse_chan *ch)
86 {
87     se->op.process(se->data, buf, len, ch);
88 }
89 
fuse_session_destroy(struct fuse_session * se)90 void fuse_session_destroy(struct fuse_session *se)
91 {
92     if (se->op.destroy)
93         se->op.destroy(se->data);
94     if (se->ch != NULL)
95         fuse_chan_destroy(se->ch);
96     free(se);
97 }
98 
fuse_session_exit(struct fuse_session * se)99 void fuse_session_exit(struct fuse_session *se)
100 {
101     if (se->op.exit)
102         se->op.exit(se->data, 1);
103     se->exited = 1;
104 }
105 
fuse_session_reset(struct fuse_session * se)106 void fuse_session_reset(struct fuse_session *se)
107 {
108     if (se->op.exit)
109         se->op.exit(se->data, 0);
110     se->exited = 0;
111 }
112 
fuse_session_exited(struct fuse_session * se)113 int fuse_session_exited(struct fuse_session *se)
114 {
115     if (se->op.exited)
116         return se->op.exited(se->data);
117     else
118         return se->exited;
119 }
120 
fuse_chan_new_common(struct fuse_chan_ops * op,int fd,size_t bufsize,void * data)121 static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd,
122                                 size_t bufsize, void *data)
123 {
124     struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch));
125     if (ch == NULL) {
126         fprintf(stderr, "fuse: failed to allocate channel\n");
127         return NULL;
128     }
129 
130     memset(ch, 0, sizeof(*ch));
131     ch->op = *op;
132     ch->fd = fd;
133     ch->bufsize = bufsize;
134     ch->data = data;
135 
136     return ch;
137 }
138 
fuse_chan_new(struct fuse_chan_ops * op,int fd,size_t bufsize,void * data)139 struct 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);
143 }
144 
fuse_chan_fd(struct fuse_chan * ch)145 int fuse_chan_fd(struct fuse_chan *ch)
146 {
147     return ch->fd;
148 }
149 
fuse_chan_bufsize(struct fuse_chan * ch)150 size_t fuse_chan_bufsize(struct fuse_chan *ch)
151 {
152     return ch->bufsize;
153 }
154 
fuse_chan_data(struct fuse_chan * ch)155 void *fuse_chan_data(struct fuse_chan *ch)
156 {
157     return ch->data;
158 }
159 
fuse_chan_session(struct fuse_chan * ch)160 struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
161 {
162     return ch->se;
163 }
164 
fuse_chan_recv(struct fuse_chan ** chp,char * buf,size_t size)165 int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
166 {
167     struct fuse_chan *ch = *chp;
168 
169     return ch->op.receive(chp, buf, size);
170 }
171 
172 #ifdef __SOLARIS__
fuse_chan_receive(struct fuse_chan * ch,char * buf,size_t size)173 int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
174 {
175     int res;
176 
177     res = fuse_chan_recv(&ch, buf, size);
178     return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0;
179 }
180 #endif /* __SOLARIS__ */
181 
fuse_chan_send(struct fuse_chan * ch,const struct iovec iov[],size_t count)182 int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count)
183 {
184     return ch->op.send(ch, iov, count);
185 }
186 
fuse_chan_destroy(struct fuse_chan * ch)187 void fuse_chan_destroy(struct fuse_chan *ch)
188 {
189     fuse_session_remove_chan(ch);
190     if (ch->op.destroy)
191         ch->op.destroy(ch);
192     free(ch);
193 }
194