~ubuntu-branches/ubuntu/maverick/fuse/maverick-proposed

« back to all changes in this revision

Viewing changes to lib/fuse_lowlevel.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2008-01-29 10:38:39 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20080129103839-kmz63d04pnttuuoc
Tags: 2.7.2-1ubuntu1
* Resynchronise with Debian. Remaining changes:
  - Don't install the init script; install the udev rule and the module
    configuration file instead.
  - debian/45-fuse.rules: set /dev/fuse group to fuse.
  - debian/fuse-utils.modprobe: module configuration file that mounts the
    control filesystem when fuse is loaded and unmounts it when fuse is
    unloaded, along with checking that the control FS is mounting before
    unmounting it.
  - debian/fuse-utils.install: add the udev rule, the module configuration
    file, and ulockmgr_server.
  - Load fuse on install, and set it so it gets loaded on reboot.
  - Move fusermount and ulockmgr_server to /bin and associated libraries
    to /lib.
  - Create libfuse2-udeb and fuse-utils-udeb.
  - Copy /sbin/mount.fuse and the fuse kernel module into the initramfs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
    FUSE: Filesystem in Userspace
3
 
    Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
 
2
  FUSE: Filesystem in Userspace
 
3
  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
4
4
 
5
 
    This program can be distributed under the terms of the GNU LGPLv2.
6
 
    See the file COPYING.LIB
 
5
  This program can be distributed under the terms of the GNU LGPLv2.
 
6
  See the file COPYING.LIB
7
7
*/
8
8
 
9
9
#include "fuse_lowlevel.h"
28
28
struct fuse_ll;
29
29
 
30
30
struct fuse_req {
31
 
    struct fuse_ll *f;
32
 
    uint64_t unique;
33
 
    int ctr;
34
 
    pthread_mutex_t lock;
35
 
    struct fuse_ctx ctx;
36
 
    struct fuse_chan *ch;
37
 
    int interrupted;
38
 
    union {
39
 
        struct {
40
 
            uint64_t unique;
41
 
        } i;
42
 
        struct {
43
 
            fuse_interrupt_func_t func;
44
 
            void *data;
45
 
        } ni;
46
 
    } u;
47
 
    struct fuse_req *next;
48
 
    struct fuse_req *prev;
 
31
        struct fuse_ll *f;
 
32
        uint64_t unique;
 
33
        int ctr;
 
34
        pthread_mutex_t lock;
 
35
        struct fuse_ctx ctx;
 
36
        struct fuse_chan *ch;
 
37
        int interrupted;
 
38
        union {
 
39
                struct {
 
40
                        uint64_t unique;
 
41
                } i;
 
42
                struct {
 
43
                        fuse_interrupt_func_t func;
 
44
                        void *data;
 
45
                } ni;
 
46
        } u;
 
47
        struct fuse_req *next;
 
48
        struct fuse_req *prev;
49
49
};
50
50
 
51
51
struct fuse_ll {
52
 
    int debug;
53
 
    int allow_root;
54
 
    struct fuse_lowlevel_ops op;
55
 
    int got_init;
56
 
    void *userdata;
57
 
    uid_t owner;
58
 
    struct fuse_conn_info conn;
59
 
    struct fuse_req list;
60
 
    struct fuse_req interrupts;
61
 
    pthread_mutex_t lock;
62
 
    int got_destroy;
 
52
        int debug;
 
53
        int allow_root;
 
54
        struct fuse_lowlevel_ops op;
 
55
        int got_init;
 
56
        void *userdata;
 
57
        uid_t owner;
 
58
        struct fuse_conn_info conn;
 
59
        struct fuse_req list;
 
60
        struct fuse_req interrupts;
 
61
        pthread_mutex_t lock;
 
62
        int got_destroy;
63
63
};
64
64
 
65
65
static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
66
66
{
67
 
    attr->ino       = stbuf->st_ino;
68
 
    attr->mode      = stbuf->st_mode;
69
 
    attr->nlink     = stbuf->st_nlink;
70
 
    attr->uid       = stbuf->st_uid;
71
 
    attr->gid       = stbuf->st_gid;
72
 
    attr->rdev      = stbuf->st_rdev;
73
 
    attr->size      = stbuf->st_size;
74
 
    attr->blocks    = stbuf->st_blocks;
75
 
    attr->atime     = stbuf->st_atime;
76
 
    attr->mtime     = stbuf->st_mtime;
77
 
    attr->ctime     = stbuf->st_ctime;
78
 
    attr->atimensec = ST_ATIM_NSEC(stbuf);
79
 
    attr->mtimensec = ST_MTIM_NSEC(stbuf);
80
 
    attr->ctimensec = ST_CTIM_NSEC(stbuf);
 
67
        attr->ino       = stbuf->st_ino;
 
68
        attr->mode      = stbuf->st_mode;
 
69
        attr->nlink     = stbuf->st_nlink;
 
70
        attr->uid       = stbuf->st_uid;
 
71
        attr->gid       = stbuf->st_gid;
 
72
        attr->rdev      = stbuf->st_rdev;
 
73
        attr->size      = stbuf->st_size;
 
74
        attr->blocks    = stbuf->st_blocks;
 
75
        attr->atime     = stbuf->st_atime;
 
76
        attr->mtime     = stbuf->st_mtime;
 
77
        attr->ctime     = stbuf->st_ctime;
 
78
        attr->atimensec = ST_ATIM_NSEC(stbuf);
 
79
        attr->mtimensec = ST_MTIM_NSEC(stbuf);
 
80
        attr->ctimensec = ST_CTIM_NSEC(stbuf);
81
81
}
82
82
 
83
83
static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf)
84
84
{
85
 
    stbuf->st_mode         = attr->mode;
86
 
    stbuf->st_uid          = attr->uid;
87
 
    stbuf->st_gid          = attr->gid;
88
 
    stbuf->st_size         = attr->size;
89
 
    stbuf->st_atime        = attr->atime;
90
 
    stbuf->st_mtime        = attr->mtime;
91
 
    ST_ATIM_NSEC_SET(stbuf, attr->atimensec);
92
 
    ST_MTIM_NSEC_SET(stbuf, attr->mtimensec);
 
85
        stbuf->st_mode         = attr->mode;
 
86
        stbuf->st_uid          = attr->uid;
 
87
        stbuf->st_gid          = attr->gid;
 
88
        stbuf->st_size         = attr->size;
 
89
        stbuf->st_atime        = attr->atime;
 
90
        stbuf->st_mtime        = attr->mtime;
 
91
        ST_ATIM_NSEC_SET(stbuf, attr->atimensec);
 
92
        ST_MTIM_NSEC_SET(stbuf, attr->mtimensec);
93
93
}
94
94
 
95
 
static  size_t iov_length(const struct iovec *iov, size_t count)
 
95
static  size_t iov_length(const struct iovec *iov, size_t count)
96
96
{
97
 
    size_t seg;
98
 
    size_t ret = 0;
 
97
        size_t seg;
 
98
        size_t ret = 0;
99
99
 
100
 
    for (seg = 0; seg < count; seg++)
101
 
        ret += iov[seg].iov_len;
102
 
    return ret;
 
100
        for (seg = 0; seg < count; seg++)
 
101
                ret += iov[seg].iov_len;
 
102
        return ret;
103
103
}
104
104
 
105
105
static void list_init_req(struct fuse_req *req)
106
106
{
107
 
    req->next = req;
108
 
    req->prev = req;
 
107
        req->next = req;
 
108
        req->prev = req;
109
109
}
110
110
 
111
111
static void list_del_req(struct fuse_req *req)
112
112
{
113
 
    struct fuse_req *prev = req->prev;
114
 
    struct fuse_req *next = req->next;
115
 
    prev->next = next;
116
 
    next->prev = prev;
 
113
        struct fuse_req *prev = req->prev;
 
114
        struct fuse_req *next = req->next;
 
115
        prev->next = next;
 
116
        next->prev = prev;
117
117
}
118
118
 
119
119
static void list_add_req(struct fuse_req *req, struct fuse_req *next)
120
120
{
121
 
    struct fuse_req *prev = next->prev;
122
 
    req->next = next;
123
 
    req->prev = prev;
124
 
    prev->next = req;
125
 
    next->prev = req;
 
121
        struct fuse_req *prev = next->prev;
 
122
        req->next = next;
 
123
        req->prev = prev;
 
124
        prev->next = req;
 
125
        next->prev = req;
126
126
}
127
127
 
128
128
static void destroy_req(fuse_req_t req)
129
129
{
130
 
    pthread_mutex_destroy(&req->lock);
131
 
    free(req);
 
130
        pthread_mutex_destroy(&req->lock);
 
131
        free(req);
132
132
}
133
133
 
134
134
static void free_req(fuse_req_t req)
135
135
{
136
 
    int ctr;
137
 
    struct fuse_ll *f = req->f;
138
 
 
139
 
    pthread_mutex_lock(&req->lock);
140
 
    req->u.ni.func = NULL;
141
 
    req->u.ni.data = NULL;
142
 
    pthread_mutex_unlock(&req->lock);
143
 
 
144
 
    pthread_mutex_lock(&f->lock);
145
 
    list_del_req(req);
146
 
    ctr = --req->ctr;
147
 
    pthread_mutex_unlock(&f->lock);
148
 
    if (!ctr)
149
 
        destroy_req(req);
 
136
        int ctr;
 
137
        struct fuse_ll *f = req->f;
 
138
 
 
139
        pthread_mutex_lock(&req->lock);
 
140
        req->u.ni.func = NULL;
 
141
        req->u.ni.data = NULL;
 
142
        pthread_mutex_unlock(&req->lock);
 
143
 
 
144
        pthread_mutex_lock(&f->lock);
 
145
        list_del_req(req);
 
146
        ctr = --req->ctr;
 
147
        pthread_mutex_unlock(&f->lock);
 
148
        if (!ctr)
 
149
                destroy_req(req);
150
150
}
151
151
 
152
152
static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
153
 
                          int count)
 
153
                          int count)
154
154
{
155
 
    struct fuse_out_header out;
156
 
    int res;
157
 
 
158
 
    if (error <= -1000 || error > 0) {
159
 
        fprintf(stderr, "fuse: bad error value: %i\n",  error);
160
 
        error = -ERANGE;
161
 
    }
162
 
 
163
 
    out.unique = req->unique;
164
 
    out.error = error;
165
 
    iov[0].iov_base = &out;
166
 
    iov[0].iov_len = sizeof(struct fuse_out_header);
167
 
    out.len = iov_length(iov, count);
168
 
 
169
 
    if (req->f->debug)
170
 
        fprintf(stderr, "   unique: %llu, error: %i (%s), outsize: %i\n",
171
 
                (unsigned long long) out.unique, out.error,
172
 
                strerror(-out.error), out.len);
173
 
    res = fuse_chan_send(req->ch, iov, count);
174
 
    free_req(req);
175
 
 
176
 
    return res;
 
155
        struct fuse_out_header out;
 
156
        int res;
 
157
 
 
158
        if (error <= -1000 || error > 0) {
 
159
                fprintf(stderr, "fuse: bad error value: %i\n",  error);
 
160
                error = -ERANGE;
 
161
        }
 
162
 
 
163
        out.unique = req->unique;
 
164
        out.error = error;
 
165
        iov[0].iov_base = &out;
 
166
        iov[0].iov_len = sizeof(struct fuse_out_header);
 
167
        out.len = iov_length(iov, count);
 
168
 
 
169
        if (req->f->debug)
 
170
                fprintf(stderr,
 
171
                        "   unique: %llu, error: %i (%s), outsize: %i\n",
 
172
                        (unsigned long long) out.unique, out.error,
 
173
                        strerror(-out.error), out.len);
 
174
        res = fuse_chan_send(req->ch, iov, count);
 
175
        free_req(req);
 
176
 
 
177
        return res;
177
178
}
178
179
 
179
180
static int send_reply(fuse_req_t req, int error, const void *arg,
180
 
                      size_t argsize)
 
181
                      size_t argsize)
181
182
{
182
 
    struct iovec iov[2];
183
 
    int count = 1;
184
 
    if (argsize) {
185
 
        iov[1].iov_base = (void *) arg;
186
 
        iov[1].iov_len = argsize;
187
 
        count++;
188
 
    }
189
 
    return send_reply_iov(req, error, iov, count);
 
183
        struct iovec iov[2];
 
184
        int count = 1;
 
185
        if (argsize) {
 
186
                iov[1].iov_base = (void *) arg;
 
187
                iov[1].iov_len = argsize;
 
188
                count++;
 
189
        }
 
190
        return send_reply_iov(req, error, iov, count);
190
191
}
191
192
 
