blob: 2ed516906caa87e9919023d73731e1cb1ab5225b [file] [log] [blame]
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu)
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include "fuse_i.h"
10#include <linux/fuse.h>
11
12#include <string.h>
Miklos Szeredi97c61e92001-11-07 12:09:43 +000013#include <stdlib.h>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000014#include <unistd.h>
Miklos Szeredi97c61e92001-11-07 12:09:43 +000015#include <limits.h>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000016#include <errno.h>
17
Miklos Szeredi97c61e92001-11-07 12:09:43 +000018#define FUSE_MAX_PATH 4096
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000019
Miklos Szeredi97c61e92001-11-07 12:09:43 +000020static struct node *__get_node(struct fuse *f, fino_t ino)
Miklos Szeredia181e612001-11-06 12:03:23 +000021{
Miklos Szeredi97c61e92001-11-07 12:09:43 +000022 size_t hash = ino % f->ino_table_size;
23 struct node *node;
24
25 for(node = f->ino_table[hash]; node != NULL; node = node->ino_next)
26 if(node->ino == ino)
27 return node;
28
29 return NULL;
Miklos Szeredia181e612001-11-06 12:03:23 +000030}
31
Miklos Szeredi97c61e92001-11-07 12:09:43 +000032static struct node *get_node(struct fuse *f, fino_t ino)
Miklos Szeredia181e612001-11-06 12:03:23 +000033{
Miklos Szeredi97c61e92001-11-07 12:09:43 +000034 struct node *node = __get_node(f, ino);
35 if(node != NULL)
36 return node;
37
38 fprintf(stderr, "fuse internal error: inode %lu not found\n", ino);
39 abort();
Miklos Szeredia181e612001-11-06 12:03:23 +000040}
41
Miklos Szeredi97c61e92001-11-07 12:09:43 +000042static void hash_ino(struct fuse *f, struct node *node, fino_t ino)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000043{
Miklos Szeredi97c61e92001-11-07 12:09:43 +000044 size_t hash = ino % f->ino_table_size;
45 node->ino = ino;
46
47 node->ino_next = f->ino_table[hash];
48 f->ino_table[hash] = node;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000049}
50
Miklos Szeredi97c61e92001-11-07 12:09:43 +000051static void unhash_ino(struct fuse *f, struct node *node)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000052{
Miklos Szeredi97c61e92001-11-07 12:09:43 +000053 size_t hash = node->ino % f->ino_table_size;
54 struct node **nodep = &f->ino_table[hash];
55
56 for(; *nodep != NULL; nodep = &(*nodep)->ino_next)
57 if(*nodep == node) {
58 *nodep = node->ino_next;
59 return;
60 }
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000061}
62
Miklos Szeredi97c61e92001-11-07 12:09:43 +000063static fino_t get_ino(struct node *node)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000064{
Miklos Szeredi97c61e92001-11-07 12:09:43 +000065 return node->ino;
66}
67
68static fino_t next_ino(struct fuse *f)
69{
70 while(f->ctr == 0 || __get_node(f, f->ctr) != NULL)
71 f->ctr++;
72
73 return f->ctr;
74}
75
76static void free_node(struct node *node)
77{
78 free(node->name);
79 free(node);
80}
81
82static unsigned int name_hash(struct fuse *f, fino_t parent, const char *name)
83{
84 unsigned int hash = *name;
85
86 if(hash)
87 for(name += 1; *name != '\0'; name++)
88 hash = (hash << 5) - hash + *name;
89
90 return (hash + parent) % f->name_table_size;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000091}
92
Miklos Szeredi19dff1b2001-10-30 15:06:52 +000093static struct node *lookup_node(struct fuse *f, fino_t parent,
94 const char *name)
95{
Miklos Szeredi97c61e92001-11-07 12:09:43 +000096 size_t hash = name_hash(f, parent, name);
97 struct node *node;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +000098
Miklos Szeredi97c61e92001-11-07 12:09:43 +000099 for(node = f->name_table[hash]; node != NULL; node = node->name_next)
100 if(node->parent == parent && strcmp(node->name, name) == 0)
101 return node;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000102
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000103 return NULL;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000104}
105
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000106static void hash_name(struct fuse *f, struct node *node, fino_t parent,
Miklos Szeredia181e612001-11-06 12:03:23 +0000107 const char *name)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000108{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000109 size_t hash = name_hash(f, parent, name);
Miklos Szeredia181e612001-11-06 12:03:23 +0000110 node->parent = parent;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000111 node->name = strdup(name);
112 node->name_next = f->name_table[hash];
113 f->name_table[hash] = node;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000114}
115
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000116static void unhash_name(struct fuse *f, struct node *node)
Miklos Szeredia181e612001-11-06 12:03:23 +0000117{
118 if(node->name != NULL) {
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000119 size_t hash = name_hash(f, node->parent, node->name);
120 struct node **nodep = &f->name_table[hash];
121
122 for(; *nodep != NULL; nodep = &(*nodep)->name_next)
123 if(*nodep == node) {
124 *nodep = node->name_next;
125 node->name_next = NULL;
126 free(node->name);
127 node->name = NULL;
128 node->parent = 0;
129 return;
130 }
131 fprintf(stderr, "fuse internal error: unable to unhash node: %lu\n",
132 node->ino);
133 abort();
Miklos Szeredia181e612001-11-06 12:03:23 +0000134 }
135}
136
137static fino_t find_node(struct fuse *f, fino_t parent, char *name,
138 struct fuse_attr *attr, int version)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000139{
140 struct node *node;
Miklos Szeredia181e612001-11-06 12:03:23 +0000141 int mode = attr->mode & S_IFMT;
142 int rdev = 0;
143
144 if(S_ISCHR(mode) || S_ISBLK(mode))
145 rdev = attr->rdev;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000146
Miklos Szeredia181e612001-11-06 12:03:23 +0000147 pthread_mutex_lock(&f->lock);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000148 node = lookup_node(f, parent, name);
149 if(node != NULL) {
Miklos Szeredia181e612001-11-06 12:03:23 +0000150 if(node->mode == mode && node->rdev == rdev)
151 goto out;
152
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000153 unhash_name(f, node);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000154 }
155
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000156 node = (struct node *) calloc(1, sizeof(struct node));
Miklos Szeredia181e612001-11-06 12:03:23 +0000157 node->mode = mode;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000158 node->rdev = rdev;
159 hash_ino(f, node, next_ino(f));
160 hash_name(f, node, parent, name);
Miklos Szeredia181e612001-11-06 12:03:23 +0000161
162 out:
163 node->version = version;
164 pthread_mutex_unlock(&f->lock);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000165 return get_ino(node);
166}
167
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000168static char *add_name(char *buf, char *s, const char *name)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000169{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000170 size_t len = strlen(name);
171 s -= len;
172 if(s <= buf) {
173 fprintf(stderr, "fuse: path too long: ...%s\n", s + len);
174 return NULL;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000175 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000176 strncpy(s, name, len);
177 s--;
178 *s = '/';
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000179
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000180 return s;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000181}
182
Miklos Szeredia181e612001-11-06 12:03:23 +0000183static char *get_path_name(struct fuse *f, fino_t ino, const char *name)
Miklos Szeredib483c932001-10-29 14:57:57 +0000184{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000185 char buf[FUSE_MAX_PATH];
186 char *s = buf + FUSE_MAX_PATH - 1;
187 struct node *node;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000188
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000189 *s = '\0';
Miklos Szeredia181e612001-11-06 12:03:23 +0000190
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000191 if(name != NULL) {
192 s = add_name(buf, s, name);
193 if(s == NULL)
194 return NULL;
195 }
196
197 pthread_mutex_lock(&f->lock);
198 for(node = get_node(f, ino); node->ino != FUSE_ROOT_INO;
199 node = get_node(f, node->parent)) {
200 if(node->name == NULL) {
201 s = NULL;
202 break;
203 }
204
205 s = add_name(buf, s, node->name);
206 if(s == NULL)
207 break;
208 }
209 pthread_mutex_unlock(&f->lock);
210
211 if(s == NULL)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000212 return NULL;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000213 else if(*s == '\0')
214 return strdup("/");
215 else
216 return strdup(s);
217}
Miklos Szeredia181e612001-11-06 12:03:23 +0000218
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000219static char *get_path(struct fuse *f, fino_t ino)
220{
221 return get_path_name(f, ino, NULL);
Miklos Szeredib483c932001-10-29 14:57:57 +0000222}
223
Miklos Szeredia181e612001-11-06 12:03:23 +0000224static void destroy_node(struct fuse *f, fino_t ino, int version)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000225{
Miklos Szeredia181e612001-11-06 12:03:23 +0000226 struct node *node;
227
228 pthread_mutex_lock(&f->lock);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000229 node = get_node(f, ino);
Miklos Szeredi39f28672001-11-14 14:52:54 +0000230 if(node->version == version && ino != FUSE_ROOT_INO) {
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000231 unhash_name(f, node);
232 unhash_ino(f, node);
Miklos Szeredia181e612001-11-06 12:03:23 +0000233 free_node(node);
234 }
235 pthread_mutex_unlock(&f->lock);
236
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000237}
238
Miklos Szeredi5e183482001-10-31 14:52:35 +0000239static void remove_node(struct fuse *f, fino_t dir, const char *name)
240{
Miklos Szeredia181e612001-11-06 12:03:23 +0000241 struct node *node;
242
243 pthread_mutex_lock(&f->lock);
244 node = lookup_node(f, dir, name);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000245 if(node == NULL) {
246 fprintf(stderr, "fuse internal error: unable to remove node %lu/%s\n",
247 dir, name);
248 abort();
249 }
250 unhash_name(f, node);
Miklos Szeredia181e612001-11-06 12:03:23 +0000251 pthread_mutex_unlock(&f->lock);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000252}
253
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000254static void rename_node(struct fuse *f, fino_t olddir, const char *oldname,
255 fino_t newdir, const char *newname)
256{
Miklos Szeredia181e612001-11-06 12:03:23 +0000257 struct node *node;
258 struct node *newnode;
259
260 pthread_mutex_lock(&f->lock);
261 node = lookup_node(f, olddir, oldname);
262 newnode = lookup_node(f, newdir, newname);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000263 if(node == NULL) {
264 fprintf(stderr, "fuse internal error: unable to rename node %lu/%s\n",
265 olddir, oldname);
266 abort();
267 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000268
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000269 if(newnode != NULL)
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000270 unhash_name(f, newnode);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000271
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000272 unhash_name(f, node);
273 hash_name(f, node, newdir, newname);
Miklos Szeredia181e612001-11-06 12:03:23 +0000274 pthread_mutex_unlock(&f->lock);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000275}
276
277
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000278static void convert_stat(struct stat *stbuf, struct fuse_attr *attr)
279{
280 attr->mode = stbuf->st_mode;
281 attr->nlink = stbuf->st_nlink;
282 attr->uid = stbuf->st_uid;
283 attr->gid = stbuf->st_gid;
284 attr->rdev = stbuf->st_rdev;
285 attr->size = stbuf->st_size;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000286 attr->blocks = stbuf->st_blocks;
287 attr->atime = stbuf->st_atime;
288 attr->mtime = stbuf->st_mtime;
289 attr->ctime = stbuf->st_ctime;
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000290 attr->_dummy = 4096;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000291}
292
Miklos Szeredia181e612001-11-06 12:03:23 +0000293static int fill_dir(struct fuse_dirhandle *dh, char *name, int type)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000294{
295 struct fuse_dirent dirent;
296 size_t reclen;
297 size_t res;
298
Miklos Szeredi43696432001-11-18 19:15:05 +0000299 dirent.ino = (unsigned long) -1;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000300 dirent.namelen = strlen(name);
301 strncpy(dirent.name, name, sizeof(dirent.name));
302 dirent.type = type;
303 reclen = FUSE_DIRENT_SIZE(&dirent);
304 res = fwrite(&dirent, reclen, 1, dh->fp);
305 if(res == 0) {
306 perror("writing directory file");
307 return -EIO;
308 }
309 return 0;
310}
311
Miklos Szeredi43696432001-11-18 19:15:05 +0000312static void send_reply_raw(struct fuse *f, char *outbuf, size_t outsize)
313{
314 int res;
315
316 if((f->flags & FUSE_DEBUG)) {
317 struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
318 printf(" unique: %i, error: %i (%s), outsize: %i\n", out->unique,
319 out->error, strerror(-out->error), outsize);
320 fflush(stdout);
321 }
322
323 res = write(f->fd, outbuf, outsize);
324 if(res == -1) {
325 /* ENOENT means the operation was interrupted */
326 if(errno != ENOENT)
327 perror("writing fuse device");
328 }
329}
330
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000331static void send_reply(struct fuse *f, struct fuse_in_header *in, int error,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000332 void *arg, size_t argsize)
333{
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000334 char *outbuf;
335 size_t outsize;
336 struct fuse_out_header *out;
337
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000338 if(error > 0) {
339 fprintf(stderr, "positive error code: %i\n", error);
340 error = -ERANGE;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000341 }
342
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000343 if(error)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000344 argsize = 0;
345
346 outsize = sizeof(struct fuse_out_header) + argsize;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000347 outbuf = (char *) malloc(outsize);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000348 out = (struct fuse_out_header *) outbuf;
349 out->unique = in->unique;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000350 out->error = error;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000351 if(argsize != 0)
352 memcpy(outbuf + sizeof(struct fuse_out_header), arg, argsize);
353
Miklos Szeredi43696432001-11-18 19:15:05 +0000354 send_reply_raw(f, outbuf, outsize);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000355
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000356 free(outbuf);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000357}
358
359static void do_lookup(struct fuse *f, struct fuse_in_header *in, char *name)
360{
361 int res;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000362 char *path;
363 struct stat buf;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000364 struct fuse_lookup_out arg;
365
Miklos Szeredi5e183482001-10-31 14:52:35 +0000366 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000367 path = get_path_name(f, in->ino, name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000368 if(path != NULL) {
369 res = -ENOSYS;
370 if(f->op.getattr)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000371 res = f->op.getattr(path, &buf);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000372 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000373 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000374 if(res == 0) {
375 convert_stat(&buf, &arg.attr);
Miklos Szeredia181e612001-11-06 12:03:23 +0000376 arg.ino = find_node(f, in->ino, name, &arg.attr, in->unique);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000377 }
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000378 send_reply(f, in, res, &arg, sizeof(arg));
379}
380
Miklos Szeredia181e612001-11-06 12:03:23 +0000381static void do_forget(struct fuse *f, struct fuse_in_header *in,
382 struct fuse_forget_in *arg)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000383{
Miklos Szeredi43696432001-11-18 19:15:05 +0000384 if(f->flags & FUSE_DEBUG) {
385 printf("FORGET %li/%i\n", in->ino, arg->version);
386 fflush(stdout);
387 }
Miklos Szeredia181e612001-11-06 12:03:23 +0000388 destroy_node(f, in->ino, arg->version);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000389}
390
391static void do_getattr(struct fuse *f, struct fuse_in_header *in)
392{
393 int res;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000394 char *path;
395 struct stat buf;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000396 struct fuse_getattr_out arg;
397
Miklos Szeredi5e183482001-10-31 14:52:35 +0000398 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000399 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000400 if(path != NULL) {
401 res = -ENOSYS;
402 if(f->op.getattr)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000403 res = f->op.getattr(path, &buf);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000404 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000405 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000406 if(res == 0)
407 convert_stat(&buf, &arg.attr);
408
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000409 send_reply(f, in, res, &arg, sizeof(arg));
410}
411
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000412static int do_chmod(struct fuse *f, const char *path, struct fuse_attr *attr)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000413{
414 int res;
415
416 res = -ENOSYS;
417 if(f->op.chmod)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000418 res = f->op.chmod(path, attr->mode);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000419
420 return res;
421}
422
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000423static int do_chown(struct fuse *f, const char *path, struct fuse_attr *attr,
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000424 int valid)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000425{
426 int res;
427 uid_t uid = (valid & FATTR_UID) ? attr->uid : (uid_t) -1;
428 gid_t gid = (valid & FATTR_GID) ? attr->gid : (gid_t) -1;
429
430 res = -ENOSYS;
431 if(f->op.chown)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000432 res = f->op.chown(path, uid, gid);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000433
434 return res;
435}
436
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000437static int do_truncate(struct fuse *f, const char *path,
438 struct fuse_attr *attr)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000439{
440 int res;
441
442 res = -ENOSYS;
443 if(f->op.truncate)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000444 res = f->op.truncate(path, attr->size);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000445
446 return res;
447}
448
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000449static int do_utime(struct fuse *f, const char *path, struct fuse_attr *attr)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000450{
451 int res;
452 struct utimbuf buf;
453 buf.actime = attr->atime;
454 buf.modtime = attr->mtime;
455 res = -ENOSYS;
456 if(f->op.utime)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000457 res = f->op.utime(path, &buf);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000458
459 return res;
460}
461
Miklos Szeredi5e183482001-10-31 14:52:35 +0000462static void do_setattr(struct fuse *f, struct fuse_in_header *in,
463 struct fuse_setattr_in *arg)
464{
465 int res;
466 char *path;
467 int valid = arg->valid;
468 struct fuse_attr *attr = &arg->attr;
Miklos Szeredia181e612001-11-06 12:03:23 +0000469 struct fuse_setattr_out outarg;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000470
471 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000472 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000473 if(path != NULL) {
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000474 res = -ENOSYS;
475 if(f->op.getattr) {
476 res = 0;
477 if(!res && (valid & FATTR_MODE))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000478 res = do_chmod(f, path, attr);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000479 if(!res && (valid & (FATTR_UID | FATTR_GID)))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000480 res = do_chown(f, path, attr, valid);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000481 if(!res && (valid & FATTR_SIZE))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000482 res = do_truncate(f, path, attr);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000483 if(!res && (valid & FATTR_UTIME))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000484 res = do_utime(f, path, attr);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000485 if(!res) {
486 struct stat buf;
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000487 res = f->op.getattr(path, &buf);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000488 if(!res)
489 convert_stat(&buf, &outarg.attr);
Miklos Szeredia181e612001-11-06 12:03:23 +0000490 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000491 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000492 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000493 }
Miklos Szeredia181e612001-11-06 12:03:23 +0000494 send_reply(f, in, res, &outarg, sizeof(outarg));
Miklos Szeredi5e183482001-10-31 14:52:35 +0000495}
496
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000497static void do_readlink(struct fuse *f, struct fuse_in_header *in)
498{
499 int res;
500 char link[PATH_MAX + 1];
Miklos Szeredib483c932001-10-29 14:57:57 +0000501 char *path;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000502
Miklos Szeredi5e183482001-10-31 14:52:35 +0000503 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000504 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000505 if(path != NULL) {
506 res = -ENOSYS;
507 if(f->op.readlink)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000508 res = f->op.readlink(path, link, sizeof(link));
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000509 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000510 }
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000511 link[PATH_MAX] = '\0';
Miklos Szeredi5e183482001-10-31 14:52:35 +0000512 send_reply(f, in, res, link, !res ? strlen(link) : 0);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000513}
514
515static void do_getdir(struct fuse *f, struct fuse_in_header *in)
516{
517 int res;
518 struct fuse_getdir_out arg;
Miklos Szeredia181e612001-11-06 12:03:23 +0000519 struct fuse_dirhandle dh;
Miklos Szeredib483c932001-10-29 14:57:57 +0000520 char *path;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000521
Miklos Szeredib483c932001-10-29 14:57:57 +0000522 dh.fuse = f;
523 dh.fp = tmpfile();
524 dh.dir = in->ino;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000525 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000526 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000527 if(path != NULL) {
528 res = -ENOSYS;
529 if(f->op.getdir)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000530 res = f->op.getdir(path, &dh, (fuse_dirfil_t) fill_dir);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000531 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000532 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000533 fflush(dh.fp);
534 arg.fd = fileno(dh.fp);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000535 send_reply(f, in, res, &arg, sizeof(arg));
Miklos Szeredib483c932001-10-29 14:57:57 +0000536 fclose(dh.fp);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000537}
538
Miklos Szeredib483c932001-10-29 14:57:57 +0000539static void do_mknod(struct fuse *f, struct fuse_in_header *in,
540 struct fuse_mknod_in *inarg)
541{
542 int res;
543 char *path;
544 struct fuse_mknod_out outarg;
545 struct stat buf;
546
Miklos Szeredi5e183482001-10-31 14:52:35 +0000547 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000548 path = get_path_name(f, in->ino, inarg->name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000549 if(path != NULL) {
550 res = -ENOSYS;
551 if(f->op.mknod && f->op.getattr) {
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000552 res = f->op.mknod(path, inarg->mode, inarg->rdev);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000553 if(res == 0)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000554 res = f->op.getattr(path, &buf);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000555 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000556 free(path);
Miklos Szeredib483c932001-10-29 14:57:57 +0000557 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000558 if(res == 0) {
Miklos Szeredib483c932001-10-29 14:57:57 +0000559 convert_stat(&buf, &outarg.attr);
Miklos Szeredia181e612001-11-06 12:03:23 +0000560 outarg.ino = find_node(f, in->ino, inarg->name, &outarg.attr,
561 in->unique);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000562 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000563
564 send_reply(f, in, res, &outarg, sizeof(outarg));
565}
566
567static void do_mkdir(struct fuse *f, struct fuse_in_header *in,
568 struct fuse_mkdir_in *inarg)
569{
570 int res;
571 char *path;
572
Miklos Szeredi5e183482001-10-31 14:52:35 +0000573 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000574 path = get_path_name(f, in->ino, inarg->name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000575 if(path != NULL) {
576 res = -ENOSYS;
577 if(f->op.mkdir)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000578 res = f->op.mkdir(path, inarg->mode);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000579 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000580 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000581 send_reply(f, in, res, NULL, 0);
582}
583
584static void do_remove(struct fuse *f, struct fuse_in_header *in, char *name)
585{
586 int res;
587 char *path;
588
Miklos Szeredi5e183482001-10-31 14:52:35 +0000589 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000590 path = get_path_name(f, in->ino, name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000591 if(path != NULL) {
592 res = -ENOSYS;
593 if(in->opcode == FUSE_UNLINK) {
594 if(f->op.unlink)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000595 res = f->op.unlink(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000596 }
597 else {
598 if(f->op.rmdir)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000599 res = f->op.rmdir(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000600 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000601 free(path);
Miklos Szeredib483c932001-10-29 14:57:57 +0000602 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000603 if(res == 0)
604 remove_node(f, in->ino, name);
Miklos Szeredib483c932001-10-29 14:57:57 +0000605 send_reply(f, in, res, NULL, 0);
606}
607
608static void do_symlink(struct fuse *f, struct fuse_in_header *in, char *name,
609 char *link)
610{
611 int res;
612 char *path;
613
Miklos Szeredi5e183482001-10-31 14:52:35 +0000614 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000615 path = get_path_name(f, in->ino, name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000616 if(path != NULL) {
617 res = -ENOSYS;
618 if(f->op.symlink)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000619 res = f->op.symlink(link, path);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000620 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000621 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000622 send_reply(f, in, res, NULL, 0);
623}
624
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000625static void do_rename(struct fuse *f, struct fuse_in_header *in,
626 struct fuse_rename_in *inarg)
627{
628 int res;
629 fino_t olddir = in->ino;
630 fino_t newdir = inarg->newdir;
631 char *oldname = inarg->names;
632 char *newname = inarg->names + strlen(oldname) + 1;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000633 char *oldpath;
634 char *newpath;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000635
Miklos Szeredi5e183482001-10-31 14:52:35 +0000636 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000637 oldpath = get_path_name(f, olddir, oldname);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000638 if(oldpath != NULL) {
Miklos Szeredia181e612001-11-06 12:03:23 +0000639 newpath = get_path_name(f, newdir, newname);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000640 if(newpath != NULL) {
641 res = -ENOSYS;
642 if(f->op.rename)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000643 res = f->op.rename(oldpath, newpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000644 if(res == 0)
645 rename_node(f, olddir, oldname, newdir, newname);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000646 free(newpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000647 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000648 free(oldpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000649 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000650 send_reply(f, in, res, NULL, 0);
651}
652
653static void do_link(struct fuse *f, struct fuse_in_header *in,
Miklos Szeredi5e183482001-10-31 14:52:35 +0000654 struct fuse_link_in *arg)
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000655{
656 int res;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000657 char *oldpath;
658 char *newpath;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000659
Miklos Szeredi5e183482001-10-31 14:52:35 +0000660 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000661 oldpath = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000662 if(oldpath != NULL) {
Miklos Szeredia181e612001-11-06 12:03:23 +0000663 newpath = get_path_name(f, arg->newdir, arg->name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000664 if(newpath != NULL) {
665 res = -ENOSYS;
666 if(f->op.link)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000667 res = f->op.link(oldpath, newpath);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000668 free(newpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000669 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000670 free(oldpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000671 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000672 send_reply(f, in, res, NULL, 0);
673}
674
Miklos Szeredi5e183482001-10-31 14:52:35 +0000675static void do_open(struct fuse *f, struct fuse_in_header *in,
676 struct fuse_open_in *arg)
677{
678 int res;
679 char *path;
680
681 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000682 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000683 if(path != NULL) {
684 res = -ENOSYS;
685 if(f->op.open)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000686 res = f->op.open(path, arg->flags);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000687 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000688 }
689 send_reply(f, in, res, NULL, 0);
690}
691
692static void do_read(struct fuse *f, struct fuse_in_header *in,
693 struct fuse_read_in *arg)
694{
695 int res;
696 char *path;
Miklos Szeredi43696432001-11-18 19:15:05 +0000697 char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + arg->size);
698 struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
699 char *buf = outbuf + sizeof(struct fuse_out_header);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000700 size_t size;
Miklos Szeredi43696432001-11-18 19:15:05 +0000701 size_t outsize;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000702
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000703 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000704 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000705 if(path != NULL) {
706 res = -ENOSYS;
Miklos Szeredia181e612001-11-06 12:03:23 +0000707 if(f->op.read)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000708 res = f->op.read(path, buf, arg->size, arg->offset);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000709 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000710 }
711
712 size = 0;
713 if(res > 0) {
714 size = res;
715 res = 0;
716 }
Miklos Szeredi43696432001-11-18 19:15:05 +0000717 out->unique = in->unique;
718 out->error = res;
719 outsize = sizeof(struct fuse_out_header) + size;
720
721 send_reply_raw(f, outbuf, outsize);
722 free(outbuf);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000723}
Miklos Szeredib483c932001-10-29 14:57:57 +0000724
Miklos Szeredia181e612001-11-06 12:03:23 +0000725static void do_write(struct fuse *f, struct fuse_in_header *in,
726 struct fuse_write_in *arg)
727{
728 int res;
729 char *path;
Miklos Szeredia181e612001-11-06 12:03:23 +0000730
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000731 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000732 path = get_path(f, in->ino);
733 if(path != NULL) {
734 res = -ENOSYS;
735 if(f->op.write)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000736 res = f->op.write(path, arg->buf, arg->size, arg->offset);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000737 free(path);
Miklos Szeredia181e612001-11-06 12:03:23 +0000738 }
739
740 if(res > 0) {
741 if((size_t) res != arg->size) {
742 fprintf(stderr, "short write: %u (should be %u)\n", res,
743 arg->size);
744 res = -EIO;
745 }
746 else
747 res = 0;
748 }
749
750 send_reply(f, in, res, NULL, 0);
751}
752
Miklos Szeredi43696432001-11-18 19:15:05 +0000753static void free_cmd(struct fuse_cmd *cmd)
754{
755 free(cmd->buf);
756 free(cmd);
757}
758
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000759void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
Miklos Szeredia181e612001-11-06 12:03:23 +0000760{
Miklos Szeredia181e612001-11-06 12:03:23 +0000761 struct fuse_in_header *in = (struct fuse_in_header *) cmd->buf;
762 void *inarg = cmd->buf + sizeof(struct fuse_in_header);
763 size_t argsize;
Miklos Szeredia181e612001-11-06 12:03:23 +0000764
Miklos Szeredic0938ea2001-11-07 12:35:06 +0000765 if((f->flags & FUSE_DEBUG)) {
766 printf("unique: %i, opcode: %i, ino: %li, insize: %i\n", in->unique,
767 in->opcode, in->ino, cmd->buflen);
768 fflush(stdout);
769 }
Miklos Szeredia181e612001-11-06 12:03:23 +0000770
771 argsize = cmd->buflen - sizeof(struct fuse_in_header);
772
773 switch(in->opcode) {
774 case FUSE_LOOKUP:
775 do_lookup(f, in, (char *) inarg);
776 break;
777
Miklos Szeredia181e612001-11-06 12:03:23 +0000778 case FUSE_GETATTR:
779 do_getattr(f, in);
780 break;
781
782 case FUSE_SETATTR:
783 do_setattr(f, in, (struct fuse_setattr_in *) inarg);
784 break;
785
786 case FUSE_READLINK:
787 do_readlink(f, in);
788 break;
789
790 case FUSE_GETDIR:
791 do_getdir(f, in);
792 break;
793
794 case FUSE_MKNOD:
795 do_mknod(f, in, (struct fuse_mknod_in *) inarg);
796 break;
797
798 case FUSE_MKDIR:
799 do_mkdir(f, in, (struct fuse_mkdir_in *) inarg);
800 break;
801
802 case FUSE_UNLINK:
803 case FUSE_RMDIR:
804 do_remove(f, in, (char *) inarg);
805 break;
806
807 case FUSE_SYMLINK:
808 do_symlink(f, in, (char *) inarg,
809 ((char *) inarg) + strlen((char *) inarg) + 1);
810 break;
811
812 case FUSE_RENAME:
813 do_rename(f, in, (struct fuse_rename_in *) inarg);
814 break;
815
816 case FUSE_LINK:
817 do_link(f, in, (struct fuse_link_in *) inarg);
818 break;
819
820 case FUSE_OPEN:
821 do_open(f, in, (struct fuse_open_in *) inarg);
822 break;
823
824 case FUSE_READ:
825 do_read(f, in, (struct fuse_read_in *) inarg);
826 break;
827
828 case FUSE_WRITE:
829 do_write(f, in, (struct fuse_write_in *) inarg);
830 break;
831
832 default:
833 fprintf(stderr, "Operation %i not implemented\n", in->opcode);
Miklos Szeredi43696432001-11-18 19:15:05 +0000834 send_reply(f, in, -ENOSYS, NULL, 0);
Miklos Szeredia181e612001-11-06 12:03:23 +0000835 }
Miklos Szeredi43696432001-11-18 19:15:05 +0000836
837 free_cmd(cmd);
Miklos Szeredia181e612001-11-06 12:03:23 +0000838}
839
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000840struct fuse_cmd *__fuse_read_cmd(struct fuse *f)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000841{
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000842 ssize_t res;
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000843 struct fuse_cmd *cmd;
Miklos Szeredi43696432001-11-18 19:15:05 +0000844 struct fuse_in_header *in;
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000845
Miklos Szeredi43696432001-11-18 19:15:05 +0000846 cmd = (struct fuse_cmd *) malloc(sizeof(struct fuse_cmd));
847 cmd->buf = (char *) malloc(FUSE_MAX_IN);
848
849 do {
850 res = read(f->fd, cmd->buf, FUSE_MAX_IN);
851 if(res == -1) {
852 perror("reading fuse device");
853 /* BAD... This will happen again */
854 free_cmd(cmd);
855 return NULL;
856 }
857 if((size_t) res < sizeof(struct fuse_in_header)) {
858 fprintf(stderr, "short read on fuse device\n");
859 /* Cannot happen */
860 free_cmd(cmd);
861 return NULL;
862 }
863 cmd->buflen = res;
864
865 /* FORGET is special: it can be done without calling filesystem
866 methods. */
867 in = (struct fuse_in_header *) cmd->buf;
868 if(in->opcode == FUSE_FORGET) {
869 void *inarg = cmd->buf + sizeof(struct fuse_in_header);
870 do_forget(f, in, (struct fuse_forget_in *) inarg);
871 }
872 } while(in->opcode == FUSE_FORGET);
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000873
874 return cmd;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000875}
876
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000877
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000878void fuse_loop(struct fuse *f)
879{
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000880 while(1) {
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000881 struct fuse_cmd *cmd = __fuse_read_cmd(f);
882 if(cmd == NULL)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000883 exit(1);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000884
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000885 __fuse_process_cmd(f, cmd);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000886 }
887}
888
Miklos Szeredi8cffdb92001-11-09 14:49:18 +0000889struct fuse *fuse_new(int fd, int flags)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000890{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000891 struct fuse *f;
892 struct node *root;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000893
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000894 f = (struct fuse *) calloc(1, sizeof(struct fuse));
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000895
Miklos Szeredia181e612001-11-06 12:03:23 +0000896 f->flags = flags;
Miklos Szeredi8cffdb92001-11-09 14:49:18 +0000897 f->fd = fd;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000898 f->ctr = 0;
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000899 /* FIXME: Dynamic hash table */
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000900 f->name_table_size = 14057;
901 f->name_table = (struct node **)
902 calloc(1, sizeof(struct node *) * f->name_table_size);
903 f->ino_table_size = 14057;
904 f->ino_table = (struct node **)
905 calloc(1, sizeof(struct node *) * f->ino_table_size);
Miklos Szeredia181e612001-11-06 12:03:23 +0000906 pthread_mutex_init(&f->lock, NULL);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000907
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000908 root = (struct node *) calloc(1, sizeof(struct node));
Miklos Szeredi8cffdb92001-11-09 14:49:18 +0000909 root->mode = 0;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000910 root->rdev = 0;
911 root->name = strdup("/");
912 root->parent = 0;
913 hash_ino(f, root, FUSE_ROOT_INO);
914
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000915 return f;
916}
917
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000918void fuse_set_operations(struct fuse *f, const struct fuse_operations *op)
919{
920 f->op = *op;
921}
922
923void fuse_destroy(struct fuse *f)
924{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000925 size_t i;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000926 for(i = 0; i < f->ino_table_size; i++) {
927 struct node *node;
928 struct node *next;
929 for(node = f->ino_table[i]; node != NULL; node = next) {
930 next = node->ino_next;
931 free_node(node);
932 }
933 }
934 free(f->ino_table);
935 free(f->name_table);
Miklos Szeredia181e612001-11-06 12:03:23 +0000936 pthread_mutex_destroy(&f->lock);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000937 free(f);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000938}