blob: 1e120e8752f459dc8f01ce4446f1a46f889b47ab [file] [log] [blame]
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001/*
2 FUSE: Filesystem in Userspace
Miklos Szeredi2e6b6f22004-07-07 19:19:53 +00003 Copyright (C) 2001-2004 Miklos Szeredi <miklos@szeredi.hu>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00004
Miklos Szeredi8b39a9f2002-10-25 12:41:16 +00005 This program can be distributed under the terms of the GNU LGPL.
6 See the file COPYING.LIB
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00007*/
8
Miklos Szeredicb264512004-06-23 18:52:50 +00009#include <config.h>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000010#include "fuse_i.h"
Miklos Szeredib9b94cd2004-12-01 18:56:39 +000011#include "fuse_kernel.h"
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000012
13#include <string.h>
Miklos Szeredi97c61e92001-11-07 12:09:43 +000014#include <stdlib.h>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000015#include <unistd.h>
Miklos Szeredi97c61e92001-11-07 12:09:43 +000016#include <limits.h>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000017#include <errno.h>
Miklos Szeredi019b4e92001-12-26 18:08:09 +000018#include <sys/param.h>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000019
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +000020#define FUSE_KERNEL_MINOR_VERSION_NEED 1
Miklos Szeredia25d4c22004-11-23 22:32:16 +000021#define FUSE_VERSION_FILE_OLD "/proc/fs/fuse/version"
Miklos Szeredi162bcbb2004-11-29 23:43:44 +000022#define FUSE_VERSION_FILE_NEW "/sys/fs/fuse/version"
Miklos Szeredia25d4c22004-11-23 22:32:16 +000023#define FUSE_DEV_OLD "/proc/fs/fuse/dev"
24
Miklos Szeredi97c61e92001-11-07 12:09:43 +000025#define FUSE_MAX_PATH 4096
Miklos Szeredi6bf8b682002-10-28 08:49:39 +000026#define PARAM(inarg) (((char *)(inarg)) + sizeof(*inarg))
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000027
Miklos Szeredi254d5ed2004-03-02 11:11:24 +000028#define ENTRY_REVALIDATE_TIME 1 /* sec */
29#define ATTR_REVALIDATE_TIME 1 /* sec */
30
Miklos Szeredid169f312004-09-22 08:48:26 +000031static struct fuse_context *(*fuse_getcontext)(void) = NULL;
32
Miklos Szeredic8ba2372002-12-10 12:26:00 +000033static const char *opname(enum fuse_opcode opcode)
34{
Miklos Szeredi7eafcce2004-06-19 22:42:38 +000035 switch (opcode) {
Miklos Szeredi3ed84232004-03-30 15:17:26 +000036 case FUSE_LOOKUP: return "LOOKUP";
37 case FUSE_FORGET: return "FORGET";
38 case FUSE_GETATTR: return "GETATTR";
39 case FUSE_SETATTR: return "SETATTR";
40 case FUSE_READLINK: return "READLINK";
41 case FUSE_SYMLINK: return "SYMLINK";
42 case FUSE_GETDIR: return "GETDIR";
43 case FUSE_MKNOD: return "MKNOD";
44 case FUSE_MKDIR: return "MKDIR";
45 case FUSE_UNLINK: return "UNLINK";
46 case FUSE_RMDIR: return "RMDIR";
47 case FUSE_RENAME: return "RENAME";
48 case FUSE_LINK: return "LINK";
49 case FUSE_OPEN: return "OPEN";
50 case FUSE_READ: return "READ";
51 case FUSE_WRITE: return "WRITE";
52 case FUSE_STATFS: return "STATFS";
Miklos Szeredi99f20742004-05-19 08:01:10 +000053 case FUSE_FLUSH: return "FLUSH";
Miklos Szeredi3ed84232004-03-30 15:17:26 +000054 case FUSE_RELEASE: return "RELEASE";
55 case FUSE_FSYNC: return "FSYNC";
56 case FUSE_SETXATTR: return "SETXATTR";
57 case FUSE_GETXATTR: return "GETXATTR";
58 case FUSE_LISTXATTR: return "LISTXATTR";
59 case FUSE_REMOVEXATTR: return "REMOVEXATTR";
Miklos Szeredi99f20742004-05-19 08:01:10 +000060 default: return "???";
Miklos Szeredic8ba2372002-12-10 12:26:00 +000061 }
62}
63
Miklos Szeredi99ddf0e2001-11-25 17:19:59 +000064static inline void dec_avail(struct fuse *f)
65{
66 pthread_mutex_lock(&f->lock);
67 f->numavail --;
68 pthread_mutex_unlock(&f->lock);
69}
70
Miklos Szeredif458b8c2004-12-07 16:46:42 +000071static struct node *get_node_nocheck(struct fuse *f, nodeid_t nodeid)
Miklos Szeredia181e612001-11-06 12:03:23 +000072{
Miklos Szeredia13d9002004-11-02 17:32:03 +000073 size_t hash = nodeid % f->id_table_size;
Miklos Szeredi97c61e92001-11-07 12:09:43 +000074 struct node *node;
75
Miklos Szeredia13d9002004-11-02 17:32:03 +000076 for (node = f->id_table[hash]; node != NULL; node = node->id_next)
77 if (node->nodeid == nodeid)
Miklos Szeredi97c61e92001-11-07 12:09:43 +000078 return node;
79
80 return NULL;
Miklos Szeredia181e612001-11-06 12:03:23 +000081}
82
Miklos Szeredia13d9002004-11-02 17:32:03 +000083static struct node *get_node(struct fuse *f, nodeid_t nodeid)
Miklos Szeredia181e612001-11-06 12:03:23 +000084{
Miklos Szeredif458b8c2004-12-07 16:46:42 +000085 struct node *node = get_node_nocheck(f, nodeid);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +000086 if (node != NULL)
Miklos Szeredi97c61e92001-11-07 12:09:43 +000087 return node;
88
Miklos Szeredia13d9002004-11-02 17:32:03 +000089 fprintf(stderr, "fuse internal error: inode %lu not found\n", nodeid);
Miklos Szeredi97c61e92001-11-07 12:09:43 +000090 abort();
Miklos Szeredia181e612001-11-06 12:03:23 +000091}
92
Miklos Szeredia13d9002004-11-02 17:32:03 +000093static void hash_id(struct fuse *f, struct node *node)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000094{
Miklos Szeredia13d9002004-11-02 17:32:03 +000095 size_t hash = node->nodeid % f->id_table_size;
96 node->id_next = f->id_table[hash];
97 f->id_table[hash] = node;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000098}
99
Miklos Szeredia13d9002004-11-02 17:32:03 +0000100static void unhash_id(struct fuse *f, struct node *node)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000101{
Miklos Szeredia13d9002004-11-02 17:32:03 +0000102 size_t hash = node->nodeid % f->id_table_size;
103 struct node **nodep = &f->id_table[hash];
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000104
Miklos Szeredia13d9002004-11-02 17:32:03 +0000105 for (; *nodep != NULL; nodep = &(*nodep)->id_next)
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000106 if (*nodep == node) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000107 *nodep = node->id_next;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000108 return;
109 }
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000110}
111
Miklos Szeredia13d9002004-11-02 17:32:03 +0000112static nodeid_t next_id(struct fuse *f)
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000113{
Miklos Szeredi76f65782004-02-19 16:55:40 +0000114 do {
115 f->ctr++;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000116 if (!f->ctr)
Miklos Szeredi76f65782004-02-19 16:55:40 +0000117 f->generation ++;
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000118 } while (f->ctr == 0 || get_node_nocheck(f, f->ctr) != NULL);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000119 return f->ctr;
120}
121
122static void free_node(struct node *node)
123{
124 free(node->name);
125 free(node);
126}
127
Miklos Szeredia13d9002004-11-02 17:32:03 +0000128static unsigned int name_hash(struct fuse *f, nodeid_t parent, const char *name)
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000129{
130 unsigned int hash = *name;
131
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000132 if (hash)
133 for (name += 1; *name != '\0'; name++)
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000134 hash = (hash << 5) - hash + *name;
135
136 return (hash + parent) % f->name_table_size;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000137}
138
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000139static struct node *lookup_node(struct fuse *f, nodeid_t parent,
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000140 const char *name)
141{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000142 size_t hash = name_hash(f, parent, name);
143 struct node *node;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000144
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000145 for (node = f->name_table[hash]; node != NULL; node = node->name_next)
146 if (node->parent == parent && strcmp(node->name, name) == 0)
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000147 return node;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000148
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000149 return NULL;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000150}
151
Miklos Szeredia13d9002004-11-02 17:32:03 +0000152static int hash_name(struct fuse *f, struct node *node, nodeid_t parent,
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000153 const char *name)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000154{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000155 size_t hash = name_hash(f, parent, name);
Miklos Szeredia181e612001-11-06 12:03:23 +0000156 node->parent = parent;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000157 node->name = strdup(name);
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000158 if (node->name == NULL)
159 return -1;
160
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000161 node->name_next = f->name_table[hash];
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000162 f->name_table[hash] = node;
163 return 0;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000164}
165
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000166static void unhash_name(struct fuse *f, struct node *node)
Miklos Szeredia181e612001-11-06 12:03:23 +0000167{
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000168 if (node->name != NULL) {
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000169 size_t hash = name_hash(f, node->parent, node->name);
170 struct node **nodep = &f->name_table[hash];
171
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000172 for (; *nodep != NULL; nodep = &(*nodep)->name_next)
173 if (*nodep == node) {
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000174 *nodep = node->name_next;
175 node->name_next = NULL;
176 free(node->name);
177 node->name = NULL;
178 node->parent = 0;
179 return;
180 }
181 fprintf(stderr, "fuse internal error: unable to unhash node: %lu\n",
Miklos Szeredia13d9002004-11-02 17:32:03 +0000182 node->nodeid);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000183 abort();
Miklos Szeredia181e612001-11-06 12:03:23 +0000184 }
185}
186
Miklos Szeredia13d9002004-11-02 17:32:03 +0000187static struct node *find_node(struct fuse *f, nodeid_t parent, char *name,
Miklos Szeredi76f65782004-02-19 16:55:40 +0000188 struct fuse_attr *attr, int version)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000189{
190 struct node *node;
Miklos Szeredia181e612001-11-06 12:03:23 +0000191 int mode = attr->mode & S_IFMT;
192 int rdev = 0;
193
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000194 if (S_ISCHR(mode) || S_ISBLK(mode))
Miklos Szeredia181e612001-11-06 12:03:23 +0000195 rdev = attr->rdev;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000196
Miklos Szeredia181e612001-11-06 12:03:23 +0000197 pthread_mutex_lock(&f->lock);
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000198 node = lookup_node(f, parent, name);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000199 if (node != NULL) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000200 if (node->mode == mode && node->rdev == rdev &&
201 (!(f->flags & FUSE_USE_INO) || node->ino == attr->ino)) {
202 if (!(f->flags & FUSE_USE_INO))
203 attr->ino = node->nodeid;
204
Miklos Szeredia181e612001-11-06 12:03:23 +0000205 goto out;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000206 }
Miklos Szeredia181e612001-11-06 12:03:23 +0000207
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000208 unhash_name(f, node);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000209 }
210
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000211 node = (struct node *) calloc(1, sizeof(struct node));
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000212 if (node == NULL)
Miklos Szeredic2309912004-09-21 13:40:38 +0000213 goto out_err;
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000214
Miklos Szeredia13d9002004-11-02 17:32:03 +0000215 node->nodeid = next_id(f);
216 if (!(f->flags & FUSE_USE_INO))
217 attr->ino = node->nodeid;
Miklos Szeredia181e612001-11-06 12:03:23 +0000218 node->mode = mode;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000219 node->rdev = rdev;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000220 node->ino = attr->ino;
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000221 node->open_count = 0;
222 node->is_hidden = 0;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000223 node->generation = f->generation;
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000224 if (hash_name(f, node, parent, name) == -1) {
225 free(node);
Miklos Szeredic2309912004-09-21 13:40:38 +0000226 node = NULL;
227 goto out_err;
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000228 }
Miklos Szeredia13d9002004-11-02 17:32:03 +0000229 hash_id(f, node);
Miklos Szeredia181e612001-11-06 12:03:23 +0000230
Miklos Szeredic2309912004-09-21 13:40:38 +0000231 out:
Miklos Szeredia181e612001-11-06 12:03:23 +0000232 node->version = version;
Miklos Szeredic2309912004-09-21 13:40:38 +0000233 out_err:
Miklos Szeredia181e612001-11-06 12:03:23 +0000234 pthread_mutex_unlock(&f->lock);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000235 return node;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000236}
237
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000238static char *add_name(char *buf, char *s, const char *name)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000239{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000240 size_t len = strlen(name);
241 s -= len;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000242 if (s <= buf) {
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000243 fprintf(stderr, "fuse: path too long: ...%s\n", s + len);
244 return NULL;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000245 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000246 strncpy(s, name, len);
247 s--;
248 *s = '/';
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000249
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000250 return s;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000251}
252
Miklos Szeredia13d9002004-11-02 17:32:03 +0000253static char *get_path_name(struct fuse *f, nodeid_t nodeid, const char *name)
Miklos Szeredib483c932001-10-29 14:57:57 +0000254{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000255 char buf[FUSE_MAX_PATH];
256 char *s = buf + FUSE_MAX_PATH - 1;
257 struct node *node;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000258
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000259 *s = '\0';
Miklos Szeredia181e612001-11-06 12:03:23 +0000260
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000261 if (name != NULL) {
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000262 s = add_name(buf, s, name);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000263 if (s == NULL)
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000264 return NULL;
265 }
266
267 pthread_mutex_lock(&f->lock);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000268 for (node = get_node(f, nodeid); node->nodeid != FUSE_ROOT_ID;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000269 node = get_node(f, node->parent)) {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000270 if (node->name == NULL) {
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000271 s = NULL;
272 break;
273 }
274
275 s = add_name(buf, s, node->name);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000276 if (s == NULL)
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000277 break;
278 }
279 pthread_mutex_unlock(&f->lock);
280
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000281 if (s == NULL)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000282 return NULL;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000283 else if (*s == '\0')
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000284 return strdup("/");
285 else
286 return strdup(s);
287}
Miklos Szeredia181e612001-11-06 12:03:23 +0000288
Miklos Szeredia13d9002004-11-02 17:32:03 +0000289static char *get_path(struct fuse *f, nodeid_t nodeid)
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000290{
Miklos Szeredia13d9002004-11-02 17:32:03 +0000291 return get_path_name(f, nodeid, NULL);
Miklos Szeredib483c932001-10-29 14:57:57 +0000292}
293
Miklos Szeredia13d9002004-11-02 17:32:03 +0000294static void destroy_node(struct fuse *f, nodeid_t nodeid, int version)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000295{
Miklos Szeredia181e612001-11-06 12:03:23 +0000296 struct node *node;
297
298 pthread_mutex_lock(&f->lock);
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000299 node = get_node_nocheck(f, nodeid);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000300 if (node && node->version == version && nodeid != FUSE_ROOT_ID) {
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000301 unhash_name(f, node);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000302 unhash_id(f, node);
Miklos Szeredia181e612001-11-06 12:03:23 +0000303 free_node(node);
304 }
305 pthread_mutex_unlock(&f->lock);
306
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000307}
308
Miklos Szeredia13d9002004-11-02 17:32:03 +0000309static void remove_node(struct fuse *f, nodeid_t dir, const char *name)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000310{
Miklos Szeredia181e612001-11-06 12:03:23 +0000311 struct node *node;
312
313 pthread_mutex_lock(&f->lock);
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000314 node = lookup_node(f, dir, name);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000315 if (node == NULL) {
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000316 fprintf(stderr, "fuse internal error: unable to remove node %lu/%s\n",
317 dir, name);
318 abort();
319 }
320 unhash_name(f, node);
Miklos Szeredia181e612001-11-06 12:03:23 +0000321 pthread_mutex_unlock(&f->lock);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000322}
323
Miklos Szeredia13d9002004-11-02 17:32:03 +0000324static int rename_node(struct fuse *f, nodeid_t olddir, const char *oldname,
325 nodeid_t newdir, const char *newname, int hide)
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000326{
Miklos Szeredia181e612001-11-06 12:03:23 +0000327 struct node *node;
328 struct node *newnode;
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000329 int err = 0;
Miklos Szeredia181e612001-11-06 12:03:23 +0000330
331 pthread_mutex_lock(&f->lock);
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000332 node = lookup_node(f, olddir, oldname);
333 newnode = lookup_node(f, newdir, newname);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000334 if (node == NULL) {
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000335 fprintf(stderr, "fuse internal error: unable to rename node %lu/%s\n",
336 olddir, oldname);
337 abort();
338 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000339
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000340 if (newnode != NULL) {
341 if (hide) {
342 fprintf(stderr, "fuse: hidden file got created during hiding\n");
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000343 err = -EBUSY;
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000344 goto out;
345 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000346 unhash_name(f, newnode);
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000347 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000348
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000349 unhash_name(f, node);
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000350 if (hash_name(f, node, newdir, newname) == -1) {
351 err = -ENOMEM;
352 goto out;
353 }
354
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000355 if (hide)
356 node->is_hidden = 1;
357
358 out:
Miklos Szeredia181e612001-11-06 12:03:23 +0000359 pthread_mutex_unlock(&f->lock);
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000360 return err;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000361}
362
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000363static void convert_stat(struct stat *stbuf, struct fuse_attr *attr)
364{
Miklos Szeredia13d9002004-11-02 17:32:03 +0000365 attr->ino = stbuf->st_ino;
Miklos Szeredib5958612004-02-20 14:10:49 +0000366 attr->mode = stbuf->st_mode;
367 attr->nlink = stbuf->st_nlink;
368 attr->uid = stbuf->st_uid;
369 attr->gid = stbuf->st_gid;
370 attr->rdev = stbuf->st_rdev;
371 attr->size = stbuf->st_size;
372 attr->blocks = stbuf->st_blocks;
373 attr->atime = stbuf->st_atime;
Miklos Szeredib5958612004-02-20 14:10:49 +0000374 attr->mtime = stbuf->st_mtime;
Miklos Szeredib5958612004-02-20 14:10:49 +0000375 attr->ctime = stbuf->st_ctime;
Miklos Szeredicb264512004-06-23 18:52:50 +0000376#ifdef HAVE_STRUCT_STAT_ST_ATIM
377 attr->atimensec = stbuf->st_atim.tv_nsec;
378 attr->mtimensec = stbuf->st_mtim.tv_nsec;
Miklos Szeredib5958612004-02-20 14:10:49 +0000379 attr->ctimensec = stbuf->st_ctim.tv_nsec;
Miklos Szeredicb264512004-06-23 18:52:50 +0000380#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000381}
382
Miklos Szeredi8fb48fe2004-11-08 14:48:52 +0000383static int fill_dir(struct fuse_dirhandle *dh, const char *name, int type,
384 ino_t ino)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000385{
386 struct fuse_dirent dirent;
387 size_t reclen;
388 size_t res;
389
Miklos Szeredi8fb48fe2004-11-08 14:48:52 +0000390 if ((dh->fuse->flags & FUSE_USE_INO))
391 dirent.ino = ino;
392 else
393 dirent.ino = (unsigned long) -1;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000394 dirent.namelen = strlen(name);
395 strncpy(dirent.name, name, sizeof(dirent.name));
396 dirent.type = type;
397 reclen = FUSE_DIRENT_SIZE(&dirent);
398 res = fwrite(&dirent, reclen, 1, dh->fp);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000399 if (res == 0) {
Miklos Szeredi96249982001-11-21 12:21:19 +0000400 perror("fuse: writing directory file");
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000401 return -EIO;
402 }
403 return 0;
404}
405
Miklos Szeredi73798f92004-07-12 15:55:11 +0000406static int send_reply_raw(struct fuse *f, char *outbuf, size_t outsize,
407 int locked)
Miklos Szeredi43696432001-11-18 19:15:05 +0000408{
409 int res;
410
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000411 if ((f->flags & FUSE_DEBUG)) {
Miklos Szeredi43696432001-11-18 19:15:05 +0000412 struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
413 printf(" unique: %i, error: %i (%s), outsize: %i\n", out->unique,
414 out->error, strerror(-out->error), outsize);
415 fflush(stdout);
416 }
Miklos Szeredi99ddf0e2001-11-25 17:19:59 +0000417
Miklos Szeredi4e71c9f2004-02-09 12:05:14 +0000418 /* This needs to be done before the reply, otherwise the scheduler
419 could play tricks with us, and only let the counter be increased
Miklos Szeredi99ddf0e2001-11-25 17:19:59 +0000420 long after the operation is done */
Miklos Szeredi73798f92004-07-12 15:55:11 +0000421 if (!locked)
422 pthread_mutex_lock(&f->lock);
423 f->numavail ++;
424 if (!locked)
425 pthread_mutex_unlock(&f->lock);
Miklos Szeredi99ddf0e2001-11-25 17:19:59 +0000426
Miklos Szeredi43696432001-11-18 19:15:05 +0000427 res = write(f->fd, outbuf, outsize);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000428 if (res == -1) {
Miklos Szeredi43696432001-11-18 19:15:05 +0000429 /* ENOENT means the operation was interrupted */
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000430 if (!f->exited && errno != ENOENT)
Miklos Szeredi96249982001-11-21 12:21:19 +0000431 perror("fuse: writing device");
Miklos Szeredi40b9a5a2002-12-10 16:09:02 +0000432 return -errno;
Miklos Szeredi43696432001-11-18 19:15:05 +0000433 }
Miklos Szeredi40b9a5a2002-12-10 16:09:02 +0000434 return 0;
Miklos Szeredi43696432001-11-18 19:15:05 +0000435}
436
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000437static int do_send_reply(struct fuse *f, struct fuse_in_header *in, int error,
438 void *arg, size_t argsize, int locked)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000439{
Miklos Szeredi40b9a5a2002-12-10 16:09:02 +0000440 int res;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000441 char *outbuf;
442 size_t outsize;
443 struct fuse_out_header *out;
444
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000445 if (error <= -1000 || error > 0) {
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000446 fprintf(stderr, "fuse: bad error value: %i\n", error);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000447 error = -ERANGE;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000448 }
449
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000450 if (error)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000451 argsize = 0;
452
453 outsize = sizeof(struct fuse_out_header) + argsize;
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000454 outbuf = (char *) malloc(outsize);
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000455 if (outbuf == NULL) {
456 fprintf(stderr, "fuse: failed to allocate reply buffer\n");
457 res = -ENOMEM;
458 } else {
459 out = (struct fuse_out_header *) outbuf;
460 memset(out, 0, sizeof(struct fuse_out_header));
461 out->unique = in->unique;
462 out->error = error;
463 if (argsize != 0)
464 memcpy(outbuf + sizeof(struct fuse_out_header), arg, argsize);
465
466 res = send_reply_raw(f, outbuf, outsize, locked);
467 free(outbuf);
468 }
Miklos Szeredi40b9a5a2002-12-10 16:09:02 +0000469
470 return res;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000471}
472
Miklos Szeredi73798f92004-07-12 15:55:11 +0000473static int send_reply(struct fuse *f, struct fuse_in_header *in, int error,
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000474 void *arg, size_t argsize)
Miklos Szeredi73798f92004-07-12 15:55:11 +0000475{
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000476 return do_send_reply(f, in, error, arg, argsize, 0);
477}
478
479static int send_reply_locked(struct fuse *f, struct fuse_in_header *in,
480 int error, void *arg, size_t argsize)
481{
482 return do_send_reply(f, in, error, arg, argsize, 1);
Miklos Szeredi73798f92004-07-12 15:55:11 +0000483}
484
Miklos Szeredia13d9002004-11-02 17:32:03 +0000485static int is_open(struct fuse *f, nodeid_t dir, const char *name)
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000486{
487 struct node *node;
488 int isopen = 0;
489 pthread_mutex_lock(&f->lock);
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000490 node = lookup_node(f, dir, name);
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000491 if (node && node->open_count > 0)
492 isopen = 1;
493 pthread_mutex_unlock(&f->lock);
494 return isopen;
495}
496
Miklos Szeredia13d9002004-11-02 17:32:03 +0000497static char *hidden_name(struct fuse *f, nodeid_t dir, const char *oldname,
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000498 char *newname, size_t bufsize)
499{
500 struct stat buf;
501 struct node *node;
502 struct node *newnode;
503 char *newpath;
504 int res;
505 int failctr = 10;
506
507 if (!f->op.getattr)
508 return NULL;
509
510 do {
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000511 pthread_mutex_lock(&f->lock);
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000512 node = lookup_node(f, dir, oldname);
513 if (node == NULL) {
514 fprintf(stderr, "fuse internal error: node %lu/%s not found\n",
515 dir, oldname);
516 abort();
517 }
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000518 do {
519 f->hidectr ++;
520 snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
Miklos Szeredia13d9002004-11-02 17:32:03 +0000521 (unsigned int) node->nodeid, f->hidectr);
Miklos Szeredif458b8c2004-12-07 16:46:42 +0000522 newnode = lookup_node(f, dir, newname);
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000523 } while(newnode);
524 pthread_mutex_unlock(&f->lock);
525
526 newpath = get_path_name(f, dir, newname);
527 if (!newpath)
528 break;
529
530 res = f->op.getattr(newpath, &buf);
531 if (res != 0)
532 break;
533 free(newpath);
534 newpath = NULL;
535 } while(--failctr);
536
537 return newpath;
538}
539
Miklos Szeredia13d9002004-11-02 17:32:03 +0000540static int hide_node(struct fuse *f, const char *oldpath, nodeid_t dir,
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000541 const char *oldname)
542{
543 char newname[64];
544 char *newpath;
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000545 int err = -EBUSY;
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000546
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000547 if (f->op.rename && f->op.unlink) {
548 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
549 if (newpath) {
550 int res = f->op.rename(oldpath, newpath);
551 if (res == 0)
552 err = rename_node(f, dir, oldname, dir, newname, 1);
553 free(newpath);
554 }
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000555 }
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000556 return err;
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000557}
558
Miklos Szeredia13d9002004-11-02 17:32:03 +0000559static int lookup_path(struct fuse *f, nodeid_t nodeid, int version, char *name,
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000560 const char *path, struct fuse_entry_out *arg)
Miklos Szeredi76f65782004-02-19 16:55:40 +0000561{
562 int res;
563 struct stat buf;
564
565 res = f->op.getattr(path, &buf);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000566 if (res == 0) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000567 struct node *node;
568
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000569 memset(arg, 0, sizeof(struct fuse_entry_out));
Miklos Szeredi76f65782004-02-19 16:55:40 +0000570 convert_stat(&buf, &arg->attr);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000571 node = find_node(f, nodeid, name, &arg->attr, version);
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000572 if (node == NULL)
573 res = -ENOMEM;
574 else {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000575 arg->nodeid = node->nodeid;
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000576 arg->generation = node->generation;
577 arg->entry_valid = ENTRY_REVALIDATE_TIME;
578 arg->entry_valid_nsec = 0;
579 arg->attr_valid = ATTR_REVALIDATE_TIME;
580 arg->attr_valid_nsec = 0;
581 if (f->flags & FUSE_DEBUG) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000582 printf(" NODEID: %li\n", arg->nodeid);
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000583 fflush(stdout);
584 }
Miklos Szeredi76f65782004-02-19 16:55:40 +0000585 }
586 }
587 return res;
588}
589
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000590static void do_lookup(struct fuse *f, struct fuse_in_header *in, char *name)
591{
592 int res;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000593 int res2;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000594 char *path;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000595 struct fuse_entry_out arg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000596
Miklos Szeredi5e183482001-10-31 14:52:35 +0000597 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000598 path = get_path_name(f, in->nodeid, name);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000599 if (path != NULL) {
600 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi6ebe2342002-01-06 21:44:16 +0000601 printf("LOOKUP %s\n", path);
602 fflush(stdout);
603 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000604 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000605 if (f->op.getattr)
Miklos Szeredia13d9002004-11-02 17:32:03 +0000606 res = lookup_path(f, in->nodeid, in->unique, name, path, &arg);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000607 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000608 }
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000609 res2 = send_reply(f, in, res, &arg, sizeof(arg));
610 if (res == 0 && res2 == -ENOENT)
Miklos Szeredia13d9002004-11-02 17:32:03 +0000611 destroy_node(f, arg.nodeid, in->unique);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000612}
613
Miklos Szeredia181e612001-11-06 12:03:23 +0000614static void do_forget(struct fuse *f, struct fuse_in_header *in,
615 struct fuse_forget_in *arg)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000616{
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000617 if (f->flags & FUSE_DEBUG) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000618 printf("FORGET %li/%i\n", in->nodeid, arg->version);
Miklos Szeredi43696432001-11-18 19:15:05 +0000619 fflush(stdout);
620 }
Miklos Szeredia13d9002004-11-02 17:32:03 +0000621 destroy_node(f, in->nodeid, arg->version);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000622}
623
624static void do_getattr(struct fuse *f, struct fuse_in_header *in)
625{
626 int res;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000627 char *path;
628 struct stat buf;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000629 struct fuse_attr_out arg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000630
Miklos Szeredi5e183482001-10-31 14:52:35 +0000631 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000632 path = get_path(f, in->nodeid);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000633 if (path != NULL) {
Miklos Szeredi5e183482001-10-31 14:52:35 +0000634 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000635 if (f->op.getattr)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000636 res = f->op.getattr(path, &buf);
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000637 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000638 }
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000639
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000640 if (res == 0) {
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000641 memset(&arg, 0, sizeof(struct fuse_attr_out));
642 arg.attr_valid = ATTR_REVALIDATE_TIME;
643 arg.attr_valid_nsec = 0;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000644 convert_stat(&buf, &arg.attr);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000645 if (!(f->flags & FUSE_USE_INO))
646 arg.attr.ino = in->nodeid;
647 else {
648 struct node *node = get_node(f, in->nodeid);
649 node->ino = arg.attr.ino;
650 }
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000651 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000652
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000653 send_reply(f, in, res, &arg, sizeof(arg));
654}
655
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000656static int do_chmod(struct fuse *f, const char *path, struct fuse_attr *attr)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000657{
658 int res;
659
660 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000661 if (f->op.chmod)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000662 res = f->op.chmod(path, attr->mode);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000663
664 return res;
665}
666
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000667static int do_chown(struct fuse *f, const char *path, struct fuse_attr *attr,
Miklos Szeredi2e50d432001-12-20 12:17:25 +0000668 int valid)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000669{
670 int res;
671 uid_t uid = (valid & FATTR_UID) ? attr->uid : (uid_t) -1;
672 gid_t gid = (valid & FATTR_GID) ? attr->gid : (gid_t) -1;
673
674 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000675 if (f->op.chown)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000676 res = f->op.chown(path, uid, gid);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000677
678 return res;
679}
680
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000681static int do_truncate(struct fuse *f, const char *path,
682 struct fuse_attr *attr)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000683{
684 int res;
685
686 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000687 if (f->op.truncate)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000688 res = f->op.truncate(path, attr->size);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000689
690 return res;
691}
692
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000693static int do_utime(struct fuse *f, const char *path, struct fuse_attr *attr)
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000694{
695 int res;
696 struct utimbuf buf;
697 buf.actime = attr->atime;
698 buf.modtime = attr->mtime;
699 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000700 if (f->op.utime)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000701 res = f->op.utime(path, &buf);
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000702
703 return res;
704}
705
Miklos Szeredi5e183482001-10-31 14:52:35 +0000706static void do_setattr(struct fuse *f, struct fuse_in_header *in,
707 struct fuse_setattr_in *arg)
708{
709 int res;
710 char *path;
711 int valid = arg->valid;
712 struct fuse_attr *attr = &arg->attr;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000713 struct fuse_attr_out outarg;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000714
715 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000716 path = get_path(f, in->nodeid);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000717 if (path != NULL) {
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000718 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000719 if (f->op.getattr) {
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000720 res = 0;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000721 if (!res && (valid & FATTR_MODE))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000722 res = do_chmod(f, path, attr);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000723 if (!res && (valid & (FATTR_UID | FATTR_GID)))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000724 res = do_chown(f, path, attr, valid);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000725 if (!res && (valid & FATTR_SIZE))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000726 res = do_truncate(f, path, attr);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000727 if (!res && (valid & (FATTR_ATIME | FATTR_MTIME)) ==
Miklos Szeredib5958612004-02-20 14:10:49 +0000728 (FATTR_ATIME | FATTR_MTIME))
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000729 res = do_utime(f, path, attr);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000730 if (!res) {
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000731 struct stat buf;
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000732 res = f->op.getattr(path, &buf);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000733 if (!res) {
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000734 memset(&outarg, 0, sizeof(struct fuse_attr_out));
735 outarg.attr_valid = ATTR_REVALIDATE_TIME;
736 outarg.attr_valid_nsec = 0;
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000737 convert_stat(&buf, &outarg.attr);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000738 if (!(f->flags & FUSE_USE_INO))
739 outarg.attr.ino = in->nodeid;
740 else {
741 struct node *node = get_node(f, in->nodeid);
742 node->ino = outarg.attr.ino;
743 }
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000744 }
Miklos Szeredia181e612001-11-06 12:03:23 +0000745 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000746 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000747 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000748 }
Miklos Szeredia181e612001-11-06 12:03:23 +0000749 send_reply(f, in, res, &outarg, sizeof(outarg));
Miklos Szeredi5e183482001-10-31 14:52:35 +0000750}
751
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000752static void do_readlink(struct fuse *f, struct fuse_in_header *in)
753{
754 int res;
755 char link[PATH_MAX + 1];
Miklos Szeredib483c932001-10-29 14:57:57 +0000756 char *path;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000757
Miklos Szeredi5e183482001-10-31 14:52:35 +0000758 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000759 path = get_path(f, in->nodeid);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000760 if (path != NULL) {
Miklos Szeredi5e183482001-10-31 14:52:35 +0000761 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000762 if (f->op.readlink)
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000763 res = f->op.readlink(path, link, sizeof(link));
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000764 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000765 }
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000766 link[PATH_MAX] = '\0';
Miklos Szeredi4b2bef42002-01-09 12:23:27 +0000767 send_reply(f, in, res, link, res == 0 ? strlen(link) : 0);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000768}
769
770static void do_getdir(struct fuse *f, struct fuse_in_header *in)
771{
772 int res;
773 struct fuse_getdir_out arg;
Miklos Szeredia181e612001-11-06 12:03:23 +0000774 struct fuse_dirhandle dh;
Miklos Szeredib483c932001-10-29 14:57:57 +0000775 char *path;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000776
Miklos Szeredib483c932001-10-29 14:57:57 +0000777 dh.fuse = f;
778 dh.fp = tmpfile();
Miklos Szeredia13d9002004-11-02 17:32:03 +0000779 dh.dir = in->nodeid;
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000780
Miklos Szeredi65afea12004-09-14 07:13:45 +0000781 res = -EIO;
782 if (dh.fp == NULL)
783 perror("fuse: failed to create temporary file");
784 else {
785 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000786 path = get_path(f, in->nodeid);
Miklos Szeredi65afea12004-09-14 07:13:45 +0000787 if (path != NULL) {
788 res = -ENOSYS;
789 if (f->op.getdir)
Miklos Szeredi8fb48fe2004-11-08 14:48:52 +0000790 res = f->op.getdir(path, &dh, fill_dir);
Miklos Szeredi65afea12004-09-14 07:13:45 +0000791 free(path);
792 }
793 fflush(dh.fp);
794 }
Miklos Szeredi0f48a262002-12-05 14:23:01 +0000795 memset(&arg, 0, sizeof(struct fuse_getdir_out));
Miklos Szeredi65afea12004-09-14 07:13:45 +0000796 if (res == 0)
797 arg.fd = fileno(dh.fp);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000798 send_reply(f, in, res, &arg, sizeof(arg));
Miklos Szeredi65afea12004-09-14 07:13:45 +0000799 if (dh.fp != NULL)
800 fclose(dh.fp);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000801}
802
Miklos Szeredib483c932001-10-29 14:57:57 +0000803static void do_mknod(struct fuse *f, struct fuse_in_header *in,
804 struct fuse_mknod_in *inarg)
805{
806 int res;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000807 int res2;
Miklos Szeredib483c932001-10-29 14:57:57 +0000808 char *path;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000809 char *name = PARAM(inarg);
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000810 struct fuse_entry_out outarg;
Miklos Szeredib483c932001-10-29 14:57:57 +0000811
Miklos Szeredi5e183482001-10-31 14:52:35 +0000812 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000813 path = get_path_name(f, in->nodeid, name);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000814 if (path != NULL) {
815 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000816 printf("MKNOD %s\n", path);
817 fflush(stdout);
818 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000819 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000820 if (f->op.mknod && f->op.getattr) {
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000821 res = f->op.mknod(path, inarg->mode, inarg->rdev);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000822 if (res == 0)
Miklos Szeredia13d9002004-11-02 17:32:03 +0000823 res = lookup_path(f, in->nodeid, in->unique, name, path, &outarg);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000824 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000825 free(path);
Miklos Szeredib483c932001-10-29 14:57:57 +0000826 }
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000827 res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
828 if (res == 0 && res2 == -ENOENT)
Miklos Szeredia13d9002004-11-02 17:32:03 +0000829 destroy_node(f, outarg.nodeid, in->unique);
Miklos Szeredib483c932001-10-29 14:57:57 +0000830}
831
832static void do_mkdir(struct fuse *f, struct fuse_in_header *in,
833 struct fuse_mkdir_in *inarg)
834{
835 int res;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000836 int res2;
Miklos Szeredib483c932001-10-29 14:57:57 +0000837 char *path;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000838 char *name = PARAM(inarg);
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000839 struct fuse_entry_out outarg;
Miklos Szeredib483c932001-10-29 14:57:57 +0000840
Miklos Szeredi5e183482001-10-31 14:52:35 +0000841 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000842 path = get_path_name(f, in->nodeid, name);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000843 if (path != NULL) {
844 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000845 printf("MKDIR %s\n", path);
846 fflush(stdout);
847 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000848 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000849 if (f->op.mkdir && f->op.getattr) {
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000850 res = f->op.mkdir(path, inarg->mode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000851 if (res == 0)
Miklos Szeredia13d9002004-11-02 17:32:03 +0000852 res = lookup_path(f, in->nodeid, in->unique, name, path, &outarg);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000853 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000854 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000855 }
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000856 res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
857 if (res == 0 && res2 == -ENOENT)
Miklos Szeredia13d9002004-11-02 17:32:03 +0000858 destroy_node(f, outarg.nodeid, in->unique);
Miklos Szeredib483c932001-10-29 14:57:57 +0000859}
860
Miklos Szeredib5958612004-02-20 14:10:49 +0000861static void do_unlink(struct fuse *f, struct fuse_in_header *in, char *name)
Miklos Szeredib483c932001-10-29 14:57:57 +0000862{
863 int res;
864 char *path;
865
Miklos Szeredi5e183482001-10-31 14:52:35 +0000866 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000867 path = get_path_name(f, in->nodeid, name);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000868 if (path != NULL) {
Miklos Szeredi209f5d02004-07-24 19:56:16 +0000869 if (f->flags & FUSE_DEBUG) {
870 printf("UNLINK %s\n", path);
871 fflush(stdout);
872 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000873 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000874 if (f->op.unlink) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000875 if (!(f->flags & FUSE_HARD_REMOVE) && is_open(f, in->nodeid, name))
876 res = hide_node(f, path, in->nodeid, name);
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000877 else {
878 res = f->op.unlink(path);
879 if (res == 0)
Miklos Szeredia13d9002004-11-02 17:32:03 +0000880 remove_node(f, in->nodeid, name);
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000881 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000882 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000883 free(path);
Miklos Szeredib483c932001-10-29 14:57:57 +0000884 }
Miklos Szeredib5958612004-02-20 14:10:49 +0000885 send_reply(f, in, res, NULL, 0);
886}
887
888static void do_rmdir(struct fuse *f, struct fuse_in_header *in, char *name)
889{
890 int res;
891 char *path;
892
893 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000894 path = get_path_name(f, in->nodeid, name);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000895 if (path != NULL) {
Miklos Szeredi209f5d02004-07-24 19:56:16 +0000896 if (f->flags & FUSE_DEBUG) {
897 printf("RMDIR %s\n", path);
898 fflush(stdout);
899 }
Miklos Szeredib5958612004-02-20 14:10:49 +0000900 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000901 if (f->op.rmdir) {
Miklos Szeredib5958612004-02-20 14:10:49 +0000902 res = f->op.rmdir(path);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000903 if (res == 0)
Miklos Szeredia13d9002004-11-02 17:32:03 +0000904 remove_node(f, in->nodeid, name);
Miklos Szeredib5958612004-02-20 14:10:49 +0000905 }
906 free(path);
907 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000908 send_reply(f, in, res, NULL, 0);
909}
910
911static void do_symlink(struct fuse *f, struct fuse_in_header *in, char *name,
912 char *link)
913{
914 int res;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000915 int res2;
Miklos Szeredib483c932001-10-29 14:57:57 +0000916 char *path;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000917 struct fuse_entry_out outarg;
Miklos Szeredib483c932001-10-29 14:57:57 +0000918
Miklos Szeredi5e183482001-10-31 14:52:35 +0000919 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000920 path = get_path_name(f, in->nodeid, name);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000921 if (path != NULL) {
922 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000923 printf("SYMLINK %s\n", path);
924 fflush(stdout);
925 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000926 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000927 if (f->op.symlink && f->op.getattr) {
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000928 res = f->op.symlink(link, path);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000929 if (res == 0)
Miklos Szeredia13d9002004-11-02 17:32:03 +0000930 res = lookup_path(f, in->nodeid, in->unique, name, path, &outarg);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000931 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000932 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000933 }
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000934 res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
935 if (res == 0 && res2 == -ENOENT)
Miklos Szeredia13d9002004-11-02 17:32:03 +0000936 destroy_node(f, outarg.nodeid, in->unique);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000937
Miklos Szeredib483c932001-10-29 14:57:57 +0000938}
939
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000940static void do_rename(struct fuse *f, struct fuse_in_header *in,
941 struct fuse_rename_in *inarg)
942{
943 int res;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000944 nodeid_t olddir = in->nodeid;
945 nodeid_t newdir = inarg->newdir;
Miklos Szeredi6bf8b682002-10-28 08:49:39 +0000946 char *oldname = PARAM(inarg);
947 char *newname = oldname + strlen(oldname) + 1;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000948 char *oldpath;
949 char *newpath;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000950
Miklos Szeredi5e183482001-10-31 14:52:35 +0000951 res = -ENOENT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000952 oldpath = get_path_name(f, olddir, oldname);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000953 if (oldpath != NULL) {
Miklos Szeredia181e612001-11-06 12:03:23 +0000954 newpath = get_path_name(f, newdir, newname);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000955 if (newpath != NULL) {
Miklos Szeredi209f5d02004-07-24 19:56:16 +0000956 if (f->flags & FUSE_DEBUG) {
957 printf("RENAME %s -> %s\n", oldpath, newpath);
958 fflush(stdout);
959 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000960 res = -ENOSYS;
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000961 if (f->op.rename) {
962 res = 0;
Miklos Szeredi2529ca22004-07-13 15:36:52 +0000963 if (!(f->flags & FUSE_HARD_REMOVE) &&
964 is_open(f, newdir, newname))
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000965 res = hide_node(f, newpath, newdir, newname);
966 if (res == 0) {
967 res = f->op.rename(oldpath, newpath);
968 if (res == 0)
Miklos Szeredib2cf9562004-09-16 08:42:40 +0000969 res = rename_node(f, olddir, oldname, newdir, newname, 0);
Miklos Szeredi1ea9c962004-06-24 21:00:00 +0000970 }
971 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000972 free(newpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000973 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000974 free(oldpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000975 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000976 send_reply(f, in, res, NULL, 0);
977}
978
979static void do_link(struct fuse *f, struct fuse_in_header *in,
Miklos Szeredi5e183482001-10-31 14:52:35 +0000980 struct fuse_link_in *arg)
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000981{
982 int res;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000983 int res2;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000984 char *oldpath;
985 char *newpath;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000986 char *name = PARAM(arg);
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000987 struct fuse_entry_out outarg;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000988
Miklos Szeredi5e183482001-10-31 14:52:35 +0000989 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000990 oldpath = get_path(f, in->nodeid);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000991 if (oldpath != NULL) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000992 newpath = get_path_name(f, arg->newdir, name);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000993 if (newpath != NULL) {
994 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000995 printf("LINK %s\n", newpath);
996 fflush(stdout);
997 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000998 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000999 if (f->op.link && f->op.getattr) {
Miklos Szeredi0a7077f2001-11-11 18:20:17 +00001000 res = f->op.link(oldpath, newpath);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001001 if (res == 0)
Miklos Szeredi76f65782004-02-19 16:55:40 +00001002 res = lookup_path(f, arg->newdir, in->unique, name,
1003 newpath, &outarg);
1004 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001005 free(newpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +00001006 }
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001007 free(oldpath);
Miklos Szeredi5e183482001-10-31 14:52:35 +00001008 }
Miklos Szeredi2778f6c2004-06-21 09:45:30 +00001009 res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
1010 if (res == 0 && res2 == -ENOENT)
Miklos Szeredia13d9002004-11-02 17:32:03 +00001011 destroy_node(f, outarg.nodeid, in->unique);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +00001012}
1013
Miklos Szeredi5e183482001-10-31 14:52:35 +00001014static void do_open(struct fuse *f, struct fuse_in_header *in,
1015 struct fuse_open_in *arg)
1016{
1017 int res;
1018 char *path;
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001019 struct fuse_open_out outarg;
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001020 struct fuse_file_info fi;
Miklos Szeredi5e183482001-10-31 14:52:35 +00001021
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001022 memset(&fi, 0, sizeof(fi));
1023 fi.flags = arg->flags;
Miklos Szeredi5e183482001-10-31 14:52:35 +00001024 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001025 path = get_path(f, in->nodeid);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001026 if (path != NULL) {
Miklos Szeredi5e183482001-10-31 14:52:35 +00001027 res = -ENOSYS;
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001028 if (f->op.open.curr) {
1029 if (!f->compat)
1030 res = f->op.open.curr(path, &fi);
1031 else
1032 res = f->op.open.compat2(path, fi.flags);
1033 }
Miklos Szeredi40b9a5a2002-12-10 16:09:02 +00001034 }
Miklos Szeredi73798f92004-07-12 15:55:11 +00001035 if (res == 0) {
1036 int res2;
1037
1038 /* If the request is interrupted the lock must be held until
1039 the cancellation is finished. Otherwise there could be
1040 races with rename/unlink, against which the kernel can't
1041 protect */
1042 pthread_mutex_lock(&f->lock);
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001043 outarg.fh = fi.fh;
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001044 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi1eea0322004-09-27 18:50:11 +00001045 printf("OPEN[%lu] flags: 0x%x\n", outarg.fh, arg->flags);
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001046 fflush(stdout);
1047 }
1048
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001049 res2 = send_reply_locked(f, in, res, &outarg, sizeof(outarg));
Miklos Szeredi1ea9c962004-06-24 21:00:00 +00001050 if(res2 == -ENOENT) {
1051 /* The open syscall was interrupted, so it must be cancelled */
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001052 if(f->op.release.curr) {
1053 if (!f->compat)
1054 f->op.release.curr(path, &fi);
1055 else
1056 f->op.release.compat2(path, fi.flags);
1057 }
Miklos Szeredi73798f92004-07-12 15:55:11 +00001058 } else
Miklos Szeredia13d9002004-11-02 17:32:03 +00001059 get_node(f, in->nodeid)->open_count ++;
Miklos Szeredi73798f92004-07-12 15:55:11 +00001060 pthread_mutex_unlock(&f->lock);
1061
1062 } else
1063 send_reply(f, in, res, NULL, 0);
1064
Miklos Szeredi9a31cca2004-06-26 21:11:25 +00001065 if (path)
1066 free(path);
Miklos Szeredi5e183482001-10-31 14:52:35 +00001067}
1068
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001069static void do_flush(struct fuse *f, struct fuse_in_header *in,
1070 struct fuse_flush_in *arg)
Miklos Szeredie2e4ac22004-05-18 08:45:28 +00001071{
1072 char *path;
1073 int res;
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001074 struct fuse_file_info fi;
Miklos Szeredie2e4ac22004-05-18 08:45:28 +00001075
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001076 memset(&fi, 0, sizeof(fi));
1077 fi.fh = arg->fh;
Miklos Szeredie2e4ac22004-05-18 08:45:28 +00001078 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001079 path = get_path(f, in->nodeid);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001080 if (path != NULL) {
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001081 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi1eea0322004-09-27 18:50:11 +00001082 printf("FLUSH[%lu]\n", arg->fh);
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001083 fflush(stdout);
1084 }
Miklos Szeredie2e4ac22004-05-18 08:45:28 +00001085 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001086 if (f->op.flush)
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001087 res = f->op.flush(path, &fi);
Miklos Szeredie2e4ac22004-05-18 08:45:28 +00001088 free(path);
1089 }
1090 send_reply(f, in, res, NULL, 0);
1091}
1092
Miklos Szeredi9478e862002-12-11 09:50:26 +00001093static void do_release(struct fuse *f, struct fuse_in_header *in,
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001094 struct fuse_release_in *arg)
Miklos Szeredic8ba2372002-12-10 12:26:00 +00001095{
Miklos Szeredi1ea9c962004-06-24 21:00:00 +00001096 struct node *node;
1097 char *path;
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001098 struct fuse_file_info fi;
1099
1100 memset(&fi, 0, sizeof(fi));
1101 fi.flags = arg->flags;
1102 fi.fh = arg->fh;
Miklos Szeredic8ba2372002-12-10 12:26:00 +00001103
Miklos Szeredi1ea9c962004-06-24 21:00:00 +00001104 pthread_mutex_lock(&f->lock);
Miklos Szeredia13d9002004-11-02 17:32:03 +00001105 node = get_node(f, in->nodeid);
Miklos Szeredi1ea9c962004-06-24 21:00:00 +00001106 --node->open_count;
1107 pthread_mutex_unlock(&f->lock);
1108
Miklos Szeredia13d9002004-11-02 17:32:03 +00001109 path = get_path(f, in->nodeid);
Miklos Szeredi1ea9c962004-06-24 21:00:00 +00001110 if (path != NULL) {
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001111 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi1eea0322004-09-27 18:50:11 +00001112 printf("RELEASE[%lu]\n", arg->fh);
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001113 fflush(stdout);
1114 }
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001115 if (f->op.release.curr) {
1116 if (!f->compat)
1117 f->op.release.curr(path, &fi);
1118 else
1119 f->op.release.compat2(path, fi.flags);
1120 }
Miklos Szeredi1ea9c962004-06-24 21:00:00 +00001121
1122 if(node->is_hidden && node->open_count == 0)
1123 /* can now clean up this hidden file */
1124 f->op.unlink(path);
1125
1126 free(path);
Miklos Szeredic8ba2372002-12-10 12:26:00 +00001127 }
Miklos Szeredi556d03d2004-06-30 11:13:41 +00001128 send_reply(f, in, 0, NULL, 0);
Miklos Szeredic8ba2372002-12-10 12:26:00 +00001129}
1130
Miklos Szeredi5e183482001-10-31 14:52:35 +00001131static void do_read(struct fuse *f, struct fuse_in_header *in,
1132 struct fuse_read_in *arg)
1133{
1134 int res;
1135 char *path;
Miklos Szeredi43696432001-11-18 19:15:05 +00001136 char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + arg->size);
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001137 if (outbuf == NULL)
1138 send_reply(f, in, -ENOMEM, NULL, 0);
1139 else {
1140 struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
1141 char *buf = outbuf + sizeof(struct fuse_out_header);
1142 size_t size;
1143 size_t outsize;
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001144 struct fuse_file_info fi;
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001145
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001146 memset(&fi, 0, sizeof(fi));
1147 fi.fh = arg->fh;
1148
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001149 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001150 path = get_path(f, in->nodeid);
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001151 if (path != NULL) {
1152 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi1eea0322004-09-27 18:50:11 +00001153 printf("READ[%lu] %u bytes from %llu\n", arg->fh, arg->size,
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001154 arg->offset);
1155 fflush(stdout);
1156 }
1157
1158 res = -ENOSYS;
1159 if (f->op.read)
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001160 res = f->op.read(path, buf, arg->size, arg->offset, &fi);
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001161 free(path);
Miklos Szeredi6ebe2342002-01-06 21:44:16 +00001162 }
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001163
1164 size = 0;
1165 if (res >= 0) {
1166 size = res;
1167 res = 0;
1168 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi1eea0322004-09-27 18:50:11 +00001169 printf(" READ[%lu] %u bytes\n", arg->fh, size);
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001170 fflush(stdout);
1171 }
Miklos Szeredi6ebe2342002-01-06 21:44:16 +00001172 }
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001173 memset(out, 0, sizeof(struct fuse_out_header));
1174 out->unique = in->unique;
1175 out->error = res;
1176 outsize = sizeof(struct fuse_out_header) + size;
1177
1178 send_reply_raw(f, outbuf, outsize, 0);
1179 free(outbuf);
Miklos Szeredi5e183482001-10-31 14:52:35 +00001180 }
Miklos Szeredi5e183482001-10-31 14:52:35 +00001181}
Miklos Szeredib483c932001-10-29 14:57:57 +00001182
Miklos Szeredia181e612001-11-06 12:03:23 +00001183static void do_write(struct fuse *f, struct fuse_in_header *in,
1184 struct fuse_write_in *arg)
1185{
1186 int res;
1187 char *path;
Miklos Szerediad051c32004-07-02 09:22:50 +00001188 struct fuse_write_out outarg;
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001189 struct fuse_file_info fi;
1190
1191 memset(&fi, 0, sizeof(fi));
1192 fi.fh = arg->fh;
Miklos Szeredid59bb9d2004-12-07 10:04:24 +00001193 fi.writepage = arg->writepage;
Miklos Szeredia181e612001-11-06 12:03:23 +00001194
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001195 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001196 path = get_path(f, in->nodeid);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001197 if (path != NULL) {
1198 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi1eea0322004-09-27 18:50:11 +00001199 printf("WRITE%s[%lu] %u bytes to %llu\n",
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001200 arg->writepage ? "PAGE" : "", arg->fh, arg->size,
1201 arg->offset);
Miklos Szeredi6ebe2342002-01-06 21:44:16 +00001202 fflush(stdout);
1203 }
1204
Miklos Szeredia181e612001-11-06 12:03:23 +00001205 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001206 if (f->op.write)
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001207 res = f->op.write(path, PARAM(arg), arg->size, arg->offset, &fi);
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001208 free(path);
Miklos Szeredia181e612001-11-06 12:03:23 +00001209 }
1210
Miklos Szerediad051c32004-07-02 09:22:50 +00001211 if (res >= 0) {
1212 outarg.size = res;
1213 res = 0;
Miklos Szeredia181e612001-11-06 12:03:23 +00001214 }
1215
Miklos Szerediad051c32004-07-02 09:22:50 +00001216 send_reply(f, in, res, &outarg, sizeof(outarg));
Miklos Szeredia181e612001-11-06 12:03:23 +00001217}
1218
Miklos Szeredi77f39942004-03-25 11:17:52 +00001219static int default_statfs(struct statfs *buf)
1220{
1221 buf->f_namelen = 255;
1222 buf->f_bsize = 512;
1223 return 0;
1224}
1225
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001226static void convert_statfs_compat(struct fuse_statfs_compat1 *compatbuf,
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001227 struct statfs *statfs)
1228{
1229 statfs->f_bsize = compatbuf->block_size;
1230 statfs->f_blocks = compatbuf->blocks;
1231 statfs->f_bfree = compatbuf->blocks_free;
1232 statfs->f_bavail = compatbuf->blocks_free;
1233 statfs->f_files = compatbuf->files;
1234 statfs->f_ffree = compatbuf->files_free;
1235 statfs->f_namelen = compatbuf->namelen;
1236}
1237
Miklos Szeredi18e75e42004-02-19 14:23:27 +00001238static void convert_statfs(struct statfs *statfs, struct fuse_kstatfs *kstatfs)
1239{
1240 kstatfs->bsize = statfs->f_bsize;
1241 kstatfs->blocks = statfs->f_blocks;
1242 kstatfs->bfree = statfs->f_bfree;
1243 kstatfs->bavail = statfs->f_bavail;
1244 kstatfs->files = statfs->f_files;
1245 kstatfs->ffree = statfs->f_ffree;
1246 kstatfs->namelen = statfs->f_namelen;
1247}
1248
Mark Glinesd84b39a2002-01-07 16:32:02 +00001249static void do_statfs(struct fuse *f, struct fuse_in_header *in)
1250{
1251 int res;
Mark Glinesd84b39a2002-01-07 16:32:02 +00001252 struct fuse_statfs_out arg;
Miklos Szeredi18e75e42004-02-19 14:23:27 +00001253 struct statfs buf;
Mark Glinesd84b39a2002-01-07 16:32:02 +00001254
Miklos Szeredi77f39942004-03-25 11:17:52 +00001255 memset(&buf, 0, sizeof(struct statfs));
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001256 if (f->op.statfs.curr) {
1257 if (!f->compat || f->compat > 11)
1258 res = f->op.statfs.curr("/", &buf);
1259 else {
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001260 struct fuse_statfs_compat1 compatbuf;
1261 memset(&compatbuf, 0, sizeof(struct fuse_statfs_compat1));
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001262 res = f->op.statfs.compat1(&compatbuf);
1263 if (res == 0)
1264 convert_statfs_compat(&compatbuf, &buf);
1265 }
1266 }
Miklos Szeredi77f39942004-03-25 11:17:52 +00001267 else
1268 res = default_statfs(&buf);
1269
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001270 if (res == 0)
Miklos Szeredi77f39942004-03-25 11:17:52 +00001271 convert_statfs(&buf, &arg.st);
Miklos Szeredi4b2bef42002-01-09 12:23:27 +00001272
Mark Glinesd84b39a2002-01-07 16:32:02 +00001273 send_reply(f, in, res, &arg, sizeof(arg));
1274}
1275
Miklos Szeredi5e43f2c2003-12-12 14:06:41 +00001276static void do_fsync(struct fuse *f, struct fuse_in_header *in,
1277 struct fuse_fsync_in *inarg)
1278{
1279 int res;
1280 char *path;
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001281 struct fuse_file_info fi;
1282
1283 memset(&fi, 0, sizeof(fi));
1284 fi.fh = inarg->fh;
Miklos Szeredi5e43f2c2003-12-12 14:06:41 +00001285
1286 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001287 path = get_path(f, in->nodeid);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001288 if (path != NULL) {
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001289 if (f->flags & FUSE_DEBUG) {
Miklos Szeredi1eea0322004-09-27 18:50:11 +00001290 printf("FSYNC[%lu]\n", inarg->fh);
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001291 fflush(stdout);
1292 }
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001293 res = -ENOSYS;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001294 if (f->op.fsync)
Miklos Szeredifb28c5e2004-11-26 12:15:06 +00001295 res = f->op.fsync(path, inarg->datasync, &fi);
Miklos Szeredi5e43f2c2003-12-12 14:06:41 +00001296 free(path);
1297 }
1298 send_reply(f, in, res, NULL, 0);
1299}
1300
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001301static void do_setxattr(struct fuse *f, struct fuse_in_header *in,
1302 struct fuse_setxattr_in *arg)
1303{
1304 int res;
1305 char *path;
1306 char *name = PARAM(arg);
1307 unsigned char *value = name + strlen(name) + 1;
1308
1309 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001310 path = get_path(f, in->nodeid);
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001311 if (path != NULL) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001312 res = -ENOSYS;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001313 if (f->op.setxattr)
1314 res = f->op.setxattr(path, name, value, arg->size, arg->flags);
1315 free(path);
1316 }
1317 send_reply(f, in, res, NULL, 0);
1318}
1319
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001320static int common_getxattr(struct fuse *f, struct fuse_in_header *in,
1321 const char *name, char *value, size_t size)
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001322{
1323 int res;
1324 char *path;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001325
1326 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001327 path = get_path(f, in->nodeid);
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001328 if (path != NULL) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001329 res = -ENOSYS;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001330 if (f->op.getxattr)
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001331 res = f->op.getxattr(path, name, value, size);
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001332 free(path);
1333 }
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001334 return res;
1335}
1336
1337static void do_getxattr_read(struct fuse *f, struct fuse_in_header *in,
1338 const char *name, size_t size)
1339{
1340 int res;
1341 char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + size);
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001342 if (outbuf == NULL)
1343 send_reply(f, in, -ENOMEM, NULL, 0);
1344 else {
1345 struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
1346 char *value = outbuf + sizeof(struct fuse_out_header);
1347
1348 res = common_getxattr(f, in, name, value, size);
1349 size = 0;
1350 if (res > 0) {
1351 size = res;
1352 res = 0;
1353 }
1354 memset(out, 0, sizeof(struct fuse_out_header));
1355 out->unique = in->unique;
1356 out->error = res;
1357
1358 send_reply_raw(f, outbuf, sizeof(struct fuse_out_header) + size, 0);
1359 free(outbuf);
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001360 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001361}
1362
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001363static void do_getxattr_size(struct fuse *f, struct fuse_in_header *in,
1364 const char *name)
1365{
1366 int res;
1367 struct fuse_getxattr_out arg;
1368
1369 res = common_getxattr(f, in, name, NULL, 0);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001370 if (res >= 0) {
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001371 arg.size = res;
1372 res = 0;
1373 }
1374 send_reply(f, in, res, &arg, sizeof(arg));
1375}
1376
1377static void do_getxattr(struct fuse *f, struct fuse_in_header *in,
1378 struct fuse_getxattr_in *arg)
1379{
1380 char *name = PARAM(arg);
1381
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001382 if (arg->size)
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001383 do_getxattr_read(f, in, name, arg->size);
1384 else
1385 do_getxattr_size(f, in, name);
1386}
1387
1388static int common_listxattr(struct fuse *f, struct fuse_in_header *in,
1389 char *list, size_t size)
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001390{
1391 int res;
1392 char *path;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001393
1394 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001395 path = get_path(f, in->nodeid);
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001396 if (path != NULL) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001397 res = -ENOSYS;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001398 if (f->op.listxattr)
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001399 res = f->op.listxattr(path, list, size);
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001400 free(path);
1401 }
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001402 return res;
1403}
1404
1405static void do_listxattr_read(struct fuse *f, struct fuse_in_header *in,
1406 size_t size)
1407{
1408 int res;
1409 char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + size);
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001410 if (outbuf == NULL)
1411 send_reply(f, in, -ENOMEM, NULL, 0);
1412 else {
1413 struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
1414 char *list = outbuf + sizeof(struct fuse_out_header);
1415
1416 res = common_listxattr(f, in, list, size);
1417 size = 0;
1418 if (res > 0) {
1419 size = res;
1420 res = 0;
1421 }
1422 memset(out, 0, sizeof(struct fuse_out_header));
1423 out->unique = in->unique;
1424 out->error = res;
1425
1426 send_reply_raw(f, outbuf, sizeof(struct fuse_out_header) + size, 0);
1427 free(outbuf);
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001428 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001429}
1430
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001431static void do_listxattr_size(struct fuse *f, struct fuse_in_header *in)
1432{
1433 int res;
1434 struct fuse_getxattr_out arg;
1435
1436 res = common_listxattr(f, in, NULL, 0);
1437 if (res >= 0) {
1438 arg.size = res;
1439 res = 0;
1440 }
1441 send_reply(f, in, res, &arg, sizeof(arg));
1442}
1443
1444static void do_listxattr(struct fuse *f, struct fuse_in_header *in,
1445 struct fuse_getxattr_in *arg)
1446{
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001447 if (arg->size)
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001448 do_listxattr_read(f, in, arg->size);
1449 else
1450 do_listxattr_size(f, in);
1451}
1452
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001453static void do_removexattr(struct fuse *f, struct fuse_in_header *in,
1454 char *name)
1455{
1456 int res;
1457 char *path;
1458
1459 res = -ENOENT;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001460 path = get_path(f, in->nodeid);
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001461 if (path != NULL) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001462 res = -ENOSYS;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001463 if (f->op.removexattr)
1464 res = f->op.removexattr(path, name);
1465 free(path);
1466 }
1467 send_reply(f, in, res, NULL, 0);
1468}
1469
1470
Miklos Szeredi43696432001-11-18 19:15:05 +00001471static void free_cmd(struct fuse_cmd *cmd)
1472{
1473 free(cmd->buf);
1474 free(cmd);
1475}
1476
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001477void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
Miklos Szeredia181e612001-11-06 12:03:23 +00001478{
Miklos Szeredia181e612001-11-06 12:03:23 +00001479 struct fuse_in_header *in = (struct fuse_in_header *) cmd->buf;
1480 void *inarg = cmd->buf + sizeof(struct fuse_in_header);
1481 size_t argsize;
Miklos Szeredid169f312004-09-22 08:48:26 +00001482 struct fuse_context *ctx = fuse_get_context();
Miklos Szeredia181e612001-11-06 12:03:23 +00001483
Miklos Szeredi99ddf0e2001-11-25 17:19:59 +00001484 dec_avail(f);
Miklos Szeredi33232032001-11-19 17:55:51 +00001485
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001486 if ((f->flags & FUSE_DEBUG)) {
Miklos Szeredia13d9002004-11-02 17:32:03 +00001487 printf("unique: %i, opcode: %s (%i), nodeid: %li, insize: %i\n",
1488 in->unique, opname(in->opcode), in->opcode, in->nodeid,
Miklos Szeredic8ba2372002-12-10 12:26:00 +00001489 cmd->buflen);
Miklos Szeredic0938ea2001-11-07 12:35:06 +00001490 fflush(stdout);
1491 }
Miklos Szeredife25def2001-12-20 15:38:05 +00001492
Miklos Szeredid169f312004-09-22 08:48:26 +00001493 ctx->fuse = f;
Miklos Szeredife25def2001-12-20 15:38:05 +00001494 ctx->uid = in->uid;
1495 ctx->gid = in->gid;
Miklos Szeredi1f18db52004-09-27 06:54:49 +00001496 ctx->pid = in->pid;
Miklos Szeredia181e612001-11-06 12:03:23 +00001497
1498 argsize = cmd->buflen - sizeof(struct fuse_in_header);
1499
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001500 switch (in->opcode) {
Miklos Szeredia181e612001-11-06 12:03:23 +00001501 case FUSE_LOOKUP:
1502 do_lookup(f, in, (char *) inarg);
1503 break;
1504
Miklos Szeredia181e612001-11-06 12:03:23 +00001505 case FUSE_GETATTR:
1506 do_getattr(f, in);
1507 break;
1508
1509 case FUSE_SETATTR:
1510 do_setattr(f, in, (struct fuse_setattr_in *) inarg);
1511 break;
1512
1513 case FUSE_READLINK:
1514 do_readlink(f, in);
1515 break;
1516
1517 case FUSE_GETDIR:
1518 do_getdir(f, in);
1519 break;
1520
1521 case FUSE_MKNOD:
1522 do_mknod(f, in, (struct fuse_mknod_in *) inarg);
1523 break;
1524
1525 case FUSE_MKDIR:
1526 do_mkdir(f, in, (struct fuse_mkdir_in *) inarg);
1527 break;
1528
1529 case FUSE_UNLINK:
Miklos Szeredib5958612004-02-20 14:10:49 +00001530 do_unlink(f, in, (char *) inarg);
1531 break;
1532
Miklos Szeredia181e612001-11-06 12:03:23 +00001533 case FUSE_RMDIR:
Miklos Szeredib5958612004-02-20 14:10:49 +00001534 do_rmdir(f, in, (char *) inarg);
Miklos Szeredia181e612001-11-06 12:03:23 +00001535 break;
1536
1537 case FUSE_SYMLINK:
1538 do_symlink(f, in, (char *) inarg,
1539 ((char *) inarg) + strlen((char *) inarg) + 1);
1540 break;
1541
1542 case FUSE_RENAME:
1543 do_rename(f, in, (struct fuse_rename_in *) inarg);
1544 break;
1545
1546 case FUSE_LINK:
1547 do_link(f, in, (struct fuse_link_in *) inarg);
1548 break;
1549
1550 case FUSE_OPEN:
1551 do_open(f, in, (struct fuse_open_in *) inarg);
1552 break;
1553
Miklos Szeredie2e4ac22004-05-18 08:45:28 +00001554 case FUSE_FLUSH:
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001555 do_flush(f, in, (struct fuse_flush_in *) inarg);
Miklos Szeredie2e4ac22004-05-18 08:45:28 +00001556 break;
1557
Miklos Szeredi9478e862002-12-11 09:50:26 +00001558 case FUSE_RELEASE:
Miklos Szeredi209f5d02004-07-24 19:56:16 +00001559 do_release(f, in, (struct fuse_release_in *) inarg);
Miklos Szeredi9478e862002-12-11 09:50:26 +00001560 break;
1561
Miklos Szeredia181e612001-11-06 12:03:23 +00001562 case FUSE_READ:
1563 do_read(f, in, (struct fuse_read_in *) inarg);
1564 break;
1565
1566 case FUSE_WRITE:
1567 do_write(f, in, (struct fuse_write_in *) inarg);
1568 break;
1569
Mark Glinesd84b39a2002-01-07 16:32:02 +00001570 case FUSE_STATFS:
1571 do_statfs(f, in);
1572 break;
1573
Miklos Szeredi5e43f2c2003-12-12 14:06:41 +00001574 case FUSE_FSYNC:
1575 do_fsync(f, in, (struct fuse_fsync_in *) inarg);
1576 break;
1577
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001578 case FUSE_SETXATTR:
1579 do_setxattr(f, in, (struct fuse_setxattr_in *) inarg);
1580 break;
1581
1582 case FUSE_GETXATTR:
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001583 do_getxattr(f, in, (struct fuse_getxattr_in *) inarg);
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001584 break;
1585
1586 case FUSE_LISTXATTR:
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001587 do_listxattr(f, in, (struct fuse_getxattr_in *) inarg);
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001588 break;
1589
1590 case FUSE_REMOVEXATTR:
1591 do_removexattr(f, in, (char *) inarg);
1592 break;
1593
Miklos Szeredia181e612001-11-06 12:03:23 +00001594 default:
Miklos Szeredi43696432001-11-18 19:15:05 +00001595 send_reply(f, in, -ENOSYS, NULL, 0);
Miklos Szeredia181e612001-11-06 12:03:23 +00001596 }
Miklos Szeredi43696432001-11-18 19:15:05 +00001597
1598 free_cmd(cmd);
Miklos Szeredia181e612001-11-06 12:03:23 +00001599}
1600
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001601int fuse_exited(struct fuse* f)
Miklos Szeredi65cf7c72004-06-30 11:34:56 +00001602{
1603 return f->exited;
1604}
1605
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001606struct fuse_cmd *fuse_read_cmd(struct fuse *f)
Miklos Szeredi2df1c042001-11-06 15:07:17 +00001607{
Miklos Szeredifff56ab2001-11-16 10:12:59 +00001608 ssize_t res;
Miklos Szeredifff56ab2001-11-16 10:12:59 +00001609 struct fuse_cmd *cmd;
Miklos Szeredi99ddf0e2001-11-25 17:19:59 +00001610 struct fuse_in_header *in;
1611 void *inarg;
Miklos Szeredifff56ab2001-11-16 10:12:59 +00001612
Miklos Szeredi43696432001-11-18 19:15:05 +00001613 cmd = (struct fuse_cmd *) malloc(sizeof(struct fuse_cmd));
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001614 if (cmd == NULL) {
1615 fprintf(stderr, "fuse: failed to allocate cmd in read\n");
1616 return NULL;
1617 }
Miklos Szeredi43696432001-11-18 19:15:05 +00001618 cmd->buf = (char *) malloc(FUSE_MAX_IN);
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001619 if (cmd->buf == NULL) {
1620 fprintf(stderr, "fuse: failed to allocate read buffer\n");
1621 free(cmd);
1622 return NULL;
1623 }
Miklos Szeredi99ddf0e2001-11-25 17:19:59 +00001624 in = (struct fuse_in_header *) cmd->buf;
1625 inarg = cmd->buf + sizeof(struct fuse_in_header);
Miklos Szeredi43696432001-11-18 19:15:05 +00001626
Miklos Szeredi65cf7c72004-06-30 11:34:56 +00001627 res = read(f->fd, cmd->buf, FUSE_MAX_IN);
1628 if (res == -1) {
1629 free_cmd(cmd);
Miklos Szeredie56818b2004-12-12 11:45:24 +00001630 if (fuse_exited(f) || errno == EINTR || errno == ENOENT)
Miklos Szeredi99ddf0e2001-11-25 17:19:59 +00001631 return NULL;
Miklos Szeredi99ddf0e2001-11-25 17:19:59 +00001632
Miklos Szeredi65cf7c72004-06-30 11:34:56 +00001633 /* ENODEV means we got unmounted, so we silenty return failure */
1634 if (errno != ENODEV) {
1635 /* BAD... This will happen again */
1636 perror("fuse: reading device");
1637 }
1638
1639 fuse_exit(f);
1640 return NULL;
1641 }
1642 if ((size_t) res < sizeof(struct fuse_in_header)) {
1643 free_cmd(cmd);
1644 /* Cannot happen */
1645 fprintf(stderr, "short read on fuse device\n");
1646 fuse_exit(f);
1647 return NULL;
1648 }
1649 cmd->buflen = res;
1650
1651 /* Forget is special, it can be done without messing with threads. */
1652 if (in->opcode == FUSE_FORGET) {
1653 do_forget(f, in, (struct fuse_forget_in *) inarg);
1654 free_cmd(cmd);
1655 return NULL;
1656 }
Miklos Szeredi99ddf0e2001-11-25 17:19:59 +00001657
Miklos Szeredifff56ab2001-11-16 10:12:59 +00001658 return cmd;
Miklos Szeredi2df1c042001-11-06 15:07:17 +00001659}
1660
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001661int fuse_loop(struct fuse *f)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001662{
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001663 if (f == NULL)
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001664 return -1;
Miklos Szeredic40748a2004-02-20 16:38:45 +00001665
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001666 while (1) {
Miklos Szeredi0f48a262002-12-05 14:23:01 +00001667 struct fuse_cmd *cmd;
1668
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001669 if (fuse_exited(f))
Miklos Szeredi874e3c12004-11-01 23:15:20 +00001670 break;
Miklos Szeredi0f48a262002-12-05 14:23:01 +00001671
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001672 cmd = fuse_read_cmd(f);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001673 if (cmd == NULL)
Miklos Szeredi0f48a262002-12-05 14:23:01 +00001674 continue;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001675
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001676 fuse_process_cmd(f, cmd);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001677 }
Miklos Szeredi874e3c12004-11-01 23:15:20 +00001678 f->exited = 0;
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001679 return 0;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001680}
1681
Miklos Szeredi891b8742004-07-29 09:27:49 +00001682int fuse_invalidate(struct fuse *f, const char *path)
1683{
Miklos Szeredie56818b2004-12-12 11:45:24 +00001684 (void) f;
1685 (void) path;
1686 return -EINVAL;
Miklos Szeredi891b8742004-07-29 09:27:49 +00001687}
1688
Miklos Szeredi0f48a262002-12-05 14:23:01 +00001689void fuse_exit(struct fuse *f)
1690{
1691 f->exited = 1;
1692}
1693
Miklos Szeredid169f312004-09-22 08:48:26 +00001694struct fuse_context *fuse_get_context()
Miklos Szeredi2e50d432001-12-20 12:17:25 +00001695{
Miklos Szeredid169f312004-09-22 08:48:26 +00001696 static struct fuse_context context;
1697 if (fuse_getcontext)
1698 return fuse_getcontext();
Miklos Szeredi2e50d432001-12-20 12:17:25 +00001699 else
Miklos Szeredid169f312004-09-22 08:48:26 +00001700 return &context;
1701}
1702
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001703void fuse_set_getcontext_func(struct fuse_context *(*func)(void))
Miklos Szeredid169f312004-09-22 08:48:26 +00001704{
1705 fuse_getcontext = func;
Miklos Szeredi2e50d432001-12-20 12:17:25 +00001706}
1707
Miklos Szeredic40748a2004-02-20 16:38:45 +00001708static int check_version(struct fuse *f)
1709{
1710 int res;
Miklos Szeredi162bcbb2004-11-29 23:43:44 +00001711 const char *version_file = FUSE_VERSION_FILE_NEW;
Miklos Szeredif3845c42004-11-20 11:18:34 +00001712 FILE *vf = fopen(version_file, "r");
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001713 if (vf == NULL) {
Miklos Szeredia25d4c22004-11-23 22:32:16 +00001714 version_file = FUSE_VERSION_FILE_OLD;
Miklos Szeredif3845c42004-11-20 11:18:34 +00001715 vf = fopen(version_file, "r");
1716 if (vf == NULL) {
Miklos Szeredia25d4c22004-11-23 22:32:16 +00001717 struct stat tmp;
1718 if (stat(FUSE_DEV_OLD, &tmp) != -1) {
1719 fprintf(stderr, "fuse: kernel interface too old, need >= %i.%i\n",
1720 FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
1721 return -1;
1722 } else {
1723 fprintf(stderr, "fuse: warning: version of kernel interface unknown\n");
1724 return 0;
1725 }
Miklos Szeredif3845c42004-11-20 11:18:34 +00001726 }
Miklos Szeredic40748a2004-02-20 16:38:45 +00001727 }
1728 res = fscanf(vf, "%i.%i", &f->majorver, &f->minorver);
1729 fclose(vf);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001730 if (res != 2) {
Miklos Szeredif3845c42004-11-20 11:18:34 +00001731 fprintf(stderr, "fuse: error reading %s\n", version_file);
Miklos Szeredic40748a2004-02-20 16:38:45 +00001732 return -1;
1733 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001734 if (f->majorver != FUSE_KERNEL_VERSION) {
Miklos Szeredic40748a2004-02-20 16:38:45 +00001735 fprintf(stderr, "fuse: bad kernel interface major version: needs %i\n",
1736 FUSE_KERNEL_VERSION);
1737 return -1;
1738 }
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001739 if (f->minorver < FUSE_KERNEL_MINOR_VERSION_NEED) {
Miklos Szeredi256739a2004-11-20 12:22:37 +00001740 fprintf(stderr, "fuse: kernel interface too old: need >= %i.%i\n",
Miklos Szeredic40748a2004-02-20 16:38:45 +00001741 FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
1742 return -1;
1743 }
1744
1745 return 0;
1746}
1747
Miklos Szeredibd7661b2004-07-23 17:16:29 +00001748
1749int fuse_is_lib_option(const char *opt)
1750{
1751 if (strcmp(opt, "debug") == 0 ||
Miklos Szeredia13d9002004-11-02 17:32:03 +00001752 strcmp(opt, "hard_remove") == 0 ||
1753 strcmp(opt, "use_ino") == 0)
Miklos Szeredibd7661b2004-07-23 17:16:29 +00001754 return 1;
1755 else
1756 return 0;
1757}
1758
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001759static int parse_lib_opts(struct fuse *f, const char *opts)
Miklos Szeredibd7661b2004-07-23 17:16:29 +00001760{
1761 if (opts) {
1762 char *xopts = strdup(opts);
1763 char *s = xopts;
1764 char *opt;
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001765
Miklos Szeredie56818b2004-12-12 11:45:24 +00001766 if (xopts == NULL) {
1767 fprintf(stderr, "fuse: memory allocation failed\n");
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001768 return -1;
Miklos Szeredie56818b2004-12-12 11:45:24 +00001769 }
Miklos Szeredibd7661b2004-07-23 17:16:29 +00001770
1771 while((opt = strsep(&s, ","))) {
1772 if (strcmp(opt, "debug") == 0)
1773 f->flags |= FUSE_DEBUG;
1774 else if (strcmp(opt, "hard_remove") == 0)
1775 f->flags |= FUSE_HARD_REMOVE;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001776 else if (strcmp(opt, "use_ino") == 0)
1777 f->flags |= FUSE_USE_INO;
Miklos Szeredibd7661b2004-07-23 17:16:29 +00001778 else
1779 fprintf(stderr, "fuse: warning: unknown option `%s'\n", opt);
1780 }
1781 free(xopts);
1782 }
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001783 return 0;
Miklos Szeredibd7661b2004-07-23 17:16:29 +00001784}
1785
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001786struct fuse *fuse_new_common(int fd, const char *opts,
1787 const struct fuse_operations *op,
1788 size_t op_size, int compat)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001789{
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001790 struct fuse *f;
1791 struct node *root;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001792
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001793 if (sizeof(struct fuse_operations_i) < op_size) {
1794 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
1795 op_size = sizeof(struct fuse_operations_i);
1796 }
1797
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001798 f = (struct fuse *) calloc(1, sizeof(struct fuse));
Miklos Szeredie56818b2004-12-12 11:45:24 +00001799 if (f == NULL) {
1800 fprintf(stderr, "fuse: failed to allocate fuse object\n");
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001801 goto out;
Miklos Szeredie56818b2004-12-12 11:45:24 +00001802 }
Miklos Szeredi2df1c042001-11-06 15:07:17 +00001803
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001804 if (check_version(f) == -1)
1805 goto out_free;
Miklos Szeredic40748a2004-02-20 16:38:45 +00001806
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001807 if (parse_lib_opts(f, opts) == -1)
1808 goto out_free;
1809
Miklos Szeredi8cffdb92001-11-09 14:49:18 +00001810 f->fd = fd;
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001811 f->ctr = 0;
Miklos Szeredi76f65782004-02-19 16:55:40 +00001812 f->generation = 0;
Miklos Szeredifff56ab2001-11-16 10:12:59 +00001813 /* FIXME: Dynamic hash table */
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001814 f->name_table_size = 14057;
1815 f->name_table = (struct node **)
1816 calloc(1, sizeof(struct node *) * f->name_table_size);
Miklos Szeredie56818b2004-12-12 11:45:24 +00001817 if (f->name_table == NULL) {
1818 fprintf(stderr, "fuse: memory allocation failed\n");
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001819 goto out_free;
Miklos Szeredie56818b2004-12-12 11:45:24 +00001820 }
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001821
Miklos Szeredia13d9002004-11-02 17:32:03 +00001822 f->id_table_size = 14057;
1823 f->id_table = (struct node **)
1824 calloc(1, sizeof(struct node *) * f->id_table_size);
Miklos Szeredie56818b2004-12-12 11:45:24 +00001825 if (f->id_table == NULL) {
1826 fprintf(stderr, "fuse: memory allocation failed\n");
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001827 goto out_free_name_table;
Miklos Szeredie56818b2004-12-12 11:45:24 +00001828 }
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001829
Miklos Szeredia25d4c22004-11-23 22:32:16 +00001830#ifndef USE_UCLIBC
1831 pthread_mutex_init(&f->lock, NULL);
1832#else
1833 {
1834 pthread_mutexattr_t attr;
1835 pthread_mutexattr_init(&attr);
1836 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
1837 pthread_mutex_init(&f->lock, &attr);
1838 pthread_mutexattr_destroy(&attr);
1839 }
1840#endif
Miklos Szeredi33232032001-11-19 17:55:51 +00001841 f->numworker = 0;
1842 f->numavail = 0;
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001843 memcpy(&f->op, op, op_size);
1844 f->compat = compat;
Miklos Szeredi0f48a262002-12-05 14:23:01 +00001845 f->exited = 0;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001846
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001847 root = (struct node *) calloc(1, sizeof(struct node));
Miklos Szeredie56818b2004-12-12 11:45:24 +00001848 if (root == NULL) {
1849 fprintf(stderr, "fuse: memory allocation failed\n");
Miklos Szeredia13d9002004-11-02 17:32:03 +00001850 goto out_free_id_table;
Miklos Szeredie56818b2004-12-12 11:45:24 +00001851 }
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001852
Miklos Szeredi8cffdb92001-11-09 14:49:18 +00001853 root->mode = 0;
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001854 root->rdev = 0;
1855 root->name = strdup("/");
Miklos Szeredie56818b2004-12-12 11:45:24 +00001856 if (root->name == NULL) {
1857 fprintf(stderr, "fuse: memory allocation failed\n");
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001858 goto out_free_root;
Miklos Szeredie56818b2004-12-12 11:45:24 +00001859 }
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001860
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001861 root->parent = 0;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001862 root->nodeid = FUSE_ROOT_ID;
Miklos Szeredi76f65782004-02-19 16:55:40 +00001863 root->generation = 0;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001864 hash_id(f, root);
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001865
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001866 return f;
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001867
1868 out_free_root:
1869 free(root);
Miklos Szeredia13d9002004-11-02 17:32:03 +00001870 out_free_id_table:
1871 free(f->id_table);
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001872 out_free_name_table:
1873 free(f->name_table);
1874 out_free:
1875 free(f);
1876 out:
Miklos Szeredib2cf9562004-09-16 08:42:40 +00001877 return NULL;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001878}
1879
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001880struct fuse *fuse_new(int fd, const char *opts,
1881 const struct fuse_operations *op, size_t op_size)
1882{
1883 return fuse_new_common(fd, opts, op, op_size, 0);
1884}
1885
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001886struct fuse *fuse_new_compat2(int fd, const char *opts,
1887 const struct fuse_operations_compat2 *op)
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001888{
1889 return fuse_new_common(fd, opts, (struct fuse_operations *) op,
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001890 sizeof(struct fuse_operations_compat2), 21);
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001891}
1892
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001893struct fuse *fuse_new_compat1(int fd, int flags,
1894 const struct fuse_operations_compat1 *op)
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001895{
1896 char *opts = NULL;
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001897 if (flags & FUSE_DEBUG_COMPAT1)
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001898 opts = "debug";
1899 return fuse_new_common(fd, opts, (struct fuse_operations *) op,
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001900 sizeof(struct fuse_operations_compat1), 11);
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001901}
1902
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001903void fuse_destroy(struct fuse *f)
1904{
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001905 size_t i;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001906 for (i = 0; i < f->id_table_size; i++) {
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001907 struct node *node;
Miklos Szeredi1ea9c962004-06-24 21:00:00 +00001908
Miklos Szeredia13d9002004-11-02 17:32:03 +00001909 for (node = f->id_table[i]; node != NULL; node = node->id_next) {
Miklos Szeredi1ea9c962004-06-24 21:00:00 +00001910 if (node->is_hidden) {
Miklos Szeredia13d9002004-11-02 17:32:03 +00001911 char *path = get_path(f, node->nodeid);
Miklos Szeredi1ea9c962004-06-24 21:00:00 +00001912 if (path)
1913 f->op.unlink(path);
1914 }
1915 }
1916 }
Miklos Szeredia13d9002004-11-02 17:32:03 +00001917 for (i = 0; i < f->id_table_size; i++) {
Miklos Szeredi1ea9c962004-06-24 21:00:00 +00001918 struct node *node;
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001919 struct node *next;
Miklos Szeredi1ea9c962004-06-24 21:00:00 +00001920
Miklos Szeredia13d9002004-11-02 17:32:03 +00001921 for (node = f->id_table[i]; node != NULL; node = next) {
1922 next = node->id_next;
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001923 free_node(node);
1924 }
1925 }
Miklos Szeredia13d9002004-11-02 17:32:03 +00001926 free(f->id_table);
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001927 free(f->name_table);
Miklos Szeredia181e612001-11-06 12:03:23 +00001928 pthread_mutex_destroy(&f->lock);
Miklos Szeredi97c61e92001-11-07 12:09:43 +00001929 free(f);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001930}
Miklos Szeredi0b6a0ad2004-12-04 00:40:50 +00001931
Miklos Szeredif458b8c2004-12-07 16:46:42 +00001932__asm__(".symver fuse_exited,__fuse_exited@");
1933__asm__(".symver fuse_process_cmd,__fuse_process_cmd@");
1934__asm__(".symver fuse_read_cmd,__fuse_read_cmd@");
1935__asm__(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@");
1936__asm__(".symver fuse_new_compat2,fuse_new@");