192
193
int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count)
193
194
{
194
 
    int res;
195
 
    struct iovec *padded_iov;
196
 
 
197
 
    padded_iov = malloc((count + 1) * sizeof(struct iovec));
198
 
    if (padded_iov == NULL)
199
 
        return fuse_reply_err(req, -ENOMEM);
200
 
 
201
 
    memcpy(padded_iov + 1, iov, count * sizeof(struct iovec));
202
 
    count++;
203
 
 
204
 
    res = send_reply_iov(req, 0, padded_iov, count);
205
 
    free(padded_iov);
206
 
 
207
 
    return res;
 
195
        int res;
 
196
        struct iovec *padded_iov;
 
197
 
 
198
        padded_iov = malloc((count + 1) * sizeof(struct iovec));
 
199
        if (padded_iov == NULL)
 
200
                return fuse_reply_err(req, -ENOMEM);
 
201
 
 
202
        memcpy(padded_iov + 1, iov, count * sizeof(struct iovec));
 
203
        count++;
 
204
 
 
205
        res = send_reply_iov(req, 0, padded_iov, count);
 
206
        free(padded_iov);
 
207
 
 
208
        return res;
208
209
}
209
210
 
210
211
size_t fuse_dirent_size(size_t namelen)
211
212
{
212
 
    return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen);
 
213
        return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen);
213
214
}
214
215
 
215
216
char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
216
 
                      off_t off)
 
217
                      off_t off)
217
218
{
218
 
    unsigned namelen = strlen(name);
219
 
    unsigned entlen = FUSE_NAME_OFFSET + namelen;
220
 
    unsigned entsize = fuse_dirent_size(namelen);
221
 
    unsigned padlen = entsize - entlen;
222
 
    struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
223
 
 
224
 
    dirent->ino = stbuf->st_ino;
225
 
    dirent->off = off;
226
 
    dirent->namelen = namelen;
227
 
    dirent->type = (stbuf->st_mode & 0170000) >> 12;
228
 
    strncpy(dirent->name, name, namelen);
229
 
    if (padlen)
230
 
        memset(buf + entlen, 0, padlen);
231
 
 
232
 
    return buf + entsize;
 
219
        unsigned namelen = strlen(name);
 
220
        unsigned entlen = FUSE_NAME_OFFSET + namelen;
 
221
        unsigned entsize = fuse_dirent_size(namelen);
 
222
        unsigned padlen = entsize - entlen;
 
223
        struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
 
224
 
 
225
        dirent->ino = stbuf->st_ino;
 
226
        dirent->off = off;
 
227
        dirent->namelen = namelen;
 
228
        dirent->type = (stbuf->st_mode & 0170000) >> 12;
 
229
        strncpy(dirent->name, name, namelen);
 
230
        if (padlen)
 
231
                memset(buf + entlen, 0, padlen);
 
232
 
 
233
        return buf + entsize;
233
234
}
234
235
 
235
236
size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
236
 
                         const char *name, const struct stat *stbuf, off_t off)
 
237
                         const char *name, const struct stat *stbuf, off_t off)
237
238
{
238
 
    size_t entsize;
 
239
        size_t entsize;
239
240
 
240
 
    (void) req;
241
 
    entsize = fuse_dirent_size(strlen(name));
242
 
    if (entsize <= bufsize && buf)
243
 
        fuse_add_dirent(buf, name, stbuf, off);
244
 
    return entsize;
 
241
        (void) req;
 
242
        entsize = fuse_dirent_size(strlen(name));
 
243
        if (entsize <= bufsize && buf)
 
244
                fuse_add_dirent(buf, name, stbuf, off);
 
245
        return entsize;
245
246
}
246
247
 
247
248
static void convert_statfs(const struct statvfs *stbuf,
248
 
                           struct fuse_kstatfs *kstatfs)
 
249
                           struct fuse_kstatfs *kstatfs)
249
250
{
250
 
    kstatfs->bsize      = stbuf->f_bsize;
251
 
    kstatfs->frsize     = stbuf->f_frsize;
252
 
    kstatfs->blocks     = stbuf->f_blocks;
253
 
    kstatfs->bfree      = stbuf->f_bfree;
254
 
    kstatfs->bavail     = stbuf->f_bavail;
255
 
    kstatfs->files      = stbuf->f_files;
256
 
    kstatfs->ffree      = stbuf->f_ffree;
257
 
    kstatfs->namelen    = stbuf->f_namemax;
 
251
        kstatfs->bsize   = stbuf->f_bsize;
 
252
        kstatfs->frsize  = stbuf->f_frsize;
 
253
        kstatfs->blocks  = stbuf->f_blocks;
 
254
        kstatfs->bfree   = stbuf->f_bfree;
 
255
        kstatfs->bavail  = stbuf->f_bavail;
 
256
        kstatfs->files   = stbuf->f_files;
 
257
        kstatfs->ffree   = stbuf->f_ffree;
 
258
        kstatfs->namelen = stbuf->f_namemax;
258
259
}
259
260
 
260
261
static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize)
261
262
{
262
 
    return send_reply(req, 0, arg, argsize);
 
263
        return send_reply(req, 0, arg, argsize);
263
264
}
264
265
 
265
266
int fuse_reply_err(fuse_req_t req, int err)
266
267
{
267
 
    return send_reply(req, -err, NULL, 0);
 
268
        return send_reply(req, -err, NULL, 0);
268
269
}
269
270
 
270
271
void fuse_reply_none(fuse_req_t req)
271
272
{
272
 
    fuse_chan_send(req->ch, NULL, 0);
273
 
    free_req(req);
 
273
        fuse_chan_send(req->ch, NULL, 0);
 
274
        free_req(req);
274
275
}
275
276
 
276
277
static unsigned long calc_timeout_sec(double t)
277
278
{
278
 
    if (t > (double) ULONG_MAX)
279
 
        return ULONG_MAX;
280
 
    else if (t < 0.0)
281
 
        return 0;
282
 
    else
283
 
        return (unsigned long) t;
 
279
        if (t > (double) ULONG_MAX)
 
280
                return ULONG_MAX;
 
281
        else if (t < 0.0)
 
282
                return 0;
 
283
        else
 
284
                return (unsigned long) t;
284
285
}
285
286
 
286
287
static unsigned int calc_timeout_nsec(double t)
287
288
{
288
 
    double f = t - (double) calc_timeout_sec(t);
289
 
    if (f < 0.0)
290
 
        return 0;
291
 
    else if (f >= 0.999999999)
292
 
        return 999999999;
293
 
    else
294
 
        return (unsigned int) (f * 1.0e9);
 
289
        double f = t - (double) calc_timeout_sec(t);
 
290
        if (f < 0.0)
 
291
                return 0;
 
292
        else if (f >= 0.999999999)
 
293
                return 999999999;
 
294
        else
 
295
                return (unsigned int) (f * 1.0e9);
295
296
}
296
297
 
297
298
static void fill_entry(struct fuse_entry_out *arg,
298
 
                       const struct fuse_entry_param *e)
 
299
                       const struct fuse_entry_param *e)
299
300
{
300
 
    arg->nodeid = e->ino;
301
 
    arg->generation = e->generation;
302
 
    arg->entry_valid = calc_timeout_sec(e->entry_timeout);
303
 
    arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout);
304
 
    arg->attr_valid = calc_timeout_sec(e->attr_timeout);
305
 
    arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout);
306
 
    convert_stat(&e->attr, &arg->attr);
 
301
        arg->nodeid = e->ino;
 
302
        arg->generation = e->generation;
 
303
        arg->entry_valid = calc_timeout_sec(e->entry_timeout);
 
304
        arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout);
 
305
        arg->attr_valid = calc_timeout_sec(e->attr_timeout);
 
306
        arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout);
 
307
        convert_stat(&e->attr, &arg->attr);
307
308
}
308
309
 
309
310
static void fill_open(struct fuse_open_out *arg,
310
 
                      const struct fuse_file_info *f)
 
311
                      const struct fuse_file_info *f)
311
312
{
312
 
    arg->fh = f->fh;
313
 
    if (f->direct_io)
314
 
        arg->open_flags |= FOPEN_DIRECT_IO;
315
 
    if (f->keep_cache)
316
 
        arg->open_flags |= FOPEN_KEEP_CACHE;
 
313
        arg->fh = f->fh;
 
314
        if (f->direct_io)
 
315
                arg->open_flags |= FOPEN_DIRECT_IO;
 
316
        if (f->keep_cache)
 
317
                arg->open_flags |= FOPEN_KEEP_CACHE;
317
318
}
318
319
 
319
320
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
320
321
{
321
 
    struct fuse_entry_out arg;
322
 
 
323
 
    /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
324
 
       negative entry */
325
 
    if (!e->ino && req->f->conn.proto_minor < 4)
326
 
        return fuse_reply_err(req, ENOENT);
327
 
 
328
 
    memset(&arg, 0, sizeof(arg));
329
 
    fill_entry(&arg, e);
330
 
    return send_reply_ok(req, &arg, sizeof(arg));
 
322
        struct fuse_entry_out arg;
 
323
 
 
324
        /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
 
325
           negative entry */
 
326
        if (!e->ino && req->f->conn.proto_minor < 4)
 
327
                return fuse_reply_err(req, ENOENT);
 
328
 
 
329
        memset(&arg, 0, sizeof(arg));
 
330
        fill_entry(&arg, e);
 
331
        return send_reply_ok(req, &arg, sizeof(arg));
331
332
}
332
333
 
333
334
int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
334
 
                      const struct fuse_file_info *f)
 
335
                      const struct fuse_file_info *f)
335
336
{
336
 
    struct {
337
 
        struct fuse_entry_out e;
338
 
        struct fuse_open_out o;
339
 
    } arg;
 
337
        struct {
 
338
                struct fuse_entry_out e;
 
339
                struct fuse_open_out o;
 
340
        } arg;
340
341
 
341
 
    memset(&arg, 0, sizeof(arg));
342
 
    fill_entry(&arg.e, e);
343
 
    fill_open(&arg.o, f);
344
 
    return send_reply_ok(req, &arg, sizeof(arg));
 
342
        memset(&arg, 0, sizeof(arg));
 
343
        fill_entry(&arg.e, e);
 
344
        fill_open(&arg.o, f);
 
345
        return send_reply_ok(req, &arg, sizeof(arg));
345
346
}
346
347
 
347
348
int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
348
 
                    double attr_timeout)
 
349
                    double attr_timeout)
349
350
{
350
 
    struct fuse_attr_out arg;
351
 
 
352
 
    memset(&arg, 0, sizeof(arg));
353
 
    arg.attr_valid = calc_timeout_sec(attr_timeout);
354
 
    arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
355
 
    convert_stat(attr, &arg.attr);
356
 
 
357
 
    return send_reply_ok(req, &arg, sizeof(arg));
 
351
        struct fuse_attr_out arg;
 
352
 
 
353
        memset(&arg, 0, sizeof(arg));
 
354
        arg.attr_valid = calc_timeout_sec(attr_timeout);
 
355
        arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
 
356
        convert_stat(attr, &arg.attr);
 
357
 
 
358
        return send_reply_ok(req, &arg, sizeof(arg));
358
359
}
359
360
 
360
361
int fuse_reply_readlink(fuse_req_t req, const char *linkname)
361
362
{
362
 
    return send_reply_ok(req, linkname, strlen(linkname));
 
363
        return send_reply_ok(req, linkname, strlen(linkname));
363
364
}
364
365
 
365
366
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f)
366
367
{
367
 
    struct fuse_open_out arg;
 
368
        struct fuse_open_out arg;
368
369
 
369
 
    memset(&arg, 0, sizeof(arg));
370
 
    fill_open(&arg, f);
371
 
    return send_reply_ok(req, &arg, sizeof(arg));
 
370
        memset(&arg, 0, sizeof(arg));
 
371
        fill_open(&arg, f);
 
372
        return send_reply_ok(req, &arg, sizeof(arg));
372
373
}
373
374
 
374
375
int fuse_reply_write(fuse_req_t req, size_t count)
375
376
{
376
 
    struct fuse_write_out arg;
377
 
 
378
 
    memset(&arg, 0, sizeof(arg));
379
 
    arg.size = count;
380
 
 
381
 
    return send_reply_ok(req, &arg, sizeof(arg));
 
377
        struct fuse_write_out arg;
 
378
 
 
379
        memset(&arg, 0, sizeof(arg));
 
380
        arg.size = count;
 
381
 
 
382
        return send_reply_ok(req, &arg, sizeof(arg));
382
383
}
383
384
 
