| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |     FUSE: Filesystem in Userspace | 
| Miklos Szeredi | 2e6b6f2 | 2004-07-07 19:19:53 +0000 | [diff] [blame] | 3 |     Copyright (C) 2001-2004  Miklos Szeredi <miklos@szeredi.hu> | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 4 |  | 
| Miklos Szeredi | 8b39a9f | 2002-10-25 12:41:16 +0000 | [diff] [blame] | 5 |     This program can be distributed under the terms of the GNU LGPL. | 
 | 6 |     See the file COPYING.LIB | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 7 | */ | 
 | 8 |  | 
| Miklos Szeredi | cb26451 | 2004-06-23 18:52:50 +0000 | [diff] [blame] | 9 | #include <config.h> | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 10 | #include "fuse_i.h" | 
 | 11 | #include <linux/fuse.h> | 
 | 12 |  | 
 | 13 | #include <string.h> | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 14 | #include <stdlib.h> | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 15 | #include <unistd.h> | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 16 | #include <limits.h> | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 17 | #include <errno.h> | 
| Miklos Szeredi | 019b4e9 | 2001-12-26 18:08:09 +0000 | [diff] [blame] | 18 | #include <sys/param.h> | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 19 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 20 | #define FUSE_MAX_PATH 4096 | 
| Miklos Szeredi | 6bf8b68 | 2002-10-28 08:49:39 +0000 | [diff] [blame] | 21 | #define PARAM(inarg) (((char *)(inarg)) + sizeof(*inarg)) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 22 |  | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 23 | #define ENTRY_REVALIDATE_TIME 1 /* sec */ | 
 | 24 | #define ATTR_REVALIDATE_TIME 1 /* sec */ | 
 | 25 |  | 
| Miklos Szeredi | c8ba237 | 2002-12-10 12:26:00 +0000 | [diff] [blame] | 26 | static const char *opname(enum fuse_opcode opcode) | 
 | 27 | { | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 28 |     switch (opcode) {  | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 29 |     case FUSE_LOOKUP:		return "LOOKUP"; | 
 | 30 |     case FUSE_FORGET:		return "FORGET"; | 
 | 31 |     case FUSE_GETATTR:		return "GETATTR"; | 
 | 32 |     case FUSE_SETATTR:		return "SETATTR"; | 
 | 33 |     case FUSE_READLINK:		return "READLINK"; | 
 | 34 |     case FUSE_SYMLINK:		return "SYMLINK"; | 
 | 35 |     case FUSE_GETDIR:		return "GETDIR"; | 
 | 36 |     case FUSE_MKNOD:		return "MKNOD"; | 
 | 37 |     case FUSE_MKDIR:		return "MKDIR"; | 
 | 38 |     case FUSE_UNLINK:		return "UNLINK"; | 
 | 39 |     case FUSE_RMDIR:		return "RMDIR"; | 
 | 40 |     case FUSE_RENAME:		return "RENAME"; | 
 | 41 |     case FUSE_LINK:		return "LINK"; | 
 | 42 |     case FUSE_OPEN:		return "OPEN"; | 
 | 43 |     case FUSE_READ:		return "READ"; | 
 | 44 |     case FUSE_WRITE:		return "WRITE"; | 
 | 45 |     case FUSE_STATFS:		return "STATFS"; | 
| Miklos Szeredi | 99f2074 | 2004-05-19 08:01:10 +0000 | [diff] [blame] | 46 |     case FUSE_FLUSH:		return "FLUSH"; | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 47 |     case FUSE_RELEASE:		return "RELEASE"; | 
 | 48 |     case FUSE_FSYNC:		return "FSYNC"; | 
 | 49 |     case FUSE_SETXATTR:		return "SETXATTR"; | 
 | 50 |     case FUSE_GETXATTR:		return "GETXATTR"; | 
 | 51 |     case FUSE_LISTXATTR:	return "LISTXATTR"; | 
 | 52 |     case FUSE_REMOVEXATTR:	return "REMOVEXATTR"; | 
| Miklos Szeredi | 99f2074 | 2004-05-19 08:01:10 +0000 | [diff] [blame] | 53 |     default: 			return "???"; | 
| Miklos Szeredi | c8ba237 | 2002-12-10 12:26:00 +0000 | [diff] [blame] | 54 |     } | 
 | 55 | } | 
 | 56 |  | 
| Miklos Szeredi | 99ddf0e | 2001-11-25 17:19:59 +0000 | [diff] [blame] | 57 |  | 
 | 58 | static inline void dec_avail(struct fuse *f) | 
 | 59 | { | 
 | 60 |     pthread_mutex_lock(&f->lock); | 
 | 61 |     f->numavail --; | 
 | 62 |     pthread_mutex_unlock(&f->lock); | 
 | 63 | } | 
 | 64 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 65 | static struct node *__get_node(struct fuse *f, fino_t ino) | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 66 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 67 |     size_t hash = ino % f->ino_table_size; | 
 | 68 |     struct node *node; | 
 | 69 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 70 |     for (node = f->ino_table[hash]; node != NULL; node = node->ino_next) | 
 | 71 |         if (node->ino == ino) | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 72 |             return node; | 
 | 73 |      | 
 | 74 |     return NULL; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 75 | } | 
 | 76 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 77 | static struct node *get_node(struct fuse *f, fino_t ino) | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 78 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 79 |     struct node *node = __get_node(f, ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 80 |     if (node != NULL) | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 81 |         return node; | 
 | 82 |      | 
 | 83 |     fprintf(stderr, "fuse internal error: inode %lu not found\n", ino); | 
 | 84 |     abort(); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 85 | } | 
 | 86 |  | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 87 | static void hash_ino(struct fuse *f, struct node *node) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 88 | { | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 89 |     size_t hash = node->ino % f->ino_table_size; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 90 |     node->ino_next = f->ino_table[hash]; | 
 | 91 |     f->ino_table[hash] = node;     | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 92 | } | 
 | 93 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 94 | static void unhash_ino(struct fuse *f, struct node *node) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 95 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 96 |     size_t hash = node->ino % f->ino_table_size; | 
 | 97 |     struct node **nodep = &f->ino_table[hash]; | 
 | 98 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 99 |     for (; *nodep != NULL; nodep = &(*nodep)->ino_next)  | 
 | 100 |         if (*nodep == node) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 101 |             *nodep = node->ino_next; | 
 | 102 |             return; | 
 | 103 |         } | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 104 | } | 
 | 105 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 106 | static fino_t next_ino(struct fuse *f) | 
 | 107 | { | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 108 |     do { | 
 | 109 |         f->ctr++; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 110 |         if (!f->ctr) | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 111 |             f->generation ++; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 112 |     } while (f->ctr == 0 || __get_node(f, f->ctr) != NULL); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 113 |     return f->ctr; | 
 | 114 | } | 
 | 115 |  | 
 | 116 | static void free_node(struct node *node) | 
 | 117 | { | 
 | 118 |     free(node->name); | 
 | 119 |     free(node); | 
 | 120 | } | 
 | 121 |  | 
 | 122 | static unsigned int name_hash(struct fuse *f, fino_t parent, const char *name) | 
 | 123 | { | 
 | 124 |     unsigned int hash = *name; | 
 | 125 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 126 |     if (hash) | 
 | 127 |         for (name += 1; *name != '\0'; name++) | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 128 |             hash = (hash << 5) - hash + *name; | 
 | 129 |  | 
 | 130 |     return (hash + parent) % f->name_table_size; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 131 | } | 
 | 132 |  | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 133 | static struct node *__lookup_node(struct fuse *f, fino_t parent, | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 134 |                                 const char *name) | 
 | 135 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 136 |     size_t hash = name_hash(f, parent, name); | 
 | 137 |     struct node *node; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 138 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 139 |     for (node = f->name_table[hash]; node != NULL; node = node->name_next) | 
 | 140 |         if (node->parent == parent && strcmp(node->name, name) == 0) | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 141 |             return node; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 142 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 143 |     return NULL; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 144 | } | 
 | 145 |  | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 146 | static struct node *lookup_node(struct fuse *f, fino_t parent, | 
 | 147 |                                 const char *name) | 
 | 148 | { | 
 | 149 |     struct node *node; | 
 | 150 |  | 
 | 151 |     pthread_mutex_lock(&f->lock); | 
 | 152 |     node = __lookup_node(f, parent, name); | 
 | 153 |     pthread_mutex_unlock(&f->lock); | 
 | 154 |     if (node != NULL) | 
 | 155 |         return node; | 
 | 156 |      | 
 | 157 |     fprintf(stderr, "fuse internal error: node %lu/%s not found\n", parent, | 
 | 158 |             name); | 
 | 159 |     abort(); | 
 | 160 | } | 
 | 161 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 162 | static void hash_name(struct fuse *f, struct node *node, fino_t parent, | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 163 |                       const char *name) | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 164 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 165 |     size_t hash = name_hash(f, parent, name); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 166 |     node->parent = parent; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 167 |     node->name = strdup(name); | 
 | 168 |     node->name_next = f->name_table[hash]; | 
 | 169 |     f->name_table[hash] = node;     | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 170 | } | 
 | 171 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 172 | static void unhash_name(struct fuse *f, struct node *node) | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 173 | { | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 174 |     if (node->name != NULL) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 175 |         size_t hash = name_hash(f, node->parent, node->name); | 
 | 176 |         struct node **nodep = &f->name_table[hash]; | 
 | 177 |          | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 178 |         for (; *nodep != NULL; nodep = &(*nodep)->name_next) | 
 | 179 |             if (*nodep == node) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 180 |                 *nodep = node->name_next; | 
 | 181 |                 node->name_next = NULL; | 
 | 182 |                 free(node->name); | 
 | 183 |                 node->name = NULL; | 
 | 184 |                 node->parent = 0; | 
 | 185 |                 return; | 
 | 186 |             } | 
 | 187 |         fprintf(stderr, "fuse internal error: unable to unhash node: %lu\n", | 
 | 188 |                 node->ino); | 
 | 189 |         abort(); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 190 |     } | 
 | 191 | } | 
 | 192 |  | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 193 | static struct node *find_node(struct fuse *f, fino_t parent, char *name, | 
 | 194 |                               struct fuse_attr *attr, int version) | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 195 | { | 
 | 196 |     struct node *node; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 197 |     int mode = attr->mode & S_IFMT; | 
 | 198 |     int rdev = 0; | 
 | 199 |      | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 200 |     if (S_ISCHR(mode) || S_ISBLK(mode)) | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 201 |         rdev = attr->rdev; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 202 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 203 |     pthread_mutex_lock(&f->lock); | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 204 |     node = __lookup_node(f, parent, name); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 205 |     if (node != NULL) { | 
 | 206 |         if (node->mode == mode && node->rdev == rdev) | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 207 |             goto out; | 
 | 208 |          | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 209 |         unhash_name(f, node); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 210 |     } | 
 | 211 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 212 |     node = (struct node *) calloc(1, sizeof(struct node)); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 213 |     node->mode = mode; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 214 |     node->rdev = rdev; | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 215 |     node->open_count = 0; | 
 | 216 |     node->is_hidden = 0; | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 217 |     node->ino = next_ino(f); | 
 | 218 |     node->generation = f->generation; | 
 | 219 |     hash_ino(f, node); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 220 |     hash_name(f, node, parent, name); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 221 |  | 
 | 222 |   out: | 
 | 223 |     node->version = version; | 
 | 224 |     pthread_mutex_unlock(&f->lock); | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 225 |     return node; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 226 | } | 
 | 227 |  | 
