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 19struct 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 29struct 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 41struct 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 56void 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 64void 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 74struct 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 84void 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 90void 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 99void 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 106void 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 113int 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 121static 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 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); 143} 144 145int fuse_chan_fd(struct fuse_chan *ch) 146{ 147 return ch->fd; 148} 149 150size_t fuse_chan_bufsize(struct fuse_chan *ch) 151{ 152 return ch->bufsize; 153} 154 155void *fuse_chan_data(struct fuse_chan *ch) 156{ 157 return ch->data; 158} 159 160struct fuse_session *fuse_chan_session(struct fuse_chan *ch) 161{ 162 return ch->se; 163} 164 165int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size) 166{ 167 struct fuse_chan *ch = *chp; 168 return ch->op.receive(chp, buf, size); 169} 170 171int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count) 172{ 173 return ch->op.send(ch, iov, count); 174} 175 176void fuse_chan_destroy(struct fuse_chan *ch) 177{ 178 fuse_session_remove_chan(ch); 179 if (ch->op.destroy) 180 ch->op.destroy(ch); 181 free(ch); 182} 183 184