384
385
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
385
386
{
386
 
    return send_reply_ok(req, buf, size);
 
387
        return send_reply_ok(req, buf, size);
387
388
}
388
389
 
389
390
int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
390
391
{
391
 
    struct fuse_statfs_out arg;
392
 
    size_t size = req->f->conn.proto_minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
393
 
 
394
 
    memset(&arg, 0, sizeof(arg));
395
 
    convert_statfs(stbuf, &arg.st);
396
 
 
397
 
    return send_reply_ok(req, &arg, size);
 
392
        struct fuse_statfs_out arg;
 
393
        size_t size = req->f->conn.proto_minor < 4 ?
 
394
                FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
 
395
 
 
396
        memset(&arg, 0, sizeof(arg));
 
397
        convert_statfs(stbuf, &arg.st);
 
398
 
 
399
        return send_reply_ok(req, &arg, size);
398
400
}
399
401
 
400
402
int fuse_reply_xattr(fuse_req_t req, size_t count)
401
403
{
402
 
    struct fuse_getxattr_out arg;
403
 
 
404
 
    memset(&arg, 0, sizeof(arg));
405
 
    arg.size = count;
406
 
 
407
 
    return send_reply_ok(req, &arg, sizeof(arg));
 
404
        struct fuse_getxattr_out arg;
 
405
 
 
406
        memset(&arg, 0, sizeof(arg));
 
407
        arg.size = count;
 
408
 
 
409
        return send_reply_ok(req, &arg, sizeof(arg));
408
410
}
409
411
 
410
412
int fuse_reply_lock(fuse_req_t req, struct flock *lock)
411
413
{
412
 
    struct fuse_lk_out arg;
 
414
        struct fuse_lk_out arg;
413
415
 
414
 
    memset(&arg, 0, sizeof(arg));
415
 
    arg.lk.type = lock->l_type;
416
 
    if (lock->l_type != F_UNLCK) {
417
 
        arg.lk.start = lock->l_start;
418
 
        if (lock->l_len == 0)
419
 
            arg.lk.end = OFFSET_MAX;
420
 
        else
421
 
            arg.lk.end = lock->l_start + lock->l_len - 1;
422
 
    }
423
 
    arg.lk.pid = lock->l_pid;
424
 
    return send_reply_ok(req, &arg, sizeof(arg));
 
416
        memset(&arg, 0, sizeof(arg));
 
417
        arg.lk.type = lock->l_type;
 
418
        if (lock->l_type != F_UNLCK) {
 
419
                arg.lk.start = lock->l_start;
 
420
                if (lock->l_len == 0)
 
421
                        arg.lk.end = OFFSET_MAX;
 
422
                else
 
423
                        arg.lk.end = lock->l_start + lock->l_len - 1;
 
424
        }
 
425
        arg.lk.pid = lock->l_pid;
 
426
        return send_reply_ok(req, &arg, sizeof(arg));
425
427
}
426
428
 
427
429
int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
428
430
{
429
 
    struct fuse_bmap_out arg;
430
 
 
431
 
    memset(&arg, 0, sizeof(arg));
432
 
    arg.block = idx;
433
 
 
434
 
    return send_reply_ok(req, &arg, sizeof(arg));
 
431
        struct fuse_bmap_out arg;
 
432
 
 
433
        memset(&arg, 0, sizeof(arg));
 
434
        arg.block = idx;
 
435
 
 
436
        return send_reply_ok(req, &arg, sizeof(arg));
435
437
}
436
438
 
437
439
static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
438
440
{
439
 
    char *name = (char *) inarg;
 
441
        char *name = (char *) inarg;
440
442
 
441
 
    if (req->f->op.lookup)
442
 
        req->f->op.lookup(req, nodeid, name);
443
 
    else
444
 
        fuse_reply_err(req, ENOSYS);
 
443
        if (req->f->op.lookup)
 
444
                req->f->op.lookup(req, nodeid, name);
 
445
        else
 
446
                fuse_reply_err(req, ENOSYS);
445
447
}
446
448
 
447
449
static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
448
450
{
449
 
    struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg;
 
451
        struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg;
450
452
 
451
 
    if (req->f->op.forget)
452
 
        req->f->op.forget(req, nodeid, arg->nlookup);
453
 
    else
454
 
        fuse_reply_none(req);
 
453
        if (req->f->op.forget)
 
454
                req->f->op.forget(req, nodeid, arg->nlookup);
 
455
        else
 
456
                fuse_reply_none(req);
455
457
}
456
458
 
457
459
static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
458
460
{
459
 
    (void) inarg;
 
461
        (void) inarg;
460
462
 
461
 
    if (req->f->op.getattr)
462
 
        req->f->op.getattr(req, nodeid, NULL);
463
 
    else
464
 
        fuse_reply_err(req, ENOSYS);
 
463
        if (req->f->op.getattr)
 
464
                req->f->op.getattr(req, nodeid, NULL);
 
465
        else
 
466
                fuse_reply_err(req, ENOSYS);
465
467
}
466
468
 
467
469
static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
468
470
{
469
 
    struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg;
 
471
        struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg;
470
472
 
471
 
    if (req->f->op.setattr) {
472
 
        struct fuse_file_info *fi = NULL;
473
 
        struct fuse_file_info fi_store;
474
 
        struct stat stbuf;
475
 
        memset(&stbuf, 0, sizeof(stbuf));
476
 
        convert_attr(arg, &stbuf);
477
 
        if (arg->valid & FATTR_FH) {
478
 
            arg->valid &= ~FATTR_FH;
479
 
            memset(&fi_store, 0, sizeof(fi_store));
480
 
            fi = &fi_store;
481
 
            fi->fh = arg->fh;
482
 
            fi->fh_old = fi->fh;
483
 
        }
484
 
        req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
485
 
    } else
486
 
        fuse_reply_err(req, ENOSYS);
 
473
        if (req->f->op.setattr) {
 
474
                struct fuse_file_info *fi = NULL;
 
475
                struct fuse_file_info fi_store;
 
476
                struct stat stbuf;
 
477
                memset(&stbuf, 0, sizeof(stbuf));
 
478
                convert_attr(arg, &stbuf);
 
479
                if (arg->valid & FATTR_FH) {
 
480
                        arg->valid &= ~FATTR_FH;
 
481
                        memset(&fi_store, 0, sizeof(fi_store));
 
482
                        fi = &fi_store;
 
483
                        fi->fh = arg->fh;
 
484
                        fi->fh_old = fi->fh;
 
485
                }
 
486
                req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
 
487
        } else
 
488
                fuse_reply_err(req, ENOSYS);
487
489
}
488
490
 
489
491
static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
490
492
{
491
 
    struct fuse_access_in *arg = (struct fuse_access_in *) inarg;
 
493
        struct fuse_access_in *arg = (struct fuse_access_in *) inarg;
492
494
 
493
 
    if (req->f->op.access)
494
 
        req->f->op.access(req, nodeid, arg->mask);
495
 
    else
496
 
        fuse_reply_err(req, ENOSYS);
 
495
        if (req->f->op.access)
 
496
                req->f->op.access(req, nodeid, arg->mask);
 
497
        else
 
498
                fuse_reply_err(req, ENOSYS);
497
499
}
498
500
 
499
501
static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
500
502
{
501
 
    (void) inarg;
 
503
        (void) inarg;
502
504
 
503
 
    if (req->f->op.readlink)
504
 
        req->f->op.readlink(req, nodeid);
505
 
    else
506
 
        fuse_reply_err(req, ENOSYS);
 
505
        if (req->f->op.readlink)
 
506
                req->f->op.readlink(req, nodeid);
 
507
        else
 
508
                fuse_reply_err(req, ENOSYS);
507
509
}
508
510
 
509
511
static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
510
512
{
511
 
    struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg;
 
513
        struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg;
512
514
 
513
 
    if (req->f->op.mknod)
514
 
        req->f->op.mknod(req, nodeid, PARAM(arg), arg->mode, arg->rdev);
515
 
    else
516
 
        fuse_reply_err(req, ENOSYS);
 
515
        if (req->f->op.mknod)
 
516
                req->f->op.mknod(req, nodeid, PARAM(arg), arg->mode, arg->rdev);
 
517
        else
 
518
                fuse_reply_err(req, ENOSYS);
517
519
}
518
520
 
519
521
static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
520
522
{
521
 
    struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg;
 
523
        struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg;
522
524
 
523
 
    if (req->f->op.mkdir)
524
 
        req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
525
 
    else
526
 
        fuse_reply_err(req, ENOSYS);
 
525
        if (req->f->op.mkdir)
 
526
                req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
 
527
        else
 
528
                fuse_reply_err(req, ENOSYS);
527
529
}
528
530
 
529
531
static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
530
532
{
531
 
    char *name = (char *) inarg;
 
533
        char *name = (char *) inarg;
532
534
 
533
 
    if (req->f->op.unlink)
534
 
        req->f->op.unlink(req, nodeid, name);
535
 
    else
536
 
        fuse_reply_err(req, ENOSYS);
 
535
        if (req->f->op.unlink)
 
536
                req->f->op.unlink(req, nodeid, name);
 
537
        else
 
538
                fuse_reply_err(req, ENOSYS);
537
539
}
538
540
 
539
541
static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
540
542
{
541
 
    char *name = (char *) inarg;
 
543
        char *name = (char *) inarg;
542
544
 
543
 
    if (req->f->op.rmdir)
544
 
        req->f->op.rmdir(req, nodeid, name);
545
 
    else
546
 
        fuse_reply_err(req, ENOSYS);
 
545
        if (req->f->op.rmdir)
 
546
                req->f->op.rmdir(req, nodeid, name);
 
547
        else
 
548
                fuse_reply_err(req, ENOSYS);
547
549
}
548
550
 
549
551
static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
550
552
{
551
 
    char *name = (char *) inarg;
552
 
    char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1;
 
553
        char *name = (char *) inarg;
 
554
        char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1;
553
555
 
554
 
    if (req->f->op.symlink)
555
 
        req->f->op.symlink(req, linkname, nodeid, name);
556
 
    else
557
 
        fuse_reply_err(req, ENOSYS);
 
556
        if (req->f->op.symlink)
 
557
                req->f->op.symlink(req, linkname, nodeid, name);
 
558
        else
 
559
                fuse_reply_err(req, ENOSYS);
558
560
}
559
561
 
560
562
static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
561
563
{
562
 
    struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg;
563
 
    char *oldname = PARAM(arg);
564
 
    char *newname = oldname + strlen(oldname) + 1;
 
564
        struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg;
 
565
        char *oldname = PARAM(arg);
 
566
        char *newname = oldname + strlen(oldname) + 1;
565
567
 
566
 
    if (req->f->op.rename)
567
 
        req->f->op.rename(req, nodeid, oldname, arg->newdir, newname);
568
 
    else
569
 
        fuse_reply_err(req, ENOSYS);
 
568
        if (req->f->op.rename)
 
569
                req->f->op.rename(req, nodeid, oldname, arg->newdir, newname);
 
570
        else
 
571
                fuse_reply_err(req, ENOSYS);
570
572
}
571
573
 
572
574
static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
573
575
{
574
 
    struct fuse_link_in *arg = (struct fuse_link_in *) inarg;
 
576
        struct fuse_link_in *arg = (struct fuse_link_in *) inarg;
575
577
 
576
 
    if (req->f->op.link)
577
 
        req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
578
 
    else
579
 
        fuse_reply_err(req, ENOSYS);
 
578
        if (req->f->op.link)
 
579
                req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
 
580
        else
 
581
                fuse_reply_err(req, ENOSYS);
580
582
}
581
583
 
582
584
static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
583
585
{
584
 
    struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
585
 
 
586
 
    if (req->f->op.create) {
587
 
        struct fuse_file_info fi;
588
 
 
589
 
        memset(&fi, 0, sizeof(fi));
590
 
        fi.flags = arg->flags;
591
 
 
592
 
        req->f->op.create(req, nodeid, PARAM(arg), arg->mode, &fi);
593
 
    } else
594
 
        fuse_reply_err(req, ENOSYS);
 
586
        struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
 
587
 
 
588
        if (req->f->op.create) {
 
589
                struct fuse_file_info fi;
 
590
 
 
591
                memset(&fi, 0, sizeof(fi));
 
592
                fi.flags = arg->flags;
 
593
 
 
594
                req->f->op.create(req, nodeid, PARAM(arg), arg->mode, &fi);
 
595
        } else
 
596
                fuse_reply_err(req, ENOSYS);
595
597
}
596
598
 
