blob: d5d79b169490fb6c42abe6266778a628ad185b51 [file] [log] [blame]
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu)
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include "fuse_i.h"
10
Miklos Szeredi05033042001-11-13 16:11:35 +000011#include <linux/pagemap.h>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000012#include <linux/slab.h>
Miklos Szeredi5e183482001-10-31 14:52:35 +000013#include <linux/file.h>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000014
Miklos Szeredib483c932001-10-29 14:57:57 +000015static struct inode_operations fuse_dir_inode_operations;
16static struct inode_operations fuse_file_inode_operations;
17static struct inode_operations fuse_symlink_inode_operations;
Miklos Szeredib483c932001-10-29 14:57:57 +000018
19static struct file_operations fuse_dir_operations;
Miklos Szeredib483c932001-10-29 14:57:57 +000020
Miklos Szeredi307242f2004-01-26 11:28:44 +000021static struct dentry_operations fuse_dentry_operations;
Miklos Szeredib483c932001-10-29 14:57:57 +000022
Miklos Szeredi7c35cf92004-01-14 16:56:49 +000023#ifndef KERNEL_2_6
24#define new_decode_dev(x) (x)
25#define new_encode_dev(x) (x)
26#endif
27
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000028static void change_attributes(struct inode *inode, struct fuse_attr *attr)
29{
Miklos Szeredid1199f82004-02-06 15:29:22 +000030 if(S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) {
Miklos Szeredif85ab242004-01-07 12:16:45 +000031#ifdef KERNEL_2_6
32 invalidate_inode_pages(inode->i_mapping);
33#else
Miklos Szeredia181e612001-11-06 12:03:23 +000034 invalidate_inode_pages(inode);
Miklos Szeredif85ab242004-01-07 12:16:45 +000035#endif
36 }
Miklos Szeredia181e612001-11-06 12:03:23 +000037
Miklos Szeredi5e183482001-10-31 14:52:35 +000038 inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000039 inode->i_nlink = attr->nlink;
40 inode->i_uid = attr->uid;
41 inode->i_gid = attr->gid;
Miklos Szeredid1199f82004-02-06 15:29:22 +000042 i_size_write(inode, attr->size);
Miklos Szeredi05033042001-11-13 16:11:35 +000043 inode->i_blksize = PAGE_CACHE_SIZE;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000044 inode->i_blocks = attr->blocks;
Miklos Szeredif85ab242004-01-07 12:16:45 +000045#ifdef KERNEL_2_6
46 inode->i_atime.tv_sec = attr->atime;
Miklos Szeredib5958612004-02-20 14:10:49 +000047 inode->i_atime.tv_nsec = attr->atimensec;
Miklos Szeredif85ab242004-01-07 12:16:45 +000048 inode->i_mtime.tv_sec = attr->mtime;
Miklos Szeredib5958612004-02-20 14:10:49 +000049 inode->i_mtime.tv_nsec = attr->mtimensec;
Miklos Szeredif85ab242004-01-07 12:16:45 +000050 inode->i_ctime.tv_sec = attr->ctime;
Miklos Szeredib5958612004-02-20 14:10:49 +000051 inode->i_ctime.tv_nsec = attr->ctimensec;
Miklos Szeredif85ab242004-01-07 12:16:45 +000052#else
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000053 inode->i_atime = attr->atime;
54 inode->i_mtime = attr->mtime;
55 inode->i_ctime = attr->ctime;
Miklos Szeredif85ab242004-01-07 12:16:45 +000056#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000057}
58
Miklos Szeredia181e612001-11-06 12:03:23 +000059static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000060{
Miklos Szeredia181e612001-11-06 12:03:23 +000061 inode->i_mode = attr->mode & S_IFMT;
Miklos Szeredid1199f82004-02-06 15:29:22 +000062 i_size_write(inode, attr->size);
Miklos Szeredib483c932001-10-29 14:57:57 +000063 if(S_ISREG(inode->i_mode)) {
64 inode->i_op = &fuse_file_inode_operations;
Miklos Szeredi5e183482001-10-31 14:52:35 +000065 fuse_init_file_inode(inode);
Miklos Szeredib483c932001-10-29 14:57:57 +000066 }
67 else if(S_ISDIR(inode->i_mode)) {
68 inode->i_op = &fuse_dir_inode_operations;
69 inode->i_fop = &fuse_dir_operations;
70 }
Miklos Szeredi5e183482001-10-31 14:52:35 +000071 else if(S_ISLNK(inode->i_mode)) {
Miklos Szeredib483c932001-10-29 14:57:57 +000072 inode->i_op = &fuse_symlink_inode_operations;
Miklos Szeredi5e183482001-10-31 14:52:35 +000073 }
Miklos Szeredi76f65782004-02-19 16:55:40 +000074 else if(S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
75 S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)){
Miklos Szeredia181e612001-11-06 12:03:23 +000076 inode->i_op = &fuse_file_inode_operations;
Miklos Szeredi7c35cf92004-01-14 16:56:49 +000077 init_special_inode(inode, inode->i_mode,
78 new_decode_dev(attr->rdev));
Miklos Szeredi76f65782004-02-19 16:55:40 +000079 } else
80 printk("fuse_init_inode: bad file type: %o\n", inode->i_mode);
81
Miklos Szeredi5e183482001-10-31 14:52:35 +000082 inode->u.generic_ip = inode;
83}
84
Miklos Szeredi76f65782004-02-19 16:55:40 +000085struct inode *fuse_iget(struct super_block *sb, ino_t ino, int generation,
Miklos Szeredia181e612001-11-06 12:03:23 +000086 struct fuse_attr *attr, int version)
Miklos Szeredi5e183482001-10-31 14:52:35 +000087{
88 struct inode *inode;
89
90 inode = iget(sb, ino);
91 if(inode) {
Miklos Szeredi76f65782004-02-19 16:55:40 +000092 if(!inode->u.generic_ip) {
93 inode->i_generation = generation;
Miklos Szeredia181e612001-11-06 12:03:23 +000094 fuse_init_inode(inode, attr);
Miklos Szeredi76f65782004-02-19 16:55:40 +000095 } else if(inode->i_generation != generation)
96 printk("fuse_iget: bad generation for ino %lu\n", ino);
Miklos Szeredie815c032004-01-19 18:20:49 +000097
Miklos Szeredi5e183482001-10-31 14:52:35 +000098 change_attributes(inode, attr);
Miklos Szeredia181e612001-11-06 12:03:23 +000099 inode->i_version = version;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000100 }
101
102 return inode;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000103}
104
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000105static int fuse_do_lookup(struct inode *dir, struct dentry *entry,
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000106 struct fuse_entry_out *outarg, int *version)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000107{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000108 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000109 struct fuse_in in = FUSE_IN_INIT;
110 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000111
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000112 in.h.opcode = FUSE_LOOKUP;
113 in.h.ino = dir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000114 in.numargs = 1;
115 in.args[0].size = entry->d_name.len + 1;
116 in.args[0].value = entry->d_name.name;
117 out.numargs = 1;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000118 out.args[0].size = sizeof(struct fuse_entry_out);
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000119 out.args[0].value = outarg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000120 request_send(fc, &in, &out);
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000121
122 *version = out.h.unique;
123 return out.h.error;
124}
125
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000126static inline unsigned long time_to_jiffies(unsigned long sec,
127 unsigned long nsec)
128{
129 /* prevent wrapping of jiffies */
130 if(sec + 1 >= LONG_MAX / HZ)
131 return 0;
132
133 return jiffies + sec * HZ + nsec / (1000000000 / HZ);
134}
135
Miklos Szeredie815c032004-01-19 18:20:49 +0000136static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
137 struct inode **inodep)
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000138{
Miklos Szeredie815c032004-01-19 18:20:49 +0000139 int err;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000140 struct fuse_entry_out outarg;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000141 int version;
Miklos Szeredie815c032004-01-19 18:20:49 +0000142 struct inode *inode = NULL;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000143
Miklos Szeredie815c032004-01-19 18:20:49 +0000144 err = fuse_do_lookup(dir, entry, &outarg, &version);
145 if(!err) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000146 inode = fuse_iget(dir->i_sb, outarg.ino, outarg.generation,
147 &outarg.attr, version);
Miklos Szeredie815c032004-01-19 18:20:49 +0000148 if(!inode)
149 return -ENOMEM;
150 } else if(err != -ENOENT)
151 return err;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000152
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000153 entry->d_time = time_to_jiffies(outarg.entry_valid,
154 outarg.entry_valid_nsec);
Miklos Szeredi307242f2004-01-26 11:28:44 +0000155 entry->d_op = &fuse_dentry_operations;
Miklos Szeredie815c032004-01-19 18:20:49 +0000156 *inodep = inode;
157 return 0;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000158}
159
Miklos Szeredi76f65782004-02-19 16:55:40 +0000160static int lookup_new_entry(struct inode *dir, struct dentry *entry,
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000161 struct fuse_entry_out *outarg, int version,
Miklos Szeredi76f65782004-02-19 16:55:40 +0000162 int mode)
163{
164 struct inode *inode;
165 inode = fuse_iget(dir->i_sb, outarg->ino, outarg->generation,
166 &outarg->attr, version);
167 if(!inode)
168 return -ENOMEM;
169
170 /* Don't allow userspace to do really stupid things... */
171 if((inode->i_mode ^ mode) & S_IFMT) {
172 iput(inode);
173 printk("fuse_mknod: inode has wrong type\n");
174 return -EINVAL;
175 }
176
177 d_instantiate(entry, inode);
178 return 0;
179}
180
181
Miklos Szeredif85ab242004-01-07 12:16:45 +0000182static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
183 dev_t rdev)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000184{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000185 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000186 struct fuse_in in = FUSE_IN_INIT;
187 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi43696432001-11-18 19:15:05 +0000188 struct fuse_mknod_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000189 struct fuse_entry_out outarg;
Miklos Szeredi43696432001-11-18 19:15:05 +0000190
191 memset(&inarg, 0, sizeof(inarg));
192 inarg.mode = mode;
Miklos Szeredi7c35cf92004-01-14 16:56:49 +0000193 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000194
195 in.h.opcode = FUSE_MKNOD;
196 in.h.ino = dir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000197 in.numargs = 2;
198 in.args[0].size = sizeof(inarg);
199 in.args[0].value = &inarg;
200 in.args[1].size = entry->d_name.len + 1;
201 in.args[1].value = entry->d_name.name;
202 out.numargs = 1;
203 out.args[0].size = sizeof(outarg);
204 out.args[0].value = &outarg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000205 request_send(fc, &in, &out);
Miklos Szeredib483c932001-10-29 14:57:57 +0000206
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000207 if(out.h.error)
208 return out.h.error;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000209
Miklos Szeredi76f65782004-02-19 16:55:40 +0000210 return lookup_new_entry(dir, entry, &outarg, out.h.unique, mode);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000211}
212
Miklos Szeredif85ab242004-01-07 12:16:45 +0000213static int _fuse_create(struct inode *dir, struct dentry *entry, int mode)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000214{
Miklos Szeredif85ab242004-01-07 12:16:45 +0000215 return _fuse_mknod(dir, entry, mode, 0);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000216}
217
Miklos Szeredie815c032004-01-19 18:20:49 +0000218
Miklos Szeredib483c932001-10-29 14:57:57 +0000219static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
220{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000221 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredib483c932001-10-29 14:57:57 +0000222 struct fuse_in in = FUSE_IN_INIT;
223 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi43696432001-11-18 19:15:05 +0000224 struct fuse_mkdir_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000225 struct fuse_entry_out outarg;
Miklos Szeredi43696432001-11-18 19:15:05 +0000226
227 memset(&inarg, 0, sizeof(inarg));
228 inarg.mode = mode;
Miklos Szeredib483c932001-10-29 14:57:57 +0000229
230 in.h.opcode = FUSE_MKDIR;
231 in.h.ino = dir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000232 in.numargs = 2;
233 in.args[0].size = sizeof(inarg);
234 in.args[0].value = &inarg;
235 in.args[1].size = entry->d_name.len + 1;
236 in.args[1].value = entry->d_name.name;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000237 out.numargs = 1;
238 out.args[0].size = sizeof(outarg);
239 out.args[0].value = &outarg;
Miklos Szeredib483c932001-10-29 14:57:57 +0000240 request_send(fc, &in, &out);
Miklos Szeredie815c032004-01-19 18:20:49 +0000241 if(out.h.error)
242 return out.h.error;
Miklos Szeredib483c932001-10-29 14:57:57 +0000243
Miklos Szeredi76f65782004-02-19 16:55:40 +0000244 return lookup_new_entry(dir, entry, &outarg, out.h.unique, S_IFDIR);
Miklos Szeredib483c932001-10-29 14:57:57 +0000245}
246
247static int fuse_symlink(struct inode *dir, struct dentry *entry,
248 const char *link)
249{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000250 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredib483c932001-10-29 14:57:57 +0000251 struct fuse_in in = FUSE_IN_INIT;
252 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000253 struct fuse_entry_out outarg;
Miklos Szeredib483c932001-10-29 14:57:57 +0000254
255 in.h.opcode = FUSE_SYMLINK;
256 in.h.ino = dir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000257 in.numargs = 2;
258 in.args[0].size = entry->d_name.len + 1;
259 in.args[0].value = entry->d_name.name;
260 in.args[1].size = strlen(link) + 1;
261 in.args[1].value = link;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000262 out.numargs = 1;
263 out.args[0].size = sizeof(outarg);
264 out.args[0].value = &outarg;
Miklos Szeredib483c932001-10-29 14:57:57 +0000265 request_send(fc, &in, &out);
Miklos Szeredie815c032004-01-19 18:20:49 +0000266 if(out.h.error)
267 return out.h.error;
Miklos Szeredi43696432001-11-18 19:15:05 +0000268
Miklos Szeredi76f65782004-02-19 16:55:40 +0000269 return lookup_new_entry(dir, entry, &outarg, out.h.unique, S_IFLNK);
Miklos Szeredib483c932001-10-29 14:57:57 +0000270}
271
Miklos Szeredib5958612004-02-20 14:10:49 +0000272static int fuse_unlink(struct inode *dir, struct dentry *entry)
Miklos Szeredib483c932001-10-29 14:57:57 +0000273{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000274 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredib483c932001-10-29 14:57:57 +0000275 struct fuse_in in = FUSE_IN_INIT;
276 struct fuse_out out = FUSE_OUT_INIT;
277
Miklos Szeredib5958612004-02-20 14:10:49 +0000278 in.h.opcode = FUSE_UNLINK;
Miklos Szeredib483c932001-10-29 14:57:57 +0000279 in.h.ino = dir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000280 in.numargs = 1;
281 in.args[0].size = entry->d_name.len + 1;
282 in.args[0].value = entry->d_name.name;
Miklos Szeredib483c932001-10-29 14:57:57 +0000283 request_send(fc, &in, &out);
Miklos Szeredi43696432001-11-18 19:15:05 +0000284
Miklos Szeredib5958612004-02-20 14:10:49 +0000285 if(!out.h.error) {
286 /* Set nlink to zero so the inode can be cleared, if
287 the inode does have more links this will be
288 discovered at the next lookup/getattr */
289 /* FIXME: mark inode "not uptodate" */
290 entry->d_inode->i_nlink = 0;
Miklos Szeredif4f8b892004-01-27 17:04:59 +0000291 }
Miklos Szeredib5958612004-02-20 14:10:49 +0000292
293 return out.h.error;
Miklos Szeredib483c932001-10-29 14:57:57 +0000294}
295
296static int fuse_rmdir(struct inode *dir, struct dentry *entry)
297{
Miklos Szeredib5958612004-02-20 14:10:49 +0000298 struct fuse_conn *fc = INO_FC(dir);
299 struct fuse_in in = FUSE_IN_INIT;
300 struct fuse_out out = FUSE_OUT_INIT;
301
302 in.h.opcode = FUSE_RMDIR;
303 in.h.ino = dir->i_ino;
304 in.numargs = 1;
305 in.args[0].size = entry->d_name.len + 1;
306 in.args[0].value = entry->d_name.name;
307 request_send(fc, &in, &out);
308 if(!out.h.error)
Miklos Szeredif4f8b892004-01-27 17:04:59 +0000309 entry->d_inode->i_nlink = 0;
Miklos Szeredib5958612004-02-20 14:10:49 +0000310
311 return out.h.error;
Miklos Szeredib483c932001-10-29 14:57:57 +0000312}
313
314static int fuse_rename(struct inode *olddir, struct dentry *oldent,
315 struct inode *newdir, struct dentry *newent)
316{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000317 struct fuse_conn *fc = INO_FC(olddir);
Miklos Szeredib483c932001-10-29 14:57:57 +0000318 struct fuse_in in = FUSE_IN_INIT;
319 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi43696432001-11-18 19:15:05 +0000320 struct fuse_rename_in inarg;
Miklos Szeredib483c932001-10-29 14:57:57 +0000321
Miklos Szeredi43696432001-11-18 19:15:05 +0000322 memset(&inarg, 0, sizeof(inarg));
323 inarg.newdir = newdir->i_ino;
Miklos Szeredib483c932001-10-29 14:57:57 +0000324
325 in.h.opcode = FUSE_RENAME;
326 in.h.ino = olddir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000327 in.numargs = 3;
328 in.args[0].size = sizeof(inarg);
329 in.args[0].value = &inarg;
330 in.args[1].size = oldent->d_name.len + 1;
331 in.args[1].value = oldent->d_name.name;
332 in.args[2].size = newent->d_name.len + 1;
333 in.args[2].value = newent->d_name.name;
Miklos Szeredib483c932001-10-29 14:57:57 +0000334 request_send(fc, &in, &out);
Miklos Szeredib483c932001-10-29 14:57:57 +0000335
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000336 return out.h.error;
337}
338
339static int fuse_link(struct dentry *entry, struct inode *newdir,
340 struct dentry *newent)
341{
342 struct inode *inode = entry->d_inode;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000343 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000344 struct fuse_in in = FUSE_IN_INIT;
345 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi43696432001-11-18 19:15:05 +0000346 struct fuse_link_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000347 struct fuse_entry_out outarg;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000348
Miklos Szeredi43696432001-11-18 19:15:05 +0000349 memset(&inarg, 0, sizeof(inarg));
350 inarg.newdir = newdir->i_ino;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000351
352 in.h.opcode = FUSE_LINK;
353 in.h.ino = inode->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000354 in.numargs = 2;
355 in.args[0].size = sizeof(inarg);
356 in.args[0].value = &inarg;
357 in.args[1].size = newent->d_name.len + 1;
358 in.args[1].value = newent->d_name.name;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000359 out.numargs = 1;
360 out.args[0].size = sizeof(outarg);
361 out.args[0].value = &outarg;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000362 request_send(fc, &in, &out);
Miklos Szeredie815c032004-01-19 18:20:49 +0000363 if(out.h.error)
364 return out.h.error;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000365
Miklos Szeredie815c032004-01-19 18:20:49 +0000366 /* Invalidate old entry, so attributes are refreshed */
367 d_invalidate(entry);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000368 return lookup_new_entry(newdir, newent, &outarg, out.h.unique,
369 inode->i_mode);
Miklos Szeredib483c932001-10-29 14:57:57 +0000370}
371
Miklos Szeredif85ab242004-01-07 12:16:45 +0000372int fuse_do_getattr(struct inode *inode)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000373{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000374 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000375 struct fuse_in in = FUSE_IN_INIT;
376 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000377 struct fuse_attr_out arg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000378
379 in.h.opcode = FUSE_GETATTR;
380 in.h.ino = inode->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000381 out.numargs = 1;
382 out.args[0].size = sizeof(arg);
383 out.args[0].value = &arg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000384 request_send(fc, &in, &out);
385
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000386 if(!out.h.error)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000387 change_attributes(inode, &arg.attr);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000388
389 return out.h.error;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000390}
391
Miklos Szeredife25def2001-12-20 15:38:05 +0000392static int fuse_revalidate(struct dentry *entry)
393{
394 struct inode *inode = entry->d_inode;
395 struct fuse_conn *fc = INO_FC(inode);
396
397 if(inode->i_ino == FUSE_ROOT_INO) {
Miklos Szeredif85ab242004-01-07 12:16:45 +0000398 if(!(fc->flags & FUSE_ALLOW_OTHER) &&
399 current->fsuid != fc->uid)
Miklos Szeredife25def2001-12-20 15:38:05 +0000400 return -EACCES;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000401 } else if(!entry->d_time || time_before_eq(jiffies, entry->d_time))
Miklos Szeredife25def2001-12-20 15:38:05 +0000402 return 0;
403
Miklos Szeredif85ab242004-01-07 12:16:45 +0000404 return fuse_do_getattr(inode);
Miklos Szeredife25def2001-12-20 15:38:05 +0000405}
406
Miklos Szeredif85ab242004-01-07 12:16:45 +0000407static int _fuse_permission(struct inode *inode, int mask)
Miklos Szeredife25def2001-12-20 15:38:05 +0000408{
409 struct fuse_conn *fc = INO_FC(inode);
410
411 if(!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->uid)
412 return -EACCES;
413 else if(fc->flags & FUSE_DEFAULT_PERMISSIONS) {
414 int err = vfs_permission(inode, mask);
415
416 /* If permission is denied, try to refresh file
417 attributes. This is also needed, because the root
418 node will at first have no permissions */
419
420 if(err == -EACCES) {
Miklos Szeredif85ab242004-01-07 12:16:45 +0000421 err = fuse_do_getattr(inode);
Miklos Szeredife25def2001-12-20 15:38:05 +0000422 if(!err)
423 err = vfs_permission(inode, mask);
424 }
425
426 /* FIXME: Need some mechanism to revoke permissions:
427 currently if the filesystem suddenly changes the
428 file mode, we will not be informed abot that, and
429 continue to allow access to the file/directory.
430
431 This is actually not so grave, since the user can
432 simply keep access to the file/directory anyway by
433 keeping it open... */
434
435 return err;
Miklos Szeredi69cc79a2004-02-17 08:57:29 +0000436 } else
Miklos Szeredife25def2001-12-20 15:38:05 +0000437 return 0;
438}
439
Miklos Szeredib483c932001-10-29 14:57:57 +0000440static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
441 void *dstbuf, filldir_t filldir)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000442{
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000443 while(nbytes >= FUSE_NAME_OFFSET) {
Miklos Szeredib483c932001-10-29 14:57:57 +0000444 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000445 size_t reclen = FUSE_DIRENT_SIZE(dirent);
446 int over;
447 if(dirent->namelen > NAME_MAX) {
448 printk("fuse_readdir: name too long\n");
Miklos Szeredib483c932001-10-29 14:57:57 +0000449 return -EPROTO;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000450 }
451 if(reclen > nbytes)
452 break;
453
454 over = filldir(dstbuf, dirent->name, dirent->namelen,
455 file->f_pos, dirent->ino, dirent->type);
456 if(over)
457 break;
458
Miklos Szeredib483c932001-10-29 14:57:57 +0000459 buf += reclen;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000460 file->f_pos += reclen;
461 nbytes -= reclen;
462 }
463
Miklos Szeredib483c932001-10-29 14:57:57 +0000464 return 0;
465}
466
467#define DIR_BUFSIZE 2048
468static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
469{
470 struct file *cfile = file->private_data;
471 char *buf;
472 int ret;
Miklos Szeredie815c032004-01-19 18:20:49 +0000473
474 if(!cfile)
475 return -EISDIR;
476
Miklos Szeredib483c932001-10-29 14:57:57 +0000477 buf = kmalloc(DIR_BUFSIZE, GFP_KERNEL);
478 if(!buf)
479 return -ENOMEM;
Miklos Szeredie815c032004-01-19 18:20:49 +0000480
Miklos Szeredib483c932001-10-29 14:57:57 +0000481 ret = kernel_read(cfile, file->f_pos, buf, DIR_BUFSIZE);
482 if(ret < 0)
483 printk("fuse_readdir: failed to read container file\n");
484 else
485 ret = parse_dirfile(buf, ret, file, dstbuf, filldir);
486
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000487 kfree(buf);
488 return ret;
489}
490
Miklos Szeredi05033042001-11-13 16:11:35 +0000491static char *read_link(struct dentry *dentry)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000492{
493 struct inode *inode = dentry->d_inode;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000494 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000495 struct fuse_in in = FUSE_IN_INIT;
496 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi05033042001-11-13 16:11:35 +0000497 char *link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000498
Miklos Szeredi05033042001-11-13 16:11:35 +0000499 link = (char *) __get_free_page(GFP_KERNEL);
500 if(!link)
501 return ERR_PTR(-ENOMEM);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000502
503 in.h.opcode = FUSE_READLINK;
504 in.h.ino = inode->i_ino;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000505 out.argvar = 1;
Miklos Szeredi43696432001-11-18 19:15:05 +0000506 out.numargs = 1;
507 out.args[0].size = PAGE_SIZE - 1;
508 out.args[0].value = link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000509 request_send(fc, &in, &out);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000510 if(out.h.error) {
Miklos Szeredi05033042001-11-13 16:11:35 +0000511 free_page((unsigned long) link);
512 return ERR_PTR(out.h.error);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000513 }
514
Miklos Szeredi43696432001-11-18 19:15:05 +0000515 link[out.args[0].size] = '\0';
Miklos Szeredi05033042001-11-13 16:11:35 +0000516 return link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000517}
518
519static void free_link(char *link)
520{
Miklos Szeredi05033042001-11-13 16:11:35 +0000521 if(!IS_ERR(link))
522 free_page((unsigned long) link);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000523}
524
525static int fuse_readlink(struct dentry *dentry, char *buffer, int buflen)
526{
527 int ret;
528 char *link;
529
Miklos Szeredi05033042001-11-13 16:11:35 +0000530 link = read_link(dentry);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000531 ret = vfs_readlink(dentry, buffer, buflen, link);
532 free_link(link);
533 return ret;
534}
535
536static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
537{
538 int ret;
539 char *link;
540
Miklos Szeredi05033042001-11-13 16:11:35 +0000541 link = read_link(dentry);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000542 ret = vfs_follow_link(nd, link);
543 free_link(link);
544 return ret;
545}
546
547static int fuse_dir_open(struct inode *inode, struct file *file)
548{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000549 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000550 struct fuse_in in = FUSE_IN_INIT;
551 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000552 struct fuse_getdir_out_i outarg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000553
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000554 in.h.opcode = FUSE_GETDIR;
555 in.h.ino = inode->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000556 out.numargs = 1;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000557 out.args[0].size = sizeof(struct fuse_getdir_out);
Miklos Szeredi43696432001-11-18 19:15:05 +0000558 out.args[0].value = &outarg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000559 request_send(fc, &in, &out);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000560 if(!out.h.error) {
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000561 struct file *cfile = outarg.file;
562 struct inode *inode;
563 if(!cfile) {
564 printk("fuse_getdir: invalid file\n");
565 return -EPROTO;
566 }
567 inode = cfile->f_dentry->d_inode;
568 if(!S_ISREG(inode->i_mode)) {
569 printk("fuse_getdir: not a regular file\n");
570 fput(cfile);
571 return -EPROTO;
572 }
573
574 file->private_data = cfile;
575 }
576
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000577 return out.h.error;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000578}
579
580static int fuse_dir_release(struct inode *inode, struct file *file)
581{
582 struct file *cfile = file->private_data;
Miklos Szeredia181e612001-11-06 12:03:23 +0000583
584 if(cfile)
585 fput(cfile);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000586
587 return 0;
588}
589
Miklos Szeredi5e183482001-10-31 14:52:35 +0000590static unsigned int iattr_to_fattr(struct iattr *iattr,
591 struct fuse_attr *fattr)
592{
593 unsigned int ivalid = iattr->ia_valid;
594 unsigned int fvalid = 0;
595
596 memset(fattr, 0, sizeof(*fattr));
597
598 if(ivalid & ATTR_MODE)
599 fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode;
600 if(ivalid & ATTR_UID)
601 fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid;
602 if(ivalid & ATTR_GID)
603 fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid;
604 if(ivalid & ATTR_SIZE)
605 fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
606 /* You can only _set_ these together (they may change by themselves) */
607 if((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
Miklos Szeredib5958612004-02-20 14:10:49 +0000608 fvalid |= FATTR_ATIME | FATTR_MTIME;
Miklos Szeredif85ab242004-01-07 12:16:45 +0000609#ifdef KERNEL_2_6
610 fattr->atime = iattr->ia_atime.tv_sec;
611 fattr->mtime = iattr->ia_mtime.tv_sec;
612#else
Miklos Szeredi5e183482001-10-31 14:52:35 +0000613 fattr->atime = iattr->ia_atime;
614 fattr->mtime = iattr->ia_mtime;
Miklos Szeredif85ab242004-01-07 12:16:45 +0000615#endif
Miklos Szeredi5e183482001-10-31 14:52:35 +0000616 }
617
618 return fvalid;
619}
620
621static int fuse_setattr(struct dentry *entry, struct iattr *attr)
622{
623 struct inode *inode = entry->d_inode;
624 struct fuse_conn *fc = INO_FC(inode);
625 struct fuse_in in = FUSE_IN_INIT;
626 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000627 struct fuse_setattr_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000628 struct fuse_attr_out outarg;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000629
Miklos Szeredi43696432001-11-18 19:15:05 +0000630 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredia181e612001-11-06 12:03:23 +0000631 inarg.valid = iattr_to_fattr(attr, &inarg.attr);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000632
633 in.h.opcode = FUSE_SETATTR;
634 in.h.ino = inode->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000635 in.numargs = 1;
636 in.args[0].size = sizeof(inarg);
637 in.args[0].value = &inarg;
638 out.numargs = 1;
639 out.args[0].size = sizeof(outarg);
640 out.args[0].value = &outarg;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000641 request_send(fc, &in, &out);
642
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000643 if(!out.h.error) {
644 if(attr->ia_valid & ATTR_SIZE &&
Miklos Szeredid1199f82004-02-06 15:29:22 +0000645 outarg.attr.size < i_size_read(inode))
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000646 vmtruncate(inode, outarg.attr.size);
Miklos Szeredia181e612001-11-06 12:03:23 +0000647
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000648 change_attributes(inode, &outarg.attr);
649 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000650 return out.h.error;
651}
652
Miklos Szeredif85ab242004-01-07 12:16:45 +0000653static int _fuse_dentry_revalidate(struct dentry *entry)
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000654{
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000655 if(!entry->d_inode)
656 return 0;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000657 else if(entry->d_time && time_after(jiffies, entry->d_time)) {
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000658 struct inode *inode = entry->d_inode;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000659 struct fuse_entry_out outarg;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000660 int version;
661 int ret;
662
663 ret = fuse_do_lookup(entry->d_parent->d_inode, entry, &outarg,
664 &version);
665 if(ret)
666 return 0;
667
668 if(outarg.ino != inode->i_ino)
669 return 0;
670
671 change_attributes(inode, &outarg.attr);
672 inode->i_version = version;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000673 entry->d_time = time_to_jiffies(outarg.entry_valid,
674 outarg.entry_valid_nsec);
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000675 }
676 return 1;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000677}
678
Miklos Szeredif85ab242004-01-07 12:16:45 +0000679#ifdef KERNEL_2_6
680
681#define fuse_mknod _fuse_mknod
682
683static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
684 struct kstat *stat)
685{
686 struct inode *inode = entry->d_inode;
687 int err = fuse_revalidate(entry);
688 if(!err)
689 generic_fillattr(inode, stat);
690
691 return err;
692}
693
694static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
695 struct nameidata *nd)
696{
Miklos Szeredie815c032004-01-19 18:20:49 +0000697 struct inode *inode;
698 int err = fuse_lookup_iget(dir, entry, &inode);
699 if (err)
700 return ERR_PTR(err);
701 return d_splice_alias(inode, entry);
Miklos Szeredif85ab242004-01-07 12:16:45 +0000702}
703
704static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
705 struct nameidata *nd)
706{
707 return _fuse_create(dir, entry, mode);
708}
709
710static int fuse_permission(struct inode *inode, int mask,
711 struct nameidata *nd)
712{
713 return _fuse_permission(inode, mask);
714}
715
716static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
717{
718 return _fuse_dentry_revalidate(entry);
719}
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000720
721static int fuse_setxattr(struct dentry *entry, const char *name,
722 const void *value, size_t size, int flags)
723{
724 struct inode *inode = entry->d_inode;
725 struct fuse_conn *fc = INO_FC(inode);
726 struct fuse_in in = FUSE_IN_INIT;
727 struct fuse_out out = FUSE_OUT_INIT;
728 struct fuse_setxattr_in inarg;
729
730 memset(&inarg, 0, sizeof(inarg));
731 inarg.size = size;
732 inarg.flags = flags;
733
734 in.h.opcode = FUSE_SETXATTR;
735 in.h.ino = inode->i_ino;
736 in.numargs = 3;
737 in.args[0].size = sizeof(inarg);
738 in.args[0].value = &inarg;
739 in.args[1].size = strlen(name) + 1;
740 in.args[1].value = name;
741 in.args[2].size = size;
742 in.args[2].value = value;
743 request_send(fc, &in, &out);
744 return out.h.error;
745}
746
747static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
748 void *value, size_t size)
749{
750 struct inode *inode = entry->d_inode;
751 struct fuse_conn *fc = INO_FC(inode);
752 struct fuse_in in = FUSE_IN_INIT;
753 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000754 struct fuse_getxattr_in inarg;
755 struct fuse_getxattr_out outarg;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000756
757 memset(&inarg, 0, sizeof(inarg));
758 inarg.size = size;
759
760 in.h.opcode = FUSE_GETXATTR;
761 in.h.ino = inode->i_ino;
762 in.numargs = 2;
763 in.args[0].size = sizeof(inarg);
764 in.args[0].value = &inarg;
765 in.args[1].size = strlen(name) + 1;
766 in.args[1].value = name;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000767 /* This is really two different operations rolled into one */
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000768 out.numargs = 1;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000769 if(size) {
770 out.argvar = 1;
771 out.args[0].size = size;
772 out.args[0].value = value;
773 } else {
774 out.args[0].size = sizeof(outarg);
775 out.args[0].value = &outarg;
776 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000777 request_send(fc, &in, &out);
778 if(!out.h.error)
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000779 return size ? out.args[0].size : outarg.size;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000780 else
781 return out.h.error;
782}
783
784static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
785{
786 struct inode *inode = entry->d_inode;
787 struct fuse_conn *fc = INO_FC(inode);
788 struct fuse_in in = FUSE_IN_INIT;
789 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000790 struct fuse_getxattr_in inarg;
791 struct fuse_getxattr_out outarg;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000792
793 memset(&inarg, 0, sizeof(inarg));
794 inarg.size = size;
795
796 in.h.opcode = FUSE_LISTXATTR;
797 in.h.ino = inode->i_ino;
798 in.numargs = 1;
799 in.args[0].size = sizeof(inarg);
800 in.args[0].value = &inarg;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000801 /* This is really two different operations rolled into one */
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000802 out.numargs = 1;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000803 if(size) {
804 out.argvar = 1;
805 out.args[0].size = size;
806 out.args[0].value = list;
807 } else {
808 out.args[0].size = sizeof(outarg);
809 out.args[0].value = &outarg;
810 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000811 request_send(fc, &in, &out);
812 if(!out.h.error)
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000813 return size ? out.args[0].size : outarg.size;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000814 else
815 return out.h.error;
816}
817
818static int fuse_removexattr(struct dentry *entry, const char *name)
819{
820 struct inode *inode = entry->d_inode;
821 struct fuse_conn *fc = INO_FC(inode);
822 struct fuse_in in = FUSE_IN_INIT;
823 struct fuse_out out = FUSE_OUT_INIT;
824
825 in.h.opcode = FUSE_REMOVEXATTR;
826 in.h.ino = inode->i_ino;
827 in.numargs = 1;
828 in.args[0].size = strlen(name) + 1;
829 in.args[0].value = name;
830 request_send(fc, &in, &out);
831 return out.h.error;
832
833}
834
Miklos Szeredif85ab242004-01-07 12:16:45 +0000835#else /* KERNEL_2_6 */
836
Miklos Szeredif85ab242004-01-07 12:16:45 +0000837#define fuse_create _fuse_create
838#define fuse_permission _fuse_permission
839
Miklos Szeredie815c032004-01-19 18:20:49 +0000840static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry)
841{
842 struct inode *inode;
843 struct dentry *alias;
844
845 int err = fuse_lookup_iget(dir, entry, &inode);
846 if(err)
847 return ERR_PTR(err);
848
849 if(inode && S_ISDIR(inode->i_mode) &&
850 (alias = d_find_alias(inode)) != NULL) {
851 dput(alias);
852 iput(inode);
853 printk("fuse: cannot assign an existing directory\n");
Miklos Szeredid23b70a2004-01-26 12:17:53 +0000854 return ERR_PTR(-EPROTO);
Miklos Szeredie815c032004-01-19 18:20:49 +0000855 }
856
857 d_add(entry, inode);
858 return NULL;
859}
860
Miklos Szeredif85ab242004-01-07 12:16:45 +0000861static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
862 int rdev)
863{
864 return fuse_mknod(dir, entry, mode, rdev);
865}
866
867static int fuse_dentry_revalidate(struct dentry *entry, int flags)
868{
869 return _fuse_dentry_revalidate(entry);
870}
871#endif /* KERNEL_2_6 */
872
873
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000874static struct inode_operations fuse_dir_inode_operations =
875{
Miklos Szeredie8663f32004-01-13 15:33:12 +0000876 .lookup = fuse_lookup,
877 .create = fuse_create,
878 .mknod = fuse_mknod,
879 .mkdir = fuse_mkdir,
880 .symlink = fuse_symlink,
881 .unlink = fuse_unlink,
882 .rmdir = fuse_rmdir,
883 .rename = fuse_rename,
884 .link = fuse_link,
885 .setattr = fuse_setattr,
886 .permission = fuse_permission,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000887#ifdef KERNEL_2_6
Miklos Szeredie8663f32004-01-13 15:33:12 +0000888 .getattr = fuse_getattr,
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000889 .setxattr = fuse_setxattr,
890 .getxattr = fuse_getxattr,
891 .listxattr = fuse_listxattr,
892 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000893#else
Miklos Szeredie8663f32004-01-13 15:33:12 +0000894 .revalidate = fuse_revalidate,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000895#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000896};
897
898static struct file_operations fuse_dir_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +0000899 .read = generic_read_dir,
900 .readdir = fuse_readdir,
901 .open = fuse_dir_open,
902 .release = fuse_dir_release,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000903};
904
905static struct inode_operations fuse_file_inode_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +0000906 .setattr = fuse_setattr,
907 .permission = fuse_permission,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000908#ifdef KERNEL_2_6
Miklos Szeredie8663f32004-01-13 15:33:12 +0000909 .getattr = fuse_getattr,
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000910 .setxattr = fuse_setxattr,
911 .getxattr = fuse_getxattr,
912 .listxattr = fuse_listxattr,
913 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000914#else
Miklos Szeredie8663f32004-01-13 15:33:12 +0000915 .revalidate = fuse_revalidate,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000916#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000917};
918
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000919static struct inode_operations fuse_symlink_inode_operations =
920{
Miklos Szeredie8663f32004-01-13 15:33:12 +0000921 .setattr = fuse_setattr,
922 .readlink = fuse_readlink,
923 .follow_link = fuse_follow_link,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000924#ifdef KERNEL_2_6
Miklos Szeredie8663f32004-01-13 15:33:12 +0000925 .getattr = fuse_getattr,
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000926 .setxattr = fuse_setxattr,
927 .getxattr = fuse_getxattr,
928 .listxattr = fuse_listxattr,
929 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000930#else
Miklos Szeredie8663f32004-01-13 15:33:12 +0000931 .revalidate = fuse_revalidate,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000932#endif
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000933};
934
Miklos Szeredi307242f2004-01-26 11:28:44 +0000935static struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +0000936 .d_revalidate = fuse_dentry_revalidate,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000937};
938
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000939/*
940 * Local Variables:
941 * indent-tabs-mode: t
942 * c-basic-offset: 8
943 * End:
944 */