blob: b1b074903c18f903f065aa53793b26c98d2a633e [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 }
Miklos Szeredi33232032001-11-19 17:55:51 +0000322
323 pthread_mutex_lock(&f->lock);
324 f->numavail ++;
325 pthread_mutex_unlock(&f->lock);
326
Miklos Szeredi43696432001-11-18 19:15:05 +0000327 res = write(f->fd, outbuf, outsize);
328 if(res == -1) {
329 /* ENOENT means the operation was interrupted */
330 if(errno != ENOENT)
331 perror("writing fuse device");
332 }
333}
334
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000335static void send_reply(struct fuse *f, struct fuse_in_header *in, int error,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000336 void *arg, size_t argsize)
337{
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000338 char *outbuf;
339 size_t outsize;
340 struct fuse_out_header *out;
341
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000342 if(error > 0) {
343 fprintf(stderr, "positive error code: %i\n", error);
344 error = -ERANGE;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000345 }
346
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000347 if(error)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000348 argsize = 0;
349
350 outsize = sizeof(struct fuse_out_header) + argsize;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000351 outbuf = (char *) malloc(outsize);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000352 out = (struct fuse_out_header *) outbuf;
353 out->unique = in->unique;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000354 out->error = error;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000355 if(argsize != 0)
356 memcpy(outbuf + sizeof(struct fuse_out_header), arg, argsize);
357
Miklos Szeredi43696432001-11-18 19:15:05 +0000358 send_reply_raw(f, outbuf, outsize);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000359
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000360 free(outbuf);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000361}
362
363static void do_lookup(struct fuse *f, struct fuse_in_header *in, char *name)
364{
365 int res;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000366 char *path;
367 struct stat buf;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000368 struct fuse_lookup_out arg;
369
Miklos Szeredi5e183482001-10-31 14:52:35 +0000370 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000371 path = get_path_name(f, in->ino, name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000372 if(path != NULL) {
373 res = -ENOSYS;
374 if(f->op.getattr)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000375 res = f->op.getattr(path, &buf);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000376 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000377 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000378 if(res == 0) {
379 convert_stat(&buf, &arg.attr);
Miklos Szeredia181e612001-11-06 12:03:23 +0000380 arg.ino = find_node(f, in->ino, name, &arg.attr, in->unique);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000381 }
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000382 send_reply(f, in, res, &arg, sizeof(arg));
383}
384
Miklos Szeredia181e612001-11-06 12:03:23 +0000385static void do_forget(struct fuse *f, struct fuse_in_header *in,
386 struct fuse_forget_in *arg)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000387{
Miklos Szeredi43696432001-11-18 19:15:05 +0000388 if(f->flags & FUSE_DEBUG) {
389 printf("FORGET %li/%i\n", in->ino, arg->version);
390 fflush(stdout);
391 }
Miklos Szeredia181e612001-11-06 12:03:23 +0000392 destroy_node(f, in->ino, arg->version);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000393}
394
395static void do_getattr(struct fuse *f, struct fuse_in_header *in)
396{
397 int res;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000398 char *path;
399 struct stat buf;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000400 struct fuse_getattr_out arg;
401
Miklos Szeredi5e183482001-10-31 14:52:35 +0000402 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000403 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000404 if(path != NULL) {
405 res = -ENOSYS;
406 if(f->op.getattr)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000407 res = f->op.getattr(path, &buf);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000408 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000409 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000410 if(res == 0)
411 convert_stat(&buf, &arg.attr);
412
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000413 send_reply(f, in, res, &arg, sizeof(arg));
414}
415
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000416static int do_chmod(struct fuse *f, const char *path, struct fuse_attr *attr)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000417{
418 int res;
419
420 res = -ENOSYS;
421 if(f->op.chmod)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000422 res = f->op.chmod(path, attr->mode);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000423
424 return res;
425}
426
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000427static int do_chown(struct fuse *f, const char *path, struct fuse_attr *attr,
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000428 int valid)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000429{
430 int res;
431 uid_t uid = (valid & FATTR_UID) ? attr->uid : (uid_t) -1;
432 gid_t gid = (valid & FATTR_GID) ? attr->gid : (gid_t) -1;
433
434 res = -ENOSYS;
435 if(f->op.chown)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000436 res = f->op.chown(path, uid, gid);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000437
438 return res;
439}
440
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000441static int do_truncate(struct fuse *f, const char *path,
442 struct fuse_attr *attr)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000443{
444 int res;
445
446 res = -ENOSYS;
447 if(f->op.truncate)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000448 res = f->op.truncate(path, attr->size);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000449
450 return res;
451}
452
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000453static int do_utime(struct fuse *f, const char *path, struct fuse_attr *attr)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000454{
455 int res;
456 struct utimbuf buf;
457 buf.actime = attr->atime;
458 buf.modtime = attr->mtime;
459 res = -ENOSYS;
460 if(f->op.utime)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000461 res = f->op.utime(path, &buf);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000462
463 return res;
464}
465
Miklos Szeredi5e183482001-10-31 14:52:35 +0000466static void do_setattr(struct fuse *f, struct fuse_in_header *in,
467 struct fuse_setattr_in *arg)
468{
469 int res;
470 char *path;
471 int valid = arg->valid;
472 struct fuse_attr *attr = &arg->attr;
Miklos Szeredia181e612001-11-06 12:03:23 +0000473 struct fuse_setattr_out outarg;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000474
475 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000476 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000477 if(path != NULL) {
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000478 res = -ENOSYS;
479 if(f->op.getattr) {
480 res = 0;
481 if(!res && (valid & FATTR_MODE))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000482 res = do_chmod(f, path, attr);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000483 if(!res && (valid & (FATTR_UID | FATTR_GID)))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000484 res = do_chown(f, path, attr, valid);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000485 if(!res && (valid & FATTR_SIZE))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000486 res = do_truncate(f, path, attr);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000487 if(!res && (valid & FATTR_UTIME))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000488 res = do_utime(f, path, attr);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000489 if(!res) {
490 struct stat buf;
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000491 res = f->op.getattr(path, &buf);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000492 if(!res)
493 convert_stat(&buf, &outarg.attr);
Miklos Szeredia181e612001-11-06 12:03:23 +0000494 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000495 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000496 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000497 }
Miklos Szeredia181e612001-11-06 12:03:23 +0000498 send_reply(f, in, res, &outarg, sizeof(outarg));
Miklos Szeredi5e183482001-10-31 14:52:35 +0000499}
500
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000501static void do_readlink(struct fuse *f, struct fuse_in_header *in)
502{
503 int res;
504 char link[PATH_MAX + 1];
Miklos Szeredib483c932001-10-29 14:57:57 +0000505 char *path;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000506
Miklos Szeredi5e183482001-10-31 14:52:35 +0000507 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000508 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000509 if(path != NULL) {
510 res = -ENOSYS;
511 if(f->op.readlink)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000512 res = f->op.readlink(path, link, sizeof(link));
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000513 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000514 }
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000515 link[PATH_MAX] = '\0';
Miklos Szeredi5e183482001-10-31 14:52:35 +0000516 send_reply(f, in, res, link, !res ? strlen(link) : 0);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000517}
518
519static void do_getdir(struct fuse *f, struct fuse_in_header *in)
520{
521 int res;
522 struct fuse_getdir_out arg;
Miklos Szeredia181e612001-11-06 12:03:23 +0000523 struct fuse_dirhandle dh;
Miklos Szeredib483c932001-10-29 14:57:57 +0000524 char *path;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000525
Miklos Szeredib483c932001-10-29 14:57:57 +0000526 dh.fuse = f;
527 dh.fp = tmpfile();
528 dh.dir = in->ino;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000529 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000530 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000531 if(path != NULL) {
532 res = -ENOSYS;
533 if(f->op.getdir)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000534 res = f->op.getdir(path, &dh, (fuse_dirfil_t) fill_dir);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000535 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000536 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000537 fflush(dh.fp);
538 arg.fd = fileno(dh.fp);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000539 send_reply(f, in, res, &arg, sizeof(arg));
Miklos Szeredib483c932001-10-29 14:57:57 +0000540 fclose(dh.fp);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000541}
542
Miklos Szeredib483c932001-10-29 14:57:57 +0000543static void do_mknod(struct fuse *f, struct fuse_in_header *in,
544 struct fuse_mknod_in *inarg)
545{
546 int res;
547 char *path;
548 struct fuse_mknod_out outarg;
549 struct stat buf;
550
Miklos Szeredi5e183482001-10-31 14:52:35 +0000551 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000552 path = get_path_name(f, in->ino, inarg->name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000553 if(path != NULL) {
554 res = -ENOSYS;
555 if(f->op.mknod && f->op.getattr) {
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000556 res = f->op.mknod(path, inarg->mode, inarg->rdev);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000557 if(res == 0)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000558 res = f->op.getattr(path, &buf);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000559 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000560 free(path);
Miklos Szeredib483c932001-10-29 14:57:57 +0000561 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000562 if(res == 0) {
Miklos Szeredib483c932001-10-29 14:57:57 +0000563 convert_stat(&buf, &outarg.attr);
Miklos Szeredia181e612001-11-06 12:03:23 +0000564 outarg.ino = find_node(f, in->ino, inarg->name, &outarg.attr,
565 in->unique);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000566 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000567
568 send_reply(f, in, res, &outarg, sizeof(outarg));
569}
570
571static void do_mkdir(struct fuse *f, struct fuse_in_header *in,
572 struct fuse_mkdir_in *inarg)
573{
574 int res;
575 char *path;
576
Miklos Szeredi5e183482001-10-31 14:52:35 +0000577 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000578 path = get_path_name(f, in->ino, inarg->name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000579 if(path != NULL) {
580 res = -ENOSYS;
581 if(f->op.mkdir)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000582 res = f->op.mkdir(path, inarg->mode);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000583 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000584 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000585 send_reply(f, in, res, NULL, 0);
586}
587
588static void do_remove(struct fuse *f, struct fuse_in_header *in, char *name)
589{
590 int res;
591 char *path;
592
Miklos Szeredi5e183482001-10-31 14:52:35 +0000593 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000594 path = get_path_name(f, in->ino, name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000595 if(path != NULL) {
596 res = -ENOSYS;
597 if(in->opcode == FUSE_UNLINK) {
598 if(f->op.unlink)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000599 res = f->op.unlink(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000600 }
601 else {
602 if(f->op.rmdir)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000603 res = f->op.rmdir(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000604 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000605 free(path);
Miklos Szeredib483c932001-10-29 14:57:57 +0000606 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000607 if(res == 0)
608 remove_node(f, in->ino, name);
Miklos Szeredib483c932001-10-29 14:57:57 +0000609 send_reply(f, in, res, NULL, 0);
610}
611
612static void do_symlink(struct fuse *f, struct fuse_in_header *in, char *name,
613 char *link)
614{
615 int res;
616 char *path;
617
Miklos Szeredi5e183482001-10-31 14:52:35 +0000618 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000619 path = get_path_name(f, in->ino, name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000620 if(path != NULL) {
621 res = -ENOSYS;
622 if(f->op.symlink)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000623 res = f->op.symlink(link, path);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000624 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000625 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000626 send_reply(f, in, res, NULL, 0);
627}
628
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000629static void do_rename(struct fuse *f, struct fuse_in_header *in,
630 struct fuse_rename_in *inarg)
631{
632 int res;
633 fino_t olddir = in->ino;
634 fino_t newdir = inarg->newdir;
635 char *oldname = inarg->names;
636 char *newname = inarg->names + strlen(oldname) + 1;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000637 char *oldpath;
638 char *newpath;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000639
Miklos Szeredi5e183482001-10-31 14:52:35 +0000640 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000641 oldpath = get_path_name(f, olddir, oldname);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000642 if(oldpath != NULL) {
Miklos Szeredia181e612001-11-06 12:03:23 +0000643 newpath = get_path_name(f, newdir, newname);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000644 if(newpath != NULL) {
645 res = -ENOSYS;
646 if(f->op.rename)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000647 res = f->op.rename(oldpath, newpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000648 if(res == 0)
649 rename_node(f, olddir, oldname, newdir, newname);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000650 free(newpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000651 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000652 free(oldpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000653 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000654 send_reply(f, in, res, NULL, 0);
655}
656
657static void do_link(struct fuse *f, struct fuse_in_header *in,
Miklos Szeredi5e183482001-10-31 14:52:35 +0000658 struct fuse_link_in *arg)
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000659{
660 int res;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000661 char *oldpath;
662 char *newpath;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000663
Miklos Szeredi5e183482001-10-31 14:52:35 +0000664 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000665 oldpath = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000666 if(oldpath != NULL) {
Miklos Szeredia181e612001-11-06 12:03:23 +0000667 newpath = get_path_name(f, arg->newdir, arg->name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000668 if(newpath != NULL) {
669 res = -ENOSYS;
670 if(f->op.link)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000671 res = f->op.link(oldpath, newpath);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000672 free(newpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000673 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000674 free(oldpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000675 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000676 send_reply(f, in, res, NULL, 0);
677}
678
Miklos Szeredi5e183482001-10-31 14:52:35 +0000679static void do_open(struct fuse *f, struct fuse_in_header *in,
680 struct fuse_open_in *arg)
681{
682 int res;
683 char *path;
684
685 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000686 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000687 if(path != NULL) {
688 res = -ENOSYS;
689 if(f->op.open)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000690 res = f->op.open(path, arg->flags);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000691 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000692 }
693 send_reply(f, in, res, NULL, 0);
694}
695
696static void do_read(struct fuse *f, struct fuse_in_header *in,
697 struct fuse_read_in *arg)
698{
699 int res;
700 char *path;
Miklos Szeredi43696432001-11-18 19:15:05 +0000701 char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + arg->size);
702 struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
703 char *buf = outbuf + sizeof(struct fuse_out_header);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000704 size_t size;
Miklos Szeredi43696432001-11-18 19:15:05 +0000705 size_t outsize;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000706
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000707 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000708 path = get_path(f, in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000709 if(path != NULL) {
710 res = -ENOSYS;
Miklos Szeredia181e612001-11-06 12:03:23 +0000711 if(f->op.read)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000712 res = f->op.read(path, buf, arg->size, arg->offset);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000713 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000714 }
715
716 size = 0;
717 if(res > 0) {
718 size = res;
719 res = 0;
720 }
Miklos Szeredi43696432001-11-18 19:15:05 +0000721 out->unique = in->unique;
722 out->error = res;
723 outsize = sizeof(struct fuse_out_header) + size;
724
725 send_reply_raw(f, outbuf, outsize);
726 free(outbuf);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000727}
Miklos Szeredib483c932001-10-29 14:57:57 +0000728
Miklos Szeredia181e612001-11-06 12:03:23 +0000729static void do_write(struct fuse *f, struct fuse_in_header *in,
730 struct fuse_write_in *arg)
731{
732 int res;
733 char *path;
Miklos Szeredia181e612001-11-06 12:03:23 +0000734
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000735 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000736 path = get_path(f, in->ino);
737 if(path != NULL) {
738 res = -ENOSYS;
739 if(f->op.write)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000740 res = f->op.write(path, arg->buf, arg->size, arg->offset);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000741 free(path);
Miklos Szeredia181e612001-11-06 12:03:23 +0000742 }
743
744 if(res > 0) {
745 if((size_t) res != arg->size) {
746 fprintf(stderr, "short write: %u (should be %u)\n", res,
747 arg->size);
748 res = -EIO;
749 }
750 else
751 res = 0;
752 }
753
754 send_reply(f, in, res, NULL, 0);
755}
756
Miklos Szeredi43696432001-11-18 19:15:05 +0000757static void free_cmd(struct fuse_cmd *cmd)
758{
759 free(cmd->buf);
760 free(cmd);
761}
762
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000763void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
Miklos Szeredia181e612001-11-06 12:03:23 +0000764{
Miklos Szeredia181e612001-11-06 12:03:23 +0000765 struct fuse_in_header *in = (struct fuse_in_header *) cmd->buf;
766 void *inarg = cmd->buf + sizeof(struct fuse_in_header);
767 size_t argsize;
Miklos Szeredia181e612001-11-06 12:03:23 +0000768
Miklos Szeredi33232032001-11-19 17:55:51 +0000769 pthread_mutex_lock(&f->lock);
770 f->numavail --;
771 pthread_mutex_unlock(&f->lock);
772
Miklos Szeredic0938ea2001-11-07 12:35:06 +0000773 if((f->flags & FUSE_DEBUG)) {
774 printf("unique: %i, opcode: %i, ino: %li, insize: %i\n", in->unique,
775 in->opcode, in->ino, cmd->buflen);
776 fflush(stdout);
777 }
Miklos Szeredia181e612001-11-06 12:03:23 +0000778
779 argsize = cmd->buflen - sizeof(struct fuse_in_header);
780
781 switch(in->opcode) {
782 case FUSE_LOOKUP:
783 do_lookup(f, in, (char *) inarg);
784 break;
785
Miklos Szeredia181e612001-11-06 12:03:23 +0000786 case FUSE_GETATTR:
787 do_getattr(f, in);
788 break;
789
790 case FUSE_SETATTR:
791 do_setattr(f, in, (struct fuse_setattr_in *) inarg);
792 break;
793
794 case FUSE_READLINK:
795 do_readlink(f, in);
796 break;
797
798 case FUSE_GETDIR:
799 do_getdir(f, in);
800 break;
801
802 case FUSE_MKNOD:
803 do_mknod(f, in, (struct fuse_mknod_in *) inarg);
804 break;
805
806 case FUSE_MKDIR:
807 do_mkdir(f, in, (struct fuse_mkdir_in *) inarg);
808 break;
809
810 case FUSE_UNLINK:
811 case FUSE_RMDIR:
812 do_remove(f, in, (char *) inarg);
813 break;
814
815 case FUSE_SYMLINK:
816 do_symlink(f, in, (char *) inarg,
817 ((char *) inarg) + strlen((char *) inarg) + 1);
818 break;
819
820 case FUSE_RENAME:
821 do_rename(f, in, (struct fuse_rename_in *) inarg);
822 break;
823
824 case FUSE_LINK:
825 do_link(f, in, (struct fuse_link_in *) inarg);
826 break;
827
828 case FUSE_OPEN:
829 do_open(f, in, (struct fuse_open_in *) inarg);
830 break;
831
832 case FUSE_READ:
833 do_read(f, in, (struct fuse_read_in *) inarg);
834 break;
835
836 case FUSE_WRITE:
837 do_write(f, in, (struct fuse_write_in *) inarg);
838 break;
839
840 default:
841 fprintf(stderr, "Operation %i not implemented\n", in->opcode);
Miklos Szeredi43696432001-11-18 19:15:05 +0000842 send_reply(f, in, -ENOSYS, NULL, 0);
Miklos Szeredia181e612001-11-06 12:03:23 +0000843 }
Miklos Szeredi43696432001-11-18 19:15:05 +0000844
845 free_cmd(cmd);
Miklos Szeredia181e612001-11-06 12:03:23 +0000846}
847
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000848struct fuse_cmd *__fuse_read_cmd(struct fuse *f)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000849{
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000850 ssize_t res;
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000851 struct fuse_cmd *cmd;
Miklos Szeredi43696432001-11-18 19:15:05 +0000852 struct fuse_in_header *in;
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000853
Miklos Szeredi43696432001-11-18 19:15:05 +0000854 cmd = (struct fuse_cmd *) malloc(sizeof(struct fuse_cmd));
855 cmd->buf = (char *) malloc(FUSE_MAX_IN);
856
857 do {
858 res = read(f->fd, cmd->buf, FUSE_MAX_IN);
859 if(res == -1) {
860 perror("reading fuse device");
861 /* BAD... This will happen again */
862 free_cmd(cmd);
863 return NULL;
864 }
865 if((size_t) res < sizeof(struct fuse_in_header)) {
866 fprintf(stderr, "short read on fuse device\n");
867 /* Cannot happen */
868 free_cmd(cmd);
869 return NULL;
870 }
871 cmd->buflen = res;
872
873 /* FORGET is special: it can be done without calling filesystem
874 methods. */
875 in = (struct fuse_in_header *) cmd->buf;
876 if(in->opcode == FUSE_FORGET) {
877 void *inarg = cmd->buf + sizeof(struct fuse_in_header);
878 do_forget(f, in, (struct fuse_forget_in *) inarg);
879 }
880 } while(in->opcode == FUSE_FORGET);
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000881
882 return cmd;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000883}
884
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000885
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000886void fuse_loop(struct fuse *f)
887{
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000888 while(1) {
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000889 struct fuse_cmd *cmd = __fuse_read_cmd(f);
890 if(cmd == NULL)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000891 exit(1);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000892
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000893 __fuse_process_cmd(f, cmd);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000894 }
895}
896
Miklos Szeredi8cffdb92001-11-09 14:49:18 +0000897struct fuse *fuse_new(int fd, int flags)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000898{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000899 struct fuse *f;
900 struct node *root;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000901
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000902 f = (struct fuse *) calloc(1, sizeof(struct fuse));
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000903
Miklos Szeredia181e612001-11-06 12:03:23 +0000904 f->flags = flags;
Miklos Szeredi8cffdb92001-11-09 14:49:18 +0000905 f->fd = fd;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000906 f->ctr = 0;
Miklos Szeredifff56ab2001-11-16 10:12:59 +0000907 /* FIXME: Dynamic hash table */
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000908 f->name_table_size = 14057;
909 f->name_table = (struct node **)
910 calloc(1, sizeof(struct node *) * f->name_table_size);
911 f->ino_table_size = 14057;
912 f->ino_table = (struct node **)
913 calloc(1, sizeof(struct node *) * f->ino_table_size);
Miklos Szeredia181e612001-11-06 12:03:23 +0000914 pthread_mutex_init(&f->lock, NULL);
Miklos Szeredi33232032001-11-19 17:55:51 +0000915 f->numworker = 0;
916 f->numavail = 0;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000917
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000918 root = (struct node *) calloc(1, sizeof(struct node));
Miklos Szeredi8cffdb92001-11-09 14:49:18 +0000919 root->mode = 0;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000920 root->rdev = 0;
921 root->name = strdup("/");
922 root->parent = 0;
923 hash_ino(f, root, FUSE_ROOT_INO);
924
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000925 return f;
926}
927
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000928void fuse_set_operations(struct fuse *f, const struct fuse_operations *op)
929{
930 f->op = *op;
931}
932
933void fuse_destroy(struct fuse *f)
934{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000935 size_t i;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000936 for(i = 0; i < f->ino_table_size; i++) {
937 struct node *node;
938 struct node *next;
939 for(node = f->ino_table[i]; node != NULL; node = next) {
940 next = node->ino_next;
941 free_node(node);
942 }
943 }
944 free(f->ino_table);
945 free(f->name_table);
Miklos Szeredia181e612001-11-06 12:03:23 +0000946 pthread_mutex_destroy(&f->lock);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000947 free(f);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000948}