597
599
static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
598
600
{
599
 
    struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
600
 
    struct fuse_file_info fi;
601
 
 
602
 
    memset(&fi, 0, sizeof(fi));
603
 
    fi.flags = arg->flags;
604
 
 
605
 
    if (req->f->op.open)
606
 
        req->f->op.open(req, nodeid, &fi);
607
 
    else
608
 
        fuse_reply_open(req, &fi);
 
601
        struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
 
602
        struct fuse_file_info fi;
 
603
 
 
604
        memset(&fi, 0, sizeof(fi));
 
605
        fi.flags = arg->flags;
 
606
 
 
607
        if (req->f->op.open)
 
608
                req->f->op.open(req, nodeid, &fi);
 
609
        else
 
610
                fuse_reply_open(req, &fi);
609
611
}
610
612
 
611
613
static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
612
614
{
613
 
    struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
614
 
 
615
 
    if (req->f->op.read) {
616
 
        struct fuse_file_info fi;
617
 
 
618
 
        memset(&fi, 0, sizeof(fi));
619
 
        fi.fh = arg->fh;
620
 
        fi.fh_old = fi.fh;
621
 
        req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
622
 
    } else
623
 
        fuse_reply_err(req, ENOSYS);
 
615
        struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
 
616
 
 
617
        if (req->f->op.read) {
 
618
                struct fuse_file_info fi;
 
619
 
 
620
                memset(&fi, 0, sizeof(fi));
 
621
                fi.fh = arg->fh;
 
622
                fi.fh_old = fi.fh;
 
623
                req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
 
624
        } else
 
625
                fuse_reply_err(req, ENOSYS);
624
626
}
625
627
 
626
628
static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
627
629
{
628
 
    struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
629
 
    struct fuse_file_info fi;
630
 
 
631
 
    memset(&fi, 0, sizeof(fi));
632
 
    fi.fh = arg->fh;
633
 
    fi.fh_old = fi.fh;
634
 
    fi.writepage = arg->write_flags & 1;
635
 
 
636
 
    if (req->f->op.write)
637
 
        req->f->op.write(req, nodeid, PARAM(arg), arg->size, arg->offset, &fi);
638
 
    else
639
 
        fuse_reply_err(req, ENOSYS);
 
630
        struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
 
631
        struct fuse_file_info fi;
 
632
 
 
633
        memset(&fi, 0, sizeof(fi));
 
634
        fi.fh = arg->fh;
 
635
        fi.fh_old = fi.fh;
 
636
        fi.writepage = arg->write_flags & 1;
 
637
 
 
638
        if (req->f->op.write)
 
639
                req->f->op.write(req, nodeid, PARAM(arg), arg->size,
 
640
                                 arg->offset, &fi);
 
641
        else
 
642
                fuse_reply_err(req, ENOSYS);
640
643
}
641
644
 
642
645
static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
643
646
{
644
 
    struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg;
645
 
    struct fuse_file_info fi;
646
 
 
647
 
    memset(&fi, 0, sizeof(fi));
648
 
    fi.fh = arg->fh;
649
 
    fi.fh_old = fi.fh;
650
 
    fi.flush = 1;
651
 
    if (req->f->conn.proto_minor >= 7)
652
 
        fi.lock_owner = arg->lock_owner;
653
 
 
654
 
    if (req->f->op.flush)
655
 
        req->f->op.flush(req, nodeid, &fi);
656
 
    else
657
 
        fuse_reply_err(req, ENOSYS);
 
647
        struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg;
 
648
        struct fuse_file_info fi;
 
649
 
 
650
        memset(&fi, 0, sizeof(fi));
 
651
        fi.fh = arg->fh;
 
652
        fi.fh_old = fi.fh;
 
653
        fi.flush = 1;
 
654
        if (req->f->conn.proto_minor >= 7)
 
655
                fi.lock_owner = arg->lock_owner;
 
656
 
 
657
        if (req->f->op.flush)
 
658
                req->f->op.flush(req, nodeid, &fi);
 
659
        else
 
660
                fuse_reply_err(req, ENOSYS);
658
661
}
659
662
 
660
663
static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
661
664
{
662
 
    struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
663
 
    struct fuse_file_info fi;
664
 
 
665
 
    memset(&fi, 0, sizeof(fi));
666
 
    fi.flags = arg->flags;
667
 
    fi.fh = arg->fh;
668
 
    fi.fh_old = fi.fh;
669
 
    if (req->f->conn.proto_minor >= 8) {
670
 
        fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
671
 
        fi.lock_owner = arg->lock_owner;
672
 
    }
673
 
 
674
 
    if (req->f->op.release)
675
 
        req->f->op.release(req, nodeid, &fi);
676
 
    else
677
 
        fuse_reply_err(req, 0);
 
665
        struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
 
666
        struct fuse_file_info fi;
 
667
 
 
668
        memset(&fi, 0, sizeof(fi));
 
669
        fi.flags = arg->flags;
 
670
        fi.fh = arg->fh;
 
671
        fi.fh_old = fi.fh;
 
672
        if (req->f->conn.proto_minor >= 8) {
 
673
                fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
 
674
                fi.lock_owner = arg->lock_owner;
 
675
        }
 
676
 
 
677
        if (req->f->op.release)
 
678
                req->f->op.release(req, nodeid, &fi);
 
679
        else
 
680
                fuse_reply_err(req, 0);
678
681
}
679
682
 
680
683
static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
681
684
{
682
 
    struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
683
 
    struct fuse_file_info fi;
684
 
 
685
 
    memset(&fi, 0, sizeof(fi));
686
 
    fi.fh = arg->fh;
687
 
    fi.fh_old = fi.fh;
688
 
 
689
 
    if (req->f->op.fsync)
690
 
        req->f->op.fsync(req, nodeid, arg->fsync_flags & 1, &fi);
691
 
    else
692
 
        fuse_reply_err(req, ENOSYS);
 
685
        struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
 
686
        struct fuse_file_info fi;
 
687
 
 
688
        memset(&fi, 0, sizeof(fi));
 
689
        fi.fh = arg->fh;
 
690
        fi.fh_old = fi.fh;
 
691
 
 
692
        if (req->f->op.fsync)
 
693
                req->f->op.fsync(req, nodeid, arg->fsync_flags & 1, &fi);
 
694
        else
 
695
                fuse_reply_err(req, ENOSYS);
693
696
}
694
697
 
695
698
static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
696
699
{
697
 
    struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
698
 
    struct fuse_file_info fi;
699
 
 
700
 
    memset(&fi, 0, sizeof(fi));
701
 
    fi.flags = arg->flags;
702
 
 
703
 
    if (req->f->op.opendir)
704
 
        req->f->op.opendir(req, nodeid, &fi);
705
 
    else
706
 
        fuse_reply_open(req, &fi);
 
700
        struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
 
701
        struct fuse_file_info fi;
 
702
 
 
703
        memset(&fi, 0, sizeof(fi));
 
704
        fi.flags = arg->flags;
 
705
 
 
706
        if (req->f->op.opendir)
 
707
                req->f->op.opendir(req, nodeid, &fi);
 
708
        else
 
709
                fuse_reply_open(req, &fi);
707
710
}
708
711
 
709
712
static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
710
713
{
711
 
    struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
712
 
    struct fuse_file_info fi;
713
 
 
714
 
    memset(&fi, 0, sizeof(fi));
715
 
    fi.fh = arg->fh;
716
 
    fi.fh_old = fi.fh;
717
 
 
718
 
    if (req->f->op.readdir)
719
 
        req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
720
 
    else
721
 
        fuse_reply_err(req, ENOSYS);
 
714
        struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
 
715
        struct fuse_file_info fi;
 
716
 
 
717
        memset(&fi, 0, sizeof(fi));
 
718
        fi.fh = arg->fh;
 
719
        fi.fh_old = fi.fh;
 
720
 
 
721
        if (req->f->op.readdir)
 
722
                req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
 
723
        else
 
724
                fuse_reply_err(req, ENOSYS);
722
725
}
723
726
 
724
727
static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
725
728
{
726
 
    struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
727
 
    struct fuse_file_info fi;
728
 
 
729
 
    memset(&fi, 0, sizeof(fi));
730
 
    fi.flags = arg->flags;
731
 
    fi.fh = arg->fh;
732
 
    fi.fh_old = fi.fh;
733
 
 
734
 
    if (req->f->op.releasedir)
735
 
        req->f->op.releasedir(req, nodeid, &fi);
736
 
    else
737
 
        fuse_reply_err(req, 0);
 
729
        struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
 
730
        struct fuse_file_info fi;
 
731
 
 
732
        memset(&fi, 0, sizeof(fi));
 
733
        fi.flags = arg->flags;
 
734
        fi.fh = arg->fh;
 
735
        fi.fh_old = fi.fh;
 
736
 
 
737
        if (req->f->op.releasedir)
 
738
                req->f->op.releasedir(req, nodeid, &fi);
 
739
        else
 
740
                fuse_reply_err(req, 0);
738
741
}
739
742
 
740
743
static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
741
744
{
742
 
    struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
743
 
    struct fuse_file_info fi;
744
 
 
745
 
    memset(&fi, 0, sizeof(fi));
746
 
    fi.fh = arg->fh;
747
 
    fi.fh_old = fi.fh;
748
 
 
749
 
    if (req->f->op.fsyncdir)
750
 
        req->f->op.fsyncdir(req, nodeid, arg->fsync_flags & 1, &fi);
751
 
    else
752
 
        fuse_reply_err(req, ENOSYS);
 
745
        struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
 
746
        struct fuse_file_info fi;
 
747
 
 
748
        memset(&fi, 0, sizeof(fi));
 
749
        fi.fh = arg->fh;
 
750
        fi.fh_old = fi.fh;
 
751
 
 
752
        if (req->f->op.fsyncdir)
 
753
                req->f->op.fsyncdir(req, nodeid, arg->fsync_flags & 1, &fi);
 
754
        else
 
755
                fuse_reply_err(req, ENOSYS);
753
756
}
754
757
 
755
758
static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
756
759
{
757
 
    (void) nodeid;
758
 
    (void) inarg;
 
760
        (void) nodeid;
 
761
        (void) inarg;
759
762
 
760
 
    if (req->f->op.statfs)
761
 
        req->f->op.statfs(req, nodeid);
762
 
    else {
763
 
        struct statvfs buf = {
764
 
            .f_namemax = 255,
765
 
            .f_bsize = 512,
766
 
        };
767
 
        fuse_reply_statfs(req, &buf);
768
 
    }
 
763
        if (req->f->op.statfs)
 
764
                req->f->op.statfs(req, nodeid);
 
765
        else {
 
766
                struct statvfs buf = {
 
767
                        .f_namemax = 255,
 
768
                        .f_bsize = 512,
 
769
                };
 
770
                fuse_reply_statfs(req, &buf);
 
771
        }
769
772
}
770
773
 
771
774
static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
772
775
{
773
 
    struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg;
774
 
    char *name = PARAM(arg);
775
 
    char *value = name + strlen(name) + 1;
 
776
        struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg;
 
777
        char *name = PARAM(arg);
 
778
        char *value = name + strlen(name) + 1;
776
779
 
777
 
    if (req->f->op.setxattr)
778
 
        req->f->op.setxattr(req, nodeid, name, value, arg->size, arg->flags);
779
 
    else
780
 
        fuse_reply_err(req, ENOSYS);
 
780
        if (req->f->op.setxattr)
 
781
                req->f->op.setxattr(req, nodeid, name, value, arg->size,
 
782
                                    arg->flags);
 
783
        else
 
784
                fuse_reply_err(req, ENOSYS);
781
785
}
782
786
 
783
787
static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
784
788
{
785
 
    struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
 
789
        struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
786
790
 
787
 
    if (req->f->op.getxattr)
788
 
        req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size);
789
 
    else
790
 
        fuse_reply_err(req, ENOSYS);
 
791
        if (req->f->op.getxattr)
 
792
                req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size);
 
793
        else
 
794
                fuse_reply_err(req, ENOSYS);
791
795
}
792
796
 