| Miklos Szeredi | 891b874 | 2004-07-29 09:27:49 +0000 | [diff] [blame^] | 228 | static int path_lookup(struct fuse *f, const char *path, fino_t *inop) | 
 | 229 | { | 
 | 230 |     fino_t ino; | 
 | 231 |     int err; | 
 | 232 |     char *s; | 
 | 233 |     char *name; | 
 | 234 |     char *tmp = strdup(path); | 
 | 235 |     if (!tmp) | 
 | 236 |         return -ENOMEM; | 
 | 237 |  | 
 | 238 |     pthread_mutex_lock(&f->lock); | 
 | 239 |     ino = FUSE_ROOT_INO; | 
 | 240 |     err = 0; | 
 | 241 |     for  (s = tmp; (name = strsep(&s, "/")) != NULL; ) { | 
 | 242 |         if (name[0]) { | 
 | 243 |             struct node *node = __lookup_node(f, ino, name); | 
 | 244 |             if (node == NULL) { | 
 | 245 |                 err = -ENOENT; | 
 | 246 |                 break; | 
 | 247 |             } | 
 | 248 |             ino = node->ino; | 
 | 249 |         } | 
 | 250 |     } | 
 | 251 |     pthread_mutex_unlock(&f->lock); | 
 | 252 |     free(tmp); | 
 | 253 |     if (!err) | 
 | 254 |         *inop = ino; | 
 | 255 |      | 
 | 256 |     return err; | 
 | 257 | } | 
 | 258 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 259 | static char *add_name(char *buf, char *s, const char *name) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 260 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 261 |     size_t len = strlen(name); | 
 | 262 |     s -= len; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 263 |     if (s <= buf) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 264 |         fprintf(stderr, "fuse: path too long: ...%s\n", s + len); | 
 | 265 |         return NULL; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 266 |     } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 267 |     strncpy(s, name, len); | 
 | 268 |     s--; | 
 | 269 |     *s = '/'; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 270 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 271 |     return s; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 272 | } | 
 | 273 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 274 | static char *get_path_name(struct fuse *f, fino_t ino, const char *name) | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 275 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 276 |     char buf[FUSE_MAX_PATH]; | 
 | 277 |     char *s = buf + FUSE_MAX_PATH - 1; | 
 | 278 |     struct node *node; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 279 |      | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 280 |     *s = '\0'; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 281 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 282 |     if (name != NULL) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 283 |         s = add_name(buf, s, name); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 284 |         if (s == NULL) | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 285 |             return NULL; | 
 | 286 |     } | 
 | 287 |  | 
 | 288 |     pthread_mutex_lock(&f->lock); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 289 |     for (node = get_node(f, ino); node->ino != FUSE_ROOT_INO; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 290 |         node = get_node(f, node->parent)) { | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 291 |         if (node->name == NULL) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 292 |             s = NULL; | 
 | 293 |             break; | 
 | 294 |         } | 
 | 295 |          | 
 | 296 |         s = add_name(buf, s, node->name); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 297 |         if (s == NULL) | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 298 |             break; | 
 | 299 |     } | 
 | 300 |     pthread_mutex_unlock(&f->lock); | 
 | 301 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 302 |     if (s == NULL)  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 303 |         return NULL; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 304 |     else if (*s == '\0') | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 305 |         return strdup("/"); | 
 | 306 |     else | 
 | 307 |         return strdup(s); | 
 | 308 | } | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 309 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 310 | static char *get_path(struct fuse *f, fino_t ino) | 
 | 311 | { | 
 | 312 |     return get_path_name(f, ino, NULL); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 313 | } | 
 | 314 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 315 | static void destroy_node(struct fuse *f, fino_t ino, int version) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 316 | { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 317 |     struct node *node; | 
 | 318 |  | 
 | 319 |     pthread_mutex_lock(&f->lock); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 320 |     node = get_node(f, ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 321 |     if (node->version == version && ino != FUSE_ROOT_INO) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 322 |         unhash_name(f, node); | 
 | 323 |         unhash_ino(f, node); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 324 |         free_node(node); | 
 | 325 |     } | 
 | 326 |     pthread_mutex_unlock(&f->lock); | 
 | 327 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 328 | } | 
 | 329 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 330 | static void remove_node(struct fuse *f, fino_t dir, const char *name) | 
 | 331 | { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 332 |     struct node *node; | 
 | 333 |  | 
 | 334 |     pthread_mutex_lock(&f->lock); | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 335 |     node = __lookup_node(f, dir, name); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 336 |     if (node == NULL) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 337 |         fprintf(stderr, "fuse internal error: unable to remove node %lu/%s\n", | 
 | 338 |                 dir, name); | 
 | 339 |         abort(); | 
 | 340 |     } | 
 | 341 |     unhash_name(f, node); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 342 |     pthread_mutex_unlock(&f->lock); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 343 | } | 
 | 344 |  | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 345 | static int rename_node(struct fuse *f, fino_t olddir, const char *oldname, | 
 | 346 |                         fino_t newdir, const char *newname, int hide) | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 347 | { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 348 |     struct node *node; | 
 | 349 |     struct node *newnode; | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 350 |     int err = 0; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 351 |      | 
 | 352 |     pthread_mutex_lock(&f->lock); | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 353 |     node  = __lookup_node(f, olddir, oldname); | 
 | 354 |     newnode  = __lookup_node(f, newdir, newname); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 355 |     if (node == NULL) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 356 |         fprintf(stderr, "fuse internal error: unable to rename node %lu/%s\n", | 
 | 357 |                 olddir, oldname); | 
 | 358 |         abort(); | 
 | 359 |     } | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 360 |  | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 361 |     if (newnode != NULL) { | 
 | 362 |         if (hide) { | 
 | 363 |             fprintf(stderr, "fuse: hidden file got created during hiding\n"); | 
 | 364 |             err = -1; | 
 | 365 |             goto out; | 
 | 366 |         } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 367 |         unhash_name(f, newnode); | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 368 |     } | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 369 |          | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 370 |     unhash_name(f, node); | 
 | 371 |     hash_name(f, node, newdir, newname); | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 372 |     if (hide) | 
 | 373 |         node->is_hidden = 1; | 
 | 374 |  | 
 | 375 |  out: | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 376 |     pthread_mutex_unlock(&f->lock); | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 377 |     return err; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 378 | } | 
 | 379 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 380 | static void convert_stat(struct stat *stbuf, struct fuse_attr *attr) | 
 | 381 | { | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 382 |     attr->mode      = stbuf->st_mode; | 
 | 383 |     attr->nlink     = stbuf->st_nlink; | 
 | 384 |     attr->uid       = stbuf->st_uid; | 
 | 385 |     attr->gid       = stbuf->st_gid; | 
 | 386 |     attr->rdev      = stbuf->st_rdev; | 
 | 387 |     attr->size      = stbuf->st_size; | 
 | 388 |     attr->blocks    = stbuf->st_blocks; | 
 | 389 |     attr->atime     = stbuf->st_atime; | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 390 |     attr->mtime     = stbuf->st_mtime; | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 391 |     attr->ctime     = stbuf->st_ctime; | 
| Miklos Szeredi | cb26451 | 2004-06-23 18:52:50 +0000 | [diff] [blame] | 392 | #ifdef HAVE_STRUCT_STAT_ST_ATIM | 
 | 393 |     attr->atimensec = stbuf->st_atim.tv_nsec; | 
 | 394 |     attr->mtimensec = stbuf->st_mtim.tv_nsec; | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 395 |     attr->ctimensec = stbuf->st_ctim.tv_nsec; | 
| Miklos Szeredi | cb26451 | 2004-06-23 18:52:50 +0000 | [diff] [blame] | 396 | #endif | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 397 | } | 
 | 398 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 399 | static int fill_dir(struct fuse_dirhandle *dh, char *name, int type) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 400 | { | 
 | 401 |     struct fuse_dirent dirent; | 
 | 402 |     size_t reclen; | 
 | 403 |     size_t res; | 
 | 404 |  | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 405 |     dirent.ino = (unsigned long) -1; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 406 |     dirent.namelen = strlen(name); | 
 | 407 |     strncpy(dirent.name, name, sizeof(dirent.name)); | 
 | 408 |     dirent.type = type; | 
 | 409 |     reclen = FUSE_DIRENT_SIZE(&dirent); | 
 | 410 |     res = fwrite(&dirent, reclen, 1, dh->fp); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 411 |     if (res == 0) { | 
| Miklos Szeredi | 9624998 | 2001-11-21 12:21:19 +0000 | [diff] [blame] | 412 |         perror("fuse: writing directory file"); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 413 |         return -EIO; | 
 | 414 |     } | 
 | 415 |     return 0; | 
 | 416 | } | 
 | 417 |  | 
| Miklos Szeredi | 73798f9 | 2004-07-12 15:55:11 +0000 | [diff] [blame] | 418 | static int send_reply_raw(struct fuse *f, char *outbuf, size_t outsize, | 
 | 419 |                           int locked) | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 420 | { | 
 | 421 |     int res; | 
 | 422 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 423 |     if ((f->flags & FUSE_DEBUG)) { | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 424 |         struct fuse_out_header *out = (struct fuse_out_header *) outbuf; | 
 | 425 |         printf("   unique: %i, error: %i (%s), outsize: %i\n", out->unique, | 
 | 426 |                out->error, strerror(-out->error), outsize); | 
 | 427 |         fflush(stdout); | 
 | 428 |     } | 
| Miklos Szeredi | 99ddf0e | 2001-11-25 17:19:59 +0000 | [diff] [blame] | 429 |  | 
| Miklos Szeredi | 4e71c9f | 2004-02-09 12:05:14 +0000 | [diff] [blame] | 430 |     /* This needs to be done before the reply, otherwise the scheduler | 
 | 431 |     could play tricks with us, and only let the counter be increased | 
| Miklos Szeredi | 99ddf0e | 2001-11-25 17:19:59 +0000 | [diff] [blame] | 432 |     long after the operation is done */ | 
| Miklos Szeredi | 73798f9 | 2004-07-12 15:55:11 +0000 | [diff] [blame] | 433 |     if (!locked) | 
 | 434 |         pthread_mutex_lock(&f->lock); | 
 | 435 |     f->numavail ++; | 
 | 436 |     if (!locked) | 
 | 437 |         pthread_mutex_unlock(&f->lock); | 
| Miklos Szeredi | 99ddf0e | 2001-11-25 17:19:59 +0000 | [diff] [blame] | 438 |  | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 439 |     res = write(f->fd, outbuf, outsize); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 440 |     if (res == -1) { | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 441 |         /* ENOENT means the operation was interrupted */ | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 442 |         if (!f->exited && errno != ENOENT) | 
| Miklos Szeredi | 9624998 | 2001-11-21 12:21:19 +0000 | [diff] [blame] | 443 |             perror("fuse: writing device"); | 
| Miklos Szeredi | 40b9a5a | 2002-12-10 16:09:02 +0000 | [diff] [blame] | 444 |         return -errno; | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 445 |     } | 
| Miklos Szeredi | 40b9a5a | 2002-12-10 16:09:02 +0000 | [diff] [blame] | 446 |     return 0; | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 447 | } | 
 | 448 |  | 
| Miklos Szeredi | 73798f9 | 2004-07-12 15:55:11 +0000 | [diff] [blame] | 449 | static int __send_reply(struct fuse *f, struct fuse_in_header *in, int error, | 
 | 450 |                         void *arg, size_t argsize, int locked) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 451 | { | 
| Miklos Szeredi | 40b9a5a | 2002-12-10 16:09:02 +0000 | [diff] [blame] | 452 |     int res; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 453 |     char *outbuf; | 
 | 454 |     size_t outsize; | 
 | 455 |     struct fuse_out_header *out; | 
 | 456 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 457 |     if (error <= -1000 || error > 0) { | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 458 |         fprintf(stderr, "fuse: bad error value: %i\n",  error); | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 459 |         error = -ERANGE; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 460 |     } | 
 | 461 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 462 |     if (error) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 463 |         argsize = 0; | 
 | 464 |  | 
 | 465 |     outsize = sizeof(struct fuse_out_header) + argsize; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 466 |     outbuf = (char *) malloc(outsize); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 467 |     out = (struct fuse_out_header *) outbuf; | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 468 |     memset(out, 0, sizeof(struct fuse_out_header)); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 469 |     out->unique = in->unique; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 470 |     out->error = error; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 471 |     if (argsize != 0) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 472 |         memcpy(outbuf + sizeof(struct fuse_out_header), arg, argsize); | 
 | 473 |  | 
| Miklos Szeredi | 73798f9 | 2004-07-12 15:55:11 +0000 | [diff] [blame] | 474 |     res = send_reply_raw(f, outbuf, outsize, locked); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 475 |     free(outbuf); | 
| Miklos Szeredi | 40b9a5a | 2002-12-10 16:09:02 +0000 | [diff] [blame] | 476 |  | 
 | 477 |     return res; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 478 | } | 
 | 479 |  | 
| Miklos Szeredi | 73798f9 | 2004-07-12 15:55:11 +0000 | [diff] [blame] | 480 | static int send_reply(struct fuse *f, struct fuse_in_header *in, int error, | 
 | 481 |                         void *arg, size_t argsize) | 
 | 482 | { | 
 | 483 |     return __send_reply(f, in, error, arg, argsize, 0); | 
 | 484 | } | 
 | 485 |  | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 486 | static int is_open(struct fuse *f, fino_t dir, const char *name) | 
 | 487 | { | 
 | 488 |     struct node *node; | 
 | 489 |     int isopen = 0; | 
 | 490 |     pthread_mutex_lock(&f->lock); | 
 | 491 |     node = __lookup_node(f, dir, name); | 
 | 492 |     if (node && node->open_count > 0) | 
 | 493 |         isopen = 1; | 
 | 494 |     pthread_mutex_unlock(&f->lock); | 
 | 495 |     return isopen; | 
 | 496 | } | 
 | 497 |  | 
 | 498 | static char *hidden_name(struct fuse *f, fino_t dir, const char *oldname, | 
 | 499 |                         char *newname, size_t bufsize) | 
 | 500 | { | 
 | 501 |     struct stat buf; | 
 | 502 |     struct node *node; | 
 | 503 |     struct node *newnode; | 
 | 504 |     char *newpath; | 
 | 505 |     int res; | 
 | 506 |     int failctr = 10; | 
 | 507 |  | 
 | 508 |     if (!f->op.getattr) | 
 | 509 |         return NULL; | 
 | 510 |  | 
 | 511 |     do { | 
 | 512 |         node = lookup_node(f, dir, oldname); | 
 | 513 |         pthread_mutex_lock(&f->lock); | 
 | 514 |         do { | 
 | 515 |             f->hidectr ++; | 
 | 516 |             snprintf(newname, bufsize, ".fuse_hidden%08x%08x", | 
 | 517 |                      (unsigned int) node->ino, f->hidectr); | 
 | 518 |             newnode = __lookup_node(f, dir, newname); | 
 | 519 |         } while(newnode); | 
 | 520 |         pthread_mutex_unlock(&f->lock); | 
 | 521 |          | 
 | 522 |         newpath = get_path_name(f, dir, newname); | 
 | 523 |         if (!newpath) | 
 | 524 |             break; | 
 | 525 |          | 
 | 526 |         res = f->op.getattr(newpath, &buf); | 
 | 527 |         if (res != 0) | 
 | 528 |             break; | 
 | 529 |         free(newpath); | 
 | 530 |         newpath = NULL; | 
 | 531 |     } while(--failctr); | 
 | 532 |  | 
 | 533 |     return newpath; | 
 | 534 | } | 
 | 535 |  | 
 | 536 | static int hide_node(struct fuse *f, const char *oldpath, fino_t dir, | 
 | 537 |                      const char *oldname) | 
 | 538 | { | 
 | 539 |     char newname[64]; | 
 | 540 |     char *newpath; | 
 | 541 |     int err = -1; | 
 | 542 |  | 
 | 543 |     if (!f->op.rename || !f->op.unlink) | 
 | 544 |         return -EBUSY; | 
 | 545 |  | 
 | 546 |     newpath = hidden_name(f, dir, oldname, newname, sizeof(newname)); | 
 | 547 |     if (newpath) { | 
 | 548 |         err = f->op.rename(oldpath, newpath); | 
 | 549 |         if (!err) | 
 | 550 |             err = rename_node(f, dir, oldname, dir, newname, 1); | 
 | 551 |         free(newpath); | 
 | 552 |     } | 
 | 553 |     if (err) | 
 | 554 |         return -EBUSY; | 
 | 555 |      | 
 | 556 |     return 0; | 
 | 557 | } | 
 | 558 |  | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 559 | static int lookup_path(struct fuse *f, fino_t ino, int version,  char *name, | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 560 |                        const char *path, struct fuse_entry_out *arg) | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 561 | { | 
 | 562 |     int res; | 
 | 563 |     struct stat buf; | 
 | 564 |  | 
 | 565 |     res = f->op.getattr(path, &buf); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 566 |     if (res == 0) { | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 567 |         struct node *node; | 
 | 568 |  | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 569 |         memset(arg, 0, sizeof(struct fuse_entry_out)); | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 570 |         convert_stat(&buf, &arg->attr); | 
 | 571 |         node = find_node(f, ino, name, &arg->attr, version); | 
 | 572 |         arg->ino = node->ino; | 
 | 573 |         arg->generation = node->generation; | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 574 |         arg->entry_valid = ENTRY_REVALIDATE_TIME; | 
 | 575 |         arg->entry_valid_nsec = 0; | 
 | 576 |         arg->attr_valid = ATTR_REVALIDATE_TIME; | 
 | 577 |         arg->attr_valid_nsec = 0; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 578 |         if (f->flags & FUSE_DEBUG) { | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 579 |             printf("   INO: %li\n", arg->ino); | 
 | 580 |             fflush(stdout); | 
 | 581 |         } | 
 | 582 |     } | 
 | 583 |     return res; | 
 | 584 | } | 
 | 585 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 586 | static void do_lookup(struct fuse *f, struct fuse_in_header *in, char *name) | 
 | 587 | { | 
 | 588 |     int res; | 
| Miklos Szeredi | 2778f6c | 2004-06-21 09:45:30 +0000 | [diff] [blame] | 589 |     int res2; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 590 |     char *path; | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 591 |     struct fuse_entry_out arg; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 592 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 593 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 594 |     path = get_path_name(f, in->ino, name); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 595 |     if (path != NULL) { | 
 | 596 |         if (f->flags & FUSE_DEBUG) { | 
| Miklos Szeredi | 6ebe234 | 2002-01-06 21:44:16 +0000 | [diff] [blame] | 597 |             printf("LOOKUP %s\n", path); | 
 | 598 |             fflush(stdout); | 
 | 599 |         } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 600 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 601 |         if (f->op.getattr) | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 602 |             res = lookup_path(f, in->ino, in->unique, name, path, &arg); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 603 |         free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 604 |     } | 
| Miklos Szeredi | 2778f6c | 2004-06-21 09:45:30 +0000 | [diff] [blame] | 605 |     res2 = send_reply(f, in, res, &arg, sizeof(arg)); | 
 | 606 |     if (res == 0 && res2 == -ENOENT) | 
 | 607 |         destroy_node(f, arg.ino, in->unique); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 608 | } | 
 | 609 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 610 | static void do_forget(struct fuse *f, struct fuse_in_header *in, | 
 | 611 |                       struct fuse_forget_in *arg) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 612 | { | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 613 |     if (f->flags & FUSE_DEBUG) { | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 614 |         printf("FORGET %li/%i\n", in->ino, arg->version); | 
 | 615 |         fflush(stdout); | 
 | 616 |     } | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 617 |     destroy_node(f, in->ino, arg->version); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 618 | } | 
 | 619 |  | 
 | 620 | static void do_getattr(struct fuse *f, struct fuse_in_header *in) | 
 | 621 | { | 
 | 622 |     int res; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 623 |     char *path; | 
 | 624 |     struct stat buf; | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 625 |     struct fuse_attr_out arg; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 626 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 627 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 628 |     path = get_path(f, in->ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 629 |     if (path != NULL) { | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 630 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 631 |         if (f->op.getattr) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 632 |             res = f->op.getattr(path, &buf); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 633 |         free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 634 |     } | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 635 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 636 |     if (res == 0) { | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 637 |         memset(&arg, 0, sizeof(struct fuse_attr_out)); | 
 | 638 |         arg.attr_valid = ATTR_REVALIDATE_TIME; | 
 | 639 |         arg.attr_valid_nsec = 0; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 640 |         convert_stat(&buf, &arg.attr); | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 641 |     } | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 642 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 643 |     send_reply(f, in, res, &arg, sizeof(arg)); | 
 | 644 | } | 
 | 645 |  | 
| Miklos Szeredi | 680a69a | 2001-11-16 13:31:14 +0000 | [diff] [blame] | 646 | static int do_chmod(struct fuse *f, const char *path, struct fuse_attr *attr) | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 647 | { | 
 | 648 |     int res; | 
 | 649 |  | 
 | 650 |     res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 651 |     if (f->op.chmod) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 652 |         res = f->op.chmod(path, attr->mode); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 653 |  | 
 | 654 |     return res; | 
 | 655 | }         | 
 | 656 |  | 
| Miklos Szeredi | 680a69a | 2001-11-16 13:31:14 +0000 | [diff] [blame] | 657 | static int do_chown(struct fuse *f, const char *path, struct fuse_attr *attr, | 
| Miklos Szeredi | 2e50d43 | 2001-12-20 12:17:25 +0000 | [diff] [blame] | 658 |                     int valid) | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 659 | { | 
 | 660 |     int res; | 
 | 661 |     uid_t uid = (valid & FATTR_UID) ? attr->uid : (uid_t) -1; | 
 | 662 |     gid_t gid = (valid & FATTR_GID) ? attr->gid : (gid_t) -1; | 
 | 663 |      | 
 | 664 |     res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 665 |     if (f->op.chown) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 666 |         res = f->op.chown(path, uid, gid); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 667 |  | 
 | 668 |     return res; | 
 | 669 | } | 
 | 670 |  | 
| Miklos Szeredi | 680a69a | 2001-11-16 13:31:14 +0000 | [diff] [blame] | 671 | static int do_truncate(struct fuse *f, const char *path, | 
 | 672 |                        struct fuse_attr *attr) | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 673 | { | 
 | 674 |     int res; | 
 | 675 |  | 
 | 676 |     res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 677 |     if (f->op.truncate) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 678 |         res = f->op.truncate(path, attr->size); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 679 |  | 
 | 680 |     return res; | 
 | 681 | } | 
 | 682 |  | 
| Miklos Szeredi | 680a69a | 2001-11-16 13:31:14 +0000 | [diff] [blame] | 683 | static int do_utime(struct fuse *f, const char *path, struct fuse_attr *attr) | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 684 | { | 
 | 685 |     int res; | 
 | 686 |     struct utimbuf buf; | 
 | 687 |     buf.actime = attr->atime; | 
 | 688 |     buf.modtime = attr->mtime; | 
 | 689 |     res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 690 |     if (f->op.utime) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 691 |         res = f->op.utime(path, &buf); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 692 |  | 
 | 693 |     return res; | 
 | 694 | } | 
 | 695 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 696 | static void do_setattr(struct fuse *f, struct fuse_in_header *in, | 
 | 697 |                        struct fuse_setattr_in *arg) | 
 | 698 | { | 
 | 699 |     int res; | 
 | 700 |     char *path; | 
 | 701 |     int valid = arg->valid; | 
 | 702 |     struct fuse_attr *attr = &arg->attr; | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 703 |     struct fuse_attr_out outarg; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 704 |  | 
 | 705 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 706 |     path = get_path(f, in->ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 707 |     if (path != NULL) { | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 708 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 709 |         if (f->op.getattr) { | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 710 |             res = 0; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 711 |             if (!res && (valid & FATTR_MODE)) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 712 |                 res = do_chmod(f, path, attr); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 713 |             if (!res && (valid & (FATTR_UID | FATTR_GID))) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 714 |                 res = do_chown(f, path, attr, valid); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 715 |             if (!res && (valid & FATTR_SIZE)) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 716 |                 res = do_truncate(f, path, attr); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 717 |             if (!res && (valid & (FATTR_ATIME | FATTR_MTIME)) ==  | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 718 |                (FATTR_ATIME | FATTR_MTIME)) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 719 |                 res = do_utime(f, path, attr); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 720 |             if (!res) { | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 721 |                 struct stat buf; | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 722 |                 res = f->op.getattr(path, &buf); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 723 |                 if (!res) { | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 724 |                     memset(&outarg, 0, sizeof(struct fuse_attr_out)); | 
 | 725 |                     outarg.attr_valid = ATTR_REVALIDATE_TIME; | 
 | 726 |                     outarg.attr_valid_nsec = 0; | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 727 |                     convert_stat(&buf, &outarg.attr); | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 728 |                 } | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 729 |             } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 730 |         } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 731 |         free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 732 |     } | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 733 |     send_reply(f, in, res, &outarg, sizeof(outarg)); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 734 | } | 
 | 735 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 736 | static void do_readlink(struct fuse *f, struct fuse_in_header *in) | 
 | 737 | { | 
 | 738 |     int res; | 
 | 739 |     char link[PATH_MAX + 1]; | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 740 |     char *path; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 741 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 742 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 743 |     path = get_path(f, in->ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 744 |     if (path != NULL) { | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 745 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 746 |         if (f->op.readlink) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 747 |             res = f->op.readlink(path, link, sizeof(link)); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 748 |         free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 749 |     } | 
| Miklos Szeredi | 2df1c04 | 2001-11-06 15:07:17 +0000 | [diff] [blame] | 750 |     link[PATH_MAX] = '\0'; | 
| Miklos Szeredi | 4b2bef4 | 2002-01-09 12:23:27 +0000 | [diff] [blame] | 751 |     send_reply(f, in, res, link, res == 0 ? strlen(link) : 0); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 752 | } | 
 | 753 |  | 
 | 754 | static void do_getdir(struct fuse *f, struct fuse_in_header *in) | 
 | 755 | { | 
 | 756 |     int res; | 
 | 757 |     struct fuse_getdir_out arg; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 758 |     struct fuse_dirhandle dh; | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 759 |     char *path; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 760 |  | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 761 |     dh.fuse = f; | 
 | 762 |     dh.fp = tmpfile(); | 
 | 763 |     dh.dir = in->ino; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 764 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 765 |     path = get_path(f, in->ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 766 |     if (path != NULL) { | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 767 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 768 |         if (f->op.getdir) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 769 |             res = f->op.getdir(path, &dh, (fuse_dirfil_t) fill_dir); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 770 |         free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 771 |     } | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 772 |     fflush(dh.fp); | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 773 |  | 
 | 774 |     memset(&arg, 0, sizeof(struct fuse_getdir_out)); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 775 |     arg.fd = fileno(dh.fp); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 776 |     send_reply(f, in, res, &arg, sizeof(arg)); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 777 |     fclose(dh.fp); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 778 | } | 
 | 779 |  | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 780 | static void do_mknod(struct fuse *f, struct fuse_in_header *in, | 
 | 781 |                      struct fuse_mknod_in *inarg) | 
 | 782 | { | 
 | 783 |     int res; | 
| Miklos Szeredi | 2778f6c | 2004-06-21 09:45:30 +0000 | [diff] [blame] | 784 |     int res2; | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 785 |     char *path; | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 786 |     char *name = PARAM(inarg); | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 787 |     struct fuse_entry_out outarg; | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 788 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 789 |     res = -ENOENT; | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 790 |     path = get_path_name(f, in->ino, name); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 791 |     if (path != NULL) { | 
 | 792 |         if (f->flags & FUSE_DEBUG) { | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 793 |             printf("MKNOD %s\n", path); | 
 | 794 |             fflush(stdout); | 
 | 795 |         } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 796 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 797 |         if (f->op.mknod && f->op.getattr) { | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 798 |             res = f->op.mknod(path, inarg->mode, inarg->rdev); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 799 |             if (res == 0) | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 800 |                 res = lookup_path(f, in->ino, in->unique, name, path, &outarg); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 801 |         } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 802 |         free(path); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 803 |     } | 
| Miklos Szeredi | 2778f6c | 2004-06-21 09:45:30 +0000 | [diff] [blame] | 804 |     res2 = send_reply(f, in, res, &outarg, sizeof(outarg)); | 
 | 805 |     if (res == 0 && res2 == -ENOENT) | 
 | 806 |         destroy_node(f, outarg.ino, in->unique); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 807 | } | 
 | 808 |  | 
 | 809 | static void do_mkdir(struct fuse *f, struct fuse_in_header *in, | 
 | 810 |                      struct fuse_mkdir_in *inarg) | 
 | 811 | { | 
 | 812 |     int res; | 
| Miklos Szeredi | 2778f6c | 2004-06-21 09:45:30 +0000 | [diff] [blame] | 813 |     int res2; | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 814 |     char *path; | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 815 |     char *name = PARAM(inarg); | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 816 |     struct fuse_entry_out outarg; | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 817 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 818 |     res = -ENOENT; | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 819 |     path = get_path_name(f, in->ino, name); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 820 |     if (path != NULL) { | 
 | 821 |         if (f->flags & FUSE_DEBUG) { | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 822 |             printf("MKDIR %s\n", path); | 
 | 823 |             fflush(stdout); | 
 | 824 |         } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 825 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 826 |         if (f->op.mkdir && f->op.getattr) { | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 827 |             res = f->op.mkdir(path, inarg->mode); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 828 |             if (res == 0) | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 829 |                 res = lookup_path(f, in->ino, in->unique, name, path, &outarg); | 
 | 830 |         } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 831 |         free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 832 |     } | 
| Miklos Szeredi | 2778f6c | 2004-06-21 09:45:30 +0000 | [diff] [blame] | 833 |     res2 = send_reply(f, in, res, &outarg, sizeof(outarg)); | 
 | 834 |     if (res == 0 && res2 == -ENOENT) | 
 | 835 |         destroy_node(f, outarg.ino, in->unique); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 836 | } | 
 | 837 |  | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 838 | static void do_unlink(struct fuse *f, struct fuse_in_header *in, char *name) | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 839 | { | 
 | 840 |     int res; | 
 | 841 |     char *path; | 
 | 842 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 843 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 844 |     path = get_path_name(f, in->ino, name); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 845 |     if (path != NULL) { | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 846 |         if (f->flags & FUSE_DEBUG) { | 
 | 847 |             printf("UNLINK %s\n", path); | 
 | 848 |             fflush(stdout); | 
 | 849 |         } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 850 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 851 |         if (f->op.unlink) { | 
| Miklos Szeredi | 2529ca2 | 2004-07-13 15:36:52 +0000 | [diff] [blame] | 852 |             if (!(f->flags & FUSE_HARD_REMOVE) && is_open(f, in->ino, name)) | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 853 |                 res = hide_node(f, path, in->ino, name); | 
 | 854 |             else { | 
 | 855 |                 res = f->op.unlink(path); | 
 | 856 |                 if (res == 0) | 
 | 857 |                     remove_node(f, in->ino, name); | 
 | 858 |             } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 859 |         } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 860 |         free(path); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 861 |     } | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 862 |     send_reply(f, in, res, NULL, 0); | 
 | 863 | } | 
 | 864 |  | 
 | 865 | static void do_rmdir(struct fuse *f, struct fuse_in_header *in, char *name) | 
 | 866 | { | 
 | 867 |     int res; | 
 | 868 |     char *path; | 
 | 869 |  | 
 | 870 |     res = -ENOENT; | 
 | 871 |     path = get_path_name(f, in->ino, name); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 872 |     if (path != NULL) { | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 873 |         if (f->flags & FUSE_DEBUG) { | 
 | 874 |             printf("RMDIR %s\n", path); | 
 | 875 |             fflush(stdout); | 
 | 876 |         } | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 877 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 878 |         if (f->op.rmdir) { | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 879 |             res = f->op.rmdir(path); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 880 |             if (res == 0) | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 881 |                 remove_node(f, in->ino, name); | 
 | 882 |         } | 
 | 883 |         free(path); | 
 | 884 |     } | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 885 |     send_reply(f, in, res, NULL, 0); | 
 | 886 | } | 
 | 887 |  | 
 | 888 | static void do_symlink(struct fuse *f, struct fuse_in_header *in, char *name, | 
 | 889 |                        char *link) | 
 | 890 | { | 
 | 891 |     int res; | 
| Miklos Szeredi | 2778f6c | 2004-06-21 09:45:30 +0000 | [diff] [blame] | 892 |     int res2; | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 893 |     char *path; | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 894 |     struct fuse_entry_out outarg; | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 895 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 896 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 897 |     path = get_path_name(f, in->ino, name); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 898 |     if (path != NULL) { | 
 | 899 |         if (f->flags & FUSE_DEBUG) { | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 900 |             printf("SYMLINK %s\n", path); | 
 | 901 |             fflush(stdout); | 
 | 902 |         } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 903 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 904 |         if (f->op.symlink && f->op.getattr) { | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 905 |             res = f->op.symlink(link, path); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 906 |             if (res == 0) | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 907 |                 res = lookup_path(f, in->ino, in->unique, name, path, &outarg); | 
 | 908 |         } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 909 |         free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 910 |     } | 
| Miklos Szeredi | 2778f6c | 2004-06-21 09:45:30 +0000 | [diff] [blame] | 911 |     res2 = send_reply(f, in, res, &outarg, sizeof(outarg)); | 
 | 912 |     if (res == 0 && res2 == -ENOENT) | 
 | 913 |         destroy_node(f, outarg.ino, in->unique); | 
 | 914 |  | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 915 | } | 
 | 916 |  | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 917 | static void do_rename(struct fuse *f, struct fuse_in_header *in, | 
 | 918 |                       struct fuse_rename_in *inarg) | 
 | 919 | { | 
 | 920 |     int res; | 
 | 921 |     fino_t olddir = in->ino; | 
 | 922 |     fino_t newdir = inarg->newdir; | 
| Miklos Szeredi | 6bf8b68 | 2002-10-28 08:49:39 +0000 | [diff] [blame] | 923 |     char *oldname = PARAM(inarg); | 
 | 924 |     char *newname = oldname + strlen(oldname) + 1; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 925 |     char *oldpath; | 
 | 926 |     char *newpath; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 927 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 928 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 929 |     oldpath = get_path_name(f, olddir, oldname); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 930 |     if (oldpath != NULL) { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 931 |         newpath = get_path_name(f, newdir, newname); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 932 |         if (newpath != NULL) { | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 933 |             if (f->flags & FUSE_DEBUG) { | 
 | 934 |                 printf("RENAME %s -> %s\n", oldpath, newpath); | 
 | 935 |                 fflush(stdout); | 
 | 936 |             } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 937 |             res = -ENOSYS; | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 938 |             if (f->op.rename) { | 
 | 939 |                 res = 0; | 
| Miklos Szeredi | 2529ca2 | 2004-07-13 15:36:52 +0000 | [diff] [blame] | 940 |                 if (!(f->flags & FUSE_HARD_REMOVE) &&  | 
 | 941 |                     is_open(f, newdir, newname)) | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 942 |                     res = hide_node(f, newpath, newdir, newname); | 
 | 943 |                 if (res == 0) { | 
 | 944 |                     res = f->op.rename(oldpath, newpath); | 
 | 945 |                     if (res == 0) | 
 | 946 |                         rename_node(f, olddir, oldname, newdir, newname, 0); | 
 | 947 |                 } | 
 | 948 |             } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 949 |             free(newpath); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 950 |         } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 951 |         free(oldpath); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 952 |     } | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 953 |     send_reply(f, in, res, NULL, 0);    | 
 | 954 | } | 
 | 955 |  | 
 | 956 | static void do_link(struct fuse *f, struct fuse_in_header *in, | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 957 |                     struct fuse_link_in *arg) | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 958 | { | 
 | 959 |     int res; | 
| Miklos Szeredi | 2778f6c | 2004-06-21 09:45:30 +0000 | [diff] [blame] | 960 |     int res2; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 961 |     char *oldpath; | 
 | 962 |     char *newpath; | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 963 |     char *name = PARAM(arg); | 
| Miklos Szeredi | 254d5ed | 2004-03-02 11:11:24 +0000 | [diff] [blame] | 964 |     struct fuse_entry_out outarg; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 965 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 966 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 967 |     oldpath = get_path(f, in->ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 968 |     if (oldpath != NULL) { | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 969 |         newpath =  get_path_name(f, arg->newdir, name); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 970 |         if (newpath != NULL) { | 
 | 971 |             if (f->flags & FUSE_DEBUG) { | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 972 |                 printf("LINK %s\n", newpath); | 
 | 973 |                 fflush(stdout); | 
 | 974 |             } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 975 |             res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 976 |             if (f->op.link && f->op.getattr) { | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 977 |                 res = f->op.link(oldpath, newpath); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 978 |                 if (res == 0) | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 979 |                     res = lookup_path(f, arg->newdir, in->unique, name, | 
 | 980 |                                       newpath, &outarg); | 
 | 981 |             } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 982 |             free(newpath); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 983 |         } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 984 |         free(oldpath); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 985 |     } | 
| Miklos Szeredi | 2778f6c | 2004-06-21 09:45:30 +0000 | [diff] [blame] | 986 |     res2 = send_reply(f, in, res, &outarg, sizeof(outarg)); | 
 | 987 |     if (res == 0 && res2 == -ENOENT) | 
 | 988 |         destroy_node(f, outarg.ino, in->unique); | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 989 | } | 
 | 990 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 991 | static void do_open(struct fuse *f, struct fuse_in_header *in, | 
 | 992 |                     struct fuse_open_in *arg) | 
 | 993 | { | 
 | 994 |     int res; | 
 | 995 |     char *path; | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 996 |     struct fuse_open_out outarg; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 997 |  | 
 | 998 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 999 |     path = get_path(f, in->ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1000 |     if (path != NULL) { | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 1001 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1002 |         if (f->op.open) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 1003 |             res = f->op.open(path, arg->flags); | 
| Miklos Szeredi | 40b9a5a | 2002-12-10 16:09:02 +0000 | [diff] [blame] | 1004 |     } | 
| Miklos Szeredi | 73798f9 | 2004-07-12 15:55:11 +0000 | [diff] [blame] | 1005 |     if (res == 0) { | 
 | 1006 |         int res2; | 
 | 1007 |  | 
 | 1008 |         /* If the request is interrupted the lock must be held until | 
 | 1009 |            the cancellation is finished.  Otherwise there could be | 
 | 1010 |            races with rename/unlink, against which the kernel can't | 
 | 1011 |            protect */ | 
 | 1012 |         pthread_mutex_lock(&f->lock); | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 1013 |         f->fh_ctr ++; | 
 | 1014 |         outarg.fh = f->fh_ctr; | 
 | 1015 |         if (f->flags & FUSE_DEBUG) { | 
 | 1016 |             printf("OPEN[%u] flags: 0x%x\n", outarg.fh, arg->flags); | 
 | 1017 |             fflush(stdout); | 
 | 1018 |         } | 
 | 1019 |  | 
 | 1020 |         res2 = __send_reply(f, in, res, &outarg, sizeof(outarg), 1); | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 1021 |         if(res2 == -ENOENT) { | 
 | 1022 |             /* The open syscall was interrupted, so it must be cancelled */ | 
 | 1023 |             if(f->op.release) | 
 | 1024 |                 f->op.release(path, arg->flags); | 
| Miklos Szeredi | 73798f9 | 2004-07-12 15:55:11 +0000 | [diff] [blame] | 1025 |         } else | 
 | 1026 |             get_node(f, in->ino)->open_count ++; | 
 | 1027 |         pthread_mutex_unlock(&f->lock); | 
 | 1028 |  | 
 | 1029 |     } else | 
 | 1030 |         send_reply(f, in, res, NULL, 0); | 
 | 1031 |  | 
| Miklos Szeredi | 9a31cca | 2004-06-26 21:11:25 +0000 | [diff] [blame] | 1032 |     if (path) | 
 | 1033 |         free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 1034 | } | 
 | 1035 |  | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 1036 | static void do_flush(struct fuse *f, struct fuse_in_header *in, | 
 | 1037 |                      struct fuse_flush_in *arg) | 
| Miklos Szeredi | e2e4ac2 | 2004-05-18 08:45:28 +0000 | [diff] [blame] | 1038 | { | 
 | 1039 |     char *path; | 
 | 1040 |     int res; | 
 | 1041 |  | 
 | 1042 |     res = -ENOENT; | 
 | 1043 |     path = get_path(f, in->ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1044 |     if (path != NULL) { | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 1045 |         if (f->flags & FUSE_DEBUG) { | 
 | 1046 |             printf("FLUSH[%u]\n", arg->fh); | 
 | 1047 |             fflush(stdout); | 
 | 1048 |         } | 
| Miklos Szeredi | e2e4ac2 | 2004-05-18 08:45:28 +0000 | [diff] [blame] | 1049 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1050 |         if (f->op.flush) | 
| Miklos Szeredi | e2e4ac2 | 2004-05-18 08:45:28 +0000 | [diff] [blame] | 1051 |             res = f->op.flush(path); | 
 | 1052 |         free(path); | 
 | 1053 |     } | 
 | 1054 |     send_reply(f, in, res, NULL, 0); | 
 | 1055 | } | 
 | 1056 |  | 
| Miklos Szeredi | 9478e86 | 2002-12-11 09:50:26 +0000 | [diff] [blame] | 1057 | static void do_release(struct fuse *f, struct fuse_in_header *in, | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 1058 |                        struct fuse_release_in *arg) | 
| Miklos Szeredi | c8ba237 | 2002-12-10 12:26:00 +0000 | [diff] [blame] | 1059 | { | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 1060 |     struct node *node; | 
 | 1061 |     char *path; | 
| Miklos Szeredi | c8ba237 | 2002-12-10 12:26:00 +0000 | [diff] [blame] | 1062 |  | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 1063 |     pthread_mutex_lock(&f->lock); | 
 | 1064 |     node = get_node(f, in->ino); | 
 | 1065 |     --node->open_count; | 
 | 1066 |     pthread_mutex_unlock(&f->lock); | 
 | 1067 |  | 
 | 1068 |     path = get_path(f, in->ino); | 
 | 1069 |     if (path != NULL) { | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 1070 |         if (f->flags & FUSE_DEBUG) { | 
 | 1071 |             printf("RELEASE[%u]\n", arg->fh); | 
 | 1072 |             fflush(stdout); | 
 | 1073 |         } | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 1074 |         if (f->op.release) | 
| Miklos Szeredi | b321058 | 2004-06-23 13:54:33 +0000 | [diff] [blame] | 1075 |             f->op.release(path, arg->flags); | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 1076 |  | 
 | 1077 |         if(node->is_hidden && node->open_count == 0) | 
 | 1078 |             /* can now clean up this hidden file */ | 
 | 1079 |             f->op.unlink(path); | 
 | 1080 |          | 
 | 1081 |         free(path); | 
| Miklos Szeredi | c8ba237 | 2002-12-10 12:26:00 +0000 | [diff] [blame] | 1082 |     } | 
| Miklos Szeredi | 556d03d | 2004-06-30 11:13:41 +0000 | [diff] [blame] | 1083 |     send_reply(f, in, 0, NULL, 0); | 
| Miklos Szeredi | c8ba237 | 2002-12-10 12:26:00 +0000 | [diff] [blame] | 1084 | } | 
 | 1085 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 1086 | static void do_read(struct fuse *f, struct fuse_in_header *in, | 
 | 1087 |                     struct fuse_read_in *arg) | 
 | 1088 | { | 
 | 1089 |     int res; | 
 | 1090 |     char *path; | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 1091 |     char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + arg->size); | 
 | 1092 |     struct fuse_out_header *out = (struct fuse_out_header *) outbuf; | 
 | 1093 |     char *buf = outbuf + sizeof(struct fuse_out_header); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 1094 |     size_t size; | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 1095 |     size_t outsize; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 1096 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1097 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1098 |     path = get_path(f, in->ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1099 |     if (path != NULL) { | 
 | 1100 |         if (f->flags & FUSE_DEBUG) { | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 1101 |             printf("READ[%u] %u bytes from %llu\n", arg->fh, arg->size, | 
 | 1102 |                    arg->offset); | 
| Miklos Szeredi | 6ebe234 | 2002-01-06 21:44:16 +0000 | [diff] [blame] | 1103 |             fflush(stdout); | 
 | 1104 |         } | 
 | 1105 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 1106 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1107 |         if (f->op.read) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 1108 |             res = f->op.read(path, buf, arg->size, arg->offset); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1109 |         free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 1110 |     } | 
 | 1111 |      | 
 | 1112 |     size = 0; | 
| Miklos Szeredi | 25385bb | 2004-07-06 22:27:36 +0000 | [diff] [blame] | 1113 |     if (res >= 0) { | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 1114 |         size = res; | 
 | 1115 |         res = 0; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1116 |         if (f->flags & FUSE_DEBUG) { | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 1117 |             printf("   READ[%u] %u bytes\n", arg->fh, size); | 
| Miklos Szeredi | 6ebe234 | 2002-01-06 21:44:16 +0000 | [diff] [blame] | 1118 |             fflush(stdout); | 
 | 1119 |         } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 1120 |     } | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 1121 |     memset(out, 0, sizeof(struct fuse_out_header)); | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 1122 |     out->unique = in->unique; | 
 | 1123 |     out->error = res; | 
 | 1124 |     outsize = sizeof(struct fuse_out_header) + size; | 
 | 1125 |      | 
| Miklos Szeredi | 73798f9 | 2004-07-12 15:55:11 +0000 | [diff] [blame] | 1126 |     send_reply_raw(f, outbuf, outsize, 0); | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 1127 |     free(outbuf); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 1128 | } | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 1129 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1130 | static void do_write(struct fuse *f, struct fuse_in_header *in, | 
 | 1131 |                      struct fuse_write_in *arg) | 
 | 1132 | { | 
 | 1133 |     int res; | 
 | 1134 |     char *path; | 
| Miklos Szeredi | ad051c3 | 2004-07-02 09:22:50 +0000 | [diff] [blame] | 1135 |     struct fuse_write_out outarg; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1136 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1137 |     res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1138 |     path = get_path(f, in->ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1139 |     if (path != NULL) { | 
 | 1140 |         if (f->flags & FUSE_DEBUG) { | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 1141 |             printf("WRITE%s[%u] %u bytes to %llu\n", | 
 | 1142 |                    arg->writepage ? "PAGE" : "", arg->fh, arg->size, | 
 | 1143 |                    arg->offset); | 
| Miklos Szeredi | 6ebe234 | 2002-01-06 21:44:16 +0000 | [diff] [blame] | 1144 |             fflush(stdout); | 
 | 1145 |         } | 
 | 1146 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1147 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1148 |         if (f->op.write) | 
| Miklos Szeredi | 6bf8b68 | 2002-10-28 08:49:39 +0000 | [diff] [blame] | 1149 |             res = f->op.write(path, PARAM(arg), arg->size, arg->offset); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1150 |         free(path); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1151 |     } | 
 | 1152 |      | 
| Miklos Szeredi | ad051c3 | 2004-07-02 09:22:50 +0000 | [diff] [blame] | 1153 |     if (res >= 0) {  | 
 | 1154 |         outarg.size = res; | 
 | 1155 |         res = 0; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1156 |     } | 
 | 1157 |  | 
| Miklos Szeredi | ad051c3 | 2004-07-02 09:22:50 +0000 | [diff] [blame] | 1158 |     send_reply(f, in, res, &outarg, sizeof(outarg)); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1159 | } | 
 | 1160 |  | 
| Miklos Szeredi | 77f3994 | 2004-03-25 11:17:52 +0000 | [diff] [blame] | 1161 | static int default_statfs(struct statfs *buf) | 
 | 1162 | { | 
 | 1163 |     buf->f_namelen = 255; | 
 | 1164 |     buf->f_bsize = 512; | 
 | 1165 |     return 0; | 
 | 1166 | } | 
 | 1167 |  | 
| Miklos Szeredi | 18e75e4 | 2004-02-19 14:23:27 +0000 | [diff] [blame] | 1168 | static void convert_statfs(struct statfs *statfs, struct fuse_kstatfs *kstatfs) | 
 | 1169 | { | 
 | 1170 |     kstatfs->bsize	= statfs->f_bsize; | 
 | 1171 |     kstatfs->blocks	= statfs->f_blocks; | 
 | 1172 |     kstatfs->bfree	= statfs->f_bfree; | 
 | 1173 |     kstatfs->bavail	= statfs->f_bavail; | 
 | 1174 |     kstatfs->files	= statfs->f_files; | 
 | 1175 |     kstatfs->ffree	= statfs->f_ffree; | 
 | 1176 |     kstatfs->namelen	= statfs->f_namelen; | 
 | 1177 | } | 
 | 1178 |  | 
| Mark Glines | d84b39a | 2002-01-07 16:32:02 +0000 | [diff] [blame] | 1179 | static void do_statfs(struct fuse *f, struct fuse_in_header *in) | 
 | 1180 | { | 
 | 1181 |     int res; | 
| Mark Glines | d84b39a | 2002-01-07 16:32:02 +0000 | [diff] [blame] | 1182 |     struct fuse_statfs_out arg; | 
| Miklos Szeredi | 18e75e4 | 2004-02-19 14:23:27 +0000 | [diff] [blame] | 1183 |     struct statfs buf; | 
| Mark Glines | d84b39a | 2002-01-07 16:32:02 +0000 | [diff] [blame] | 1184 |  | 
| Miklos Szeredi | 77f3994 | 2004-03-25 11:17:52 +0000 | [diff] [blame] | 1185 |     memset(&buf, 0, sizeof(struct statfs)); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1186 |     if (f->op.statfs) | 
| Miklos Szeredi | 18e75e4 | 2004-02-19 14:23:27 +0000 | [diff] [blame] | 1187 |         res = f->op.statfs("/", &buf); | 
| Miklos Szeredi | 77f3994 | 2004-03-25 11:17:52 +0000 | [diff] [blame] | 1188 |     else | 
 | 1189 |         res = default_statfs(&buf); | 
 | 1190 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1191 |     if (res == 0) | 
| Miklos Szeredi | 77f3994 | 2004-03-25 11:17:52 +0000 | [diff] [blame] | 1192 |         convert_statfs(&buf, &arg.st); | 
| Miklos Szeredi | 4b2bef4 | 2002-01-09 12:23:27 +0000 | [diff] [blame] | 1193 |  | 
| Mark Glines | d84b39a | 2002-01-07 16:32:02 +0000 | [diff] [blame] | 1194 |     send_reply(f, in, res, &arg, sizeof(arg)); | 
 | 1195 | } | 
 | 1196 |  | 
| Miklos Szeredi | 5e43f2c | 2003-12-12 14:06:41 +0000 | [diff] [blame] | 1197 | static void do_fsync(struct fuse *f, struct fuse_in_header *in, | 
 | 1198 |                      struct fuse_fsync_in *inarg) | 
 | 1199 | { | 
 | 1200 |     int res; | 
 | 1201 |     char *path; | 
 | 1202 |  | 
 | 1203 |     res = -ENOENT; | 
 | 1204 |     path = get_path(f, in->ino); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1205 |     if (path != NULL) { | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 1206 |         if (f->flags & FUSE_DEBUG) { | 
 | 1207 |             printf("FSYNC[%u]\n", inarg->fh); | 
 | 1208 |             fflush(stdout); | 
 | 1209 |         } | 
| Miklos Szeredi | 63b8c1c | 2004-06-03 14:45:04 +0000 | [diff] [blame] | 1210 |         res = -ENOSYS; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1211 |         if (f->op.fsync) | 
| Miklos Szeredi | 5e43f2c | 2003-12-12 14:06:41 +0000 | [diff] [blame] | 1212 |             res = f->op.fsync(path, inarg->datasync); | 
 | 1213 |         free(path); | 
 | 1214 |     } | 
 | 1215 |     send_reply(f, in, res, NULL, 0); | 
 | 1216 | } | 
 | 1217 |  | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1218 | static void do_setxattr(struct fuse *f, struct fuse_in_header *in, | 
 | 1219 |                         struct fuse_setxattr_in *arg) | 
 | 1220 | { | 
 | 1221 |     int res; | 
 | 1222 |     char *path; | 
 | 1223 |     char *name = PARAM(arg); | 
 | 1224 |     unsigned char *value = name + strlen(name) + 1; | 
 | 1225 |  | 
 | 1226 |     res = -ENOENT; | 
 | 1227 |     path = get_path(f, in->ino); | 
 | 1228 |     if (path != NULL) { | 
| Miklos Szeredi | 63b8c1c | 2004-06-03 14:45:04 +0000 | [diff] [blame] | 1229 |         res = -ENOSYS; | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1230 |         if (f->op.setxattr) | 
 | 1231 |             res = f->op.setxattr(path, name, value, arg->size, arg->flags); | 
 | 1232 |         free(path); | 
 | 1233 |     }     | 
 | 1234 |     send_reply(f, in, res, NULL, 0); | 
 | 1235 | } | 
 | 1236 |  | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1237 | static int common_getxattr(struct fuse *f, struct fuse_in_header *in, | 
 | 1238 |                            const char *name, char *value, size_t size) | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1239 | { | 
 | 1240 |     int res; | 
 | 1241 |     char *path; | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1242 |  | 
 | 1243 |     res = -ENOENT; | 
 | 1244 |     path = get_path(f, in->ino); | 
 | 1245 |     if (path != NULL) { | 
| Miklos Szeredi | 63b8c1c | 2004-06-03 14:45:04 +0000 | [diff] [blame] | 1246 |         res = -ENOSYS; | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1247 |         if (f->op.getxattr) | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1248 |             res = f->op.getxattr(path, name, value, size); | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1249 |         free(path); | 
 | 1250 |     }     | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1251 |     return res; | 
 | 1252 | } | 
 | 1253 |  | 
 | 1254 | static void do_getxattr_read(struct fuse *f, struct fuse_in_header *in, | 
 | 1255 |                              const char *name, size_t size) | 
 | 1256 | { | 
 | 1257 |     int res; | 
 | 1258 |     char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + size); | 
 | 1259 |     struct fuse_out_header *out = (struct fuse_out_header *) outbuf; | 
 | 1260 |     char *value = outbuf + sizeof(struct fuse_out_header); | 
 | 1261 |  | 
 | 1262 |     res = common_getxattr(f, in, name, value, size); | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1263 |     size = 0; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1264 |     if (res > 0) { | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1265 |         size = res; | 
 | 1266 |         res = 0; | 
 | 1267 |     } | 
 | 1268 |     memset(out, 0, sizeof(struct fuse_out_header)); | 
 | 1269 |     out->unique = in->unique; | 
 | 1270 |     out->error = res; | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1271 |  | 
| Miklos Szeredi | 73798f9 | 2004-07-12 15:55:11 +0000 | [diff] [blame] | 1272 |     send_reply_raw(f, outbuf, sizeof(struct fuse_out_header) + size, 0); | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1273 |     free(outbuf); | 
 | 1274 | } | 
 | 1275 |  | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1276 | static void do_getxattr_size(struct fuse *f, struct fuse_in_header *in, | 
 | 1277 |                              const char *name) | 
 | 1278 | { | 
 | 1279 |     int res; | 
 | 1280 |     struct fuse_getxattr_out arg; | 
 | 1281 |  | 
 | 1282 |     res = common_getxattr(f, in, name, NULL, 0); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1283 |     if (res >= 0) { | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1284 |         arg.size = res; | 
 | 1285 |         res = 0; | 
 | 1286 |     } | 
 | 1287 |     send_reply(f, in, res, &arg, sizeof(arg)); | 
 | 1288 | } | 
 | 1289 |  | 
 | 1290 | static void do_getxattr(struct fuse *f, struct fuse_in_header *in, | 
 | 1291 |                         struct fuse_getxattr_in *arg) | 
 | 1292 | { | 
 | 1293 |     char *name = PARAM(arg); | 
 | 1294 |      | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1295 |     if (arg->size) | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1296 |         do_getxattr_read(f, in, name, arg->size); | 
 | 1297 |     else | 
 | 1298 |         do_getxattr_size(f, in, name); | 
 | 1299 | } | 
 | 1300 |  | 
 | 1301 | static int common_listxattr(struct fuse *f, struct fuse_in_header *in, | 
 | 1302 |                             char *list, size_t size) | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1303 | { | 
 | 1304 |     int res; | 
 | 1305 |     char *path; | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1306 |  | 
 | 1307 |     res = -ENOENT; | 
 | 1308 |     path = get_path(f, in->ino); | 
 | 1309 |     if (path != NULL) { | 
| Miklos Szeredi | 63b8c1c | 2004-06-03 14:45:04 +0000 | [diff] [blame] | 1310 |         res = -ENOSYS; | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1311 |         if (f->op.listxattr) | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1312 |             res = f->op.listxattr(path, list, size); | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1313 |         free(path); | 
 | 1314 |     }     | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1315 |     return res; | 
 | 1316 | } | 
 | 1317 |  | 
 | 1318 | static void do_listxattr_read(struct fuse *f, struct fuse_in_header *in, | 
 | 1319 |                               size_t size) | 
 | 1320 | { | 
 | 1321 |     int res; | 
 | 1322 |     char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + size); | 
 | 1323 |     struct fuse_out_header *out = (struct fuse_out_header *) outbuf; | 
 | 1324 |     char *list = outbuf + sizeof(struct fuse_out_header); | 
 | 1325 |  | 
 | 1326 |     res = common_listxattr(f, in, list, size); | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1327 |     size = 0; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1328 |     if (res > 0) { | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1329 |         size = res; | 
 | 1330 |         res = 0; | 
 | 1331 |     } | 
 | 1332 |     memset(out, 0, sizeof(struct fuse_out_header)); | 
 | 1333 |     out->unique = in->unique; | 
 | 1334 |     out->error = res; | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1335 |  | 
| Miklos Szeredi | 73798f9 | 2004-07-12 15:55:11 +0000 | [diff] [blame] | 1336 |     send_reply_raw(f, outbuf, sizeof(struct fuse_out_header) + size, 0); | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1337 |     free(outbuf); | 
 | 1338 | } | 
 | 1339 |  | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1340 | static void do_listxattr_size(struct fuse *f, struct fuse_in_header *in) | 
 | 1341 | { | 
 | 1342 |     int res; | 
 | 1343 |     struct fuse_getxattr_out arg; | 
 | 1344 |  | 
 | 1345 |     res = common_listxattr(f, in, NULL, 0); | 
 | 1346 |     if (res >= 0) { | 
 | 1347 |         arg.size = res; | 
 | 1348 |         res = 0; | 
 | 1349 |     } | 
 | 1350 |     send_reply(f, in, res, &arg, sizeof(arg)); | 
 | 1351 | } | 
 | 1352 |  | 
 | 1353 | static void do_listxattr(struct fuse *f, struct fuse_in_header *in, | 
 | 1354 |                          struct fuse_getxattr_in *arg) | 
 | 1355 | { | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1356 |     if (arg->size) | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1357 |         do_listxattr_read(f, in, arg->size); | 
 | 1358 |     else | 
 | 1359 |         do_listxattr_size(f, in); | 
 | 1360 | } | 
 | 1361 |  | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1362 | static void do_removexattr(struct fuse *f, struct fuse_in_header *in, | 
 | 1363 |                            char *name) | 
 | 1364 | { | 
 | 1365 |     int res; | 
 | 1366 |     char *path; | 
 | 1367 |  | 
 | 1368 |     res = -ENOENT; | 
 | 1369 |     path = get_path(f, in->ino); | 
 | 1370 |     if (path != NULL) { | 
| Miklos Szeredi | 63b8c1c | 2004-06-03 14:45:04 +0000 | [diff] [blame] | 1371 |         res = -ENOSYS; | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1372 |         if (f->op.removexattr) | 
 | 1373 |             res = f->op.removexattr(path, name); | 
 | 1374 |         free(path); | 
 | 1375 |     }     | 
 | 1376 |     send_reply(f, in, res, NULL, 0); | 
 | 1377 | } | 
 | 1378 |  | 
 | 1379 |  | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 1380 | static void free_cmd(struct fuse_cmd *cmd) | 
 | 1381 | { | 
 | 1382 |     free(cmd->buf); | 
 | 1383 |     free(cmd); | 
 | 1384 | } | 
 | 1385 |  | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 1386 | void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd) | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1387 | { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1388 |     struct fuse_in_header *in = (struct fuse_in_header *) cmd->buf; | 
 | 1389 |     void *inarg = cmd->buf + sizeof(struct fuse_in_header); | 
 | 1390 |     size_t argsize; | 
| Miklos Szeredi | fe25def | 2001-12-20 15:38:05 +0000 | [diff] [blame] | 1391 |     struct fuse_context *ctx = fuse_get_context(f); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1392 |  | 
| Miklos Szeredi | 99ddf0e | 2001-11-25 17:19:59 +0000 | [diff] [blame] | 1393 |     dec_avail(f); | 
| Miklos Szeredi | 3323203 | 2001-11-19 17:55:51 +0000 | [diff] [blame] | 1394 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1395 |     if ((f->flags & FUSE_DEBUG)) { | 
| Miklos Szeredi | c8ba237 | 2002-12-10 12:26:00 +0000 | [diff] [blame] | 1396 |         printf("unique: %i, opcode: %s (%i), ino: %li, insize: %i\n", | 
 | 1397 |                in->unique, opname(in->opcode), in->opcode, in->ino, | 
 | 1398 |                cmd->buflen); | 
| Miklos Szeredi | c0938ea | 2001-11-07 12:35:06 +0000 | [diff] [blame] | 1399 |         fflush(stdout); | 
 | 1400 |     } | 
| Miklos Szeredi | fe25def | 2001-12-20 15:38:05 +0000 | [diff] [blame] | 1401 |  | 
 | 1402 |     ctx->uid = in->uid; | 
 | 1403 |     ctx->gid = in->gid; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1404 |      | 
 | 1405 |     argsize = cmd->buflen - sizeof(struct fuse_in_header); | 
 | 1406 |          | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1407 |     switch (in->opcode) { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1408 |     case FUSE_LOOKUP: | 
 | 1409 |         do_lookup(f, in, (char *) inarg); | 
 | 1410 |         break; | 
 | 1411 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1412 |     case FUSE_GETATTR: | 
 | 1413 |         do_getattr(f, in); | 
 | 1414 |         break; | 
 | 1415 |  | 
 | 1416 |     case FUSE_SETATTR: | 
 | 1417 |         do_setattr(f, in, (struct fuse_setattr_in *) inarg); | 
 | 1418 |         break; | 
 | 1419 |  | 
 | 1420 |     case FUSE_READLINK: | 
 | 1421 |         do_readlink(f, in); | 
 | 1422 |         break; | 
 | 1423 |  | 
 | 1424 |     case FUSE_GETDIR: | 
 | 1425 |         do_getdir(f, in); | 
 | 1426 |         break; | 
 | 1427 |  | 
 | 1428 |     case FUSE_MKNOD: | 
 | 1429 |         do_mknod(f, in, (struct fuse_mknod_in *) inarg); | 
 | 1430 |         break; | 
 | 1431 |              | 
 | 1432 |     case FUSE_MKDIR: | 
 | 1433 |         do_mkdir(f, in, (struct fuse_mkdir_in *) inarg); | 
 | 1434 |         break; | 
 | 1435 |              | 
 | 1436 |     case FUSE_UNLINK: | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 1437 |         do_unlink(f, in, (char *) inarg); | 
 | 1438 |         break; | 
 | 1439 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1440 |     case FUSE_RMDIR: | 
| Miklos Szeredi | b595861 | 2004-02-20 14:10:49 +0000 | [diff] [blame] | 1441 |         do_rmdir(f, in, (char *) inarg); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1442 |         break; | 
 | 1443 |  | 
 | 1444 |     case FUSE_SYMLINK: | 
 | 1445 |         do_symlink(f, in, (char *) inarg,  | 
 | 1446 |                    ((char *) inarg) + strlen((char *) inarg) + 1); | 
 | 1447 |         break; | 
 | 1448 |  | 
 | 1449 |     case FUSE_RENAME: | 
 | 1450 |         do_rename(f, in, (struct fuse_rename_in *) inarg); | 
 | 1451 |         break; | 
 | 1452 |              | 
 | 1453 |     case FUSE_LINK: | 
 | 1454 |         do_link(f, in, (struct fuse_link_in *) inarg); | 
 | 1455 |         break; | 
 | 1456 |  | 
 | 1457 |     case FUSE_OPEN: | 
 | 1458 |         do_open(f, in, (struct fuse_open_in *) inarg); | 
 | 1459 |         break; | 
 | 1460 |  | 
| Miklos Szeredi | e2e4ac2 | 2004-05-18 08:45:28 +0000 | [diff] [blame] | 1461 |     case FUSE_FLUSH: | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 1462 |         do_flush(f, in, (struct fuse_flush_in *) inarg); | 
| Miklos Szeredi | e2e4ac2 | 2004-05-18 08:45:28 +0000 | [diff] [blame] | 1463 |         break; | 
 | 1464 |  | 
| Miklos Szeredi | 9478e86 | 2002-12-11 09:50:26 +0000 | [diff] [blame] | 1465 |     case FUSE_RELEASE: | 
| Miklos Szeredi | 209f5d0 | 2004-07-24 19:56:16 +0000 | [diff] [blame] | 1466 |         do_release(f, in, (struct fuse_release_in *) inarg); | 
| Miklos Szeredi | 9478e86 | 2002-12-11 09:50:26 +0000 | [diff] [blame] | 1467 |         break; | 
 | 1468 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1469 |     case FUSE_READ: | 
 | 1470 |         do_read(f, in, (struct fuse_read_in *) inarg); | 
 | 1471 |         break; | 
 | 1472 |  | 
 | 1473 |     case FUSE_WRITE: | 
 | 1474 |         do_write(f, in, (struct fuse_write_in *) inarg); | 
 | 1475 |         break; | 
 | 1476 |  | 
| Mark Glines | d84b39a | 2002-01-07 16:32:02 +0000 | [diff] [blame] | 1477 |     case FUSE_STATFS: | 
 | 1478 |         do_statfs(f, in); | 
 | 1479 |         break; | 
 | 1480 |  | 
| Miklos Szeredi | 5e43f2c | 2003-12-12 14:06:41 +0000 | [diff] [blame] | 1481 |     case FUSE_FSYNC: | 
 | 1482 |         do_fsync(f, in, (struct fuse_fsync_in *) inarg); | 
 | 1483 |         break; | 
 | 1484 |  | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1485 |     case FUSE_SETXATTR: | 
 | 1486 |         do_setxattr(f, in, (struct fuse_setxattr_in *) inarg); | 
 | 1487 |         break; | 
 | 1488 |  | 
 | 1489 |     case FUSE_GETXATTR: | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1490 |         do_getxattr(f, in, (struct fuse_getxattr_in *) inarg); | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1491 |         break; | 
 | 1492 |  | 
 | 1493 |     case FUSE_LISTXATTR: | 
| Miklos Szeredi | 03cebae | 2004-03-31 10:19:18 +0000 | [diff] [blame] | 1494 |         do_listxattr(f, in, (struct fuse_getxattr_in *) inarg); | 
| Miklos Szeredi | 3ed8423 | 2004-03-30 15:17:26 +0000 | [diff] [blame] | 1495 |         break; | 
 | 1496 |  | 
 | 1497 |     case FUSE_REMOVEXATTR: | 
 | 1498 |         do_removexattr(f, in, (char *) inarg); | 
 | 1499 |         break; | 
 | 1500 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1501 |     default: | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 1502 |         send_reply(f, in, -ENOSYS, NULL, 0); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1503 |     } | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 1504 |  | 
 | 1505 |     free_cmd(cmd); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1506 | } | 
 | 1507 |  | 
| Miklos Szeredi | 65cf7c7 | 2004-06-30 11:34:56 +0000 | [diff] [blame] | 1508 | int __fuse_exited(struct fuse* f) | 
 | 1509 | { | 
 | 1510 |     return f->exited; | 
 | 1511 | } | 
 | 1512 |  | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 1513 | struct fuse_cmd *__fuse_read_cmd(struct fuse *f) | 
| Miklos Szeredi | 2df1c04 | 2001-11-06 15:07:17 +0000 | [diff] [blame] | 1514 | { | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 1515 |     ssize_t res; | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 1516 |     struct fuse_cmd *cmd; | 
| Miklos Szeredi | 99ddf0e | 2001-11-25 17:19:59 +0000 | [diff] [blame] | 1517 |     struct fuse_in_header *in; | 
 | 1518 |     void *inarg; | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 1519 |  | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 1520 |     cmd = (struct fuse_cmd *) malloc(sizeof(struct fuse_cmd)); | 
 | 1521 |     cmd->buf = (char *) malloc(FUSE_MAX_IN); | 
| Miklos Szeredi | 99ddf0e | 2001-11-25 17:19:59 +0000 | [diff] [blame] | 1522 |     in = (struct fuse_in_header *) cmd->buf; | 
 | 1523 |     inarg = cmd->buf + sizeof(struct fuse_in_header); | 
| Miklos Szeredi | 4369643 | 2001-11-18 19:15:05 +0000 | [diff] [blame] | 1524 |  | 
| Miklos Szeredi | 65cf7c7 | 2004-06-30 11:34:56 +0000 | [diff] [blame] | 1525 |     res = read(f->fd, cmd->buf, FUSE_MAX_IN); | 
 | 1526 |     if (res == -1) { | 
 | 1527 |         free_cmd(cmd); | 
 | 1528 |         if (__fuse_exited(f) || errno == EINTR) | 
| Miklos Szeredi | 99ddf0e | 2001-11-25 17:19:59 +0000 | [diff] [blame] | 1529 |             return NULL; | 
| Miklos Szeredi | 99ddf0e | 2001-11-25 17:19:59 +0000 | [diff] [blame] | 1530 |          | 
| Miklos Szeredi | 65cf7c7 | 2004-06-30 11:34:56 +0000 | [diff] [blame] | 1531 |         /* ENODEV means we got unmounted, so we silenty return failure */ | 
 | 1532 |         if (errno != ENODEV) { | 
 | 1533 |             /* BAD... This will happen again */ | 
 | 1534 |             perror("fuse: reading device"); | 
 | 1535 |         } | 
 | 1536 |          | 
 | 1537 |         fuse_exit(f); | 
 | 1538 |         return NULL; | 
 | 1539 |     } | 
 | 1540 |     if ((size_t) res < sizeof(struct fuse_in_header)) { | 
 | 1541 |         free_cmd(cmd); | 
 | 1542 |         /* Cannot happen */ | 
 | 1543 |         fprintf(stderr, "short read on fuse device\n"); | 
 | 1544 |         fuse_exit(f); | 
 | 1545 |         return NULL; | 
 | 1546 |     } | 
 | 1547 |     cmd->buflen = res; | 
 | 1548 |      | 
 | 1549 |     /* Forget is special, it can be done without messing with threads. */ | 
 | 1550 |     if (in->opcode == FUSE_FORGET) { | 
 | 1551 |         do_forget(f, in, (struct fuse_forget_in *) inarg); | 
 | 1552 |         free_cmd(cmd); | 
 | 1553 |         return NULL; | 
 | 1554 |     } | 
| Miklos Szeredi | 99ddf0e | 2001-11-25 17:19:59 +0000 | [diff] [blame] | 1555 |  | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 1556 |     return cmd; | 
| Miklos Szeredi | 2df1c04 | 2001-11-06 15:07:17 +0000 | [diff] [blame] | 1557 | } | 
 | 1558 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 1559 | void fuse_loop(struct fuse *f) | 
 | 1560 | { | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1561 |     if (f == NULL) | 
| Miklos Szeredi | c40748a | 2004-02-20 16:38:45 +0000 | [diff] [blame] | 1562 |         return; | 
 | 1563 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1564 |     while (1) { | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 1565 |         struct fuse_cmd *cmd; | 
 | 1566 |  | 
| Miklos Szeredi | 65cf7c7 | 2004-06-30 11:34:56 +0000 | [diff] [blame] | 1567 |         if (__fuse_exited(f)) | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 1568 |             return; | 
 | 1569 |  | 
 | 1570 |         cmd = __fuse_read_cmd(f); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1571 |         if (cmd == NULL) | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 1572 |             continue; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 1573 |  | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 1574 |         __fuse_process_cmd(f, cmd); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 1575 |     } | 
 | 1576 | } | 
 | 1577 |  | 
| Miklos Szeredi | 891b874 | 2004-07-29 09:27:49 +0000 | [diff] [blame^] | 1578 | int fuse_invalidate(struct fuse *f, const char *path) | 
 | 1579 | { | 
 | 1580 |     int res; | 
 | 1581 |     int err; | 
 | 1582 |     fino_t ino; | 
 | 1583 |     struct fuse_user_header h; | 
 | 1584 |  | 
 | 1585 |     err = path_lookup(f, path, &ino); | 
 | 1586 |     if (err) { | 
 | 1587 |         if (err == -ENOENT) | 
 | 1588 |             return 0; | 
 | 1589 |         else | 
 | 1590 |             return err; | 
 | 1591 |     } | 
 | 1592 |  | 
 | 1593 |     memset(&h, 0, sizeof(struct fuse_user_header)); | 
 | 1594 |     h.opcode = FUSE_INVALIDATE; | 
 | 1595 |     h.ino = ino; | 
 | 1596 |      | 
 | 1597 |     if ((f->flags & FUSE_DEBUG)) { | 
 | 1598 |         printf("INVALIDATE ino: %li\n", ino); | 
 | 1599 |         fflush(stdout); | 
 | 1600 |     } | 
 | 1601 |  | 
 | 1602 |     res = write(f->fd, &h, sizeof(struct fuse_user_header)); | 
 | 1603 |     if (res == -1) { | 
 | 1604 |         if (errno != ENOENT) { | 
 | 1605 |             perror("fuse: writing device"); | 
 | 1606 |             return -errno; | 
 | 1607 |         } | 
 | 1608 |     } | 
 | 1609 |     return 0; | 
 | 1610 | } | 
 | 1611 |  | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 1612 | void fuse_exit(struct fuse *f) | 
 | 1613 | { | 
 | 1614 |     f->exited = 1; | 
 | 1615 | } | 
 | 1616 |  | 
| Miklos Szeredi | 2e50d43 | 2001-12-20 12:17:25 +0000 | [diff] [blame] | 1617 | struct fuse_context *fuse_get_context(struct fuse *f) | 
 | 1618 | { | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1619 |     if (f->getcontext) | 
| Miklos Szeredi | 2e50d43 | 2001-12-20 12:17:25 +0000 | [diff] [blame] | 1620 |         return f->getcontext(f); | 
 | 1621 |     else | 
 | 1622 |         return &f->context; | 
 | 1623 | } | 
 | 1624 |  | 
| Miklos Szeredi | c40748a | 2004-02-20 16:38:45 +0000 | [diff] [blame] | 1625 | static int check_version(struct fuse *f) | 
 | 1626 | { | 
 | 1627 |     int res; | 
 | 1628 |     FILE *vf = fopen(FUSE_VERSION_FILE, "r"); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1629 |     if (vf == NULL) { | 
| Miklos Szeredi | c40748a | 2004-02-20 16:38:45 +0000 | [diff] [blame] | 1630 |         fprintf(stderr, "fuse: kernel interface too old, need >= %i.%i\n", | 
 | 1631 |                 FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); | 
 | 1632 |         return -1; | 
 | 1633 |     } | 
 | 1634 |     res = fscanf(vf, "%i.%i", &f->majorver, &f->minorver); | 
 | 1635 |     fclose(vf); | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1636 |     if (res != 2) { | 
| Miklos Szeredi | c40748a | 2004-02-20 16:38:45 +0000 | [diff] [blame] | 1637 |         fprintf(stderr, "fuse: error reading %s\n", FUSE_VERSION_FILE); | 
 | 1638 |         return -1; | 
 | 1639 |     } | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1640 |     if (f->majorver != FUSE_KERNEL_VERSION) { | 
| Miklos Szeredi | c40748a | 2004-02-20 16:38:45 +0000 | [diff] [blame] | 1641 |         fprintf(stderr, "fuse: bad kernel interface major version: needs %i\n", | 
 | 1642 |                 FUSE_KERNEL_VERSION); | 
 | 1643 |         return -1; | 
 | 1644 |     } | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1645 |     if (f->minorver < FUSE_KERNEL_MINOR_VERSION) { | 
| Miklos Szeredi | c40748a | 2004-02-20 16:38:45 +0000 | [diff] [blame] | 1646 |         fprintf(stderr, "fuse: kernel interface too old: need >= %i.%i", | 
 | 1647 |                 FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); | 
 | 1648 |         return -1; | 
 | 1649 |     }     | 
 | 1650 |      | 
 | 1651 |     return 0; | 
 | 1652 | } | 
 | 1653 |  | 
| Miklos Szeredi | bd7661b | 2004-07-23 17:16:29 +0000 | [diff] [blame] | 1654 |  | 
 | 1655 | int fuse_is_lib_option(const char *opt) | 
 | 1656 | { | 
 | 1657 |     if (strcmp(opt, "debug") == 0 || | 
 | 1658 |         strcmp(opt, "hard_remove") == 0) | 
 | 1659 |         return 1; | 
 | 1660 |     else | 
 | 1661 |         return 0; | 
 | 1662 | } | 
 | 1663 |  | 
 | 1664 | static void parse_lib_opts(struct fuse *f, const char *opts) | 
 | 1665 | { | 
 | 1666 |     if (opts) { | 
 | 1667 |         char *xopts = strdup(opts); | 
 | 1668 |         char *s = xopts; | 
 | 1669 |         char *opt; | 
 | 1670 |          | 
 | 1671 |         while((opt = strsep(&s, ","))) { | 
 | 1672 |             if (strcmp(opt, "debug") == 0) | 
 | 1673 |                 f->flags |= FUSE_DEBUG; | 
 | 1674 |             else if (strcmp(opt, "hard_remove") == 0) | 
 | 1675 |                 f->flags |= FUSE_HARD_REMOVE; | 
 | 1676 |             else  | 
 | 1677 |                 fprintf(stderr, "fuse: warning: unknown option `%s'\n", opt); | 
 | 1678 |         } | 
 | 1679 |         free(xopts); | 
 | 1680 |     } | 
 | 1681 | } | 
 | 1682 |  | 
 | 1683 | struct fuse *fuse_new(int fd, const char *opts, const struct fuse_operations *op) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 1684 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1685 |     struct fuse *f; | 
 | 1686 |     struct node *root; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 1687 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1688 |     f = (struct fuse *) calloc(1, sizeof(struct fuse)); | 
| Miklos Szeredi | 2df1c04 | 2001-11-06 15:07:17 +0000 | [diff] [blame] | 1689 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1690 |     if (check_version(f) == -1) { | 
| Miklos Szeredi | c40748a | 2004-02-20 16:38:45 +0000 | [diff] [blame] | 1691 |         free(f); | 
 | 1692 |         return NULL; | 
 | 1693 |     } | 
 | 1694 |  | 
| Miklos Szeredi | bd7661b | 2004-07-23 17:16:29 +0000 | [diff] [blame] | 1695 |     parse_lib_opts(f, opts); | 
| Miklos Szeredi | 8cffdb9 | 2001-11-09 14:49:18 +0000 | [diff] [blame] | 1696 |     f->fd = fd; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1697 |     f->ctr = 0; | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 1698 |     f->generation = 0; | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 1699 |     /* FIXME: Dynamic hash table */ | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1700 |     f->name_table_size = 14057; | 
 | 1701 |     f->name_table = (struct node **) | 
 | 1702 |         calloc(1, sizeof(struct node *) * f->name_table_size); | 
 | 1703 |     f->ino_table_size = 14057; | 
 | 1704 |     f->ino_table = (struct node **) | 
 | 1705 |         calloc(1, sizeof(struct node *) * f->ino_table_size); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1706 |     pthread_mutex_init(&f->lock, NULL); | 
| Miklos Szeredi | 3323203 | 2001-11-19 17:55:51 +0000 | [diff] [blame] | 1707 |     f->numworker = 0; | 
 | 1708 |     f->numavail = 0; | 
| Miklos Szeredi | 2e50d43 | 2001-12-20 12:17:25 +0000 | [diff] [blame] | 1709 |     f->op = *op; | 
 | 1710 |     f->getcontext = NULL; | 
 | 1711 |     f->context.uid = 0; | 
 | 1712 |     f->context.gid = 0; | 
| Miklos Szeredi | 0f48a26 | 2002-12-05 14:23:01 +0000 | [diff] [blame] | 1713 |     f->exited = 0; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 1714 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1715 |     root = (struct node *) calloc(1, sizeof(struct node)); | 
| Miklos Szeredi | 8cffdb9 | 2001-11-09 14:49:18 +0000 | [diff] [blame] | 1716 |     root->mode = 0; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1717 |     root->rdev = 0; | 
 | 1718 |     root->name = strdup("/"); | 
 | 1719 |     root->parent = 0; | 
| Miklos Szeredi | 76f6578 | 2004-02-19 16:55:40 +0000 | [diff] [blame] | 1720 |     root->ino = FUSE_ROOT_INO; | 
 | 1721 |     root->generation = 0; | 
 | 1722 |     hash_ino(f, root); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1723 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 1724 |     return f; | 
 | 1725 | } | 
 | 1726 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 1727 | void fuse_destroy(struct fuse *f) | 
 | 1728 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1729 |     size_t i; | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1730 |     for (i = 0; i < f->ino_table_size; i++) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1731 |         struct node *node; | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 1732 |  | 
 | 1733 |         for (node = f->ino_table[i]; node != NULL; node = node->ino_next) { | 
 | 1734 |             if (node->is_hidden) { | 
 | 1735 |                 char *path = get_path(f, node->ino); | 
 | 1736 |                 if (path) | 
 | 1737 |                     f->op.unlink(path); | 
 | 1738 |             } | 
 | 1739 |         } | 
 | 1740 |     } | 
 | 1741 |     for (i = 0; i < f->ino_table_size; i++) { | 
 | 1742 |         struct node *node; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1743 |         struct node *next; | 
| Miklos Szeredi | 1ea9c96 | 2004-06-24 21:00:00 +0000 | [diff] [blame] | 1744 |  | 
| Miklos Szeredi | 7eafcce | 2004-06-19 22:42:38 +0000 | [diff] [blame] | 1745 |         for (node = f->ino_table[i]; node != NULL; node = next) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1746 |             next = node->ino_next; | 
 | 1747 |             free_node(node); | 
 | 1748 |         } | 
 | 1749 |     } | 
 | 1750 |     free(f->ino_table); | 
 | 1751 |     free(f->name_table); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 1752 |     pthread_mutex_destroy(&f->lock); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 1753 |     free(f); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 1754 | } |