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