793
797
static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
794
798
{
795
 
    struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
 
799
        struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
796
800
 
797
 
    if (req->f->op.listxattr)
798
 
        req->f->op.listxattr(req, nodeid, arg->size);
799
 
    else
800
 
        fuse_reply_err(req, ENOSYS);
 
801
        if (req->f->op.listxattr)
 
802
                req->f->op.listxattr(req, nodeid, arg->size);
 
803
        else
 
804
                fuse_reply_err(req, ENOSYS);
801
805
}
802
806
 
803
807
static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
804
808
{
805
 
    char *name = (char *) inarg;
 
809
        char *name = (char *) inarg;
806
810
 
807
 
    if (req->f->op.removexattr)
808
 
        req->f->op.removexattr(req, nodeid, name);
809
 
    else
810
 
        fuse_reply_err(req, ENOSYS);
 
811
        if (req->f->op.removexattr)
 
812
                req->f->op.removexattr(req, nodeid, name);
 
813
        else
 
814
                fuse_reply_err(req, ENOSYS);
811
815
}
812
816
 
813
817
static void convert_fuse_file_lock(struct fuse_file_lock *fl,
814
 
                                   struct flock *flock)
 
818
                                   struct flock *flock)
815
819
{
816
 
    memset(flock, 0, sizeof(struct flock));
817
 
    flock->l_type = fl->type;
818
 
    flock->l_whence = SEEK_SET;
819
 
    flock->l_start = fl->start;
820
 
    if (fl->end == OFFSET_MAX)
821
 
        flock->l_len = 0;
822
 
    else
823
 
        flock->l_len = fl->end - fl->start + 1;
824
 
    flock->l_pid = fl->pid;
 
820
        memset(flock, 0, sizeof(struct flock));
 
821
        flock->l_type = fl->type;
 
822
        flock->l_whence = SEEK_SET;
 
823
        flock->l_start = fl->start;
 
824
        if (fl->end == OFFSET_MAX)
 
825
                flock->l_len = 0;
 
826
        else
 
827
                flock->l_len = fl->end - fl->start + 1;
 
828
        flock->l_pid = fl->pid;
825
829
}
826
830
 
827
831
static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
828
832
{
829
 
    struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
830
 
    struct fuse_file_info fi;
831
 
    struct flock flock;
832
 
 
833
 
    memset(&fi, 0, sizeof(fi));
834
 
    fi.fh = arg->fh;
835
 
    fi.lock_owner = arg->owner;
836
 
 
837
 
    convert_fuse_file_lock(&arg->lk, &flock);
838
 
    if (req->f->op.getlk)
839
 
        req->f->op.getlk(req, nodeid, &fi, &flock);
840
 
    else
841
 
        fuse_reply_err(req, ENOSYS);
 
833
        struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
 
834
        struct fuse_file_info fi;
 
835
        struct flock flock;
 
836
 
 
837
        memset(&fi, 0, sizeof(fi));
 
838
        fi.fh = arg->fh;
 
839
        fi.lock_owner = arg->owner;
 
840
 
 
841
        convert_fuse_file_lock(&arg->lk, &flock);
 
842
        if (req->f->op.getlk)
 
843
                req->f->op.getlk(req, nodeid, &fi, &flock);
 
844
        else
 
845
                fuse_reply_err(req, ENOSYS);
842
846
}
843
847
 
844
848
static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid,
845
 
                            const void *inarg, int sleep)
 
849
                            const void *inarg, int sleep)
846
850
{
847
 
    struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
848
 
    struct fuse_file_info fi;
849
 
    struct flock flock;
850
 
 
851
 
    memset(&fi, 0, sizeof(fi));
852
 
    fi.fh = arg->fh;
853
 
    fi.lock_owner = arg->owner;
854
 
 
855
 
    convert_fuse_file_lock(&arg->lk, &flock);
856
 
    if (req->f->op.setlk)
857
 
        req->f->op.setlk(req, nodeid, &fi, &flock, sleep);
858
 
    else
859
 
        fuse_reply_err(req, ENOSYS);
 
851
        struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
 
852
        struct fuse_file_info fi;
 
853
        struct flock flock;
 
854
 
 
855
        memset(&fi, 0, sizeof(fi));
 
856
        fi.fh = arg->fh;
 
857
        fi.lock_owner = arg->owner;
 
858
 
 
859
        convert_fuse_file_lock(&arg->lk, &flock);
 
860
        if (req->f->op.setlk)
 
861
                req->f->op.setlk(req, nodeid, &fi, &flock, sleep);
 
862
        else
 
863
                fuse_reply_err(req, ENOSYS);
860
864
}
861
865
 
862
866
static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
863
867
{
864
 
    do_setlk_common(req, nodeid, inarg, 0);
 
868
        do_setlk_common(req, nodeid, inarg, 0);
865
869
}
866
870
 
867
871
static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
868
872
{
869
 
    do_setlk_common(req, nodeid, inarg, 1);
 
873
        do_setlk_common(req, nodeid, inarg, 1);
870
874
}
871
875
 
872
876
static int find_interrupted(struct fuse_ll *f, struct fuse_req *req)
873
877
{
874
 
    struct fuse_req *curr;
875
 
 
876
 
    for (curr = f->list.next; curr != &f->list; curr = curr->next) {
877
 
        if (curr->unique == req->u.i.unique) {
878
 
            curr->ctr++;
879
 
            pthread_mutex_unlock(&f->lock);
880
 
 
881
 
            /* Ugh, ugly locking */
882
 
            pthread_mutex_lock(&curr->lock);
883
 
            pthread_mutex_lock(&f->lock);
884
 
            curr->interrupted = 1;
885
 
            pthread_mutex_unlock(&f->lock);
886
 
            if (curr->u.ni.func)
887
 
                curr->u.ni.func(curr, curr->u.ni.data);
888
 
            pthread_mutex_unlock(&curr->lock);
889
 
 
890
 
            pthread_mutex_lock(&f->lock);
891
 
            curr->ctr--;
892
 
            if (!curr->ctr)
893
 
                destroy_req(curr);
894
 
 
895
 
            return 1;
896
 
        }
897
 
    }
898
 
    for (curr = f->interrupts.next; curr != &f->interrupts;
899
 
         curr = curr->next) {
900
 
        if (curr->u.i.unique == req->u.i.unique)
901
 
            return 1;
902
 
    }
903
 
    return 0;
 
878
        struct fuse_req *curr;
 
879
 
 
880
        for (curr = f->list.next; curr != &f->list; curr = curr->next) {
 
881
                if (curr->unique == req->u.i.unique) {
 
882
                        curr->ctr++;
 
883
                        pthread_mutex_unlock(&f->lock);
 
884
 
 
885
                        /* Ugh, ugly locking */
 
886
                        pthread_mutex_lock(&curr->lock);
 
887
                        pthread_mutex_lock(&f->lock);
 
888
                        curr->interrupted = 1;
 
889
                        pthread_mutex_unlock(&f->lock);
 
890
                        if (curr->u.ni.func)
 
891
                                curr->u.ni.func(curr, curr->u.ni.data);
 
892
                        pthread_mutex_unlock(&curr->lock);
 
893
 
 
894
                        pthread_mutex_lock(&f->lock);
 
895
                        curr->ctr--;
 
896
                        if (!curr->ctr)
 
897
                                destroy_req(curr);
 
898
 
 
899
                        return 1;
 
900
                }
 
901
        }
 
902
        for (curr = f->interrupts.next; curr != &f->interrupts;
 
903
             curr = curr->next) {
 
904
                if (curr->u.i.unique == req->u.i.unique)
 
905
                        return 1;
 
906
        }
 
907
        return 0;
904
908
}
905
909
 
906
910
static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
907
911
{
908
 
    struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg;
909
 
    struct fuse_ll *f = req->f;
910
 
 
911
 
    (void) nodeid;
912
 
    if (f->debug)
913
 
        fprintf(stderr, "INTERRUPT: %llu\n", (unsigned long long) arg->unique);
914
 
 
915
 
    req->u.i.unique = arg->unique;
916
 
 
917
 
    pthread_mutex_lock(&f->lock);
918
 
    if (find_interrupted(f, req))
919
 
        destroy_req(req);
920
 
    else
921
 
        list_add_req(req, &f->interrupts);
922
 
    pthread_mutex_unlock(&f->lock);
 
912
        struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg;
 
913
        struct fuse_ll *f = req->f;
 
914
 
 
915
        (void) nodeid;
 
916
        if (f->debug)
 
917
                fprintf(stderr, "INTERRUPT: %llu\n",
 
918
                        (unsigned long long) arg->unique);
 
919
 
 
920
        req->u.i.unique = arg->unique;
 
921
 
 
922
        pthread_mutex_lock(&f->lock);
 
923
        if (find_interrupted(f, req))
 
924
                destroy_req(req);
 
925
        else
 
926
                list_add_req(req, &f->interrupts);
 
927
        pthread_mutex_unlock(&f->lock);
923
928
}
924
929
 
925
930
static struct fuse_req *check_interrupt(struct fuse_ll *f, struct fuse_req *req)
926
931
{
927
 
    struct fuse_req *curr;
 
932
        struct fuse_req *curr;
928
933
 
929
 
    for (curr = f->interrupts.next; curr != &f->interrupts; curr = curr->next) {
930
 
        if (curr->u.i.unique == req->unique) {
931
 
            req->interrupted = 1;
932
 
            list_del_req(curr);
933
 
            free(curr);
934
 
            return NULL;
935
 
        }
936
 
    }
937
 
    curr = f->interrupts.next;
938
 
    if (curr != &f->interrupts) {
939
 
        list_del_req(curr);
940
 
        list_init_req(curr);
941
 
        return curr;
942
 
    } else
943
 
        return NULL;
 
934
        for (curr = f->interrupts.next; curr != &f->interrupts;
 
935
             curr = curr->next) {
 
936
                if (curr->u.i.unique == req->unique) {
 
937
                        req->interrupted = 1;
 
938
                        list_del_req(curr);
 
939
                        free(curr);
 
940
                        return NULL;
 
941
                }
 
942
        }
 
943
        curr = f->interrupts.next;
 
944
        if (curr != &f->interrupts) {
 
945
                list_del_req(curr);
 
946
                list_init_req(curr);
 
947
                return curr;
 
948
        } else
 
949
                return NULL;
944
950
}
945
951
 
946
952
static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
947
953
{
948
 
    struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg;
 
954
        struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg;
949
955
 
950
 
    if (req->f->op.bmap)
951
 
        req->f->op.bmap(req, nodeid, arg->blocksize, arg->block);
952
 
    else
953
 
        fuse_reply_err(req, ENOSYS);
 
956
        if (req->f->op.bmap)
 
957
                req->f->op.bmap(req, nodeid, arg->blocksize, arg->block);
 
958
        else
 
959
                fuse_reply_err(req, ENOSYS);
954
960
}
955
961
 
956
962
static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
957
963
{
958
 
    struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
959
 
    struct fuse_init_out outarg;
960
 
    struct fuse_ll *f = req->f;
961
 
    size_t bufsize = fuse_chan_bufsize(req->ch);
962
 
 
963
 
    (void) nodeid;
964
 
    if (f->debug) {
965
 
        fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
966
 
        if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
967
 
            fprintf(stderr, "flags=0x%08x\n", arg->flags);
968
 
            fprintf(stderr, "max_readahead=0x%08x\n", arg->max_readahead);
969
 
        }
970
 
    }
971
 
    f->conn.proto_major = arg->major;
972
 
    f->conn.proto_minor = arg->minor;
973
 
 
974
 
    if (arg->major < 7) {
975
 
        fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
976
 
                arg->major, arg->minor);
977
 
        fuse_reply_err(req, EPROTO);
978
 
        return;
979
 
    }
980
 
 
981
 
    if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
982
 
        if (f->conn.async_read)
983
 
            f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
984
 
        if (arg->max_readahead < f->conn.max_readahead)
985
 
            f->conn.max_readahead = arg->max_readahead;
986
 
    } else {
987
 
        f->conn.async_read = 0;
988
 
        f->conn.max_readahead = 0;
989
 
    }
990
 
 
991
 
    if (bufsize < FUSE_MIN_READ_BUFFER) {
992
 
        fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
993
 
                bufsize);
994
 
        bufsize = FUSE_MIN_READ_BUFFER;
995
 
    }
996
 
 
997
 
    bufsize -= 4096;
998
 
    if (bufsize < f->conn.max_write)
999
 
        f->conn.max_write = bufsize;
1000
 
 
1001
 
    f->got_init = 1;
1002
 
    if (f->op.init)
1003
 
        f->op.init(f->userdata, &f->conn);
