blob: 9e2ac335c17397cc5dab4ae6ee696978499a4b10 [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 Szeredic26c14d2004-04-09 17:48:32 +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 Szeredic26c14d2004-04-09 17:48:32 +000063 if (S_ISREG(inode->i_mode)) {
Miklos Szeredib483c932001-10-29 14:57:57 +000064 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 }
Miklos Szeredic26c14d2004-04-09 17:48:32 +000067 else if (S_ISDIR(inode->i_mode)) {
Miklos Szeredib483c932001-10-29 14:57:57 +000068 inode->i_op = &fuse_dir_inode_operations;
69 inode->i_fop = &fuse_dir_operations;
70 }
Miklos Szeredic26c14d2004-04-09 17:48:32 +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 Szeredic26c14d2004-04-09 17:48:32 +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);
Miklos Szeredic26c14d2004-04-09 17:48:32 +000091 if (inode) {
92 if (!inode->u.generic_ip) {
Miklos Szeredi76f65782004-02-19 16:55:40 +000093 inode->i_generation = generation;
Miklos Szeredia181e612001-11-06 12:03:23 +000094 fuse_init_inode(inode, attr);
Miklos Szeredic26c14d2004-04-09 17:48:32 +000095 } else if (inode->i_generation != generation)
Miklos Szeredi76f65782004-02-19 16:55:40 +000096 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 Szeredic26c14d2004-04-09 17:48:32 +0000112
113 if (entry->d_name.len > FUSE_NAME_MAX)
114 return -ENAMETOOLONG;
115
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000116 in.h.opcode = FUSE_LOOKUP;
117 in.h.ino = dir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000118 in.numargs = 1;
119 in.args[0].size = entry->d_name.len + 1;
120 in.args[0].value = entry->d_name.name;
121 out.numargs = 1;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000122 out.args[0].size = sizeof(struct fuse_entry_out);
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000123 out.args[0].value = outarg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000124 request_send(fc, &in, &out);
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000125
126 *version = out.h.unique;
127 return out.h.error;
128}
129
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000130static inline unsigned long time_to_jiffies(unsigned long sec,
131 unsigned long nsec)
132{
133 /* prevent wrapping of jiffies */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000134 if (sec + 1 >= LONG_MAX / HZ)
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000135 return 0;
136
137 return jiffies + sec * HZ + nsec / (1000000000 / HZ);
138}
139
Miklos Szeredie815c032004-01-19 18:20:49 +0000140static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
141 struct inode **inodep)
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000142{
Miklos Szeredie815c032004-01-19 18:20:49 +0000143 int err;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000144 struct fuse_entry_out outarg;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000145 int version;
Miklos Szeredie815c032004-01-19 18:20:49 +0000146 struct inode *inode = NULL;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000147
Miklos Szeredie815c032004-01-19 18:20:49 +0000148 err = fuse_do_lookup(dir, entry, &outarg, &version);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000149 if (!err) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000150 inode = fuse_iget(dir->i_sb, outarg.ino, outarg.generation,
151 &outarg.attr, version);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000152 if (!inode)
Miklos Szeredie815c032004-01-19 18:20:49 +0000153 return -ENOMEM;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000154 } else if (err != -ENOENT)
Miklos Szeredie815c032004-01-19 18:20:49 +0000155 return err;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000156
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000157 entry->d_time = time_to_jiffies(outarg.entry_valid,
158 outarg.entry_valid_nsec);
Miklos Szeredi307242f2004-01-26 11:28:44 +0000159 entry->d_op = &fuse_dentry_operations;
Miklos Szeredie815c032004-01-19 18:20:49 +0000160 *inodep = inode;
161 return 0;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000162}
163
Miklos Szeredi76f65782004-02-19 16:55:40 +0000164static int lookup_new_entry(struct inode *dir, struct dentry *entry,
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000165 struct fuse_entry_out *outarg, int version,
Miklos Szeredi76f65782004-02-19 16:55:40 +0000166 int mode)
167{
168 struct inode *inode;
169 inode = fuse_iget(dir->i_sb, outarg->ino, outarg->generation,
170 &outarg->attr, version);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000171 if (!inode)
Miklos Szeredi76f65782004-02-19 16:55:40 +0000172 return -ENOMEM;
173
174 /* Don't allow userspace to do really stupid things... */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000175 if ((inode->i_mode ^ mode) & S_IFMT) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000176 iput(inode);
177 printk("fuse_mknod: inode has wrong type\n");
178 return -EINVAL;
179 }
180
181 d_instantiate(entry, inode);
182 return 0;
183}
184
185
Miklos Szeredif85ab242004-01-07 12:16:45 +0000186static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
187 dev_t rdev)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000188{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000189 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000190 struct fuse_in in = FUSE_IN_INIT;
191 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi43696432001-11-18 19:15:05 +0000192 struct fuse_mknod_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000193 struct fuse_entry_out outarg;
Miklos Szeredi43696432001-11-18 19:15:05 +0000194
195 memset(&inarg, 0, sizeof(inarg));
196 inarg.mode = mode;
Miklos Szeredi7c35cf92004-01-14 16:56:49 +0000197 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000198
199 in.h.opcode = FUSE_MKNOD;
200 in.h.ino = dir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000201 in.numargs = 2;
202 in.args[0].size = sizeof(inarg);
203 in.args[0].value = &inarg;
204 in.args[1].size = entry->d_name.len + 1;
205 in.args[1].value = entry->d_name.name;
206 out.numargs = 1;
207 out.args[0].size = sizeof(outarg);
208 out.args[0].value = &outarg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000209 request_send(fc, &in, &out);
Miklos Szeredib483c932001-10-29 14:57:57 +0000210
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000211 if (out.h.error)
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000212 return out.h.error;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000213
Miklos Szeredi76f65782004-02-19 16:55:40 +0000214 return lookup_new_entry(dir, entry, &outarg, out.h.unique, mode);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000215}
216
Miklos Szeredif85ab242004-01-07 12:16:45 +0000217static int _fuse_create(struct inode *dir, struct dentry *entry, int mode)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000218{
Miklos Szeredif85ab242004-01-07 12:16:45 +0000219 return _fuse_mknod(dir, entry, mode, 0);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000220}
221
Miklos Szeredie815c032004-01-19 18:20:49 +0000222
Miklos Szeredib483c932001-10-29 14:57:57 +0000223static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
224{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000225 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredib483c932001-10-29 14:57:57 +0000226 struct fuse_in in = FUSE_IN_INIT;
227 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi43696432001-11-18 19:15:05 +0000228 struct fuse_mkdir_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000229 struct fuse_entry_out outarg;
Miklos Szeredi43696432001-11-18 19:15:05 +0000230
231 memset(&inarg, 0, sizeof(inarg));
232 inarg.mode = mode;
Miklos Szeredib483c932001-10-29 14:57:57 +0000233
234 in.h.opcode = FUSE_MKDIR;
235 in.h.ino = dir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000236 in.numargs = 2;
237 in.args[0].size = sizeof(inarg);
238 in.args[0].value = &inarg;
239 in.args[1].size = entry->d_name.len + 1;
240 in.args[1].value = entry->d_name.name;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000241 out.numargs = 1;
242 out.args[0].size = sizeof(outarg);
243 out.args[0].value = &outarg;
Miklos Szeredib483c932001-10-29 14:57:57 +0000244 request_send(fc, &in, &out);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000245 if (out.h.error)
Miklos Szeredie815c032004-01-19 18:20:49 +0000246 return out.h.error;
Miklos Szeredib483c932001-10-29 14:57:57 +0000247
Miklos Szeredi76f65782004-02-19 16:55:40 +0000248 return lookup_new_entry(dir, entry, &outarg, out.h.unique, S_IFDIR);
Miklos Szeredib483c932001-10-29 14:57:57 +0000249}
250
251static int fuse_symlink(struct inode *dir, struct dentry *entry,
252 const char *link)
253{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000254 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredib483c932001-10-29 14:57:57 +0000255 struct fuse_in in = FUSE_IN_INIT;
256 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000257 struct fuse_entry_out outarg;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000258 unsigned int len = strlen(link) + 1;
259
260 if (len > FUSE_SYMLINK_MAX)
261 return -ENAMETOOLONG;
Miklos Szeredib483c932001-10-29 14:57:57 +0000262
263 in.h.opcode = FUSE_SYMLINK;
264 in.h.ino = dir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000265 in.numargs = 2;
266 in.args[0].size = entry->d_name.len + 1;
267 in.args[0].value = entry->d_name.name;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000268 in.args[1].size = len;
Miklos Szeredi43696432001-11-18 19:15:05 +0000269 in.args[1].value = link;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000270 out.numargs = 1;
271 out.args[0].size = sizeof(outarg);
272 out.args[0].value = &outarg;
Miklos Szeredib483c932001-10-29 14:57:57 +0000273 request_send(fc, &in, &out);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000274 if (out.h.error)
Miklos Szeredie815c032004-01-19 18:20:49 +0000275 return out.h.error;
Miklos Szeredi43696432001-11-18 19:15:05 +0000276
Miklos Szeredi76f65782004-02-19 16:55:40 +0000277 return lookup_new_entry(dir, entry, &outarg, out.h.unique, S_IFLNK);
Miklos Szeredib483c932001-10-29 14:57:57 +0000278}
279
Miklos Szeredib5958612004-02-20 14:10:49 +0000280static int fuse_unlink(struct inode *dir, struct dentry *entry)
Miklos Szeredib483c932001-10-29 14:57:57 +0000281{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000282 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredib483c932001-10-29 14:57:57 +0000283 struct fuse_in in = FUSE_IN_INIT;
284 struct fuse_out out = FUSE_OUT_INIT;
285
Miklos Szeredib5958612004-02-20 14:10:49 +0000286 in.h.opcode = FUSE_UNLINK;
Miklos Szeredib483c932001-10-29 14:57:57 +0000287 in.h.ino = dir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000288 in.numargs = 1;
289 in.args[0].size = entry->d_name.len + 1;
290 in.args[0].value = entry->d_name.name;
Miklos Szeredib483c932001-10-29 14:57:57 +0000291 request_send(fc, &in, &out);
Miklos Szeredi43696432001-11-18 19:15:05 +0000292
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000293 if (!out.h.error) {
Miklos Szeredib5958612004-02-20 14:10:49 +0000294 /* Set nlink to zero so the inode can be cleared, if
295 the inode does have more links this will be
296 discovered at the next lookup/getattr */
297 /* FIXME: mark inode "not uptodate" */
298 entry->d_inode->i_nlink = 0;
Miklos Szeredif4f8b892004-01-27 17:04:59 +0000299 }
Miklos Szeredib5958612004-02-20 14:10:49 +0000300
301 return out.h.error;
Miklos Szeredib483c932001-10-29 14:57:57 +0000302}
303
304static int fuse_rmdir(struct inode *dir, struct dentry *entry)
305{
Miklos Szeredib5958612004-02-20 14:10:49 +0000306 struct fuse_conn *fc = INO_FC(dir);
307 struct fuse_in in = FUSE_IN_INIT;
308 struct fuse_out out = FUSE_OUT_INIT;
309
310 in.h.opcode = FUSE_RMDIR;
311 in.h.ino = dir->i_ino;
312 in.numargs = 1;
313 in.args[0].size = entry->d_name.len + 1;
314 in.args[0].value = entry->d_name.name;
315 request_send(fc, &in, &out);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000316 if (!out.h.error)
Miklos Szeredif4f8b892004-01-27 17:04:59 +0000317 entry->d_inode->i_nlink = 0;
Miklos Szeredib5958612004-02-20 14:10:49 +0000318
319 return out.h.error;
Miklos Szeredib483c932001-10-29 14:57:57 +0000320}
321
322static int fuse_rename(struct inode *olddir, struct dentry *oldent,
323 struct inode *newdir, struct dentry *newent)
324{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000325 struct fuse_conn *fc = INO_FC(olddir);
Miklos Szeredib483c932001-10-29 14:57:57 +0000326 struct fuse_in in = FUSE_IN_INIT;
327 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi43696432001-11-18 19:15:05 +0000328 struct fuse_rename_in inarg;
Miklos Szeredib483c932001-10-29 14:57:57 +0000329
Miklos Szeredi43696432001-11-18 19:15:05 +0000330 memset(&inarg, 0, sizeof(inarg));
331 inarg.newdir = newdir->i_ino;
Miklos Szeredib483c932001-10-29 14:57:57 +0000332
333 in.h.opcode = FUSE_RENAME;
334 in.h.ino = olddir->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000335 in.numargs = 3;
336 in.args[0].size = sizeof(inarg);
337 in.args[0].value = &inarg;
338 in.args[1].size = oldent->d_name.len + 1;
339 in.args[1].value = oldent->d_name.name;
340 in.args[2].size = newent->d_name.len + 1;
341 in.args[2].value = newent->d_name.name;
Miklos Szeredib483c932001-10-29 14:57:57 +0000342 request_send(fc, &in, &out);
Miklos Szeredib483c932001-10-29 14:57:57 +0000343
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000344 return out.h.error;
345}
346
347static int fuse_link(struct dentry *entry, struct inode *newdir,
348 struct dentry *newent)
349{
350 struct inode *inode = entry->d_inode;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000351 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000352 struct fuse_in in = FUSE_IN_INIT;
353 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi43696432001-11-18 19:15:05 +0000354 struct fuse_link_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000355 struct fuse_entry_out outarg;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000356
Miklos Szeredi43696432001-11-18 19:15:05 +0000357 memset(&inarg, 0, sizeof(inarg));
358 inarg.newdir = newdir->i_ino;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000359
360 in.h.opcode = FUSE_LINK;
361 in.h.ino = inode->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000362 in.numargs = 2;
363 in.args[0].size = sizeof(inarg);
364 in.args[0].value = &inarg;
365 in.args[1].size = newent->d_name.len + 1;
366 in.args[1].value = newent->d_name.name;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000367 out.numargs = 1;
368 out.args[0].size = sizeof(outarg);
369 out.args[0].value = &outarg;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000370 request_send(fc, &in, &out);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000371 if (out.h.error)
Miklos Szeredie815c032004-01-19 18:20:49 +0000372 return out.h.error;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000373
Miklos Szeredie815c032004-01-19 18:20:49 +0000374 /* Invalidate old entry, so attributes are refreshed */
375 d_invalidate(entry);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000376 return lookup_new_entry(newdir, newent, &outarg, out.h.unique,
377 inode->i_mode);
Miklos Szeredib483c932001-10-29 14:57:57 +0000378}
379
Miklos Szeredif85ab242004-01-07 12:16:45 +0000380int fuse_do_getattr(struct inode *inode)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000381{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000382 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000383 struct fuse_in in = FUSE_IN_INIT;
384 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000385 struct fuse_attr_out arg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000386
387 in.h.opcode = FUSE_GETATTR;
388 in.h.ino = inode->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000389 out.numargs = 1;
390 out.args[0].size = sizeof(arg);
391 out.args[0].value = &arg;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000392 request_send(fc, &in, &out);
393
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000394 if (!out.h.error)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000395 change_attributes(inode, &arg.attr);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000396
397 return out.h.error;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000398}
399
Miklos Szeredife25def2001-12-20 15:38:05 +0000400static int fuse_revalidate(struct dentry *entry)
401{
402 struct inode *inode = entry->d_inode;
403 struct fuse_conn *fc = INO_FC(inode);
404
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000405 if (inode->i_ino == FUSE_ROOT_INO) {
406 if (!(fc->flags & FUSE_ALLOW_OTHER) &&
407 current->fsuid != fc->uid)
Miklos Szeredife25def2001-12-20 15:38:05 +0000408 return -EACCES;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000409 } else if (!entry->d_time || time_before_eq(jiffies, entry->d_time))
Miklos Szeredife25def2001-12-20 15:38:05 +0000410 return 0;
411
Miklos Szeredif85ab242004-01-07 12:16:45 +0000412 return fuse_do_getattr(inode);
Miklos Szeredife25def2001-12-20 15:38:05 +0000413}
414
Miklos Szeredif85ab242004-01-07 12:16:45 +0000415static int _fuse_permission(struct inode *inode, int mask)
Miklos Szeredife25def2001-12-20 15:38:05 +0000416{
417 struct fuse_conn *fc = INO_FC(inode);
418
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000419 if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->uid)
Miklos Szeredife25def2001-12-20 15:38:05 +0000420 return -EACCES;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000421 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Miklos Szeredife25def2001-12-20 15:38:05 +0000422 int err = vfs_permission(inode, mask);
423
424 /* If permission is denied, try to refresh file
425 attributes. This is also needed, because the root
426 node will at first have no permissions */
427
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000428 if (err == -EACCES) {
Miklos Szeredif85ab242004-01-07 12:16:45 +0000429 err = fuse_do_getattr(inode);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000430 if (!err)
Miklos Szeredife25def2001-12-20 15:38:05 +0000431 err = vfs_permission(inode, mask);
432 }
433
434 /* FIXME: Need some mechanism to revoke permissions:
435 currently if the filesystem suddenly changes the
436 file mode, we will not be informed abot that, and
437 continue to allow access to the file/directory.
438
439 This is actually not so grave, since the user can
440 simply keep access to the file/directory anyway by
441 keeping it open... */
442
443 return err;
Miklos Szeredi69cc79a2004-02-17 08:57:29 +0000444 } else
Miklos Szeredife25def2001-12-20 15:38:05 +0000445 return 0;
446}
447
Miklos Szeredib483c932001-10-29 14:57:57 +0000448static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
449 void *dstbuf, filldir_t filldir)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000450{
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000451 while (nbytes >= FUSE_NAME_OFFSET) {
Miklos Szeredib483c932001-10-29 14:57:57 +0000452 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000453 size_t reclen = FUSE_DIRENT_SIZE(dirent);
454 int over;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000455 if (dirent->namelen > NAME_MAX) {
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000456 printk("fuse_readdir: name too long\n");
Miklos Szeredib483c932001-10-29 14:57:57 +0000457 return -EPROTO;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000458 }
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000459 if (reclen > nbytes)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000460 break;
461
462 over = filldir(dstbuf, dirent->name, dirent->namelen,
463 file->f_pos, dirent->ino, dirent->type);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000464 if (over)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000465 break;
466
Miklos Szeredib483c932001-10-29 14:57:57 +0000467 buf += reclen;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000468 file->f_pos += reclen;
469 nbytes -= reclen;
470 }
471
Miklos Szeredib483c932001-10-29 14:57:57 +0000472 return 0;
473}
474
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000475static int fuse_getdir(struct file *file)
476{
477 struct inode *inode = file->f_dentry->d_inode;
478 struct fuse_conn *fc = INO_FC(inode);
479 struct fuse_in in = FUSE_IN_INIT;
480 struct fuse_out out = FUSE_OUT_INIT;
481 struct fuse_getdir_out_i outarg;
482
483 in.h.opcode = FUSE_GETDIR;
484 in.h.ino = inode->i_ino;
485 out.numargs = 1;
486 out.args[0].size = sizeof(struct fuse_getdir_out);
487 out.args[0].value = &outarg;
488 request_send(fc, &in, &out);
489 if (!out.h.error) {
490 struct file *cfile = outarg.file;
491 struct inode *inode;
492 if (!cfile) {
493 printk("fuse_getdir: invalid file\n");
494 return -EPROTO;
495 }
496 inode = cfile->f_dentry->d_inode;
497 if (!S_ISREG(inode->i_mode)) {
498 printk("fuse_getdir: not a regular file\n");
499 fput(cfile);
500 return -EPROTO;
501 }
502
503 file->private_data = cfile;
504 }
505
506 return out.h.error;
507}
508
Miklos Szeredib483c932001-10-29 14:57:57 +0000509#define DIR_BUFSIZE 2048
510static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
511{
512 struct file *cfile = file->private_data;
513 char *buf;
514 int ret;
Miklos Szeredie815c032004-01-19 18:20:49 +0000515
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000516 if (!cfile) {
517 ret = fuse_getdir(file);
518 if (ret)
519 return ret;
520
521 cfile = file->private_data;
522 }
Miklos Szeredie815c032004-01-19 18:20:49 +0000523
Miklos Szeredib483c932001-10-29 14:57:57 +0000524 buf = kmalloc(DIR_BUFSIZE, GFP_KERNEL);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000525 if (!buf)
Miklos Szeredib483c932001-10-29 14:57:57 +0000526 return -ENOMEM;
Miklos Szeredie815c032004-01-19 18:20:49 +0000527
Miklos Szeredib483c932001-10-29 14:57:57 +0000528 ret = kernel_read(cfile, file->f_pos, buf, DIR_BUFSIZE);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000529 if (ret < 0)
Miklos Szeredib483c932001-10-29 14:57:57 +0000530 printk("fuse_readdir: failed to read container file\n");
531 else
532 ret = parse_dirfile(buf, ret, file, dstbuf, filldir);
533
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000534 kfree(buf);
535 return ret;
536}
537
Miklos Szeredi05033042001-11-13 16:11:35 +0000538static char *read_link(struct dentry *dentry)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000539{
540 struct inode *inode = dentry->d_inode;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000541 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000542 struct fuse_in in = FUSE_IN_INIT;
543 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi05033042001-11-13 16:11:35 +0000544 char *link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000545
Miklos Szeredi05033042001-11-13 16:11:35 +0000546 link = (char *) __get_free_page(GFP_KERNEL);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000547 if (!link)
Miklos Szeredi05033042001-11-13 16:11:35 +0000548 return ERR_PTR(-ENOMEM);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000549
550 in.h.opcode = FUSE_READLINK;
551 in.h.ino = inode->i_ino;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000552 out.argvar = 1;
Miklos Szeredi43696432001-11-18 19:15:05 +0000553 out.numargs = 1;
554 out.args[0].size = PAGE_SIZE - 1;
555 out.args[0].value = link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000556 request_send(fc, &in, &out);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000557 if (out.h.error) {
Miklos Szeredi05033042001-11-13 16:11:35 +0000558 free_page((unsigned long) link);
559 return ERR_PTR(out.h.error);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000560 }
561
Miklos Szeredi43696432001-11-18 19:15:05 +0000562 link[out.args[0].size] = '\0';
Miklos Szeredi05033042001-11-13 16:11:35 +0000563 return link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000564}
565
566static void free_link(char *link)
567{
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000568 if (!IS_ERR(link))
Miklos Szeredi05033042001-11-13 16:11:35 +0000569 free_page((unsigned long) link);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000570}
571
572static int fuse_readlink(struct dentry *dentry, char *buffer, int buflen)
573{
574 int ret;
575 char *link;
576
Miklos Szeredi05033042001-11-13 16:11:35 +0000577 link = read_link(dentry);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000578 ret = vfs_readlink(dentry, buffer, buflen, link);
579 free_link(link);
580 return ret;
581}
582
583static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
584{
585 int ret;
586 char *link;
587
Miklos Szeredi05033042001-11-13 16:11:35 +0000588 link = read_link(dentry);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000589 ret = vfs_follow_link(nd, link);
590 free_link(link);
591 return ret;
592}
593
594static int fuse_dir_open(struct inode *inode, struct file *file)
595{
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000596 file->private_data = NULL;
597 return 0;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000598}
599
600static int fuse_dir_release(struct inode *inode, struct file *file)
601{
602 struct file *cfile = file->private_data;
Miklos Szeredia181e612001-11-06 12:03:23 +0000603
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000604 if (cfile)
Miklos Szeredia181e612001-11-06 12:03:23 +0000605 fput(cfile);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000606
607 return 0;
608}
609
Miklos Szeredi5e183482001-10-31 14:52:35 +0000610static unsigned int iattr_to_fattr(struct iattr *iattr,
611 struct fuse_attr *fattr)
612{
613 unsigned int ivalid = iattr->ia_valid;
614 unsigned int fvalid = 0;
615
616 memset(fattr, 0, sizeof(*fattr));
617
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000618 if (ivalid & ATTR_MODE)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000619 fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000620 if (ivalid & ATTR_UID)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000621 fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000622 if (ivalid & ATTR_GID)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000623 fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000624 if (ivalid & ATTR_SIZE)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000625 fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
626 /* You can only _set_ these together (they may change by themselves) */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000627 if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
Miklos Szeredib5958612004-02-20 14:10:49 +0000628 fvalid |= FATTR_ATIME | FATTR_MTIME;
Miklos Szeredif85ab242004-01-07 12:16:45 +0000629#ifdef KERNEL_2_6
630 fattr->atime = iattr->ia_atime.tv_sec;
631 fattr->mtime = iattr->ia_mtime.tv_sec;
632#else
Miklos Szeredi5e183482001-10-31 14:52:35 +0000633 fattr->atime = iattr->ia_atime;
634 fattr->mtime = iattr->ia_mtime;
Miklos Szeredif85ab242004-01-07 12:16:45 +0000635#endif
Miklos Szeredi5e183482001-10-31 14:52:35 +0000636 }
637
638 return fvalid;
639}
640
641static int fuse_setattr(struct dentry *entry, struct iattr *attr)
642{
643 struct inode *inode = entry->d_inode;
644 struct fuse_conn *fc = INO_FC(inode);
645 struct fuse_in in = FUSE_IN_INIT;
646 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredia181e612001-11-06 12:03:23 +0000647 struct fuse_setattr_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000648 struct fuse_attr_out outarg;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000649
Miklos Szeredi43696432001-11-18 19:15:05 +0000650 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredia181e612001-11-06 12:03:23 +0000651 inarg.valid = iattr_to_fattr(attr, &inarg.attr);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000652
653 in.h.opcode = FUSE_SETATTR;
654 in.h.ino = inode->i_ino;
Miklos Szeredi43696432001-11-18 19:15:05 +0000655 in.numargs = 1;
656 in.args[0].size = sizeof(inarg);
657 in.args[0].value = &inarg;
658 out.numargs = 1;
659 out.args[0].size = sizeof(outarg);
660 out.args[0].value = &outarg;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000661 request_send(fc, &in, &out);
662
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000663 if (!out.h.error) {
664 if (attr->ia_valid & ATTR_SIZE &&
665 outarg.attr.size < i_size_read(inode))
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000666 vmtruncate(inode, outarg.attr.size);
Miklos Szeredia181e612001-11-06 12:03:23 +0000667
Miklos Szeredif3ea83b2001-11-07 14:55:16 +0000668 change_attributes(inode, &outarg.attr);
669 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000670 return out.h.error;
671}
672
Miklos Szeredif85ab242004-01-07 12:16:45 +0000673static int _fuse_dentry_revalidate(struct dentry *entry)
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000674{
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000675 if (!entry->d_inode)
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000676 return 0;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000677 else if (entry->d_time && time_after(jiffies, entry->d_time)) {
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000678 struct inode *inode = entry->d_inode;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000679 struct fuse_entry_out outarg;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000680 int version;
681 int ret;
682
683 ret = fuse_do_lookup(entry->d_parent->d_inode, entry, &outarg,
684 &version);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000685 if (ret)
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000686 return 0;
687
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000688 if (outarg.ino != inode->i_ino)
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000689 return 0;
690
691 change_attributes(inode, &outarg.attr);
692 inode->i_version = version;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000693 entry->d_time = time_to_jiffies(outarg.entry_valid,
694 outarg.entry_valid_nsec);
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000695 }
696 return 1;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000697}
698
Miklos Szeredif85ab242004-01-07 12:16:45 +0000699#ifdef KERNEL_2_6
700
701#define fuse_mknod _fuse_mknod
702
703static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
704 struct kstat *stat)
705{
706 struct inode *inode = entry->d_inode;
707 int err = fuse_revalidate(entry);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000708 if (!err)
Miklos Szeredif85ab242004-01-07 12:16:45 +0000709 generic_fillattr(inode, stat);
710
711 return err;
712}
713
714static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
715 struct nameidata *nd)
716{
Miklos Szeredie815c032004-01-19 18:20:49 +0000717 struct inode *inode;
718 int err = fuse_lookup_iget(dir, entry, &inode);
719 if (err)
720 return ERR_PTR(err);
721 return d_splice_alias(inode, entry);
Miklos Szeredif85ab242004-01-07 12:16:45 +0000722}
723
724static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
725 struct nameidata *nd)
726{
727 return _fuse_create(dir, entry, mode);
728}
729
730static int fuse_permission(struct inode *inode, int mask,
731 struct nameidata *nd)
732{
733 return _fuse_permission(inode, mask);
734}
735
736static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
737{
738 return _fuse_dentry_revalidate(entry);
739}
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000740
Miklos Szeredi689f5632004-05-04 08:49:16 +0000741#else /* KERNEL_2_6 */
742
743#define fuse_create _fuse_create
744#define fuse_permission _fuse_permission
745
746static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry)
747{
748 struct inode *inode;
749 struct dentry *alias;
750
751 int err = fuse_lookup_iget(dir, entry, &inode);
752 if (err)
753 return ERR_PTR(err);
754
755 if (inode && S_ISDIR(inode->i_mode) &&
756 (alias = d_find_alias(inode)) != NULL) {
757 dput(alias);
758 iput(inode);
759 printk("fuse: cannot assign an existing directory\n");
760 return ERR_PTR(-EPROTO);
761 }
762
763 d_add(entry, inode);
764 return NULL;
765}
766
767static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
768 int rdev)
769{
770 return fuse_mknod(dir, entry, mode, rdev);
771}
772
773static int fuse_dentry_revalidate(struct dentry *entry, int flags)
774{
775 return _fuse_dentry_revalidate(entry);
776}
777#endif /* KERNEL_2_6 */
778
779#ifdef HAVE_KERNEL_XATTR
780
781#ifdef KERNEL_2_6
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000782static int fuse_setxattr(struct dentry *entry, const char *name,
783 const void *value, size_t size, int flags)
Miklos Szeredi689f5632004-05-04 08:49:16 +0000784#else
785static int fuse_setxattr(struct dentry *entry, const char *name,
786 void *value, size_t size, int flags)
787#endif
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000788{
789 struct inode *inode = entry->d_inode;
790 struct fuse_conn *fc = INO_FC(inode);
791 struct fuse_in in = FUSE_IN_INIT;
792 struct fuse_out out = FUSE_OUT_INIT;
793 struct fuse_setxattr_in inarg;
794
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000795 if (size > FUSE_XATTR_SIZE_MAX)
796 return -E2BIG;
797
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000798 if (fc->no_setxattr)
799 return -EOPNOTSUPP;
800
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000801 memset(&inarg, 0, sizeof(inarg));
802 inarg.size = size;
803 inarg.flags = flags;
804
805 in.h.opcode = FUSE_SETXATTR;
806 in.h.ino = inode->i_ino;
807 in.numargs = 3;
808 in.args[0].size = sizeof(inarg);
809 in.args[0].value = &inarg;
810 in.args[1].size = strlen(name) + 1;
811 in.args[1].value = name;
812 in.args[2].size = size;
813 in.args[2].value = value;
814 request_send(fc, &in, &out);
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000815 if (out.h.error == -ENOSYS) {
816 fc->no_setxattr = 1;
817 return -EOPNOTSUPP;
818 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000819 return out.h.error;
820}
821
822static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
823 void *value, size_t size)
824{
825 struct inode *inode = entry->d_inode;
826 struct fuse_conn *fc = INO_FC(inode);
827 struct fuse_in in = FUSE_IN_INIT;
828 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000829 struct fuse_getxattr_in inarg;
830 struct fuse_getxattr_out outarg;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000831
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000832 if (fc->no_getxattr)
833 return -EOPNOTSUPP;
834
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000835 memset(&inarg, 0, sizeof(inarg));
836 inarg.size = size;
837
838 in.h.opcode = FUSE_GETXATTR;
839 in.h.ino = inode->i_ino;
840 in.numargs = 2;
841 in.args[0].size = sizeof(inarg);
842 in.args[0].value = &inarg;
843 in.args[1].size = strlen(name) + 1;
844 in.args[1].value = name;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000845 /* This is really two different operations rolled into one */
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000846 out.numargs = 1;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000847 if (size) {
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000848 out.argvar = 1;
849 out.args[0].size = size;
850 out.args[0].value = value;
851 } else {
852 out.args[0].size = sizeof(outarg);
853 out.args[0].value = &outarg;
854 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000855 request_send(fc, &in, &out);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000856 if (!out.h.error)
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000857 return size ? out.args[0].size : outarg.size;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000858 else {
859 if (out.h.error == -ENOSYS) {
860 fc->no_getxattr = 1;
861 return -EOPNOTSUPP;
862 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000863 return out.h.error;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000864 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000865}
866
867static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
868{
869 struct inode *inode = entry->d_inode;
870 struct fuse_conn *fc = INO_FC(inode);
871 struct fuse_in in = FUSE_IN_INIT;
872 struct fuse_out out = FUSE_OUT_INIT;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000873 struct fuse_getxattr_in inarg;
874 struct fuse_getxattr_out outarg;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000875
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000876 if (fc->no_listxattr)
877 return -EOPNOTSUPP;
878
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000879 memset(&inarg, 0, sizeof(inarg));
880 inarg.size = size;
881
882 in.h.opcode = FUSE_LISTXATTR;
883 in.h.ino = inode->i_ino;
884 in.numargs = 1;
885 in.args[0].size = sizeof(inarg);
886 in.args[0].value = &inarg;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000887 /* This is really two different operations rolled into one */
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000888 out.numargs = 1;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000889 if (size) {
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000890 out.argvar = 1;
891 out.args[0].size = size;
892 out.args[0].value = list;
893 } else {
894 out.args[0].size = sizeof(outarg);
895 out.args[0].value = &outarg;
896 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000897 request_send(fc, &in, &out);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000898 if (!out.h.error)
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000899 return size ? out.args[0].size : outarg.size;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000900 else {
901 if (out.h.error == -ENOSYS) {
902 fc->no_listxattr = 1;
903 return -EOPNOTSUPP;
904 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000905 return out.h.error;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000906 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000907}
908
909static int fuse_removexattr(struct dentry *entry, const char *name)
910{
911 struct inode *inode = entry->d_inode;
912 struct fuse_conn *fc = INO_FC(inode);
913 struct fuse_in in = FUSE_IN_INIT;
914 struct fuse_out out = FUSE_OUT_INIT;
915
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000916 if (fc->no_removexattr)
917 return -EOPNOTSUPP;
918
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000919 in.h.opcode = FUSE_REMOVEXATTR;
920 in.h.ino = inode->i_ino;
921 in.numargs = 1;
922 in.args[0].size = strlen(name) + 1;
923 in.args[0].value = name;
924 request_send(fc, &in, &out);
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000925 if (out.h.error == -ENOSYS) {
926 fc->no_removexattr = 1;
927 return -EOPNOTSUPP;
928 }
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000929 return out.h.error;
930
931}
932
Miklos Szeredi689f5632004-05-04 08:49:16 +0000933#endif
Miklos Szeredif85ab242004-01-07 12:16:45 +0000934
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000935static struct inode_operations fuse_dir_inode_operations =
936{
Miklos Szeredie8663f32004-01-13 15:33:12 +0000937 .lookup = fuse_lookup,
938 .create = fuse_create,
939 .mknod = fuse_mknod,
940 .mkdir = fuse_mkdir,
941 .symlink = fuse_symlink,
942 .unlink = fuse_unlink,
943 .rmdir = fuse_rmdir,
944 .rename = fuse_rename,
945 .link = fuse_link,
946 .setattr = fuse_setattr,
947 .permission = fuse_permission,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000948#ifdef KERNEL_2_6
Miklos Szeredie8663f32004-01-13 15:33:12 +0000949 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +0000950#else
951 .revalidate = fuse_revalidate,
952#endif
953#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000954 .setxattr = fuse_setxattr,
955 .getxattr = fuse_getxattr,
956 .listxattr = fuse_listxattr,
957 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000958#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000959};
960
961static struct file_operations fuse_dir_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +0000962 .read = generic_read_dir,
963 .readdir = fuse_readdir,
964 .open = fuse_dir_open,
965 .release = fuse_dir_release,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000966};
967
968static struct inode_operations fuse_file_inode_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +0000969 .setattr = fuse_setattr,
970 .permission = fuse_permission,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000971#ifdef KERNEL_2_6
Miklos Szeredie8663f32004-01-13 15:33:12 +0000972 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +0000973#else
974 .revalidate = fuse_revalidate,
975#endif
976#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000977 .setxattr = fuse_setxattr,
978 .getxattr = fuse_getxattr,
979 .listxattr = fuse_listxattr,
980 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000981#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000982};
983
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000984static struct inode_operations fuse_symlink_inode_operations =
985{
Miklos Szeredie8663f32004-01-13 15:33:12 +0000986 .setattr = fuse_setattr,
987 .readlink = fuse_readlink,
988 .follow_link = fuse_follow_link,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000989#ifdef KERNEL_2_6
Miklos Szeredie8663f32004-01-13 15:33:12 +0000990 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +0000991#else
992 .revalidate = fuse_revalidate,
993#endif
994#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000995 .setxattr = fuse_setxattr,
996 .getxattr = fuse_getxattr,
997 .listxattr = fuse_listxattr,
998 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000999#endif
Miklos Szeredi19dff1b2001-10-30 15:06:52 +00001000};
1001
Miklos Szeredi307242f2004-01-26 11:28:44 +00001002static struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +00001003 .d_revalidate = fuse_dentry_revalidate,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001004};
1005
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001006/*
1007 * Local Variables:
1008 * indent-tabs-mode: t
1009 * c-basic-offset: 8
1010 * End:
1011 */