| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 1 | /* | 
|  | 2 | FUSE: Filesystem in Userspace | 
|  | 3 | Copyright (C) 2001  Miklos Szeredi (mszeredi@inf.bme.hu) | 
|  | 4 |  | 
|  | 5 | This program can be distributed under the terms of the GNU GPL. | 
|  | 6 | See the file COPYING. | 
|  | 7 | */ | 
|  | 8 |  | 
|  | 9 | #include "fuse_i.h" | 
|  | 10 | #include <linux/fuse.h> | 
|  | 11 |  | 
|  | 12 | #include <string.h> | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 13 | #include <stdlib.h> | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 14 | #include <unistd.h> | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 15 | #include <limits.h> | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 16 | #include <errno.h> | 
|  | 17 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 18 | #define FUSE_MAX_PATH 4096 | 
| 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 | static struct node *__get_node(struct fuse *f, fino_t ino) | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 21 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 22 | size_t hash = ino % f->ino_table_size; | 
|  | 23 | struct node *node; | 
|  | 24 |  | 
|  | 25 | for(node = f->ino_table[hash]; node != NULL; node = node->ino_next) | 
|  | 26 | if(node->ino == ino) | 
|  | 27 | return node; | 
|  | 28 |  | 
|  | 29 | return NULL; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 30 | } | 
|  | 31 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 32 | static struct node *get_node(struct fuse *f, fino_t ino) | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 33 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 34 | struct node *node = __get_node(f, ino); | 
|  | 35 | if(node != NULL) | 
|  | 36 | return node; | 
|  | 37 |  | 
|  | 38 | fprintf(stderr, "fuse internal error: inode %lu not found\n", ino); | 
|  | 39 | abort(); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 40 | } | 
|  | 41 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 42 | static void hash_ino(struct fuse *f, struct node *node, fino_t ino) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 43 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 44 | size_t hash = ino % f->ino_table_size; | 
|  | 45 | node->ino = ino; | 
|  | 46 |  | 
|  | 47 | node->ino_next = f->ino_table[hash]; | 
|  | 48 | f->ino_table[hash] = node; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 49 | } | 
|  | 50 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 51 | static void unhash_ino(struct fuse *f, struct node *node) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 52 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 53 | size_t hash = node->ino % f->ino_table_size; | 
|  | 54 | struct node **nodep = &f->ino_table[hash]; | 
|  | 55 |  | 
|  | 56 | for(; *nodep != NULL; nodep = &(*nodep)->ino_next) | 
|  | 57 | if(*nodep == node) { | 
|  | 58 | *nodep = node->ino_next; | 
|  | 59 | return; | 
|  | 60 | } | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 61 | } | 
|  | 62 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 63 | static fino_t get_ino(struct node *node) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 64 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 65 | return node->ino; | 
|  | 66 | } | 
|  | 67 |  | 
|  | 68 | static fino_t next_ino(struct fuse *f) | 
|  | 69 | { | 
|  | 70 | while(f->ctr == 0 || __get_node(f, f->ctr) != NULL) | 
|  | 71 | f->ctr++; | 
|  | 72 |  | 
|  | 73 | return f->ctr; | 
|  | 74 | } | 
|  | 75 |  | 
|  | 76 | static void free_node(struct node *node) | 
|  | 77 | { | 
|  | 78 | free(node->name); | 
|  | 79 | free(node); | 
|  | 80 | } | 
|  | 81 |  | 
|  | 82 | static unsigned int name_hash(struct fuse *f, fino_t parent, const char *name) | 
|  | 83 | { | 
|  | 84 | unsigned int hash = *name; | 
|  | 85 |  | 
|  | 86 | if(hash) | 
|  | 87 | for(name += 1; *name != '\0'; name++) | 
|  | 88 | hash = (hash << 5) - hash + *name; | 
|  | 89 |  | 
|  | 90 | return (hash + parent) % f->name_table_size; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 91 | } | 
|  | 92 |  | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 93 | static struct node *lookup_node(struct fuse *f, fino_t parent, | 
|  | 94 | const char *name) | 
|  | 95 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 96 | size_t hash = name_hash(f, parent, name); | 
|  | 97 | struct node *node; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 98 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 99 | for(node = f->name_table[hash]; node != NULL; node = node->name_next) | 
|  | 100 | if(node->parent == parent && strcmp(node->name, name) == 0) | 
|  | 101 | return node; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 102 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 103 | return NULL; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 104 | } | 
|  | 105 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 106 | 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] | 107 | const char *name) | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 108 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 109 | size_t hash = name_hash(f, parent, name); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 110 | node->parent = parent; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 111 | node->name = strdup(name); | 
|  | 112 | node->name_next = f->name_table[hash]; | 
|  | 113 | f->name_table[hash] = node; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 114 | } | 
|  | 115 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 116 | static void unhash_name(struct fuse *f, struct node *node) | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 117 | { | 
|  | 118 | if(node->name != NULL) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 119 | size_t hash = name_hash(f, node->parent, node->name); | 
|  | 120 | struct node **nodep = &f->name_table[hash]; | 
|  | 121 |  | 
|  | 122 | for(; *nodep != NULL; nodep = &(*nodep)->name_next) | 
|  | 123 | if(*nodep == node) { | 
|  | 124 | *nodep = node->name_next; | 
|  | 125 | node->name_next = NULL; | 
|  | 126 | free(node->name); | 
|  | 127 | node->name = NULL; | 
|  | 128 | node->parent = 0; | 
|  | 129 | return; | 
|  | 130 | } | 
|  | 131 | fprintf(stderr, "fuse internal error: unable to unhash node: %lu\n", | 
|  | 132 | node->ino); | 
|  | 133 | abort(); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 134 | } | 
|  | 135 | } | 
|  | 136 |  | 
|  | 137 | static fino_t find_node(struct fuse *f, fino_t parent, char *name, | 
|  | 138 | struct fuse_attr *attr, int version) | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 139 | { | 
|  | 140 | struct node *node; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 141 | int mode = attr->mode & S_IFMT; | 
|  | 142 | int rdev = 0; | 
|  | 143 |  | 
|  | 144 | if(S_ISCHR(mode) || S_ISBLK(mode)) | 
|  | 145 | rdev = attr->rdev; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 146 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 147 | pthread_mutex_lock(&f->lock); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 148 | node = lookup_node(f, parent, name); | 
|  | 149 | if(node != NULL) { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 150 | if(node->mode == mode && node->rdev == rdev) | 
|  | 151 | goto out; | 
|  | 152 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 153 | unhash_name(f, node); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 154 | } | 
|  | 155 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 156 | node = (struct node *) calloc(1, sizeof(struct node)); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 157 | node->mode = mode; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 158 | node->rdev = rdev; | 
|  | 159 | hash_ino(f, node, next_ino(f)); | 
|  | 160 | hash_name(f, node, parent, name); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 161 |  | 
|  | 162 | out: | 
|  | 163 | node->version = version; | 
|  | 164 | pthread_mutex_unlock(&f->lock); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 165 | return get_ino(node); | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | static fino_t find_node_dir(struct fuse *f, fino_t parent, char *name) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 169 | { | 
|  | 170 | struct node *node; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 171 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 172 | pthread_mutex_lock(&f->lock); | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 173 | node = lookup_node(f, parent, name); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 174 | pthread_mutex_unlock(&f->lock); | 
|  | 175 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 176 | if(node != NULL) | 
|  | 177 | return get_ino(node); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 178 | else | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 179 | return (fino_t) -1; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 180 | } | 
|  | 181 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 182 | static char *add_name(char *buf, char *s, const char *name) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 183 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 184 | size_t len = strlen(name); | 
|  | 185 | s -= len; | 
|  | 186 | if(s <= buf) { | 
|  | 187 | fprintf(stderr, "fuse: path too long: ...%s\n", s + len); | 
|  | 188 | return NULL; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 189 | } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 190 | strncpy(s, name, len); | 
|  | 191 | s--; | 
|  | 192 | *s = '/'; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 193 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 194 | return s; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 195 | } | 
|  | 196 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 197 | 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] | 198 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 199 | char buf[FUSE_MAX_PATH]; | 
|  | 200 | char *s = buf + FUSE_MAX_PATH - 1; | 
|  | 201 | struct node *node; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 202 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 203 | *s = '\0'; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 204 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 205 | if(name != NULL) { | 
|  | 206 | s = add_name(buf, s, name); | 
|  | 207 | if(s == NULL) | 
|  | 208 | return NULL; | 
|  | 209 | } | 
|  | 210 |  | 
|  | 211 | pthread_mutex_lock(&f->lock); | 
|  | 212 | for(node = get_node(f, ino); node->ino != FUSE_ROOT_INO; | 
|  | 213 | node = get_node(f, node->parent)) { | 
|  | 214 | if(node->name == NULL) { | 
|  | 215 | s = NULL; | 
|  | 216 | break; | 
|  | 217 | } | 
|  | 218 |  | 
|  | 219 | s = add_name(buf, s, node->name); | 
|  | 220 | if(s == NULL) | 
|  | 221 | break; | 
|  | 222 | } | 
|  | 223 | pthread_mutex_unlock(&f->lock); | 
|  | 224 |  | 
|  | 225 | if(s == NULL) | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 226 | return NULL; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 227 | else if(*s == '\0') | 
|  | 228 | return strdup("/"); | 
|  | 229 | else | 
|  | 230 | return strdup(s); | 
|  | 231 | } | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 232 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 233 | static char *get_path(struct fuse *f, fino_t ino) | 
|  | 234 | { | 
|  | 235 | return get_path_name(f, ino, NULL); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 236 | } | 
|  | 237 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 238 | static void destroy_node(struct fuse *f, fino_t ino, int version) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 239 | { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 240 | struct node *node; | 
|  | 241 |  | 
|  | 242 | pthread_mutex_lock(&f->lock); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 243 | node = get_node(f, ino); | 
| Miklos Szeredi | 39f2867 | 2001-11-14 14:52:54 +0000 | [diff] [blame] | 244 | if(node->version == version && ino != FUSE_ROOT_INO) { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 245 | unhash_name(f, node); | 
|  | 246 | unhash_ino(f, node); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 247 | free_node(node); | 
|  | 248 | } | 
|  | 249 | pthread_mutex_unlock(&f->lock); | 
|  | 250 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 251 | } | 
|  | 252 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 253 | static void remove_node(struct fuse *f, fino_t dir, const char *name) | 
|  | 254 | { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 255 | struct node *node; | 
|  | 256 |  | 
|  | 257 | pthread_mutex_lock(&f->lock); | 
|  | 258 | node = lookup_node(f, dir, name); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 259 | if(node == NULL) { | 
|  | 260 | fprintf(stderr, "fuse internal error: unable to remove node %lu/%s\n", | 
|  | 261 | dir, name); | 
|  | 262 | abort(); | 
|  | 263 | } | 
|  | 264 | unhash_name(f, node); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 265 | pthread_mutex_unlock(&f->lock); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 266 | } | 
|  | 267 |  | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 268 | static void rename_node(struct fuse *f, fino_t olddir, const char *oldname, | 
|  | 269 | fino_t newdir, const char *newname) | 
|  | 270 | { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 271 | struct node *node; | 
|  | 272 | struct node *newnode; | 
|  | 273 |  | 
|  | 274 | pthread_mutex_lock(&f->lock); | 
|  | 275 | node  = lookup_node(f, olddir, oldname); | 
|  | 276 | newnode  = lookup_node(f, newdir, newname); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 277 | if(node == NULL) { | 
|  | 278 | fprintf(stderr, "fuse internal error: unable to rename node %lu/%s\n", | 
|  | 279 | olddir, oldname); | 
|  | 280 | abort(); | 
|  | 281 | } | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 282 |  | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 283 | if(newnode != NULL) | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 284 | unhash_name(f, newnode); | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 285 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 286 | unhash_name(f, node); | 
|  | 287 | hash_name(f, node, newdir, newname); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 288 | pthread_mutex_unlock(&f->lock); | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 289 | } | 
|  | 290 |  | 
|  | 291 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 292 | static void convert_stat(struct stat *stbuf, struct fuse_attr *attr) | 
|  | 293 | { | 
|  | 294 | attr->mode    = stbuf->st_mode; | 
|  | 295 | attr->nlink   = stbuf->st_nlink; | 
|  | 296 | attr->uid     = stbuf->st_uid; | 
|  | 297 | attr->gid     = stbuf->st_gid; | 
|  | 298 | attr->rdev    = stbuf->st_rdev; | 
|  | 299 | attr->size    = stbuf->st_size; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 300 | attr->blocks  = stbuf->st_blocks; | 
|  | 301 | attr->atime   = stbuf->st_atime; | 
|  | 302 | attr->mtime   = stbuf->st_mtime; | 
|  | 303 | attr->ctime   = stbuf->st_ctime; | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 304 | attr->_dummy  = 4096; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 305 | } | 
|  | 306 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 307 | static int fill_dir(struct fuse_dirhandle *dh, char *name, int type) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 308 | { | 
|  | 309 | struct fuse_dirent dirent; | 
|  | 310 | size_t reclen; | 
|  | 311 | size_t res; | 
|  | 312 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 313 | dirent.ino = find_node_dir(dh->fuse, dh->dir, name); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 314 | dirent.namelen = strlen(name); | 
|  | 315 | strncpy(dirent.name, name, sizeof(dirent.name)); | 
|  | 316 | dirent.type = type; | 
|  | 317 | reclen = FUSE_DIRENT_SIZE(&dirent); | 
|  | 318 | res = fwrite(&dirent, reclen, 1, dh->fp); | 
|  | 319 | if(res == 0) { | 
|  | 320 | perror("writing directory file"); | 
|  | 321 | return -EIO; | 
|  | 322 | } | 
|  | 323 | return 0; | 
|  | 324 | } | 
|  | 325 |  | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 326 | static void send_reply(struct fuse *f, struct fuse_in_header *in, int error, | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 327 | void *arg, size_t argsize) | 
|  | 328 | { | 
|  | 329 | int res; | 
|  | 330 | char *outbuf; | 
|  | 331 | size_t outsize; | 
|  | 332 | struct fuse_out_header *out; | 
|  | 333 |  | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 334 | if(error > 0) { | 
|  | 335 | fprintf(stderr, "positive error code: %i\n",  error); | 
|  | 336 | error = -ERANGE; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 337 | } | 
|  | 338 |  | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 339 | if(error) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 340 | argsize = 0; | 
|  | 341 |  | 
|  | 342 | outsize = sizeof(struct fuse_out_header) + argsize; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 343 | outbuf = (char *) malloc(outsize); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 344 | out = (struct fuse_out_header *) outbuf; | 
|  | 345 | out->unique = in->unique; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 346 | out->error = error; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 347 | if(argsize != 0) | 
|  | 348 | memcpy(outbuf + sizeof(struct fuse_out_header), arg, argsize); | 
|  | 349 |  | 
| Miklos Szeredi | c0938ea | 2001-11-07 12:35:06 +0000 | [diff] [blame] | 350 | if((f->flags & FUSE_DEBUG)) { | 
|  | 351 | printf("   unique: %i, error: %i (%s), outsize: %i\n", out->unique, | 
|  | 352 | out->error, strerror(-out->error), outsize); | 
|  | 353 | fflush(stdout); | 
|  | 354 | } | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 355 |  | 
|  | 356 | res = write(f->fd, outbuf, outsize); | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 357 | if(res == -1) { | 
|  | 358 | /* ENOENT means the operation was interrupted */ | 
|  | 359 | if(errno != ENOENT) | 
|  | 360 | perror("writing fuse device"); | 
|  | 361 | } | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 362 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 363 | free(outbuf); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 364 | } | 
|  | 365 |  | 
|  | 366 | static void do_lookup(struct fuse *f, struct fuse_in_header *in, char *name) | 
|  | 367 | { | 
|  | 368 | int res; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 369 | char *path; | 
|  | 370 | struct stat buf; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 371 | struct fuse_lookup_out arg; | 
|  | 372 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 373 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 374 | path = get_path_name(f, in->ino, name); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 375 | if(path != NULL) { | 
|  | 376 | res = -ENOSYS; | 
|  | 377 | if(f->op.getattr) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 378 | res = f->op.getattr(path, &buf); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 379 | free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 380 | } | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 381 | if(res == 0) { | 
|  | 382 | convert_stat(&buf, &arg.attr); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 383 | arg.ino = find_node(f, in->ino, name, &arg.attr, in->unique); | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 384 | } | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 385 | send_reply(f, in, res, &arg, sizeof(arg)); | 
|  | 386 | } | 
|  | 387 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 388 | static void do_forget(struct fuse *f, struct fuse_in_header *in, | 
|  | 389 | struct fuse_forget_in *arg) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 390 | { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 391 | destroy_node(f, in->ino, arg->version); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 392 | } | 
|  | 393 |  | 
|  | 394 | static void do_getattr(struct fuse *f, struct fuse_in_header *in) | 
|  | 395 | { | 
|  | 396 | int res; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 397 | char *path; | 
|  | 398 | struct stat buf; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 399 | struct fuse_getattr_out arg; | 
|  | 400 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 401 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 402 | path = get_path(f, in->ino); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 403 | if(path != NULL) { | 
|  | 404 | res = -ENOSYS; | 
|  | 405 | if(f->op.getattr) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 406 | res = f->op.getattr(path, &buf); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 407 | free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 408 | } | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 409 | if(res == 0) | 
|  | 410 | convert_stat(&buf, &arg.attr); | 
|  | 411 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 412 | send_reply(f, in, res, &arg, sizeof(arg)); | 
|  | 413 | } | 
|  | 414 |  | 
| Miklos Szeredi | 680a69a | 2001-11-16 13:31:14 +0000 | [diff] [blame^] | 415 | 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] | 416 | { | 
|  | 417 | int res; | 
|  | 418 |  | 
|  | 419 | res = -ENOSYS; | 
|  | 420 | if(f->op.chmod) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 421 | res = f->op.chmod(path, attr->mode); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 422 |  | 
|  | 423 | return res; | 
|  | 424 | } | 
|  | 425 |  | 
| Miklos Szeredi | 680a69a | 2001-11-16 13:31:14 +0000 | [diff] [blame^] | 426 | static int do_chown(struct fuse *f, const char *path, struct fuse_attr *attr, | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 427 | int valid) | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 428 | { | 
|  | 429 | int res; | 
|  | 430 | uid_t uid = (valid & FATTR_UID) ? attr->uid : (uid_t) -1; | 
|  | 431 | gid_t gid = (valid & FATTR_GID) ? attr->gid : (gid_t) -1; | 
|  | 432 |  | 
|  | 433 | res = -ENOSYS; | 
|  | 434 | if(f->op.chown) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 435 | res = f->op.chown(path, uid, gid); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 436 |  | 
|  | 437 | return res; | 
|  | 438 | } | 
|  | 439 |  | 
| Miklos Szeredi | 680a69a | 2001-11-16 13:31:14 +0000 | [diff] [blame^] | 440 | static int do_truncate(struct fuse *f, const char *path, | 
|  | 441 | struct fuse_attr *attr) | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 442 | { | 
|  | 443 | int res; | 
|  | 444 |  | 
|  | 445 | res = -ENOSYS; | 
|  | 446 | if(f->op.truncate) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 447 | res = f->op.truncate(path, attr->size); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 448 |  | 
|  | 449 | return res; | 
|  | 450 | } | 
|  | 451 |  | 
| Miklos Szeredi | 680a69a | 2001-11-16 13:31:14 +0000 | [diff] [blame^] | 452 | 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] | 453 | { | 
|  | 454 | int res; | 
|  | 455 | struct utimbuf buf; | 
|  | 456 | buf.actime = attr->atime; | 
|  | 457 | buf.modtime = attr->mtime; | 
|  | 458 | res = -ENOSYS; | 
|  | 459 | if(f->op.utime) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 460 | res = f->op.utime(path, &buf); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 461 |  | 
|  | 462 | return res; | 
|  | 463 | } | 
|  | 464 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 465 | static void do_setattr(struct fuse *f, struct fuse_in_header *in, | 
|  | 466 | struct fuse_setattr_in *arg) | 
|  | 467 | { | 
|  | 468 | int res; | 
|  | 469 | char *path; | 
|  | 470 | int valid = arg->valid; | 
|  | 471 | struct fuse_attr *attr = &arg->attr; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 472 | struct fuse_setattr_out outarg; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 473 |  | 
|  | 474 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 475 | path = get_path(f, in->ino); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 476 | if(path != NULL) { | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 477 | res = -ENOSYS; | 
|  | 478 | if(f->op.getattr) { | 
|  | 479 | res = 0; | 
|  | 480 | if(!res && (valid & FATTR_MODE)) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 481 | res = do_chmod(f, path, attr); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 482 | if(!res && (valid & (FATTR_UID | FATTR_GID))) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 483 | res = do_chown(f, path, attr, valid); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 484 | if(!res && (valid & FATTR_SIZE)) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 485 | res = do_truncate(f, path, attr); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 486 | if(!res && (valid & FATTR_UTIME)) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 487 | res = do_utime(f, path, attr); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 488 | if(!res) { | 
|  | 489 | struct stat buf; | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 490 | res = f->op.getattr(path, &buf); | 
| Miklos Szeredi | f3ea83b | 2001-11-07 14:55:16 +0000 | [diff] [blame] | 491 | if(!res) | 
|  | 492 | convert_stat(&buf, &outarg.attr); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 493 | } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 494 | } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 495 | free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 496 | } | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 497 | send_reply(f, in, res, &outarg, sizeof(outarg)); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 498 | } | 
|  | 499 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 500 | static void do_readlink(struct fuse *f, struct fuse_in_header *in) | 
|  | 501 | { | 
|  | 502 | int res; | 
|  | 503 | char link[PATH_MAX + 1]; | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 504 | char *path; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 505 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 506 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 507 | path = get_path(f, in->ino); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 508 | if(path != NULL) { | 
|  | 509 | res = -ENOSYS; | 
|  | 510 | if(f->op.readlink) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 511 | res = f->op.readlink(path, link, sizeof(link)); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 512 | free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 513 | } | 
| Miklos Szeredi | 2df1c04 | 2001-11-06 15:07:17 +0000 | [diff] [blame] | 514 | link[PATH_MAX] = '\0'; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 515 | send_reply(f, in, res, link, !res ? strlen(link) : 0); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 516 | } | 
|  | 517 |  | 
|  | 518 | static void do_getdir(struct fuse *f, struct fuse_in_header *in) | 
|  | 519 | { | 
|  | 520 | int res; | 
|  | 521 | struct fuse_getdir_out arg; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 522 | struct fuse_dirhandle dh; | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 523 | char *path; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 524 |  | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 525 | dh.fuse = f; | 
|  | 526 | dh.fp = tmpfile(); | 
|  | 527 | dh.dir = in->ino; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 528 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 529 | path = get_path(f, in->ino); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 530 | if(path != NULL) { | 
|  | 531 | res = -ENOSYS; | 
|  | 532 | if(f->op.getdir) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 533 | res = f->op.getdir(path, &dh, (fuse_dirfil_t) fill_dir); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 534 | free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 535 | } | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 536 | fflush(dh.fp); | 
|  | 537 | arg.fd = fileno(dh.fp); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 538 | send_reply(f, in, res, &arg, sizeof(arg)); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 539 | fclose(dh.fp); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 540 | } | 
|  | 541 |  | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 542 | static void do_mknod(struct fuse *f, struct fuse_in_header *in, | 
|  | 543 | struct fuse_mknod_in *inarg) | 
|  | 544 | { | 
|  | 545 | int res; | 
|  | 546 | char *path; | 
|  | 547 | struct fuse_mknod_out outarg; | 
|  | 548 | struct stat buf; | 
|  | 549 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 550 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 551 | path = get_path_name(f, in->ino, inarg->name); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 552 | if(path != NULL) { | 
|  | 553 | res = -ENOSYS; | 
|  | 554 | if(f->op.mknod && f->op.getattr) { | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 555 | res = f->op.mknod(path, inarg->mode, inarg->rdev); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 556 | if(res == 0) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 557 | res = f->op.getattr(path, &buf); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 558 | } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 559 | free(path); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 560 | } | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 561 | if(res == 0) { | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 562 | convert_stat(&buf, &outarg.attr); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 563 | outarg.ino = find_node(f, in->ino, inarg->name, &outarg.attr, | 
|  | 564 | in->unique); | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 565 | } | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 566 |  | 
|  | 567 | send_reply(f, in, res, &outarg, sizeof(outarg)); | 
|  | 568 | } | 
|  | 569 |  | 
|  | 570 | static void do_mkdir(struct fuse *f, struct fuse_in_header *in, | 
|  | 571 | struct fuse_mkdir_in *inarg) | 
|  | 572 | { | 
|  | 573 | int res; | 
|  | 574 | char *path; | 
|  | 575 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 576 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 577 | path = get_path_name(f, in->ino, inarg->name); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 578 | if(path != NULL) { | 
|  | 579 | res = -ENOSYS; | 
|  | 580 | if(f->op.mkdir) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 581 | res = f->op.mkdir(path, inarg->mode); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 582 | free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 583 | } | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 584 | send_reply(f, in, res, NULL, 0); | 
|  | 585 | } | 
|  | 586 |  | 
|  | 587 | static void do_remove(struct fuse *f, struct fuse_in_header *in, char *name) | 
|  | 588 | { | 
|  | 589 | int res; | 
|  | 590 | char *path; | 
|  | 591 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 592 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 593 | path = get_path_name(f, in->ino, name); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 594 | if(path != NULL) { | 
|  | 595 | res = -ENOSYS; | 
|  | 596 | if(in->opcode == FUSE_UNLINK) { | 
|  | 597 | if(f->op.unlink) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 598 | res = f->op.unlink(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 599 | } | 
|  | 600 | else { | 
|  | 601 | if(f->op.rmdir) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 602 | res = f->op.rmdir(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 603 | } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 604 | free(path); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 605 | } | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 606 | if(res == 0) | 
|  | 607 | remove_node(f, in->ino, name); | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 608 | send_reply(f, in, res, NULL, 0); | 
|  | 609 | } | 
|  | 610 |  | 
|  | 611 | static void do_symlink(struct fuse *f, struct fuse_in_header *in, char *name, | 
|  | 612 | char *link) | 
|  | 613 | { | 
|  | 614 | int res; | 
|  | 615 | char *path; | 
|  | 616 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 617 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 618 | path = get_path_name(f, in->ino, name); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 619 | if(path != NULL) { | 
|  | 620 | res = -ENOSYS; | 
|  | 621 | if(f->op.symlink) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 622 | res = f->op.symlink(link, path); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 623 | free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 624 | } | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 625 | send_reply(f, in, res, NULL, 0); | 
|  | 626 | } | 
|  | 627 |  | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 628 | static void do_rename(struct fuse *f, struct fuse_in_header *in, | 
|  | 629 | struct fuse_rename_in *inarg) | 
|  | 630 | { | 
|  | 631 | int res; | 
|  | 632 | fino_t olddir = in->ino; | 
|  | 633 | fino_t newdir = inarg->newdir; | 
|  | 634 | char *oldname = inarg->names; | 
|  | 635 | char *newname = inarg->names + strlen(oldname) + 1; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 636 | char *oldpath; | 
|  | 637 | char *newpath; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 638 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 639 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 640 | oldpath = get_path_name(f, olddir, oldname); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 641 | if(oldpath != NULL) { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 642 | newpath = get_path_name(f, newdir, newname); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 643 | if(newpath != NULL) { | 
|  | 644 | res = -ENOSYS; | 
|  | 645 | if(f->op.rename) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 646 | res = f->op.rename(oldpath, newpath); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 647 | if(res == 0) | 
|  | 648 | rename_node(f, olddir, oldname, newdir, newname); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 649 | free(newpath); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 650 | } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 651 | free(oldpath); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 652 | } | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 653 | send_reply(f, in, res, NULL, 0); | 
|  | 654 | } | 
|  | 655 |  | 
|  | 656 | static void do_link(struct fuse *f, struct fuse_in_header *in, | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 657 | struct fuse_link_in *arg) | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 658 | { | 
|  | 659 | int res; | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 660 | char *oldpath; | 
|  | 661 | char *newpath; | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 662 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 663 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 664 | oldpath = get_path(f, in->ino); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 665 | if(oldpath != NULL) { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 666 | newpath =  get_path_name(f, arg->newdir, arg->name); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 667 | if(newpath != NULL) { | 
|  | 668 | res = -ENOSYS; | 
|  | 669 | if(f->op.link) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 670 | res = f->op.link(oldpath, newpath); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 671 | free(newpath); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 672 | } | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 673 | free(oldpath); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 674 | } | 
| Miklos Szeredi | 19dff1b | 2001-10-30 15:06:52 +0000 | [diff] [blame] | 675 | send_reply(f, in, res, NULL, 0); | 
|  | 676 | } | 
|  | 677 |  | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 678 | static void do_open(struct fuse *f, struct fuse_in_header *in, | 
|  | 679 | struct fuse_open_in *arg) | 
|  | 680 | { | 
|  | 681 | int res; | 
|  | 682 | char *path; | 
|  | 683 |  | 
|  | 684 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 685 | path = get_path(f, in->ino); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 686 | if(path != NULL) { | 
|  | 687 | res = -ENOSYS; | 
|  | 688 | if(f->op.open) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 689 | res = f->op.open(path, arg->flags); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 690 | free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 691 | } | 
|  | 692 | send_reply(f, in, res, NULL, 0); | 
|  | 693 | } | 
|  | 694 |  | 
|  | 695 | static void do_read(struct fuse *f, struct fuse_in_header *in, | 
|  | 696 | struct fuse_read_in *arg) | 
|  | 697 | { | 
|  | 698 | int res; | 
|  | 699 | char *path; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 700 | char *buf = (char *) malloc(arg->size); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 701 | size_t size; | 
|  | 702 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 703 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 704 | path = get_path(f, in->ino); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 705 | if(path != NULL) { | 
|  | 706 | res = -ENOSYS; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 707 | if(f->op.read) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 708 | res = f->op.read(path, buf, arg->size, arg->offset); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 709 | free(path); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 710 | } | 
|  | 711 |  | 
|  | 712 | size = 0; | 
|  | 713 | if(res > 0) { | 
|  | 714 | size = res; | 
|  | 715 | res = 0; | 
|  | 716 | } | 
|  | 717 |  | 
|  | 718 | send_reply(f, in, res, buf, size); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 719 | free(buf); | 
| Miklos Szeredi | 5e18348 | 2001-10-31 14:52:35 +0000 | [diff] [blame] | 720 | } | 
| Miklos Szeredi | b483c93 | 2001-10-29 14:57:57 +0000 | [diff] [blame] | 721 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 722 | static void do_write(struct fuse *f, struct fuse_in_header *in, | 
|  | 723 | struct fuse_write_in *arg) | 
|  | 724 | { | 
|  | 725 | int res; | 
|  | 726 | char *path; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 727 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 728 | res = -ENOENT; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 729 | path = get_path(f, in->ino); | 
|  | 730 | if(path != NULL) { | 
|  | 731 | res = -ENOSYS; | 
|  | 732 | if(f->op.write) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 733 | res = f->op.write(path, arg->buf, arg->size, arg->offset); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 734 | free(path); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 735 | } | 
|  | 736 |  | 
|  | 737 | if(res > 0) { | 
|  | 738 | if((size_t) res != arg->size) { | 
|  | 739 | fprintf(stderr, "short write: %u (should be %u)\n", res, | 
|  | 740 | arg->size); | 
|  | 741 | res = -EIO; | 
|  | 742 | } | 
|  | 743 | else | 
|  | 744 | res = 0; | 
|  | 745 | } | 
|  | 746 |  | 
|  | 747 | send_reply(f, in, res, NULL, 0); | 
|  | 748 | } | 
|  | 749 |  | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 750 | void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd) | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 751 | { | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 752 | struct fuse_in_header *in = (struct fuse_in_header *) cmd->buf; | 
|  | 753 | void *inarg = cmd->buf + sizeof(struct fuse_in_header); | 
|  | 754 | size_t argsize; | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 755 |  | 
| Miklos Szeredi | c0938ea | 2001-11-07 12:35:06 +0000 | [diff] [blame] | 756 | if((f->flags & FUSE_DEBUG)) { | 
|  | 757 | printf("unique: %i, opcode: %i, ino: %li, insize: %i\n", in->unique, | 
|  | 758 | in->opcode, in->ino, cmd->buflen); | 
|  | 759 | fflush(stdout); | 
|  | 760 | } | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 761 |  | 
|  | 762 | argsize = cmd->buflen - sizeof(struct fuse_in_header); | 
|  | 763 |  | 
|  | 764 | switch(in->opcode) { | 
|  | 765 | case FUSE_LOOKUP: | 
|  | 766 | do_lookup(f, in, (char *) inarg); | 
|  | 767 | break; | 
|  | 768 |  | 
|  | 769 | case FUSE_FORGET: | 
|  | 770 | do_forget(f, in, (struct fuse_forget_in *) inarg); | 
|  | 771 | break; | 
|  | 772 |  | 
|  | 773 | case FUSE_GETATTR: | 
|  | 774 | do_getattr(f, in); | 
|  | 775 | break; | 
|  | 776 |  | 
|  | 777 | case FUSE_SETATTR: | 
|  | 778 | do_setattr(f, in, (struct fuse_setattr_in *) inarg); | 
|  | 779 | break; | 
|  | 780 |  | 
|  | 781 | case FUSE_READLINK: | 
|  | 782 | do_readlink(f, in); | 
|  | 783 | break; | 
|  | 784 |  | 
|  | 785 | case FUSE_GETDIR: | 
|  | 786 | do_getdir(f, in); | 
|  | 787 | break; | 
|  | 788 |  | 
|  | 789 | case FUSE_MKNOD: | 
|  | 790 | do_mknod(f, in, (struct fuse_mknod_in *) inarg); | 
|  | 791 | break; | 
|  | 792 |  | 
|  | 793 | case FUSE_MKDIR: | 
|  | 794 | do_mkdir(f, in, (struct fuse_mkdir_in *) inarg); | 
|  | 795 | break; | 
|  | 796 |  | 
|  | 797 | case FUSE_UNLINK: | 
|  | 798 | case FUSE_RMDIR: | 
|  | 799 | do_remove(f, in, (char *) inarg); | 
|  | 800 | break; | 
|  | 801 |  | 
|  | 802 | case FUSE_SYMLINK: | 
|  | 803 | do_symlink(f, in, (char *) inarg, | 
|  | 804 | ((char *) inarg) + strlen((char *) inarg) + 1); | 
|  | 805 | break; | 
|  | 806 |  | 
|  | 807 | case FUSE_RENAME: | 
|  | 808 | do_rename(f, in, (struct fuse_rename_in *) inarg); | 
|  | 809 | break; | 
|  | 810 |  | 
|  | 811 | case FUSE_LINK: | 
|  | 812 | do_link(f, in, (struct fuse_link_in *) inarg); | 
|  | 813 | break; | 
|  | 814 |  | 
|  | 815 | case FUSE_OPEN: | 
|  | 816 | do_open(f, in, (struct fuse_open_in *) inarg); | 
|  | 817 | break; | 
|  | 818 |  | 
|  | 819 | case FUSE_READ: | 
|  | 820 | do_read(f, in, (struct fuse_read_in *) inarg); | 
|  | 821 | break; | 
|  | 822 |  | 
|  | 823 | case FUSE_WRITE: | 
|  | 824 | do_write(f, in, (struct fuse_write_in *) inarg); | 
|  | 825 | break; | 
|  | 826 |  | 
|  | 827 | default: | 
|  | 828 | fprintf(stderr, "Operation %i not implemented\n", in->opcode); | 
|  | 829 | /* No need to send reply to async requests */ | 
|  | 830 | if(in->unique != 0) | 
|  | 831 | send_reply(f, in, -ENOSYS, NULL, 0); | 
|  | 832 | } | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 833 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 834 | free(cmd->buf); | 
|  | 835 | free(cmd); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 836 | } | 
|  | 837 |  | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 838 | struct fuse_cmd *__fuse_read_cmd(struct fuse *f) | 
| Miklos Szeredi | 2df1c04 | 2001-11-06 15:07:17 +0000 | [diff] [blame] | 839 | { | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 840 | ssize_t res; | 
|  | 841 | char inbuf[FUSE_MAX_IN]; | 
|  | 842 | struct fuse_cmd *cmd; | 
|  | 843 |  | 
|  | 844 | res = read(f->fd, inbuf, sizeof(inbuf)); | 
|  | 845 | if(res == -1) { | 
|  | 846 | perror("reading fuse device"); | 
|  | 847 | /* BAD... This will happen again */ | 
|  | 848 | return NULL; | 
|  | 849 | } | 
|  | 850 | if((size_t) res < sizeof(struct fuse_in_header)) { | 
|  | 851 | fprintf(stderr, "short read on fuse device\n"); | 
|  | 852 | /* Cannot happen */ | 
|  | 853 | return NULL; | 
|  | 854 | } | 
|  | 855 |  | 
|  | 856 | cmd = (struct fuse_cmd *) malloc(sizeof(*cmd)); | 
|  | 857 | cmd->buflen = res; | 
|  | 858 | cmd->buf = (char *) malloc(cmd->buflen); | 
|  | 859 | memcpy(cmd->buf, inbuf, cmd->buflen); | 
|  | 860 |  | 
|  | 861 | return cmd; | 
| Miklos Szeredi | 2df1c04 | 2001-11-06 15:07:17 +0000 | [diff] [blame] | 862 | } | 
|  | 863 |  | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 864 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 865 | void fuse_loop(struct fuse *f) | 
|  | 866 | { | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 867 | while(1) { | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 868 | struct fuse_cmd *cmd = __fuse_read_cmd(f); | 
|  | 869 | if(cmd == NULL) | 
| Miklos Szeredi | 0a7077f | 2001-11-11 18:20:17 +0000 | [diff] [blame] | 870 | exit(1); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 871 |  | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 872 | __fuse_process_cmd(f, cmd); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 873 | } | 
|  | 874 | } | 
|  | 875 |  | 
| Miklos Szeredi | 8cffdb9 | 2001-11-09 14:49:18 +0000 | [diff] [blame] | 876 | struct fuse *fuse_new(int fd, int flags) | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 877 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 878 | struct fuse *f; | 
|  | 879 | struct node *root; | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 880 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 881 | f = (struct fuse *) calloc(1, sizeof(struct fuse)); | 
| Miklos Szeredi | 2df1c04 | 2001-11-06 15:07:17 +0000 | [diff] [blame] | 882 |  | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 883 | f->flags = flags; | 
| Miklos Szeredi | 8cffdb9 | 2001-11-09 14:49:18 +0000 | [diff] [blame] | 884 | f->fd = fd; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 885 | f->ctr = 0; | 
| Miklos Szeredi | fff56ab | 2001-11-16 10:12:59 +0000 | [diff] [blame] | 886 | /* FIXME: Dynamic hash table */ | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 887 | f->name_table_size = 14057; | 
|  | 888 | f->name_table = (struct node **) | 
|  | 889 | calloc(1, sizeof(struct node *) * f->name_table_size); | 
|  | 890 | f->ino_table_size = 14057; | 
|  | 891 | f->ino_table = (struct node **) | 
|  | 892 | calloc(1, sizeof(struct node *) * f->ino_table_size); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 893 | pthread_mutex_init(&f->lock, NULL); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 894 |  | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 895 | root = (struct node *) calloc(1, sizeof(struct node)); | 
| Miklos Szeredi | 8cffdb9 | 2001-11-09 14:49:18 +0000 | [diff] [blame] | 896 | root->mode = 0; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 897 | root->rdev = 0; | 
|  | 898 | root->name = strdup("/"); | 
|  | 899 | root->parent = 0; | 
|  | 900 | hash_ino(f, root, FUSE_ROOT_INO); | 
|  | 901 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 902 | return f; | 
|  | 903 | } | 
|  | 904 |  | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 905 | void fuse_set_operations(struct fuse *f, const struct fuse_operations *op) | 
|  | 906 | { | 
|  | 907 | f->op = *op; | 
|  | 908 | } | 
|  | 909 |  | 
|  | 910 | void fuse_destroy(struct fuse *f) | 
|  | 911 | { | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 912 | size_t i; | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 913 | for(i = 0; i < f->ino_table_size; i++) { | 
|  | 914 | struct node *node; | 
|  | 915 | struct node *next; | 
|  | 916 | for(node = f->ino_table[i]; node != NULL; node = next) { | 
|  | 917 | next = node->ino_next; | 
|  | 918 | free_node(node); | 
|  | 919 | } | 
|  | 920 | } | 
|  | 921 | free(f->ino_table); | 
|  | 922 | free(f->name_table); | 
| Miklos Szeredi | a181e61 | 2001-11-06 12:03:23 +0000 | [diff] [blame] | 923 | pthread_mutex_destroy(&f->lock); | 
| Miklos Szeredi | 97c61e9 | 2001-11-07 12:09:43 +0000 | [diff] [blame] | 924 | free(f); | 
| Miklos Szeredi | 85c74fc | 2001-10-28 19:44:14 +0000 | [diff] [blame] | 925 | } |