1004
 
 
1005
 
    memset(&outarg, 0, sizeof(outarg));
1006
 
    outarg.major = FUSE_KERNEL_VERSION;
1007
 
    outarg.minor = FUSE_KERNEL_MINOR_VERSION;
1008
 
    if (f->conn.async_read)
1009
 
        outarg.flags |= FUSE_ASYNC_READ;
1010
 
    if (f->op.getlk && f->op.setlk)
1011
 
        outarg.flags |= FUSE_POSIX_LOCKS;
1012
 
    outarg.max_readahead = f->conn.max_readahead;
1013
 
    outarg.max_write = f->conn.max_write;
1014
 
 
1015
 
    if (f->debug) {
1016
 
        fprintf(stderr, "   INIT: %u.%u\n", outarg.major, outarg.minor);
1017
 
        fprintf(stderr, "   flags=0x%08x\n", outarg.flags);
1018
 
        fprintf(stderr, "   max_readahead=0x%08x\n", outarg.max_readahead);
1019
 
        fprintf(stderr, "   max_write=0x%08x\n", outarg.max_write);
1020
 
    }
1021
 
 
1022
 
    send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
 
964
        struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
 
965
        struct fuse_init_out outarg;
 
966
        struct fuse_ll *f = req->f;
 
967
        size_t bufsize = fuse_chan_bufsize(req->ch);
 
968
 
 
969
        (void) nodeid;
 
970
        if (f->debug) {
 
971
                fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
 
972
                if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
 
973
                        fprintf(stderr, "flags=0x%08x\n", arg->flags);
 
974
                        fprintf(stderr, "max_readahead=0x%08x\n",
 
975
                                arg->max_readahead);
 
976
                }
 
977
        }
 
978
        f->conn.proto_major = arg->major;
 
979
        f->conn.proto_minor = arg->minor;
 
980
 
 
981
        if (arg->major < 7) {
 
982
                fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
 
983
                        arg->major, arg->minor);
 
984
                fuse_reply_err(req, EPROTO);
 
985
                return;
 
986
        }
 
987
 
 
988
        if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
 
989
                if (f->conn.async_read)
 
990
                        f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
 
991
                if (arg->max_readahead < f->conn.max_readahead)
 
992
                        f->conn.max_readahead = arg->max_readahead;
 
993
        } else {
 
994
                f->conn.async_read = 0;
 
995
                f->conn.max_readahead = 0;
 
996
        }
 
997
 
 
998
        if (bufsize < FUSE_MIN_READ_BUFFER) {
 
999
                fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
 
1000
                        bufsize);
 
1001
                bufsize = FUSE_MIN_READ_BUFFER;
 
1002
        }
 
1003
 
 
1004
        bufsize -= 4096;
 
1005
        if (bufsize < f->conn.max_write)
 
1006
                f->conn.max_write = bufsize;
 
1007
 
 
1008
        f->got_init = 1;
 
1009
        if (f->op.init)
 
1010
                f->op.init(f->userdata, &f->conn);
 
1011
 
 
1012
        memset(&outarg, 0, sizeof(outarg));
 
1013
        outarg.major = FUSE_KERNEL_VERSION;
 
1014
        outarg.minor = FUSE_KERNEL_MINOR_VERSION;
 
1015
        if (f->conn.async_read)
 
1016
                outarg.flags |= FUSE_ASYNC_READ;
 
1017
        if (f->op.getlk && f->op.setlk)
 
1018
                outarg.flags |= FUSE_POSIX_LOCKS;
 
1019
        outarg.max_readahead = f->conn.max_readahead;
 
1020
        outarg.max_write = f->conn.max_write;
 
1021
 
 
1022
        if (f->debug) {
 
1023
                fprintf(stderr, "   INIT: %u.%u\n", outarg.major, outarg.minor);
 
1024
                fprintf(stderr, "   flags=0x%08x\n", outarg.flags);
 
1025
                fprintf(stderr, "   max_readahead=0x%08x\n",
 
1026
                        outarg.max_readahead);
 
1027
                fprintf(stderr, "   max_write=0x%08x\n", outarg.max_write);
 
1028
        }
 
1029
 
 
1030
        send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
1023
1031
}
1024
1032
 
1025
1033
static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1026
1034
{
1027
 
    struct fuse_ll *f = req->f;
1028
 
 
1029
 
    (void) nodeid;
1030
 
    (void) inarg;
1031
 
 
1032
 
    f->got_destroy = 1;
1033
 
    if (f->op.destroy)
1034
 
        f->op.destroy(f->userdata);
1035
 
 
1036
 
    send_reply_ok(req, NULL, 0);
 
1035
        struct fuse_ll *f = req->f;
 
1036
 
 
1037
        (void) nodeid;
 
1038
        (void) inarg;
 
1039
 
 
1040
        f->got_destroy = 1;
 
1041
        if (f->op.destroy)
 
1042
                f->op.destroy(f->userdata);
 
1043
 
 
1044
        send_reply_ok(req, NULL, 0);
1037
1045
}
1038
1046
 
1039
1047
void *fuse_req_userdata(fuse_req_t req)
1040
1048
{
1041
 
    return req->f->userdata;
 
1049
        return req->f->userdata;
1042
1050
}
1043
1051
 
1044
1052
const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
1045
1053
{
1046
 
    return &req->ctx;
 
1054
        return &req->ctx;
1047
1055
}
1048
1056
 
1049
1057
void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
1050
 
                             void *data)
 
1058
                             void *data)
1051
1059
{
1052
 
    pthread_mutex_lock(&req->lock);
1053
 
    req->u.ni.func = func;
1054
 
    req->u.ni.data = data;
1055
 
    if (req->interrupted && func)
1056
 
        func(req, data);
1057
 
    pthread_mutex_unlock(&req->lock);
 
1060
        pthread_mutex_lock(&req->lock);
 
1061
        req->u.ni.func = func;
 
1062
        req->u.ni.data = data;
 
1063
        if (req->interrupted && func)
 
1064
                func(req, data);
 
1065
        pthread_mutex_unlock(&req->lock);
1058
1066
}
1059
1067
 
1060
1068
int fuse_req_interrupted(fuse_req_t req)
1061
1069
{
1062
 
    int interrupted;
1063
 
 
1064
 
    pthread_mutex_lock(&req->f->lock);
1065
 
    interrupted = req->interrupted;
1066
 
    pthread_mutex_unlock(&req->f->lock);
1067
 
 
1068
 
    return interrupted;
 
1070
        int interrupted;
 
1071
 
 
1072
        pthread_mutex_lock(&req->f->lock);
 
1073
        interrupted = req->interrupted;
 
1074
        pthread_mutex_unlock(&req->f->lock);
 
1075
 
 
1076
        return interrupted;
1069
1077
}
1070
1078
 
1071
1079
static struct {
1072
 
    void (*func)(fuse_req_t, fuse_ino_t, const void *);
1073
 
    const char *name;
 
1080
        void (*func)(fuse_req_t, fuse_ino_t, const void *);
 
1081
        const char *name;
1074
1082
} fuse_ll_ops[] = {
1075
 
    [FUSE_LOOKUP]      = { do_lookup,      "LOOKUP"      },
1076
 
    [FUSE_FORGET]      = { do_forget,      "FORGET"      },
1077
 
    [FUSE_GETATTR]     = { do_getattr,     "GETATTR"     },
1078
 
    [FUSE_SETATTR]     = { do_setattr,     "SETATTR"     },
1079
 
    [FUSE_READLINK]    = { do_readlink,    "READLINK"    },
1080
 
    [FUSE_SYMLINK]     = { do_symlink,     "SYMLINK"     },
1081
 
    [FUSE_MKNOD]       = { do_mknod,       "MKNOD"       },
1082
 
    [FUSE_MKDIR]       = { do_mkdir,       "MKDIR"       },
1083
 
    [FUSE_UNLINK]      = { do_unlink,      "UNLINK"      },
1084
 
    [FUSE_RMDIR]       = { do_rmdir,       "RMDIR"       },
1085
 
    [FUSE_RENAME]      = { do_rename,      "RENAME"      },
1086
 
    [FUSE_LINK]        = { do_link,        "LINK"        },
1087
 
    [FUSE_OPEN]        = { do_open,        "OPEN"        },
1088
 
    [FUSE_READ]        = { do_read,        "READ"        },
1089
 
    [FUSE_WRITE]       = { do_write,       "WRITE"       },
1090
 
    [FUSE_STATFS]      = { do_statfs,      "STATFS"      },
1091
 
    [FUSE_RELEASE]     = { do_release,     "RELEASE"     },
1092
 
    [FUSE_FSYNC]       = { do_fsync,       "FSYNC"       },
1093
 
    [FUSE_SETXATTR]    = { do_setxattr,    "SETXATTR"    },
1094
 
    [FUSE_GETXATTR]    = { do_getxattr,    "GETXATTR"    },
1095
 
    [FUSE_LISTXATTR]   = { do_listxattr,   "LISTXATTR"   },
1096
 
    [FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" },
1097
 
    [FUSE_FLUSH]       = { do_flush,       "FLUSH"       },
1098
 
    [FUSE_INIT]        = { do_init,        "INIT"        },
1099
 
    [FUSE_OPENDIR]     = { do_opendir,     "OPENDIR"     },
1100
 
    [FUSE_READDIR]     = { do_readdir,     "READDIR"     },
1101
 
    [FUSE_RELEASEDIR]  = { do_releasedir,  "RELEASEDIR"  },
1102
 
    [FUSE_FSYNCDIR]    = { do_fsyncdir,    "FSYNCDIR"    },
1103
 
    [FUSE_GETLK]       = { do_getlk,       "GETLK"       },
1104
 
    [FUSE_SETLK]       = { do_setlk,       "SETLK"       },
1105
 
    [FUSE_SETLKW]      = { do_setlkw,      "SETLKW"      },
1106
 
    [FUSE_ACCESS]      = { do_access,      "ACCESS"      },
1107
 
    [FUSE_CREATE]      = { do_create,      "CREATE"      },
1108
 
    [FUSE_INTERRUPT]   = { do_interrupt,   "INTERRUPT"   },
1109
 
    [FUSE_BMAP]        = { do_bmap,        "BMAP"        },
1110
 
    [FUSE_DESTROY]     = { do_destroy,     "DESTROY"     },
 
1083
        [FUSE_LOOKUP]      = { do_lookup,      "LOOKUP"      },
 
1084
        [FUSE_FORGET]      = { do_forget,      "FORGET"      },
 
1085
        [FUSE_GETATTR]     = { do_getattr,     "GETATTR"     },
 
1086
        [FUSE_SETATTR]     = { do_setattr,     "SETATTR"     },
 
1087
        [FUSE_READLINK]    = { do_readlink,    "READLINK"    },
 
1088
        [FUSE_SYMLINK]     = { do_symlink,     "SYMLINK"     },
 
1089
        [FUSE_MKNOD]       = { do_mknod,       "MKNOD"       },
 
1090
        [FUSE_MKDIR]       = { do_mkdir,       "MKDIR"       },
 
1091
        [FUSE_UNLINK]      = { do_unlink,      "UNLINK"      },
 
1092
        [FUSE_RMDIR]       = { do_rmdir,       "RMDIR"       },
 
1093
        [FUSE_RENAME]      = { do_rename,      "RENAME"      },
 
1094
        [FUSE_LINK]        = { do_link,        "LINK"        },
 
1095
        [FUSE_OPEN]        = { do_open,        "OPEN"        },
 
1096
        [FUSE_READ]        = { do_read,        "READ"        },
 
1097
        [FUSE_WRITE]       = { do_write,       "WRITE"       },
 
1098
        [FUSE_STATFS]      = { do_statfs,      "STATFS"      },
 
1099
        [FUSE_RELEASE]     = { do_release,     "RELEASE"     },
 
1100
        [FUSE_FSYNC]       = { do_fsync,       "FSYNC"       },
 
1101
        [FUSE_SETXATTR]    = { do_setxattr,    "SETXATTR"    },
 
1102
        [FUSE_GETXATTR]    = { do_getxattr,    "GETXATTR"    },
 
1103
        [FUSE_LISTXATTR]   = { do_listxattr,   "LISTXATTR"   },
 
1104
        [FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" },
 
1105
        [FUSE_FLUSH]       = { do_flush,       "FLUSH"       },
 
1106
        [FUSE_INIT]        = { do_init,        "INIT"        },
 
1107
        [FUSE_OPENDIR]     = { do_opendir,     "OPENDIR"     },
 
1108
        [FUSE_READDIR]     = { do_readdir,     "READDIR"     },
 
1109
        [FUSE_RELEASEDIR]  = { do_releasedir,  "RELEASEDIR"  },
 
1110
        [FUSE_FSYNCDIR]    = { do_fsyncdir,    "FSYNCDIR"    },
 
1111
        [FUSE_GETLK]       = { do_getlk,       "GETLK"       },
 
1112
        [FUSE_SETLK]       = { do_setlk,       "SETLK"       },
 
1113
        [FUSE_SETLKW]      = { do_setlkw,      "SETLKW"      },
 
1114
        [FUSE_ACCESS]      = { do_access,      "ACCESS"      },
 
1115
        [FUSE_CREATE]      = { do_create,      "CREATE"      },
 
1116
        [FUSE_INTERRUPT]   = { do_interrupt,   "INTERRUPT"   },
 
1117
        [FUSE_BMAP]        = { do_bmap,        "BMAP"        },
 
1118
        [FUSE_DESTROY]     = { do_destroy,     "DESTROY"     },
1111
1119
};
1112
1120
 
1113
1121
#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
1114
1122
 
1115
1123
static const char *opname(enum fuse_opcode opcode)
1116
1124
{
1117
 
    if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
1118
 
        return "???";
1119
 
    else
1120
 
        return fuse_ll_ops[opcode].name;
 
1125
        if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
 
1126
                return "???";
 
1127
        else
 
1128
                return fuse_ll_ops[opcode].name;
1121
1129
}
1122
1130
 
1123
1131
static void fuse_ll_process(void *data, const char *buf, size_t len,
1124
 
                     struct fuse_chan *ch)
 
1132
                            struct fuse_chan *ch)
1125
1133
{
1126
 
    struct fuse_ll *f = (struct fuse_ll *) data;
1127
 
    struct fuse_in_header *in = (struct fuse_in_header *) buf;
1128
 
    const void *inarg = buf + sizeof(struct fuse_in_header);
1129
 
    struct fuse_req *req;
1130
 
 
1131
 
    if (f->debug)
1132
 
        fprintf(stderr, "unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu\n",
1133
 
                (unsigned long long) in->unique,
1134
 
                opname((enum fuse_opcode) in->opcode), in->opcode,
1135
 
                (unsigned long) in->nodeid, len);
1136
 
 
1137
 
    req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
1138
 
    if (req == NULL) {
1139
 
        fprintf(stderr, "fuse: failed to allocate request\n");
1140
 
        return;
1141
 
    }
1142
 
 
1143
 
    req->f = f;
1144
 
    req->unique = in->unique;
1145
 
    req->ctx.uid = in->uid;
1146
 
    req->ctx.gid = in->gid;
1147
 
    req->ctx.pid = in->pid;
1148
 
    req->ch = ch;
1149
 
    req->ctr = 1;
1150
 
    list_init_req(req);
1151
 
    fuse_mutex_init(&req->lock);
1152
 
 
1153
 
    if (!f->got_init && in->opcode != FUSE_INIT)
1154
 
        fuse_reply_err(req, EIO);
1155
 
    else if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
1156
 
             in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
1157
 
             in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
1158
 
             in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
1159
 
             in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) {
1160
 
        fuse_reply_err(req, EACCES);
1161
 
    } else if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
1162
 
        fuse_reply_err(req, ENOSYS);
1163
 
    else {
1164
 
        if (in->opcode != FUSE_INTERRUPT) {
1165
 
            struct fuse_req *intr;
1166
 
            pthread_mutex_lock(&f->lock);
1167
 
            intr = check_interrupt(f, req);
1168
 
            list_add_req(req, &f->list);
1169
 
            pthread_mutex_unlock(&f->lock);
1170
 
            if (intr)
1171
 
                fuse_reply_err(intr, EAGAIN);
1172
 
        }
1173
 
        fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
1174
 
    }
 
1134
        struct fuse_ll *f = (struct fuse_ll *) data;
 
1135
        struct fuse_in_header *in = (struct fuse_in_header *) buf;
 
1136
        const void *inarg = buf + sizeof(struct fuse_in_header);
 
1137
        struct fuse_req *req;
 
1138
 
 
1139
        if (f->debug)
 
1140
                fprintf(stderr,
 
1141
                        "unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu\n",
 
1142
                        (unsigned long long) in->unique,
 
1143
                        opname((enum fuse_opcode) in->opcode), in->opcode,
 
1144
                        (unsigned long) in->nodeid, len);
 
1145
 
 
1146
        req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
 
1147
        if (req == NULL) {
 
1148
                fprintf(stderr, "fuse: failed to allocate request\n");
 
1149
                return;
 
1150
        }
 
1151
 
 
1152
        req->f = f;
 
1153
        req->unique = in->unique;
 
1154
        req->ctx.uid = in->uid;
 
1155
        req->ctx.gid = in->gid;
 
1156
        req->ctx.pid = in->pid;
 
1157
        req->ch = ch;
 
1158
        req->ctr = 1;
 
1159
        list_init_req(req);
 
1160
        fuse_mutex_init(&req->lock);
 
1161
 
 
1162
        if (!f->got_init && in->opcode != FUSE_INIT)
 
1163
                fuse_reply_err(req, EIO);
 
1164
        else if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
 
1165
                 in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
 
1166
                 in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
 
1167
                 in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
 
1168
                 in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) {
 
1169
                fuse_reply_err(req, EACCES);
 
1170
        } else if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
 
