blob: e07ea79db06b1b3b24c1884255ce7055dec3106e [file] [log] [blame]
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001/*
Miklos Szeredie56818b2004-12-12 11:45:24 +00002 FUSE: Filesystem in Userspace
Miklos Szeredi149f6072005-01-10 12:29:28 +00003 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00004
Miklos Szeredie56818b2004-12-12 11:45:24 +00005 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00007*/
8
9#include "fuse_i.h"
10
Miklos Szeredi05033042001-11-13 16:11:35 +000011#include <linux/pagemap.h>
Miklos Szeredi5e183482001-10-31 14:52:35 +000012#include <linux/file.h>
Miklos Szeredi13ed4822004-11-20 11:12:21 +000013#ifdef KERNEL_2_6
14#include <linux/gfp.h>
15#else
16#include <linux/mm.h>
17#endif
18#include <linux/sched.h>
Miklos Szeredi81394522005-01-11 14:24:18 +000019#ifdef KERNEL_2_6_7_PLUS
20#include <linux/namei.h>
21#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000022
Miklos Szeredi254d5ed2004-03-02 11:11:24 +000023static inline unsigned long time_to_jiffies(unsigned long sec,
24 unsigned long nsec)
25{
Miklos Szeredi81394522005-01-11 14:24:18 +000026 struct timespec ts = {sec, nsec};
27 return jiffies + timespec_to_jiffies(&ts);
Miklos Szeredi254d5ed2004-03-02 11:11:24 +000028}
29
Miklos Szeredi0f62d722005-01-04 12:45:54 +000030static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
31 struct dentry *entry,
32 struct fuse_entry_out *outarg)
33{
34 req->in.h.opcode = FUSE_LOOKUP;
35 req->in.h.nodeid = get_node_id(dir);
36 req->inode = dir;
37 req->in.numargs = 1;
38 req->in.args[0].size = entry->d_name.len + 1;
39 req->in.args[0].value = entry->d_name.name;
40 req->out.numargs = 1;
41 req->out.args[0].size = sizeof(struct fuse_entry_out);
42 req->out.args[0].value = outarg;
43}
44
45static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
46{
47 if (!entry->d_inode || is_bad_inode(entry->d_inode))
48 return 0;
Miklos Szeredi81394522005-01-11 14:24:18 +000049 else if (time_after(jiffies, entry->d_time)) {
Miklos Szeredi0f62d722005-01-04 12:45:54 +000050 int err;
51 int version;
52 struct fuse_entry_out outarg;
53 struct inode *inode = entry->d_inode;
54 struct fuse_inode *fi = get_fuse_inode(inode);
55 struct fuse_conn *fc = get_fuse_conn(inode);
56 struct fuse_req *req = fuse_get_request_nonint(fc);
57 if (!req)
58 return 0;
59
60 fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
61 request_send_nonint(fc, req);
62 version = req->out.h.unique;
63 err = req->out.h.error;
64 fuse_put_request(fc, req);
65 if (err || outarg.nodeid != get_node_id(inode) ||
66 (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
67 return 0;
68
69 fuse_change_attributes(inode, &outarg.attr);
70 inode->i_version = version;
71 entry->d_time = time_to_jiffies(outarg.entry_valid,
72 outarg.entry_valid_nsec);
73 fi->i_time = time_to_jiffies(outarg.attr_valid,
74 outarg.attr_valid_nsec);
75 }
76 return 1;
77}
78#ifndef KERNEL_2_6
79static int fuse_dentry_revalidate_2_4(struct dentry *entry, int flags)
80{
81 return fuse_dentry_revalidate(entry, NULL);
82}
83#endif
84
85static struct dentry_operations fuse_dentry_operations = {
86#ifdef KERNEL_2_6
87 .d_revalidate = fuse_dentry_revalidate,
88#else
89 .d_revalidate = fuse_dentry_revalidate_2_4,
90#endif
91};
92
Miklos Szeredie815c032004-01-19 18:20:49 +000093static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
94 struct inode **inodep)
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +000095{
Miklos Szeredie815c032004-01-19 18:20:49 +000096 int err;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +000097 int version;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +000098 struct fuse_entry_out outarg;
Miklos Szeredie815c032004-01-19 18:20:49 +000099 struct inode *inode = NULL;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000100 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000101 struct fuse_req *req;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000102
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000103 if (entry->d_name.len > FUSE_NAME_MAX)
104 return -ENAMETOOLONG;
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000105
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000106 req = fuse_get_request(fc);
107 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000108 return -ERESTARTNOINTR;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000109
Miklos Szeredie56818b2004-12-12 11:45:24 +0000110 fuse_lookup_init(req, dir, entry, &outarg);
111 request_send(fc, req);
112 version = req->out.h.unique;
113 err = req->out.h.error;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000114 if (!err) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000115 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi76f65782004-02-19 16:55:40 +0000116 &outarg.attr, version);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000117 if (!inode) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000118 fuse_send_forget(fc, req, outarg.nodeid, version);
Miklos Szeredie815c032004-01-19 18:20:49 +0000119 return -ENOMEM;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000120 }
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000121 }
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000122 fuse_put_request(fc, req);
123 if (err && err != -ENOENT)
Miklos Szeredie815c032004-01-19 18:20:49 +0000124 return err;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000125
Miklos Szeredi069c9502004-07-16 16:17:02 +0000126 if (inode) {
Miklos Szeredi039322d2004-12-01 18:39:12 +0000127 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000128 entry->d_time = time_to_jiffies(outarg.entry_valid,
Miklos Szerediad051c32004-07-02 09:22:50 +0000129 outarg.entry_valid_nsec);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000130 fi->i_time = time_to_jiffies(outarg.attr_valid,
131 outarg.attr_valid_nsec);
132 }
Miklos Szerediad051c32004-07-02 09:22:50 +0000133
Miklos Szeredi307242f2004-01-26 11:28:44 +0000134 entry->d_op = &fuse_dentry_operations;
Miklos Szeredie815c032004-01-19 18:20:49 +0000135 *inodep = inode;
136 return 0;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000137}
138
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000139void fuse_invalidate_attr(struct inode *inode)
Miklos Szeredi015fe702004-07-12 11:52:24 +0000140{
Miklos Szeredi039322d2004-12-01 18:39:12 +0000141 get_fuse_inode(inode)->i_time = jiffies - 1;
Miklos Szeredi015fe702004-07-12 11:52:24 +0000142}
143
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000144static void fuse_invalidate_entry(struct dentry *entry)
145{
146 d_invalidate(entry);
147 entry->d_time = jiffies - 1;
148}
149
150static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000151 struct inode *dir, struct dentry *entry,
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000152 int mode)
Miklos Szeredi76f65782004-02-19 16:55:40 +0000153{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000154 struct fuse_entry_out outarg;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000155 struct inode *inode;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000156 struct fuse_inode *fi;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000157 int version;
158 int err;
159
160 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000161 req->inode = dir;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000162 req->out.numargs = 1;
163 req->out.args[0].size = sizeof(outarg);
164 req->out.args[0].value = &outarg;
165 request_send(fc, req);
166 version = req->out.h.unique;
167 err = req->out.h.error;
168 if (err) {
169 fuse_put_request(fc, req);
170 return err;
171 }
172 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
173 &outarg.attr, version);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000174 if (!inode) {
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000175 fuse_send_forget(fc, req, outarg.nodeid, version);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000176 return -ENOMEM;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000177 }
178 fuse_put_request(fc, req);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000179
180 /* Don't allow userspace to do really stupid things... */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000181 if ((inode->i_mode ^ mode) & S_IFMT) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000182 iput(inode);
Miklos Szeredie56818b2004-12-12 11:45:24 +0000183 return -EIO;
Miklos Szeredi76f65782004-02-19 16:55:40 +0000184 }
185
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000186 entry->d_time = time_to_jiffies(outarg.entry_valid,
187 outarg.entry_valid_nsec);
Miklos Szerediad051c32004-07-02 09:22:50 +0000188
Miklos Szeredi039322d2004-12-01 18:39:12 +0000189 fi = get_fuse_inode(inode);
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000190 fi->i_time = time_to_jiffies(outarg.attr_valid,
191 outarg.attr_valid_nsec);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000192
Miklos Szeredi76f65782004-02-19 16:55:40 +0000193 d_instantiate(entry, inode);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000194 fuse_invalidate_attr(dir);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000195 return 0;
196}
197
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000198static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
Miklos Szeredif85ab242004-01-07 12:16:45 +0000199 dev_t rdev)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000200{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000201 struct fuse_mknod_in inarg;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000202 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000203 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000204 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000205 return -ERESTARTNOINTR;
Miklos Szeredi43696432001-11-18 19:15:05 +0000206
207 memset(&inarg, 0, sizeof(inarg));
208 inarg.mode = mode;
Miklos Szeredi7c35cf92004-01-14 16:56:49 +0000209 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000210 req->in.h.opcode = FUSE_MKNOD;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000211 req->in.numargs = 2;
212 req->in.args[0].size = sizeof(inarg);
213 req->in.args[0].value = &inarg;
214 req->in.args[1].size = entry->d_name.len + 1;
215 req->in.args[1].value = entry->d_name.name;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000216 return create_new_entry(fc, req, dir, entry, mode);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000217}
218
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000219static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
220 struct nameidata *nd)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000221{
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000222 return fuse_mknod(dir, entry, mode, 0);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000223}
224
Miklos Szeredib483c932001-10-29 14:57:57 +0000225static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
226{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000227 struct fuse_mkdir_in inarg;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000228 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000229 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000230 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000231 return -ERESTARTNOINTR;
Miklos Szeredi43696432001-11-18 19:15:05 +0000232
233 memset(&inarg, 0, sizeof(inarg));
234 inarg.mode = mode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000235 req->in.h.opcode = FUSE_MKDIR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000236 req->in.numargs = 2;
237 req->in.args[0].size = sizeof(inarg);
238 req->in.args[0].value = &inarg;
239 req->in.args[1].size = entry->d_name.len + 1;
240 req->in.args[1].value = entry->d_name.name;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000241 return create_new_entry(fc, req, dir, entry, S_IFDIR);
Miklos Szeredib483c932001-10-29 14:57:57 +0000242}
243
244static int fuse_symlink(struct inode *dir, struct dentry *entry,
245 const char *link)
246{
Miklos Szeredi039322d2004-12-01 18:39:12 +0000247 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi83a07442004-11-30 18:25:20 +0000248 unsigned len = strlen(link) + 1;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000249 struct fuse_req *req;
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000250
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000251 if (len > FUSE_SYMLINK_MAX)
252 return -ENAMETOOLONG;
Miklos Szeredib483c932001-10-29 14:57:57 +0000253
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000254 req = fuse_get_request(fc);
255 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000256 return -ERESTARTNOINTR;
Miklos Szeredi43696432001-11-18 19:15:05 +0000257
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000258 req->in.h.opcode = FUSE_SYMLINK;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000259 req->in.numargs = 2;
260 req->in.args[0].size = entry->d_name.len + 1;
261 req->in.args[0].value = entry->d_name.name;
262 req->in.args[1].size = len;
263 req->in.args[1].value = link;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000264 return create_new_entry(fc, req, dir, entry, S_IFLNK);
Miklos Szeredib483c932001-10-29 14:57:57 +0000265}
266
Miklos Szeredib5958612004-02-20 14:10:49 +0000267static int fuse_unlink(struct inode *dir, struct dentry *entry)
Miklos Szeredib483c932001-10-29 14:57:57 +0000268{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000269 int err;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000270 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000271 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000272 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000273 return -ERESTARTNOINTR;
Miklos Szeredib483c932001-10-29 14:57:57 +0000274
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000275 req->in.h.opcode = FUSE_UNLINK;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000276 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000277 req->inode = dir;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000278 req->in.numargs = 1;
279 req->in.args[0].size = entry->d_name.len + 1;
280 req->in.args[0].value = entry->d_name.name;
281 request_send(fc, req);
282 err = req->out.h.error;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000283 fuse_put_request(fc, req);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000284 if (!err) {
Miklos Szeredi069c9502004-07-16 16:17:02 +0000285 struct inode *inode = entry->d_inode;
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000286
Miklos Szeredib5958612004-02-20 14:10:49 +0000287 /* Set nlink to zero so the inode can be cleared, if
288 the inode does have more links this will be
289 discovered at the next lookup/getattr */
Miklos Szeredi069c9502004-07-16 16:17:02 +0000290 inode->i_nlink = 0;
291 fuse_invalidate_attr(inode);
292 fuse_invalidate_attr(dir);
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000293 } else if (err == -EINTR)
294 fuse_invalidate_entry(entry);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000295 return err;
Miklos Szeredib483c932001-10-29 14:57:57 +0000296}
297
298static int fuse_rmdir(struct inode *dir, struct dentry *entry)
299{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000300 int err;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000301 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000302 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000303 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000304 return -ERESTARTNOINTR;
Miklos Szeredib5958612004-02-20 14:10:49 +0000305
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000306 req->in.h.opcode = FUSE_RMDIR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000307 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000308 req->inode = dir;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000309 req->in.numargs = 1;
310 req->in.args[0].size = entry->d_name.len + 1;
311 req->in.args[0].value = entry->d_name.name;
312 request_send(fc, req);
313 err = req->out.h.error;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000314 fuse_put_request(fc, req);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000315 if (!err) {
Miklos Szeredif4f8b892004-01-27 17:04:59 +0000316 entry->d_inode->i_nlink = 0;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000317 fuse_invalidate_attr(dir);
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000318 } else if (err == -EINTR)
319 fuse_invalidate_entry(entry);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000320 return err;
Miklos Szeredib483c932001-10-29 14:57:57 +0000321}
322
323static int fuse_rename(struct inode *olddir, struct dentry *oldent,
324 struct inode *newdir, struct dentry *newent)
325{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000326 int err;
327 struct fuse_rename_in inarg;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000328 struct fuse_conn *fc = get_fuse_conn(olddir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000329 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000330 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000331 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000332
Miklos Szeredi43696432001-11-18 19:15:05 +0000333 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi039322d2004-12-01 18:39:12 +0000334 inarg.newdir = get_node_id(newdir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000335 req->in.h.opcode = FUSE_RENAME;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000336 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000337 req->inode = olddir;
338 req->inode2 = newdir;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000339 req->in.numargs = 3;
340 req->in.args[0].size = sizeof(inarg);
341 req->in.args[0].value = &inarg;
342 req->in.args[1].size = oldent->d_name.len + 1;
343 req->in.args[1].value = oldent->d_name.name;
344 req->in.args[2].size = newent->d_name.len + 1;
345 req->in.args[2].value = newent->d_name.name;
346 request_send(fc, req);
347 err = req->out.h.error;
348 fuse_put_request(fc, req);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000349 if (!err) {
Miklos Szeredi069c9502004-07-16 16:17:02 +0000350 fuse_invalidate_attr(olddir);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000351 if (olddir != newdir)
Miklos Szeredi069c9502004-07-16 16:17:02 +0000352 fuse_invalidate_attr(newdir);
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000353 } else if (err == -EINTR) {
354 /* If request was interrupted, DEITY only knows if the
355 rename actually took place. If the invalidation
356 fails (e.g. some process has CWD under the renamed
357 directory), then there can be inconsistency between
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000358 the dcache and the real filesystem. Tough luck. */
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000359 fuse_invalidate_entry(oldent);
360 if (newent->d_inode)
361 fuse_invalidate_entry(newent);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000362 }
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000363
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000364 return err;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000365}
366
367static int fuse_link(struct dentry *entry, struct inode *newdir,
368 struct dentry *newent)
369{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000370 int err;
371 struct fuse_link_in inarg;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000372 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000373 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000374 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000375 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000376 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000377
Miklos Szeredi43696432001-11-18 19:15:05 +0000378 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi039322d2004-12-01 18:39:12 +0000379 inarg.newdir = get_node_id(newdir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000380 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000381 req->inode2 = newdir;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000382 req->in.numargs = 2;
383 req->in.args[0].size = sizeof(inarg);
384 req->in.args[0].value = &inarg;
385 req->in.args[1].size = newent->d_name.len + 1;
386 req->in.args[1].value = newent->d_name.name;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000387 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
388 /* Contrary to "normal" filesystems it can happen that link
389 makes two "logical" inodes point to the same "physical"
390 inode. We invalidate the attributes of the old one, so it
391 will reflect changes in the backing inode (link count,
392 etc.)
393 */
394 if (!err || err == -EINTR)
395 fuse_invalidate_attr(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000396 return err;
Miklos Szeredib483c932001-10-29 14:57:57 +0000397}
398
Miklos Szeredif85ab242004-01-07 12:16:45 +0000399int fuse_do_getattr(struct inode *inode)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000400{
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000401 int err;
402 struct fuse_attr_out arg;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000403 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000404 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000405 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000406 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000407
408 req->in.h.opcode = FUSE_GETATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000409 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000410 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000411 req->out.numargs = 1;
412 req->out.args[0].size = sizeof(arg);
413 req->out.args[0].value = &arg;
414 request_send(fc, req);
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000415 err = req->out.h.error;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000416 fuse_put_request(fc, req);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000417 if (!err) {
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000418 if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) {
419 make_bad_inode(inode);
420 err = -EIO;
421 } else {
422 struct fuse_inode *fi = get_fuse_inode(inode);
423 fuse_change_attributes(inode, &arg.attr);
424 fi->i_time = time_to_jiffies(arg.attr_valid,
425 arg.attr_valid_nsec);
426 }
Miklos Szeredi069c9502004-07-16 16:17:02 +0000427 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000428 return err;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000429}
430
Miklos Szeredife25def2001-12-20 15:38:05 +0000431static int fuse_revalidate(struct dentry *entry)
432{
433 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000434 struct fuse_inode *fi = get_fuse_inode(inode);
435 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredife25def2001-12-20 15:38:05 +0000436
Miklos Szeredi039322d2004-12-01 18:39:12 +0000437 if (get_node_id(inode) == FUSE_ROOT_ID) {
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000438 if (!(fc->flags & FUSE_ALLOW_OTHER) &&
Miklos Szeredi3c7d41b2005-01-09 20:05:27 +0000439 current->fsuid != fc->user_id &&
Miklos Szeredi180ff692004-11-01 16:01:05 +0000440 (!(fc->flags & FUSE_ALLOW_ROOT) ||
441 current->fsuid != 0))
Miklos Szeredife25def2001-12-20 15:38:05 +0000442 return -EACCES;
Miklos Szeredi81394522005-01-11 14:24:18 +0000443 } else if (time_before_eq(jiffies, fi->i_time))
Miklos Szeredife25def2001-12-20 15:38:05 +0000444 return 0;
445
Miklos Szeredif85ab242004-01-07 12:16:45 +0000446 return fuse_do_getattr(inode);
Miklos Szeredife25def2001-12-20 15:38:05 +0000447}
448
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000449static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
Miklos Szeredife25def2001-12-20 15:38:05 +0000450{
Miklos Szeredi039322d2004-12-01 18:39:12 +0000451 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredife25def2001-12-20 15:38:05 +0000452
Miklos Szeredi3c7d41b2005-01-09 20:05:27 +0000453 if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->user_id &&
Miklos Szeredi180ff692004-11-01 16:01:05 +0000454 (!(fc->flags & FUSE_ALLOW_ROOT) || current->fsuid != 0))
Miklos Szeredife25def2001-12-20 15:38:05 +0000455 return -EACCES;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000456 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000457#ifdef KERNEL_2_6_10_PLUS
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000458 int err = generic_permission(inode, mask, NULL);
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000459#else
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000460 int err = vfs_permission(inode, mask);
Miklos Szeredi08ddb8e2004-11-14 09:19:51 +0000461#endif
Miklos Szeredife25def2001-12-20 15:38:05 +0000462
463 /* If permission is denied, try to refresh file
464 attributes. This is also needed, because the root
465 node will at first have no permissions */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000466 if (err == -EACCES) {
Miklos Szeredif85ab242004-01-07 12:16:45 +0000467 err = fuse_do_getattr(inode);
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000468 if (!err)
469#ifdef KERNEL_2_6_10_PLUS
Miklos Szeredi08ddb8e2004-11-14 09:19:51 +0000470 err = generic_permission(inode, mask, NULL);
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000471#else
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000472 err = vfs_permission(inode, mask);
Miklos Szeredi08ddb8e2004-11-14 09:19:51 +0000473#endif
Miklos Szeredife25def2001-12-20 15:38:05 +0000474 }
475
476 /* FIXME: Need some mechanism to revoke permissions:
477 currently if the filesystem suddenly changes the
Miklos Szeredi064efb02004-11-09 17:30:29 +0000478 file mode, we will not be informed about it, and
Miklos Szeredife25def2001-12-20 15:38:05 +0000479 continue to allow access to the file/directory.
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000480
Miklos Szeredife25def2001-12-20 15:38:05 +0000481 This is actually not so grave, since the user can
482 simply keep access to the file/directory anyway by
483 keeping it open... */
484
485 return err;
Miklos Szeredi96dfad72004-11-30 00:00:02 +0000486 } else {
487 int mode = inode->i_mode;
488 if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
489 (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
490 return -EROFS;
491 if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
492 return -EACCES;
Miklos Szeredife25def2001-12-20 15:38:05 +0000493 return 0;
Miklos Szeredi96dfad72004-11-30 00:00:02 +0000494 }
Miklos Szeredife25def2001-12-20 15:38:05 +0000495}
496
Miklos Szeredib483c932001-10-29 14:57:57 +0000497static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
498 void *dstbuf, filldir_t filldir)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000499{
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000500 while (nbytes >= FUSE_NAME_OFFSET) {
Miklos Szeredib483c932001-10-29 14:57:57 +0000501 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000502 size_t reclen = FUSE_DIRENT_SIZE(dirent);
503 int over;
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000504 if (dirent->namelen > FUSE_NAME_MAX)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000505 return -EIO;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000506 if (reclen > nbytes)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000507 break;
508
509 over = filldir(dstbuf, dirent->name, dirent->namelen,
Miklos Szeredi83a07442004-11-30 18:25:20 +0000510 file->f_pos, dirent->ino, dirent->type);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000511 if (over)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000512 break;
513
Miklos Szeredib483c932001-10-29 14:57:57 +0000514 buf += reclen;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000515 file->f_pos += reclen;
516 nbytes -= reclen;
517 }
518
Miklos Szeredib483c932001-10-29 14:57:57 +0000519 return 0;
520}
521
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000522static int fuse_checkdir(struct file *cfile, struct file *file)
523{
524 struct inode *inode;
Miklos Szeredie56818b2004-12-12 11:45:24 +0000525 if (!cfile)
526 return -EIO;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000527 inode = cfile->f_dentry->d_inode;
528 if (!S_ISREG(inode->i_mode)) {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000529 fput(cfile);
Miklos Szeredie56818b2004-12-12 11:45:24 +0000530 return -EIO;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000531 }
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000532
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000533 file->private_data = cfile;
534 return 0;
535}
536
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000537static int fuse_getdir(struct file *file)
538{
539 struct inode *inode = file->f_dentry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000540 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000541 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000542 struct fuse_getdir_out_i outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000543 int err;
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000544
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000545 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000546 return -ERESTARTNOINTR;
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000547
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000548 req->in.h.opcode = FUSE_GETDIR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000549 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000550 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000551 req->out.numargs = 1;
552 req->out.args[0].size = sizeof(struct fuse_getdir_out);
553 req->out.args[0].value = &outarg;
554 request_send(fc, req);
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000555 err = req->out.h.error;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000556 fuse_put_request(fc, req);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000557 if (!err)
558 err = fuse_checkdir(outarg.file, file);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000559 return err;
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000560}
561
Miklos Szeredib483c932001-10-29 14:57:57 +0000562static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
563{
564 struct file *cfile = file->private_data;
565 char *buf;
566 int ret;
Miklos Szeredie815c032004-01-19 18:20:49 +0000567
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000568 if (!cfile) {
569 ret = fuse_getdir(file);
570 if (ret)
571 return ret;
572
573 cfile = file->private_data;
574 }
Miklos Szeredie815c032004-01-19 18:20:49 +0000575
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000576 buf = (char *) __get_free_page(GFP_KERNEL);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000577 if (!buf)
Miklos Szeredib483c932001-10-29 14:57:57 +0000578 return -ENOMEM;
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000579
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000580 ret = kernel_read(cfile, file->f_pos, buf, PAGE_SIZE);
Miklos Szeredie56818b2004-12-12 11:45:24 +0000581 if (ret > 0)
Miklos Szeredib483c932001-10-29 14:57:57 +0000582 ret = parse_dirfile(buf, ret, file, dstbuf, filldir);
583
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000584 free_page((unsigned long) buf);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000585 return ret;
586}
587
Miklos Szeredi05033042001-11-13 16:11:35 +0000588static char *read_link(struct dentry *dentry)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000589{
590 struct inode *inode = dentry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000591 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000592 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi05033042001-11-13 16:11:35 +0000593 char *link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000594
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000595 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000596 return ERR_PTR(-ERESTARTNOINTR);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000597
Miklos Szeredi05033042001-11-13 16:11:35 +0000598 link = (char *) __get_free_page(GFP_KERNEL);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000599 if (!link) {
600 link = ERR_PTR(-ENOMEM);
601 goto out;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000602 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000603 req->in.h.opcode = FUSE_READLINK;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000604 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000605 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000606 req->out.argvar = 1;
607 req->out.numargs = 1;
608 req->out.args[0].size = PAGE_SIZE - 1;
609 req->out.args[0].value = link;
610 request_send(fc, req);
611 if (req->out.h.error) {
612 free_page((unsigned long) link);
613 link = ERR_PTR(req->out.h.error);
614 } else
615 link[req->out.args[0].size] = '\0';
616 out:
617 fuse_put_request(fc, req);
Miklos Szeredi05033042001-11-13 16:11:35 +0000618 return link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000619}
620
621static void free_link(char *link)
622{
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000623 if (!IS_ERR(link))
Miklos Szeredi05033042001-11-13 16:11:35 +0000624 free_page((unsigned long) link);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000625}
626
Miklos Szeredi81394522005-01-11 14:24:18 +0000627#ifdef KERNEL_2_6_7_PLUS
628static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
629{
630 nd_set_link(nd, read_link(dentry));
631 return 0;
632}
633
634static void fuse_put_link(struct dentry *dentry, struct nameidata *nd)
635{
636 free_link(nd_get_link(nd));
637}
638#else
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000639static int fuse_readlink(struct dentry *dentry, char __user *buffer,
640 int buflen)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000641{
642 int ret;
643 char *link;
644
Miklos Szeredi05033042001-11-13 16:11:35 +0000645 link = read_link(dentry);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000646 ret = vfs_readlink(dentry, buffer, buflen, link);
647 free_link(link);
648 return ret;
649}
650
651static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
652{
653 int ret;
654 char *link;
655
Miklos Szeredi05033042001-11-13 16:11:35 +0000656 link = read_link(dentry);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000657 ret = vfs_follow_link(nd, link);
658 free_link(link);
659 return ret;
660}
Miklos Szeredi81394522005-01-11 14:24:18 +0000661#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000662
663static int fuse_dir_open(struct inode *inode, struct file *file)
664{
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000665 file->private_data = NULL;
666 return 0;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000667}
668
669static int fuse_dir_release(struct inode *inode, struct file *file)
670{
671 struct file *cfile = file->private_data;
Miklos Szeredia181e612001-11-06 12:03:23 +0000672
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000673 if (cfile)
Miklos Szeredia181e612001-11-06 12:03:23 +0000674 fput(cfile);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000675
676 return 0;
677}
678
Miklos Szeredi83a07442004-11-30 18:25:20 +0000679static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000680{
Miklos Szeredi83a07442004-11-30 18:25:20 +0000681 unsigned ivalid = iattr->ia_valid;
682 unsigned fvalid = 0;
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000683
Miklos Szeredi5e183482001-10-31 14:52:35 +0000684 memset(fattr, 0, sizeof(*fattr));
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000685
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000686 if (ivalid & ATTR_MODE)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000687 fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000688 if (ivalid & ATTR_UID)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000689 fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000690 if (ivalid & ATTR_GID)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000691 fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000692 if (ivalid & ATTR_SIZE)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000693 fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
694 /* You can only _set_ these together (they may change by themselves) */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000695 if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
Miklos Szeredib5958612004-02-20 14:10:49 +0000696 fvalid |= FATTR_ATIME | FATTR_MTIME;
Miklos Szeredif85ab242004-01-07 12:16:45 +0000697#ifdef KERNEL_2_6
698 fattr->atime = iattr->ia_atime.tv_sec;
699 fattr->mtime = iattr->ia_mtime.tv_sec;
700#else
Miklos Szeredi5e183482001-10-31 14:52:35 +0000701 fattr->atime = iattr->ia_atime;
702 fattr->mtime = iattr->ia_mtime;
Miklos Szeredif85ab242004-01-07 12:16:45 +0000703#endif
Miklos Szeredi5e183482001-10-31 14:52:35 +0000704 }
705
706 return fvalid;
707}
708
709static int fuse_setattr(struct dentry *entry, struct iattr *attr)
710{
711 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000712 struct fuse_conn *fc = get_fuse_conn(inode);
713 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi58615e02004-07-04 21:21:08 +0000714 struct fuse_req *req;
Miklos Szeredia181e612001-11-06 12:03:23 +0000715 struct fuse_setattr_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000716 struct fuse_attr_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000717 int err;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000718 int is_truncate = 0;
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000719
Miklos Szeredi94ed76a2004-07-26 19:38:45 +0000720 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
721 err = inode_change_ok(inode, attr);
722 if (err)
723 return err;
724 }
Miklos Szeredi58615e02004-07-04 21:21:08 +0000725
Miklos Szeredi069c9502004-07-16 16:17:02 +0000726 if (attr->ia_valid & ATTR_SIZE) {
727 unsigned long limit;
728 is_truncate = 1;
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000729#ifdef KERNEL_2_6_10_PLUS
Miklos Szeredi08ddb8e2004-11-14 09:19:51 +0000730 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000731#else
732 limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
Miklos Szeredi08ddb8e2004-11-14 09:19:51 +0000733#endif
734 if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
Miklos Szeredi069c9502004-07-16 16:17:02 +0000735 send_sig(SIGXFSZ, current, 0);
736 return -EFBIG;
737 }
Miklos Szeredi069c9502004-07-16 16:17:02 +0000738 }
Miklos Szeredi58615e02004-07-04 21:21:08 +0000739
740 req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000741 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000742 return -ERESTARTNOINTR;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000743
Miklos Szeredi43696432001-11-18 19:15:05 +0000744 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredia181e612001-11-06 12:03:23 +0000745 inarg.valid = iattr_to_fattr(attr, &inarg.attr);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000746 req->in.h.opcode = FUSE_SETATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000747 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000748 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000749 req->in.numargs = 1;
750 req->in.args[0].size = sizeof(inarg);
751 req->in.args[0].value = &inarg;
752 req->out.numargs = 1;
753 req->out.args[0].size = sizeof(outarg);
754 req->out.args[0].value = &outarg;
755 request_send(fc, req);
756 err = req->out.h.error;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000757 fuse_put_request(fc, req);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000758 if (!err) {
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000759 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
760 make_bad_inode(inode);
761 err = -EIO;
762 } else {
763 if (is_truncate) {
764 loff_t origsize = i_size_read(inode);
765 i_size_write(inode, outarg.attr.size);
766 if (origsize > outarg.attr.size)
767 vmtruncate(inode, outarg.attr.size);
768 }
769 fuse_change_attributes(inode, &outarg.attr);
770 fi->i_time = time_to_jiffies(outarg.attr_valid,
771 outarg.attr_valid_nsec);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000772 }
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000773 } else if (err == -EINTR)
774 fuse_invalidate_attr(inode);
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000775
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000776 return err;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000777}
778
Miklos Szeredif85ab242004-01-07 12:16:45 +0000779#ifdef KERNEL_2_6
Miklos Szeredif85ab242004-01-07 12:16:45 +0000780static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
781 struct kstat *stat)
782{
783 struct inode *inode = entry->d_inode;
784 int err = fuse_revalidate(entry);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000785 if (!err)
Miklos Szeredif85ab242004-01-07 12:16:45 +0000786 generic_fillattr(inode, stat);
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000787
Miklos Szeredif85ab242004-01-07 12:16:45 +0000788 return err;
789}
790
791static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Miklos Szeredi83a07442004-11-30 18:25:20 +0000792 struct nameidata *nd)
Miklos Szeredif85ab242004-01-07 12:16:45 +0000793{
Miklos Szeredie815c032004-01-19 18:20:49 +0000794 struct inode *inode;
795 int err = fuse_lookup_iget(dir, entry, &inode);
796 if (err)
797 return ERR_PTR(err);
798 return d_splice_alias(inode, entry);
Miklos Szeredif85ab242004-01-07 12:16:45 +0000799}
Miklos Szeredi689f5632004-05-04 08:49:16 +0000800#else /* KERNEL_2_6 */
Miklos Szeredi689f5632004-05-04 08:49:16 +0000801static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry)
802{
803 struct inode *inode;
804 struct dentry *alias;
805
806 int err = fuse_lookup_iget(dir, entry, &inode);
807 if (err)
808 return ERR_PTR(err);
809
810 if (inode && S_ISDIR(inode->i_mode) &&
811 (alias = d_find_alias(inode)) != NULL) {
812 dput(alias);
813 iput(inode);
Miklos Szeredie56818b2004-12-12 11:45:24 +0000814 return ERR_PTR(-EIO);
Miklos Szeredi689f5632004-05-04 08:49:16 +0000815 }
816
817 d_add(entry, inode);
818 return NULL;
819}
820
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000821static int fuse_mknod_2_4(struct inode *dir, struct dentry *entry, int mode,
Miklos Szeredi83a07442004-11-30 18:25:20 +0000822 int rdev)
Miklos Szeredi689f5632004-05-04 08:49:16 +0000823{
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000824 return fuse_mknod(dir, entry, mode, rdev);
Miklos Szeredi689f5632004-05-04 08:49:16 +0000825}
826
Miklos Szeredi13ed4822004-11-20 11:12:21 +0000827static int fuse_create_2_4(struct inode *dir, struct dentry *entry, int mode)
828{
829 return fuse_create(dir, entry, mode, NULL);
830}
831
832static int fuse_permission_2_4(struct inode *inode, int mask)
833{
834 return fuse_permission(inode, mask, NULL);
Miklos Szeredi689f5632004-05-04 08:49:16 +0000835}
836#endif /* KERNEL_2_6 */
837
838#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi689f5632004-05-04 08:49:16 +0000839#ifdef KERNEL_2_6
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000840static int fuse_setxattr(struct dentry *entry, const char *name,
841 const void *value, size_t size, int flags)
Miklos Szeredi689f5632004-05-04 08:49:16 +0000842#else
843static int fuse_setxattr(struct dentry *entry, const char *name,
844 void *value, size_t size, int flags)
845#endif
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000846{
847 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000848 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000849 struct fuse_req *req;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000850 struct fuse_setxattr_in inarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000851 int err;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000852
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000853 if (size > FUSE_XATTR_SIZE_MAX)
854 return -E2BIG;
855
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000856 if (fc->no_setxattr)
857 return -EOPNOTSUPP;
858
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000859 req = fuse_get_request(fc);
860 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000861 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000862
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000863 memset(&inarg, 0, sizeof(inarg));
864 inarg.size = size;
865 inarg.flags = flags;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000866 req->in.h.opcode = FUSE_SETXATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000867 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000868 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000869 req->in.numargs = 3;
870 req->in.args[0].size = sizeof(inarg);
871 req->in.args[0].value = &inarg;
872 req->in.args[1].size = strlen(name) + 1;
873 req->in.args[1].value = name;
874 req->in.args[2].size = size;
875 req->in.args[2].value = value;
876 request_send(fc, req);
877 err = req->out.h.error;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +0000878 fuse_put_request(fc, req);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000879 if (err == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000880 fc->no_setxattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000881 err = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000882 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000883 return err;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000884}
885
886static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
887 void *value, size_t size)
888{
889 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000890 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000891 struct fuse_req *req;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000892 struct fuse_getxattr_in inarg;
893 struct fuse_getxattr_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000894 ssize_t ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000895
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000896 if (fc->no_getxattr)
897 return -EOPNOTSUPP;
898
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000899 req = fuse_get_request(fc);
900 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000901 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000902
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000903 memset(&inarg, 0, sizeof(inarg));
904 inarg.size = size;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000905 req->in.h.opcode = FUSE_GETXATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000906 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000907 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000908 req->in.numargs = 2;
909 req->in.args[0].size = sizeof(inarg);
910 req->in.args[0].value = &inarg;
911 req->in.args[1].size = strlen(name) + 1;
912 req->in.args[1].value = name;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000913 /* This is really two different operations rolled into one */
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000914 req->out.numargs = 1;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000915 if (size) {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000916 req->out.argvar = 1;
917 req->out.args[0].size = size;
918 req->out.args[0].value = value;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000919 } else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000920 req->out.args[0].size = sizeof(outarg);
921 req->out.args[0].value = &outarg;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000922 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000923 request_send(fc, req);
924 ret = req->out.h.error;
925 if (!ret)
926 ret = size ? req->out.args[0].size : outarg.size;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000927 else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000928 if (ret == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000929 fc->no_getxattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000930 ret = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000931 }
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000932 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000933 fuse_put_request(fc, req);
934 return ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000935}
936
937static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
938{
939 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000940 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000941 struct fuse_req *req;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000942 struct fuse_getxattr_in inarg;
943 struct fuse_getxattr_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000944 ssize_t ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000945
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000946 if (fc->no_listxattr)
947 return -EOPNOTSUPP;
948
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000949 req = fuse_get_request(fc);
950 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000951 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000952
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000953 memset(&inarg, 0, sizeof(inarg));
954 inarg.size = size;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000955 req->in.h.opcode = FUSE_LISTXATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000956 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +0000957 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000958 req->in.numargs = 1;
959 req->in.args[0].size = sizeof(inarg);
960 req->in.args[0].value = &inarg;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000961 /* This is really two different operations rolled into one */
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000962 req->out.numargs = 1;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000963 if (size) {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000964 req->out.argvar = 1;
965 req->out.args[0].size = size;
966 req->out.args[0].value = list;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000967 } else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000968 req->out.args[0].size = sizeof(outarg);
969 req->out.args[0].value = &outarg;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000970 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000971 request_send(fc, req);
972 ret = req->out.h.error;
973 if (!ret)
974 ret = size ? req->out.args[0].size : outarg.size;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000975 else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000976 if (ret == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000977 fc->no_listxattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000978 ret = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000979 }
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000980 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000981 fuse_put_request(fc, req);
982 return ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000983}
984
985static int fuse_removexattr(struct dentry *entry, const char *name)
986{
987 struct inode *inode = entry->d_inode;
Miklos Szeredi039322d2004-12-01 18:39:12 +0000988 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000989 struct fuse_req *req;
990 int err;
Miklos Szerediaa63b6b2004-12-03 13:24:35 +0000991
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +0000992 if (fc->no_removexattr)
993 return -EOPNOTSUPP;
994
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000995 req = fuse_get_request(fc);
996 if (!req)
Miklos Szeredie56818b2004-12-12 11:45:24 +0000997 return -ERESTARTNOINTR;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000998
999 req->in.h.opcode = FUSE_REMOVEXATTR;
Miklos Szeredi039322d2004-12-01 18:39:12 +00001000 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi0f62d722005-01-04 12:45:54 +00001001 req->inode = inode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001002 req->in.numargs = 1;
1003 req->in.args[0].size = strlen(name) + 1;
1004 req->in.args[0].value = name;
1005 request_send(fc, req);
1006 err = req->out.h.error;
Miklos Szeredi0fcfa032004-12-13 15:22:28 +00001007 fuse_put_request(fc, req);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001008 if (err == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001009 fc->no_removexattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001010 err = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001011 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001012 return err;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001013}
Miklos Szeredi689f5632004-05-04 08:49:16 +00001014#endif
Miklos Szeredif85ab242004-01-07 12:16:45 +00001015
Miklos Szeredi13ed4822004-11-20 11:12:21 +00001016static struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +00001017 .lookup = fuse_lookup,
Miklos Szeredie8663f32004-01-13 15:33:12 +00001018 .mkdir = fuse_mkdir,
1019 .symlink = fuse_symlink,
1020 .unlink = fuse_unlink,
1021 .rmdir = fuse_rmdir,
1022 .rename = fuse_rename,
1023 .link = fuse_link,
1024 .setattr = fuse_setattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001025#ifdef KERNEL_2_6
Miklos Szeredi13ed4822004-11-20 11:12:21 +00001026 .create = fuse_create,
1027 .mknod = fuse_mknod,
1028 .permission = fuse_permission,
Miklos Szeredie8663f32004-01-13 15:33:12 +00001029 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001030#else
Miklos Szeredi13ed4822004-11-20 11:12:21 +00001031 .create = fuse_create_2_4,
1032 .mknod = fuse_mknod_2_4,
1033 .permission = fuse_permission_2_4,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001034 .revalidate = fuse_revalidate,
1035#endif
1036#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001037 .setxattr = fuse_setxattr,
1038 .getxattr = fuse_getxattr,
1039 .listxattr = fuse_listxattr,
1040 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001041#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001042};
1043
1044static struct file_operations fuse_dir_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +00001045 .read = generic_read_dir,
1046 .readdir = fuse_readdir,
1047 .open = fuse_dir_open,
1048 .release = fuse_dir_release,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001049};
1050
Miklos Szeredi0f62d722005-01-04 12:45:54 +00001051static struct inode_operations fuse_common_inode_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +00001052 .setattr = fuse_setattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001053#ifdef KERNEL_2_6
Miklos Szeredi13ed4822004-11-20 11:12:21 +00001054 .permission = fuse_permission,
Miklos Szeredie8663f32004-01-13 15:33:12 +00001055 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001056#else
Miklos Szeredi13ed4822004-11-20 11:12:21 +00001057 .permission = fuse_permission_2_4,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001058 .revalidate = fuse_revalidate,
1059#endif
1060#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001061 .setxattr = fuse_setxattr,
1062 .getxattr = fuse_getxattr,
1063 .listxattr = fuse_listxattr,
1064 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001065#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001066};
1067
Miklos Szeredi13ed4822004-11-20 11:12:21 +00001068static struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +00001069 .setattr = fuse_setattr,
Miklos Szeredie8663f32004-01-13 15:33:12 +00001070 .follow_link = fuse_follow_link,
Miklos Szeredi81394522005-01-11 14:24:18 +00001071#ifdef KERNEL_2_6_7_PLUS
1072 .put_link = fuse_put_link,
1073 .readlink = generic_readlink,
1074#else
1075 .readlink = fuse_readlink,
1076#endif
Miklos Szeredif85ab242004-01-07 12:16:45 +00001077#ifdef KERNEL_2_6
Miklos Szeredie8663f32004-01-13 15:33:12 +00001078 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001079#else
1080 .revalidate = fuse_revalidate,
1081#endif
1082#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001083 .setxattr = fuse_setxattr,
1084 .getxattr = fuse_getxattr,
1085 .listxattr = fuse_listxattr,
1086 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001087#endif
Miklos Szeredi19dff1b2001-10-30 15:06:52 +00001088};
1089
Miklos Szeredi0f62d722005-01-04 12:45:54 +00001090void fuse_init_common(struct inode *inode)
1091{
1092 inode->i_op = &fuse_common_inode_operations;
1093}
1094
1095void fuse_init_dir(struct inode *inode)
1096{
1097 inode->i_op = &fuse_dir_inode_operations;
1098 inode->i_fop = &fuse_dir_operations;
1099}
1100
1101void fuse_init_symlink(struct inode *inode)
1102{
1103 inode->i_op = &fuse_symlink_inode_operations;
1104}