1171
                fuse_reply_err(req, ENOSYS);
 
1172
        else {
 
1173
                if (in->opcode != FUSE_INTERRUPT) {
 
1174
                        struct fuse_req *intr;
 
1175
                        pthread_mutex_lock(&f->lock);
 
1176
                        intr = check_interrupt(f, req);
 
1177
                        list_add_req(req, &f->list);
 
1178
                        pthread_mutex_unlock(&f->lock);
 
1179
                        if (intr)
 
1180
                                fuse_reply_err(intr, EAGAIN);
 
1181
                }
 
1182
                fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
 
1183
        }
1175
1184
}
1176
1185
 
1177
1186
enum {
1178
 
    KEY_HELP,
1179
 
    KEY_VERSION,
 
1187
        KEY_HELP,
 
1188
        KEY_VERSION,
1180
1189
};
1181
1190
 
1182
1191
static struct fuse_opt fuse_ll_opts[] = {
1183
 
    { "debug", offsetof(struct fuse_ll, debug), 1 },
1184
 
    { "-d", offsetof(struct fuse_ll, debug), 1 },
1185
 
    { "allow_root", offsetof(struct fuse_ll, allow_root), 1 },
1186
 
    { "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 },
1187
 
    { "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 },
1188
 
    { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 },
1189
 
    { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 },
1190
 
    FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
1191
 
    FUSE_OPT_KEY("-h", KEY_HELP),
1192
 
    FUSE_OPT_KEY("--help", KEY_HELP),
1193
 
    FUSE_OPT_KEY("-V", KEY_VERSION),
1194
 
    FUSE_OPT_KEY("--version", KEY_VERSION),
1195
 
    FUSE_OPT_END
 
1192
        { "debug", offsetof(struct fuse_ll, debug), 1 },
 
1193
        { "-d", offsetof(struct fuse_ll, debug), 1 },
 
1194
        { "allow_root", offsetof(struct fuse_ll, allow_root), 1 },
 
1195
        { "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 },
 
1196
        { "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 },
 
1197
        { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 },
 
1198
        { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 },
 
1199
        FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
 
1200
        FUSE_OPT_KEY("-h", KEY_HELP),
 
1201
        FUSE_OPT_KEY("--help", KEY_HELP),
 
1202
        FUSE_OPT_KEY("-V", KEY_VERSION),
 
1203
        FUSE_OPT_KEY("--version", KEY_VERSION),
 
1204
        FUSE_OPT_END
1196
1205
};
1197
1206
 
1198
1207
static void fuse_ll_version(void)
1199
1208
{
1200
 
    fprintf(stderr, "using FUSE kernel interface version %i.%i\n",
1201
 
            FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
 
1209
        fprintf(stderr, "using FUSE kernel interface version %i.%i\n",
 
1210
                FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
1202
1211
}
1203
1212
 
1204
1213
static void fuse_ll_help(void)
1205
1214
{
1206
 
    fprintf(stderr,
1207
 
"    -o max_write=N         set maximum size of write requests\n"
1208
 
"    -o max_readahead=N     set maximum readahead\n"
1209
 
"    -o async_read          perform reads asynchronously (default)\n"
1210
 
"    -o sync_read           perform reads synchronously\n");
 
1215
        fprintf(stderr,
 
1216
"    -o max_write=N         set maximum size of write requests\n"
 
1217
"    -o max_readahead=N     set maximum readahead\n"
 
1218
"    -o async_read          perform reads asynchronously (default)\n"
 
1219
"    -o sync_read           perform reads synchronously\n");
1211
1220
}
1212
1221
 
1213
1222
static int fuse_ll_opt_proc(void *data, const char *arg, int key,
1214
 
                            struct fuse_args *outargs)
 
1223
                            struct fuse_args *outargs)
1215
1224
{
1216
 
    (void) data; (void) outargs;
1217
 
 
1218
 
    switch (key) {
1219
 
    case KEY_HELP:
1220
 
        fuse_ll_help();
1221
 
        break;
1222
 
 
1223
 
    case KEY_VERSION:
1224
 
        fuse_ll_version();
1225
 
        break;
1226
 
 
1227
 
    default:
1228
 
        fprintf(stderr, "fuse: unknown option `%s'\n", arg);
1229
 
    }
1230
 
 
1231
 
    return -1;
 
1225
        (void) data; (void) outargs;
 
1226
 
 
1227
        switch (key) {
 
1228
        case KEY_HELP:
 
1229
                fuse_ll_help();
 
1230
                break;
 
1231
 
 
1232
        case KEY_VERSION:
 
1233
                fuse_ll_version();
 
1234
                break;
 
1235
 
 
1236
        default:
 
1237
                fprintf(stderr, "fuse: unknown option `%s'\n", arg);
 
1238
        }
 
1239
 
 
1240
        return -1;
1232
1241
}
1233
1242
 
1234
1243
int fuse_lowlevel_is_lib_option(const char *opt)
1235
1244
{
1236
 
    return fuse_opt_match(fuse_ll_opts, opt);
 
1245
        return fuse_opt_match(fuse_ll_opts, opt);
1237
1246
}
1238
1247
 
1239
1248
static void fuse_ll_destroy(void *data)
1240
1249
{
1241
 
    struct fuse_ll *f = (struct fuse_ll *) data;
1242
 
 
1243
 
    if (f->got_init && !f->got_destroy) {
1244
 
        if (f->op.destroy)
1245
 
            f->op.destroy(f->userdata);
1246
 
    }
1247
 
 
1248
 
    pthread_mutex_destroy(&f->lock);
1249
 
    free(f);
 
1250
        struct fuse_ll *f = (struct fuse_ll *) data;
 
1251
 
 
1252
        if (f->got_init && !f->got_destroy) {
 
1253
                if (f->op.destroy)
 
1254
                        f->op.destroy(f->userdata);
 
1255
        }
 
1256
 
 
1257
        pthread_mutex_destroy(&f->lock);
 
1258
        free(f);
1250
1259
}
1251
1260
 
1252
1261
/*
1255
1264
 * version of a symbol to internal references.
1256
1265
 */
1257
1266
struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
1258
 
                                       const struct fuse_lowlevel_ops *op,
1259
 
                                       size_t op_size, void *userdata)
 
1267
                                              const struct fuse_lowlevel_ops *op,
 
1268
                                              size_t op_size, void *userdata)
1260
1269
{
1261
 
    struct fuse_ll *f;
1262
 
    struct fuse_session *se;
1263
 
    struct fuse_session_ops sop = {
1264
 
        .process = fuse_ll_process,
1265
 
        .destroy = fuse_ll_destroy,
1266
 
    };
1267
 
 
1268
 
    if (sizeof(struct fuse_lowlevel_ops) < op_size) {
1269
 
        fprintf(stderr, "fuse: warning: library too old, some operations may not work\n");
1270
 
        op_size = sizeof(struct fuse_lowlevel_ops);
1271
 
    }
1272
 
 
1273
 
    f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll));
1274
 
    if (f == NULL) {
1275
 
        fprintf(stderr, "fuse: failed to allocate fuse object\n");
1276
 
        goto out;
1277
 
    }
1278
 
 
1279
 
    f->conn.async_read = 1;
1280
 
    f->conn.max_write = UINT_MAX;
1281
 
    f->conn.max_readahead = UINT_MAX;
1282
 
    list_init_req(&f->list);
1283
 
    list_init_req(&f->interrupts);
1284
 
    fuse_mutex_init(&f->lock);
1285
 
 
1286
 
    if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
1287
 
        goto out_free;
1288
 
 
1289
 
    memcpy(&f->op, op, op_size);
1290
 
    f->owner = getuid();
1291
 
    f->userdata = userdata;
1292
 
 
1293
 
    se = fuse_session_new(&sop, f);
1294
 
    if (!se)
1295
 
        goto out_free;
1296
 
 
1297
 
    return se;
1298
 
 
1299
 
 out_free:
1300
 
    free(f);
1301
 
 out:
1302
 
    return NULL;
 
1270
        struct fuse_ll *f;
 
1271
        struct fuse_session *se;
 
1272
        struct fuse_session_ops sop = {
 
1273
                .process = fuse_ll_process,
 
1274
                .destroy = fuse_ll_destroy,
 
1275
        };
 
1276
 
 
1277
        if (sizeof(struct fuse_lowlevel_ops) < op_size) {
 
1278
                fprintf(stderr, "fuse: warning: library too old, some operations may not work\n");
 
1279
                op_size = sizeof(struct fuse_lowlevel_ops);
 
1280
        }
 
1281
 
 
1282
        f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll));
 
1283
        if (f == NULL) {
 
1284
                fprintf(stderr, "fuse: failed to allocate fuse object\n");
 
1285
                goto out;
 
1286
        }
 
1287
 
 
1288
        f->conn.async_read = 1;
 
1289
        f->conn.max_write = UINT_MAX;
 
1290
        f->conn.max_readahead = UINT_MAX;
 
1291
        list_init_req(&f->list);
 
1292
        list_init_req(&f->interrupts);
 
1293
        fuse_mutex_init(&f->lock);
 
1294
 
 
1295
        if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
 
1296
                goto out_free;
 
1297
 
 
1298
        memcpy(&f->op, op, op_size);
 
1299
        f->owner = getuid();
 
1300
        f->userdata = userdata;
 
1301
 
 
1302
        se = fuse_session_new(&sop, f);
 
1303
        if (!se)
 
1304
                goto out_free;
 
1305
 
 
1306
        return se;
 
1307
 
 
1308
out_free:
 
1309
        free(f);
 
1310
out:
 
1311
        return NULL;
1303
1312
}
1304
1313
 
1305
1314
 
1306
1315
struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
1307
 
                                       const struct fuse_lowlevel_ops *op,
1308
 
                                       size_t op_size, void *userdata)
 
1316
                                       const struct fuse_lowlevel_ops *op,
 
1317
                                       size_t op_size, void *userdata)
1309
1318
{
1310
 
    return fuse_lowlevel_new_common(args, op, op_size, userdata);
 
1319
        return fuse_lowlevel_new_common(args, op, op_size, userdata);
1311
1320
}
1312
1321
 
1313
1322
 
1314
1323
#ifndef __FreeBSD__
1315
1324
 
1316
1325
static void fill_open_compat(struct fuse_open_out *arg,
1317
 
                      const struct fuse_file_info_compat *f)
 
1326
                             const struct fuse_file_info_compat *f)
1318
1327
{
1319
 
    arg->fh = f->fh;
1320
 
    if (f->direct_io)
1321
 
        arg->open_flags |= FOPEN_DIRECT_IO;
1322
 
    if (f->keep_cache)
1323
 
        arg->open_flags |= FOPEN_KEEP_CACHE;
 
1328
        arg->fh = f->fh;
 
1329
        if (f->direct_io)
 
1330
                arg->open_flags |= FOPEN_DIRECT_IO;
 
1331
        if (f->keep_cache)
 
1332
                arg->open_flags |= FOPEN_KEEP_CACHE;
1324
1333
}
1325
1334
 
1326
1335
static void convert_statfs_compat(const struct statfs *compatbuf,
1327
 
                                  struct statvfs *buf)
 
1336
                                  struct statvfs *buf)
1328
1337
{
1329
 
    buf->f_bsize        = compatbuf->f_bsize;
1330
 
    buf->f_blocks       = compatbuf->f_blocks;
1331
 
    buf->f_bfree        = compatbuf->f_bfree;
1332
 
    buf->f_bavail       = compatbuf->f_bavail;
1333
 
    buf->f_files        = compatbuf->f_files;
1334
 
    buf->f_ffree        = compatbuf->f_ffree;
1335
 
    buf->f_namemax      = compatbuf->f_namelen;
 
1338
        buf->f_bsize    = compatbuf->f_bsize;
 
1339
        buf->f_blocks   = compatbuf->f_blocks;
 
1340
        buf->f_bfree    = compatbuf->f_bfree;
 
1341
        buf->f_bavail   = compatbuf->f_bavail;
 
1342
        buf->f_files    = compatbuf->f_files;
 
1343
        buf->f_ffree    = compatbuf->f_ffree;
 
1344
        buf->f_namemax  = compatbuf->f_namelen;
1336
1345
}
1337
1346
 
1338
1347
int fuse_reply_open_compat(fuse_req_t req,
1339
 
                           const struct fuse_file_info_compat *f)
 
1348
                           const struct fuse_file_info_compat *f)
1340
1349
{
1341
 
    struct fuse_open_out arg;
 
1350
        struct fuse_open_out arg;
1342
1351
 
1343
 
    memset(&arg, 0, sizeof(arg));
1344
 
    fill_open_compat(&arg, f);
1345
 
    return send_reply_ok(req, &arg, sizeof(arg));
 
1352
        memset(&arg, 0, sizeof(arg));
 
1353
        fill_open_compat(&arg, f);
 
1354
        return send_reply_ok(req, &arg, sizeof(arg));
1346
1355
}
1347
1356
 
1348
1357
int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf)
1349
1358
{
1350
 
    struct statvfs newbuf;
1351
 
 
1352
 
    memset(&newbuf, 0, sizeof(newbuf));
1353
 
    convert_statfs_compat(stbuf, &newbuf);
1354
 
 
1355
 
    return fuse_reply_statfs(req, &newbuf);
 
1359
        struct statvfs newbuf;
 
1360
 
 
1361
        memset(&newbuf, 0, sizeof(newbuf));
 
1362
        convert_statfs_compat(stbuf, &newbuf);
 
1363
 
 
1364
        return fuse_reply_statfs(req, &newbuf);
1356
1365
}
1357
1366
 
1358
1367
struct fuse_session *fuse_lowlevel_new_compat(const char *opts,
1359
 
                            const struct fuse_lowlevel_ops_compat *op,
1360
 
                            size_t op_size, void *userdata)
 
1368
                                const struct fuse_lowlevel_ops_compat *op,
 
1369
                                size_t op_size, void *userdata)
1361
1370
{
1362
 
    struct fuse_session *se;
1363
 
    struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
1364
 
 
1365
 
    if (opts &&
1366
 
        (fuse_opt_add_arg(&args, "") == -1 ||
1367
 
         fuse_opt_add_arg(&args, "-o") == -1 ||
1368
 
         fuse_opt_add_arg(&args, opts) == -1)) {
1369
 
        fuse_opt_free_args(&args);
1370
 
        return NULL;
1371
 
    }
1372
 
    se = fuse_lowlevel_new(&args, (const struct fuse_lowlevel_ops *) op,
1373
 
                           op_size, userdata);
1374
 
    fuse_opt_free_args(&args);
1375
 
 
1376
 
    return se;
 
1371
        struct fuse_session *se;
 
1372
        struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
 
1373
 
 
1374
        if (opts &&
 
1375
            (fuse_opt_add_arg(&args, "") == -1 ||
 
1376
             fuse_opt_add_arg(&args, "-o") == -1 ||
 
1377
             fuse_opt_add_arg(&args, opts) == -1)) {
 
1378
                fuse_opt_free_args(&args);
 
1379
                return NULL;
 
1380
        }
 
1381
        se = fuse_lowlevel_new(&args, (const struct fuse_lowlevel_ops *) op,
 
1382
                               op_size, userdata);
 
1383
        fuse_opt_free_args(&args);
 
1384
 
 
1385
        return se;
1377
1386
}
1378
1387
 
1379
1388
struct fuse_ll_compat_conf {
1380
 
    unsigned max_read;
1381
 
    int set_max_read;
 
1389
        unsigned max_read;
 
1390
        int set_max_read;
1382
1391
};
1383
1392
 
1384
1393
static const struct fuse_opt fuse_ll_opts_compat[] = {
1385
 
    { "max_read=", offsetof(struct fuse_ll_compat_conf, set_max_read), 1 },
1386
 
    { "max_read=%u", offsetof(struct fuse_ll_compat_conf, max_read), 0 },
1387
 
    FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),
1388
 
    FUSE_OPT_END
 
1394
        { "max_read=", offsetof(struct fuse_ll_compat_conf, set_max_read), 1 },
 
1395
        { "max_read=%u", offsetof(struct fuse_ll_compat_conf, max_read), 0 },
 
1396
        FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),
 
1397
        FUSE_OPT_END
1389
1398
};
1390
1399
 
1391
1400
int fuse_sync_compat_args(struct fuse_args *args)
1392
1401
{
1393
 
    struct fuse_ll_compat_conf conf;
1394
 
 
1395
 
    memset(&conf, 0, sizeof(conf));
1396
 
    if (fuse_opt_parse(args, &conf, fuse_ll_opts_compat, NULL) == -1)
1397
 
        return -1;
1398
 
 
1399
 
    if (fuse_opt_insert_arg(args, 1, "-osync_read"))
1400
 
        return -1;
1401
 
 
1402
 
    if (conf.set_max_read) {
1403
 
        char tmpbuf[64];
1404
 
 
1405
 
        sprintf(tmpbuf, "-omax_readahead=%u", conf.max_read);
1406
 
        if (fuse_opt_insert_arg(args, 1, tmpbuf) == -1)
1407
 
            return -1;
1408
 
    }
1409
 
    return 0;
 
1402
        struct fuse_ll_compat_conf conf;
 
1403
 
 
1404
        memset(&conf, 0, sizeof(conf));
 
1405
        if (fuse_opt_parse(args, &conf, fuse_ll_opts_compat, NULL) == -1)
 
1406
                return -1;
 
1407
 
 
1408
        if (fuse_opt_insert_arg(args, 1, "-osync_read"))
 
1409
                return -1;
 
1410
 
 
1411
        if (conf.set_max_read) {
 
1412
                char tmpbuf[64];
 
1413
 
 
1414
                sprintf(tmpbuf, "-omax_readahead=%u", conf.max_read);
 
1415
                if (fuse_opt_insert_arg(args, 1, tmpbuf) == -1)
 
1416
                        return -1;
 
1417
        }
 
1418
        return 0;
1410
1419
}
1411
1420
 
1412
 
__asm__(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");
1413
 
__asm__(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
1414
 
__asm__(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");
 
1421
FUSE_SYMVER(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");
 
1422
FUSE_SYMVER(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
 
1423
FUSE_SYMVER(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");
1415
1424
 
1416
1425
#else /* __FreeBSD__ */
1417
1426
 
1418
1427
int fuse_sync_compat_args(struct fuse_args *args)
1419
1428
{
1420
 
    (void) args;
1421
 
    return 0;
 
1429
        (void) args;
 
1430
        return 0;
1422
1431
}
1423
1432
 
1424
1433
#endif /* __FreeBSD__ */
1425
1434
 
1426
1435
struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args,
1427
 
                        const struct fuse_lowlevel_ops_compat25 *op,
1428
 
                        size_t op_size, void *userdata)
 
1436
                                const struct fuse_lowlevel_ops_compat25 *op,
 
1437
                                size_t op_size, void *userdata)
1429
1438
{
1430
 
    if (fuse_sync_compat_args(args) == -1)
1431
 
        return NULL;
 
1439
        if (fuse_sync_compat_args(args) == -1)
 
1440
                return NULL;
1432
1441
 
1433
 
    return fuse_lowlevel_new_common(args,
1434
 
                                    (const struct fuse_lowlevel_ops *) op,
1435
 
                                    op_size, userdata);
 
1442
        return fuse_lowlevel_new_common(args,
 
1443
                                        (const struct fuse_lowlevel_ops *) op,
 
1444
                                        op_size, userdata);
1436
1445
}
1437
1446
 
1438
 
__asm__(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5");
 
1447
FUSE_SYMVER(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5");