blob: ce6df5ddd779c3ea489fa88630207c107234d4d6 [file] [log] [blame]
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001/*
2 FUSE: Filesystem in Userspace
Miklos Szeredi2e6b6f22004-07-07 19:19:53 +00003 Copyright (C) 2001-2004 Miklos Szeredi <miklos@szeredi.hu>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00004
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 Szeredia13d9002004-11-02 17:32:03 +000038 inode->i_ino = attr->ino;
Miklos Szeredi5e183482001-10-31 14:52:35 +000039 inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000040 inode->i_nlink = attr->nlink;
41 inode->i_uid = attr->uid;
42 inode->i_gid = attr->gid;
Miklos Szeredid1199f82004-02-06 15:29:22 +000043 i_size_write(inode, attr->size);
Miklos Szeredi05033042001-11-13 16:11:35 +000044 inode->i_blksize = PAGE_CACHE_SIZE;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000045 inode->i_blocks = attr->blocks;
Miklos Szeredif85ab242004-01-07 12:16:45 +000046#ifdef KERNEL_2_6
47 inode->i_atime.tv_sec = attr->atime;
Miklos Szeredib5958612004-02-20 14:10:49 +000048 inode->i_atime.tv_nsec = attr->atimensec;
Miklos Szeredif85ab242004-01-07 12:16:45 +000049 inode->i_mtime.tv_sec = attr->mtime;
Miklos Szeredib5958612004-02-20 14:10:49 +000050 inode->i_mtime.tv_nsec = attr->mtimensec;
Miklos Szeredif85ab242004-01-07 12:16:45 +000051 inode->i_ctime.tv_sec = attr->ctime;
Miklos Szeredib5958612004-02-20 14:10:49 +000052 inode->i_ctime.tv_nsec = attr->ctimensec;
Miklos Szeredif85ab242004-01-07 12:16:45 +000053#else
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000054 inode->i_atime = attr->atime;
55 inode->i_mtime = attr->mtime;
56 inode->i_ctime = attr->ctime;
Miklos Szeredif85ab242004-01-07 12:16:45 +000057#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000058}
59
Miklos Szeredia181e612001-11-06 12:03:23 +000060static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000061{
Miklos Szeredia181e612001-11-06 12:03:23 +000062 inode->i_mode = attr->mode & S_IFMT;
Miklos Szeredid1199f82004-02-06 15:29:22 +000063 i_size_write(inode, attr->size);
Miklos Szeredic26c14d2004-04-09 17:48:32 +000064 if (S_ISREG(inode->i_mode)) {
Miklos Szeredib483c932001-10-29 14:57:57 +000065 inode->i_op = &fuse_file_inode_operations;
Miklos Szeredi5e183482001-10-31 14:52:35 +000066 fuse_init_file_inode(inode);
Miklos Szeredib483c932001-10-29 14:57:57 +000067 }
Miklos Szeredic26c14d2004-04-09 17:48:32 +000068 else if (S_ISDIR(inode->i_mode)) {
Miklos Szeredib483c932001-10-29 14:57:57 +000069 inode->i_op = &fuse_dir_inode_operations;
70 inode->i_fop = &fuse_dir_operations;
71 }
Miklos Szeredic26c14d2004-04-09 17:48:32 +000072 else if (S_ISLNK(inode->i_mode)) {
Miklos Szeredib483c932001-10-29 14:57:57 +000073 inode->i_op = &fuse_symlink_inode_operations;
Miklos Szeredi5e183482001-10-31 14:52:35 +000074 }
Miklos Szeredic26c14d2004-04-09 17:48:32 +000075 else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
76 S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)){
Miklos Szeredia181e612001-11-06 12:03:23 +000077 inode->i_op = &fuse_file_inode_operations;
Miklos Szeredi7c35cf92004-01-14 16:56:49 +000078 init_special_inode(inode, inode->i_mode,
79 new_decode_dev(attr->rdev));
Miklos Szeredi76f65782004-02-19 16:55:40 +000080 } else
81 printk("fuse_init_inode: bad file type: %o\n", inode->i_mode);
Miklos Szeredi5e183482001-10-31 14:52:35 +000082}
83
Miklos Szeredia13d9002004-11-02 17:32:03 +000084#ifdef KERNEL_2_6
85static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
86{
87 unsigned long nodeid = *(unsigned long *) _nodeidp;
88 struct fuse_inode *fi = INO_FI(inode);
89 if (fi->nodeid == nodeid)
90 return 1;
91 else
92 return 0;
93}
94
95static int fuse_inode_set(struct inode *inode, void *_nodeidp)
96{
97 unsigned long nodeid = *(unsigned long *) _nodeidp;
98 struct fuse_inode *fi = INO_FI(inode);
99 fi->nodeid = nodeid;
100 return 0;
101}
102
103struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
104 int generation, struct fuse_attr *attr, int version)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000105{
106 struct inode *inode;
107
Miklos Szeredia13d9002004-11-02 17:32:03 +0000108 inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid);
109 if (!inode)
110 return NULL;
Miklos Szeredie815c032004-01-19 18:20:49 +0000111
Miklos Szeredia13d9002004-11-02 17:32:03 +0000112 if ((inode->i_state & I_NEW)) {
113 inode->i_generation = generation;
114 fuse_init_inode(inode, attr);
115 unlock_new_inode(inode);
116 } else if (inode->i_generation != generation)
117 printk("fuse_iget: bad generation for node %lu\n", nodeid);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000118
Miklos Szeredia13d9002004-11-02 17:32:03 +0000119 change_attributes(inode, attr);
120 inode->i_version = version;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000121 return inode;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000122}
123
Miklos Szeredia13d9002004-11-02 17:32:03 +0000124struct inode *fuse_ilookup(struct fuse_conn *fc, ino_t ino, unsigned long nodeid)
125{
126 return ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid);
127}
128#else
129static int fuse_inode_eq(struct inode *inode, unsigned long ino, void *_nodeidp){
130 unsigned long nodeid = *(unsigned long *) _nodeidp;
131 struct fuse_inode *fi = INO_FI(inode);
132 if (inode->u.generic_ip && fi->nodeid == nodeid)
133 return 1;
134 else
135 return 0;
136}
137
138struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
139 int generation, struct fuse_attr *attr, int version)
140{
141 struct inode *inode;
142
143 inode = iget4(sb, attr->ino, fuse_inode_eq, &nodeid);
144 if (!inode)
145 return NULL;
146
147 if (!inode->u.generic_ip) {
148 struct fuse_inode *fi = INO_FI(inode);
149 fi->nodeid = nodeid;
150 inode->u.generic_ip = inode;
151 inode->i_generation = generation;
152 fuse_init_inode(inode, attr);
153 } else if (inode->i_generation != generation)
154 printk("fuse_iget: bad generation for node %lu\n", nodeid);
155
156 change_attributes(inode, attr);
157 inode->i_version = version;
158 return inode;
159}
160
161struct inode *fuse_ilookup(struct fuse_conn *fc, ino_t ino, unsigned long nodeid)
162{
163 struct inode *inode = iget4(fc->sb, ino, fuse_inode_eq, &nodeid);
164 if (inode && !inode->u.generic_ip) {
165 iput(inode);
166 inode = NULL;
167 }
168 return inode;
169}
170
171#endif
172
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000173static int fuse_send_lookup(struct fuse_conn *fc, struct fuse_req *req,
174 struct inode *dir, struct dentry *entry,
175 struct fuse_entry_out *outarg, int *version)
176{
Miklos Szeredia13d9002004-11-02 17:32:03 +0000177 struct fuse_inode *fi = INO_FI(dir);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000178 req->in.h.opcode = FUSE_LOOKUP;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000179 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000180 req->in.numargs = 1;
181 req->in.args[0].size = entry->d_name.len + 1;
182 req->in.args[0].value = entry->d_name.name;
183 req->out.numargs = 1;
184 req->out.args[0].size = sizeof(struct fuse_entry_out);
185 req->out.args[0].value = outarg;
186 request_send(fc, req);
187 *version = req->out.h.unique;
188 return req->out.h.error;
189}
190
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000191static int fuse_do_lookup(struct inode *dir, struct dentry *entry,
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000192 struct fuse_entry_out *outarg, int *version)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000193{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000194 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000195 struct fuse_req *req;
196 int err;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000197
198 if (entry->d_name.len > FUSE_NAME_MAX)
199 return -ENAMETOOLONG;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000200 req = fuse_get_request(fc);
201 if (!req)
202 return -ERESTARTSYS;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000203
204 err = fuse_send_lookup(fc, req, dir, entry, outarg, version);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000205 fuse_put_request(fc, req);
206 return err;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000207}
208
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000209static inline unsigned long time_to_jiffies(unsigned long sec,
210 unsigned long nsec)
211{
212 /* prevent wrapping of jiffies */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000213 if (sec + 1 >= LONG_MAX / HZ)
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000214 return 0;
215
216 return jiffies + sec * HZ + nsec / (1000000000 / HZ);
217}
218
Miklos Szeredie815c032004-01-19 18:20:49 +0000219static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
220 struct inode **inodep)
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000221{
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000222 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredie815c032004-01-19 18:20:49 +0000223 int err;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000224 struct fuse_entry_out outarg;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000225 int version;
Miklos Szeredie815c032004-01-19 18:20:49 +0000226 struct inode *inode = NULL;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000227 struct fuse_req *req;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000228
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000229 if (entry->d_name.len > FUSE_NAME_MAX)
230 return -ENAMETOOLONG;
231 req = fuse_get_request(fc);
232 if (!req)
233 return -ERESTARTSYS;
234
235 err = fuse_send_lookup(fc, req, dir, entry, &outarg, &version);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000236 if (!err) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000237 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi76f65782004-02-19 16:55:40 +0000238 &outarg.attr, version);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000239 if (!inode) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000240 fuse_send_forget(fc, req, outarg.nodeid, version);
Miklos Szeredie815c032004-01-19 18:20:49 +0000241 return -ENOMEM;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000242 }
243 }
244 fuse_put_request(fc, req);
245 if (err && err != -ENOENT)
Miklos Szeredie815c032004-01-19 18:20:49 +0000246 return err;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000247
Miklos Szeredi069c9502004-07-16 16:17:02 +0000248 if (inode) {
249 struct fuse_inode *fi = INO_FI(inode);
250 entry->d_time = time_to_jiffies(outarg.entry_valid,
Miklos Szerediad051c32004-07-02 09:22:50 +0000251 outarg.entry_valid_nsec);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000252 fi->i_time = time_to_jiffies(outarg.attr_valid,
253 outarg.attr_valid_nsec);
254 }
Miklos Szerediad051c32004-07-02 09:22:50 +0000255
Miklos Szeredi307242f2004-01-26 11:28:44 +0000256 entry->d_op = &fuse_dentry_operations;
Miklos Szeredie815c032004-01-19 18:20:49 +0000257 *inodep = inode;
258 return 0;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000259}
260
Miklos Szeredi069c9502004-07-16 16:17:02 +0000261static void fuse_invalidate_attr(struct inode *inode)
Miklos Szeredi015fe702004-07-12 11:52:24 +0000262{
Miklos Szeredi069c9502004-07-16 16:17:02 +0000263 struct fuse_inode *fi = INO_FI(inode);
264 fi->i_time = jiffies - 1;
Miklos Szeredi015fe702004-07-12 11:52:24 +0000265}
266
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000267static int lookup_new_entry(struct fuse_conn *fc, struct fuse_req *req,
268 struct inode *dir, struct dentry *entry,
269 struct fuse_entry_out *outarg, int version,
270 int mode)
Miklos Szeredi76f65782004-02-19 16:55:40 +0000271{
272 struct inode *inode;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000273 struct fuse_inode *fi;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000274 inode = fuse_iget(dir->i_sb, outarg->nodeid, outarg->generation,
Miklos Szeredi76f65782004-02-19 16:55:40 +0000275 &outarg->attr, version);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000276 if (!inode) {
Miklos Szeredia13d9002004-11-02 17:32:03 +0000277 fuse_send_forget(fc, req, outarg->nodeid, version);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000278 return -ENOMEM;
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000279 }
280 fuse_put_request(fc, req);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000281
282 /* Don't allow userspace to do really stupid things... */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000283 if ((inode->i_mode ^ mode) & S_IFMT) {
Miklos Szeredi76f65782004-02-19 16:55:40 +0000284 iput(inode);
285 printk("fuse_mknod: inode has wrong type\n");
286 return -EINVAL;
287 }
288
Miklos Szerediad051c32004-07-02 09:22:50 +0000289 entry->d_time = time_to_jiffies(outarg->entry_valid,
290 outarg->entry_valid_nsec);
291
Miklos Szeredi069c9502004-07-16 16:17:02 +0000292 fi = INO_FI(inode);
293 fi->i_time = time_to_jiffies(outarg->attr_valid,
294 outarg->attr_valid_nsec);
295
Miklos Szeredi76f65782004-02-19 16:55:40 +0000296 d_instantiate(entry, inode);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000297 fuse_invalidate_attr(dir);
Miklos Szeredi76f65782004-02-19 16:55:40 +0000298 return 0;
299}
300
301
Miklos Szeredif85ab242004-01-07 12:16:45 +0000302static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
303 dev_t rdev)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000304{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000305 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000306 struct fuse_inode *fi = INO_FI(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000307 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi43696432001-11-18 19:15:05 +0000308 struct fuse_mknod_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000309 struct fuse_entry_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000310 int err;
311
312 if (!req)
313 return -ERESTARTSYS;
Miklos Szeredi43696432001-11-18 19:15:05 +0000314
315 memset(&inarg, 0, sizeof(inarg));
316 inarg.mode = mode;
Miklos Szeredi7c35cf92004-01-14 16:56:49 +0000317 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000318 req->in.h.opcode = FUSE_MKNOD;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000319 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000320 req->in.numargs = 2;
321 req->in.args[0].size = sizeof(inarg);
322 req->in.args[0].value = &inarg;
323 req->in.args[1].size = entry->d_name.len + 1;
324 req->in.args[1].value = entry->d_name.name;
325 req->out.numargs = 1;
326 req->out.args[0].size = sizeof(outarg);
327 req->out.args[0].value = &outarg;
328 request_send(fc, req);
329 err = req->out.h.error;
330 if (!err)
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000331 err = lookup_new_entry(fc, req, dir, entry, &outarg,
332 req->out.h.unique, mode);
333 else
334 fuse_put_request(fc, req);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000335 return err;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000336}
337
Miklos Szeredif85ab242004-01-07 12:16:45 +0000338static int _fuse_create(struct inode *dir, struct dentry *entry, int mode)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000339{
Miklos Szeredif85ab242004-01-07 12:16:45 +0000340 return _fuse_mknod(dir, entry, mode, 0);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000341}
342
Miklos Szeredie815c032004-01-19 18:20:49 +0000343
Miklos Szeredib483c932001-10-29 14:57:57 +0000344static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
345{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000346 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000347 struct fuse_inode *fi = INO_FI(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000348 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi43696432001-11-18 19:15:05 +0000349 struct fuse_mkdir_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000350 struct fuse_entry_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000351 int err;
352
353 if (!req)
354 return -ERESTARTSYS;
Miklos Szeredi43696432001-11-18 19:15:05 +0000355
356 memset(&inarg, 0, sizeof(inarg));
357 inarg.mode = mode;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000358 req->in.h.opcode = FUSE_MKDIR;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000359 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000360 req->in.numargs = 2;
361 req->in.args[0].size = sizeof(inarg);
362 req->in.args[0].value = &inarg;
363 req->in.args[1].size = entry->d_name.len + 1;
364 req->in.args[1].value = entry->d_name.name;
365 req->out.numargs = 1;
366 req->out.args[0].size = sizeof(outarg);
367 req->out.args[0].value = &outarg;
368 request_send(fc, req);
369 err = req->out.h.error;
370 if (!err)
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000371 err = lookup_new_entry(fc, req, dir, entry, &outarg,
372 req->out.h.unique, S_IFDIR);
373 else
374 fuse_put_request(fc, req);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000375 return err;
Miklos Szeredib483c932001-10-29 14:57:57 +0000376}
377
378static int fuse_symlink(struct inode *dir, struct dentry *entry,
379 const char *link)
380{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000381 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000382 struct fuse_inode *fi = INO_FI(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000383 struct fuse_req *req;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000384 struct fuse_entry_out outarg;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000385 unsigned int len = strlen(link) + 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000386 int err;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000387
388 if (len > FUSE_SYMLINK_MAX)
389 return -ENAMETOOLONG;
Miklos Szeredib483c932001-10-29 14:57:57 +0000390
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000391 req = fuse_get_request(fc);
392 if (!req)
393 return -ERESTARTSYS;
Miklos Szeredi43696432001-11-18 19:15:05 +0000394
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000395 req->in.h.opcode = FUSE_SYMLINK;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000396 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000397 req->in.numargs = 2;
398 req->in.args[0].size = entry->d_name.len + 1;
399 req->in.args[0].value = entry->d_name.name;
400 req->in.args[1].size = len;
401 req->in.args[1].value = link;
402 req->out.numargs = 1;
403 req->out.args[0].size = sizeof(outarg);
404 req->out.args[0].value = &outarg;
405 request_send(fc, req);
406 err = req->out.h.error;
407 if (!err)
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000408 err = lookup_new_entry(fc, req, dir, entry, &outarg,
409 req->out.h.unique, S_IFLNK);
410 else
411 fuse_put_request(fc, req);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000412 return err;
Miklos Szeredib483c932001-10-29 14:57:57 +0000413}
414
Miklos Szeredib5958612004-02-20 14:10:49 +0000415static int fuse_unlink(struct inode *dir, struct dentry *entry)
Miklos Szeredib483c932001-10-29 14:57:57 +0000416{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000417 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000418 struct fuse_inode *fi = INO_FI(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000419 struct fuse_req *req = fuse_get_request(fc);
420 int err;
421
422 if (!req)
423 return -ERESTARTSYS;
Miklos Szeredib483c932001-10-29 14:57:57 +0000424
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000425 req->in.h.opcode = FUSE_UNLINK;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000426 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000427 req->in.numargs = 1;
428 req->in.args[0].size = entry->d_name.len + 1;
429 req->in.args[0].value = entry->d_name.name;
430 request_send(fc, req);
431 err = req->out.h.error;
432 if (!err) {
Miklos Szeredi069c9502004-07-16 16:17:02 +0000433 struct inode *inode = entry->d_inode;
434
Miklos Szeredib5958612004-02-20 14:10:49 +0000435 /* Set nlink to zero so the inode can be cleared, if
436 the inode does have more links this will be
437 discovered at the next lookup/getattr */
Miklos Szeredi069c9502004-07-16 16:17:02 +0000438 inode->i_nlink = 0;
439 fuse_invalidate_attr(inode);
440 fuse_invalidate_attr(dir);
Miklos Szeredif4f8b892004-01-27 17:04:59 +0000441 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000442 fuse_put_request(fc, req);
443 return err;
Miklos Szeredib483c932001-10-29 14:57:57 +0000444}
445
446static int fuse_rmdir(struct inode *dir, struct dentry *entry)
447{
Miklos Szeredib5958612004-02-20 14:10:49 +0000448 struct fuse_conn *fc = INO_FC(dir);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000449 struct fuse_inode *fi = INO_FI(dir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000450 struct fuse_req *req = fuse_get_request(fc);
451 int err;
452
453 if (!req)
454 return -ERESTARTSYS;
Miklos Szeredib5958612004-02-20 14:10:49 +0000455
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000456 req->in.h.opcode = FUSE_RMDIR;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000457 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000458 req->in.numargs = 1;
459 req->in.args[0].size = entry->d_name.len + 1;
460 req->in.args[0].value = entry->d_name.name;
461 request_send(fc, req);
462 err = req->out.h.error;
Miklos Szeredi015fe702004-07-12 11:52:24 +0000463 if (!err) {
Miklos Szeredif4f8b892004-01-27 17:04:59 +0000464 entry->d_inode->i_nlink = 0;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000465 fuse_invalidate_attr(dir);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000466 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000467 fuse_put_request(fc, req);
468 return err;
Miklos Szeredib483c932001-10-29 14:57:57 +0000469}
470
471static int fuse_rename(struct inode *olddir, struct dentry *oldent,
472 struct inode *newdir, struct dentry *newent)
473{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000474 struct fuse_conn *fc = INO_FC(olddir);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000475 struct fuse_inode *oldfi = INO_FI(olddir);
476 struct fuse_inode *newfi = INO_FI(newdir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000477 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi43696432001-11-18 19:15:05 +0000478 struct fuse_rename_in inarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000479 int err;
480
481 if (!req)
482 return -ERESTARTSYS;
483
Miklos Szeredi43696432001-11-18 19:15:05 +0000484 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredia13d9002004-11-02 17:32:03 +0000485 inarg.newdir = newfi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000486 req->in.h.opcode = FUSE_RENAME;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000487 req->in.h.nodeid = oldfi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000488 req->in.numargs = 3;
489 req->in.args[0].size = sizeof(inarg);
490 req->in.args[0].value = &inarg;
491 req->in.args[1].size = oldent->d_name.len + 1;
492 req->in.args[1].value = oldent->d_name.name;
493 req->in.args[2].size = newent->d_name.len + 1;
494 req->in.args[2].value = newent->d_name.name;
495 request_send(fc, req);
496 err = req->out.h.error;
497 fuse_put_request(fc, req);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000498 if (!err) {
Miklos Szeredi069c9502004-07-16 16:17:02 +0000499 fuse_invalidate_attr(olddir);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000500 if (olddir != newdir)
Miklos Szeredi069c9502004-07-16 16:17:02 +0000501 fuse_invalidate_attr(newdir);
Miklos Szeredi015fe702004-07-12 11:52:24 +0000502 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000503 return err;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000504}
505
506static int fuse_link(struct dentry *entry, struct inode *newdir,
507 struct dentry *newent)
508{
509 struct inode *inode = entry->d_inode;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000510 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000511 struct fuse_inode *fi = INO_FI(inode);
512 struct fuse_inode *newfi = INO_FI(newdir);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000513 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi43696432001-11-18 19:15:05 +0000514 struct fuse_link_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000515 struct fuse_entry_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000516 int err;
517
518 if (!req)
519 return -ERESTARTSYS;
520
Miklos Szeredi43696432001-11-18 19:15:05 +0000521 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredia13d9002004-11-02 17:32:03 +0000522 inarg.newdir = newfi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000523 req->in.h.opcode = FUSE_LINK;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000524 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000525 req->in.numargs = 2;
526 req->in.args[0].size = sizeof(inarg);
527 req->in.args[0].value = &inarg;
528 req->in.args[1].size = newent->d_name.len + 1;
529 req->in.args[1].value = newent->d_name.name;
530 req->out.numargs = 1;
531 req->out.args[0].size = sizeof(outarg);
532 req->out.args[0].value = &outarg;
533 request_send(fc, req);
534 err = req->out.h.error;
535 if (!err) {
536 /* Invalidate old entry, so attributes are refreshed */
537 d_invalidate(entry);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000538 err = lookup_new_entry(fc, req, newdir, newent, &outarg,
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000539 req->out.h.unique, inode->i_mode);
Miklos Szeredi2778f6c2004-06-21 09:45:30 +0000540 } else
541 fuse_put_request(fc, req);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000542 return err;
Miklos Szeredib483c932001-10-29 14:57:57 +0000543}
544
Miklos Szeredif85ab242004-01-07 12:16:45 +0000545int fuse_do_getattr(struct inode *inode)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000546{
Miklos Szeredi069c9502004-07-16 16:17:02 +0000547 struct fuse_inode *fi = INO_FI(inode);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000548 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000549 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000550 struct fuse_attr_out arg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000551 int err;
552
553 if (!req)
554 return -ERESTARTSYS;
555
556 req->in.h.opcode = FUSE_GETATTR;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000557 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000558 req->out.numargs = 1;
559 req->out.args[0].size = sizeof(arg);
560 req->out.args[0].value = &arg;
561 request_send(fc, req);
562 err = req->out.h.error;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000563 if (!err) {
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000564 change_attributes(inode, &arg.attr);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000565 fi->i_time = time_to_jiffies(arg.attr_valid,
566 arg.attr_valid_nsec);
567 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000568 fuse_put_request(fc, req);
569 return err;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000570}
571
Miklos Szeredife25def2001-12-20 15:38:05 +0000572static int fuse_revalidate(struct dentry *entry)
573{
574 struct inode *inode = entry->d_inode;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000575 struct fuse_inode *fi = INO_FI(inode);
Miklos Szeredife25def2001-12-20 15:38:05 +0000576 struct fuse_conn *fc = INO_FC(inode);
577
Miklos Szeredia13d9002004-11-02 17:32:03 +0000578 if (fi->nodeid == FUSE_ROOT_ID) {
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000579 if (!(fc->flags & FUSE_ALLOW_OTHER) &&
Miklos Szeredi180ff692004-11-01 16:01:05 +0000580 current->fsuid != fc->uid &&
581 (!(fc->flags & FUSE_ALLOW_ROOT) ||
582 current->fsuid != 0))
Miklos Szeredife25def2001-12-20 15:38:05 +0000583 return -EACCES;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000584 } else if (!fi->i_time || time_before_eq(jiffies, fi->i_time))
Miklos Szeredife25def2001-12-20 15:38:05 +0000585 return 0;
586
Miklos Szeredif85ab242004-01-07 12:16:45 +0000587 return fuse_do_getattr(inode);
Miklos Szeredife25def2001-12-20 15:38:05 +0000588}
589
Miklos Szeredif85ab242004-01-07 12:16:45 +0000590static int _fuse_permission(struct inode *inode, int mask)
Miklos Szeredife25def2001-12-20 15:38:05 +0000591{
592 struct fuse_conn *fc = INO_FC(inode);
593
Miklos Szeredi180ff692004-11-01 16:01:05 +0000594 if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->uid &&
595 (!(fc->flags & FUSE_ALLOW_ROOT) || current->fsuid != 0))
Miklos Szeredife25def2001-12-20 15:38:05 +0000596 return -EACCES;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000597 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Miklos Szeredife25def2001-12-20 15:38:05 +0000598 int err = vfs_permission(inode, mask);
599
600 /* If permission is denied, try to refresh file
601 attributes. This is also needed, because the root
602 node will at first have no permissions */
603
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000604 if (err == -EACCES) {
Miklos Szeredif85ab242004-01-07 12:16:45 +0000605 err = fuse_do_getattr(inode);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000606 if (!err)
Miklos Szeredife25def2001-12-20 15:38:05 +0000607 err = vfs_permission(inode, mask);
608 }
609
610 /* FIXME: Need some mechanism to revoke permissions:
611 currently if the filesystem suddenly changes the
612 file mode, we will not be informed abot that, and
613 continue to allow access to the file/directory.
614
615 This is actually not so grave, since the user can
616 simply keep access to the file/directory anyway by
617 keeping it open... */
618
619 return err;
Miklos Szeredi69cc79a2004-02-17 08:57:29 +0000620 } else
Miklos Szeredife25def2001-12-20 15:38:05 +0000621 return 0;
622}
623
Miklos Szeredib483c932001-10-29 14:57:57 +0000624static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
625 void *dstbuf, filldir_t filldir)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000626{
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000627 while (nbytes >= FUSE_NAME_OFFSET) {
Miklos Szeredib483c932001-10-29 14:57:57 +0000628 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000629 size_t reclen = FUSE_DIRENT_SIZE(dirent);
630 int over;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000631 if (dirent->namelen > NAME_MAX) {
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000632 printk("fuse_readdir: name too long\n");
Miklos Szeredib483c932001-10-29 14:57:57 +0000633 return -EPROTO;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000634 }
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000635 if (reclen > nbytes)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000636 break;
637
638 over = filldir(dstbuf, dirent->name, dirent->namelen,
639 file->f_pos, dirent->ino, dirent->type);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000640 if (over)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000641 break;
642
Miklos Szeredib483c932001-10-29 14:57:57 +0000643 buf += reclen;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000644 file->f_pos += reclen;
645 nbytes -= reclen;
646 }
647
Miklos Szeredib483c932001-10-29 14:57:57 +0000648 return 0;
649}
650
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000651static int fuse_checkdir(struct file *cfile, struct file *file)
652{
653 struct inode *inode;
654 if (!cfile) {
655 printk("fuse_getdir: invalid file\n");
656 return -EPROTO;
657 }
658 inode = cfile->f_dentry->d_inode;
659 if (!S_ISREG(inode->i_mode)) {
660 printk("fuse_getdir: not a regular file\n");
661 fput(cfile);
662 return -EPROTO;
663 }
664
665 file->private_data = cfile;
666 return 0;
667}
668
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000669static int fuse_getdir(struct file *file)
670{
671 struct inode *inode = file->f_dentry->d_inode;
672 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000673 struct fuse_inode *fi = INO_FI(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000674 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000675 struct fuse_getdir_out_i outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000676 int err;
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000677
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000678 if (!req)
679 return -ERESTARTSYS;
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000680
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000681 req->in.h.opcode = FUSE_GETDIR;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000682 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000683 req->out.numargs = 1;
684 req->out.args[0].size = sizeof(struct fuse_getdir_out);
685 req->out.args[0].value = &outarg;
686 request_send(fc, req);
687 err = req->out.h.error;
688 if (!err)
689 err = fuse_checkdir(outarg.file, file);
690 fuse_put_request(fc, req);
691 return err;
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000692}
693
Miklos Szeredib483c932001-10-29 14:57:57 +0000694#define DIR_BUFSIZE 2048
695static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
696{
697 struct file *cfile = file->private_data;
698 char *buf;
699 int ret;
Miklos Szeredie815c032004-01-19 18:20:49 +0000700
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000701 if (!cfile) {
702 ret = fuse_getdir(file);
703 if (ret)
704 return ret;
705
706 cfile = file->private_data;
707 }
Miklos Szeredie815c032004-01-19 18:20:49 +0000708
Miklos Szeredib483c932001-10-29 14:57:57 +0000709 buf = kmalloc(DIR_BUFSIZE, GFP_KERNEL);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000710 if (!buf)
Miklos Szeredib483c932001-10-29 14:57:57 +0000711 return -ENOMEM;
Miklos Szeredie815c032004-01-19 18:20:49 +0000712
Miklos Szeredib483c932001-10-29 14:57:57 +0000713 ret = kernel_read(cfile, file->f_pos, buf, DIR_BUFSIZE);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000714 if (ret < 0)
Miklos Szeredib483c932001-10-29 14:57:57 +0000715 printk("fuse_readdir: failed to read container file\n");
716 else
717 ret = parse_dirfile(buf, ret, file, dstbuf, filldir);
718
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000719 kfree(buf);
720 return ret;
721}
722
Miklos Szeredi05033042001-11-13 16:11:35 +0000723static char *read_link(struct dentry *dentry)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000724{
725 struct inode *inode = dentry->d_inode;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000726 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredia13d9002004-11-02 17:32:03 +0000727 struct fuse_inode *fi = INO_FI(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000728 struct fuse_req *req = fuse_get_request(fc);
Miklos Szeredi05033042001-11-13 16:11:35 +0000729 char *link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000730
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000731 if (!req)
732 return ERR_PTR(-ERESTARTSYS);
733
Miklos Szeredi05033042001-11-13 16:11:35 +0000734 link = (char *) __get_free_page(GFP_KERNEL);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000735 if (!link) {
736 link = ERR_PTR(-ENOMEM);
737 goto out;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000738 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000739 req->in.h.opcode = FUSE_READLINK;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000740 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000741 req->out.argvar = 1;
742 req->out.numargs = 1;
743 req->out.args[0].size = PAGE_SIZE - 1;
744 req->out.args[0].value = link;
745 request_send(fc, req);
746 if (req->out.h.error) {
747 free_page((unsigned long) link);
748 link = ERR_PTR(req->out.h.error);
749 } else
750 link[req->out.args[0].size] = '\0';
751 out:
752 fuse_put_request(fc, req);
Miklos Szeredi05033042001-11-13 16:11:35 +0000753 return link;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000754}
755
756static void free_link(char *link)
757{
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000758 if (!IS_ERR(link))
Miklos Szeredi05033042001-11-13 16:11:35 +0000759 free_page((unsigned long) link);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000760}
761
762static int fuse_readlink(struct dentry *dentry, char *buffer, int buflen)
763{
764 int ret;
765 char *link;
766
Miklos Szeredi05033042001-11-13 16:11:35 +0000767 link = read_link(dentry);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000768 ret = vfs_readlink(dentry, buffer, buflen, link);
769 free_link(link);
770 return ret;
771}
772
773static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
774{
775 int ret;
776 char *link;
777
Miklos Szeredi05033042001-11-13 16:11:35 +0000778 link = read_link(dentry);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000779 ret = vfs_follow_link(nd, link);
780 free_link(link);
781 return ret;
782}
783
784static int fuse_dir_open(struct inode *inode, struct file *file)
785{
Miklos Szeredi152f29e2004-06-03 17:52:32 +0000786 file->private_data = NULL;
787 return 0;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000788}
789
790static int fuse_dir_release(struct inode *inode, struct file *file)
791{
792 struct file *cfile = file->private_data;
Miklos Szeredia181e612001-11-06 12:03:23 +0000793
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000794 if (cfile)
Miklos Szeredia181e612001-11-06 12:03:23 +0000795 fput(cfile);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000796
797 return 0;
798}
799
Miklos Szeredi5e183482001-10-31 14:52:35 +0000800static unsigned int iattr_to_fattr(struct iattr *iattr,
801 struct fuse_attr *fattr)
802{
803 unsigned int ivalid = iattr->ia_valid;
804 unsigned int fvalid = 0;
805
806 memset(fattr, 0, sizeof(*fattr));
807
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000808 if (ivalid & ATTR_MODE)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000809 fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000810 if (ivalid & ATTR_UID)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000811 fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000812 if (ivalid & ATTR_GID)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000813 fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000814 if (ivalid & ATTR_SIZE)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000815 fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
816 /* You can only _set_ these together (they may change by themselves) */
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000817 if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
Miklos Szeredib5958612004-02-20 14:10:49 +0000818 fvalid |= FATTR_ATIME | FATTR_MTIME;
Miklos Szeredif85ab242004-01-07 12:16:45 +0000819#ifdef KERNEL_2_6
820 fattr->atime = iattr->ia_atime.tv_sec;
821 fattr->mtime = iattr->ia_mtime.tv_sec;
822#else
Miklos Szeredi5e183482001-10-31 14:52:35 +0000823 fattr->atime = iattr->ia_atime;
824 fattr->mtime = iattr->ia_mtime;
Miklos Szeredif85ab242004-01-07 12:16:45 +0000825#endif
Miklos Szeredi5e183482001-10-31 14:52:35 +0000826 }
827
828 return fvalid;
829}
830
831static int fuse_setattr(struct dentry *entry, struct iattr *attr)
832{
833 struct inode *inode = entry->d_inode;
834 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000835 struct fuse_inode *fi = INO_FI(inode);
Miklos Szeredi58615e02004-07-04 21:21:08 +0000836 struct fuse_req *req;
Miklos Szeredia181e612001-11-06 12:03:23 +0000837 struct fuse_setattr_in inarg;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000838 struct fuse_attr_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000839 int err;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000840 int is_truncate = 0;
841
Miklos Szeredi94ed76a2004-07-26 19:38:45 +0000842 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
843 err = inode_change_ok(inode, attr);
844 if (err)
845 return err;
846 }
Miklos Szeredi58615e02004-07-04 21:21:08 +0000847
Miklos Szeredi069c9502004-07-16 16:17:02 +0000848 if (attr->ia_valid & ATTR_SIZE) {
849 unsigned long limit;
850 is_truncate = 1;
851
852 limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
853 if (limit != RLIM_INFINITY && attr->ia_size > limit) {
854 send_sig(SIGXFSZ, current, 0);
855 return -EFBIG;
856 }
857 //fuse_sync_inode(inode);
858 }
Miklos Szeredi58615e02004-07-04 21:21:08 +0000859
860 req = fuse_get_request(fc);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000861 if (!req)
862 return -ERESTARTSYS;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000863
Miklos Szeredi069c9502004-07-16 16:17:02 +0000864 if (is_truncate)
865 down_write(&fi->write_sem);
866
Miklos Szeredi43696432001-11-18 19:15:05 +0000867 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredia181e612001-11-06 12:03:23 +0000868 inarg.valid = iattr_to_fattr(attr, &inarg.attr);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000869 req->in.h.opcode = FUSE_SETATTR;
Miklos Szeredia13d9002004-11-02 17:32:03 +0000870 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000871 req->in.numargs = 1;
872 req->in.args[0].size = sizeof(inarg);
873 req->in.args[0].value = &inarg;
874 req->out.numargs = 1;
875 req->out.args[0].size = sizeof(outarg);
876 req->out.args[0].value = &outarg;
877 request_send(fc, req);
878 err = req->out.h.error;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000879 fuse_put_request(fc, req);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000880
881 if (!err) {
882 if (is_truncate) {
883 loff_t origsize = i_size_read(inode);
884 i_size_write(inode, outarg.attr.size);
885 up_write(&fi->write_sem);
886 if (origsize > outarg.attr.size)
887 vmtruncate(inode, outarg.attr.size);
888 }
889 change_attributes(inode, &outarg.attr);
890 fi->i_time = time_to_jiffies(outarg.attr_valid,
891 outarg.attr_valid_nsec);
892 } else if (is_truncate)
893 up_write(&fi->write_sem);
894
Miklos Szeredi7eafcce2004-06-19 22:42:38 +0000895 return err;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000896}
897
Miklos Szeredif85ab242004-01-07 12:16:45 +0000898static int _fuse_dentry_revalidate(struct dentry *entry)
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000899{
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000900 if (!entry->d_inode)
Miklos Szeredi97c61e92001-11-07 12:09:43 +0000901 return 0;
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000902 else if (entry->d_time && time_after(jiffies, entry->d_time)) {
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000903 struct inode *inode = entry->d_inode;
Miklos Szeredi069c9502004-07-16 16:17:02 +0000904 struct fuse_inode *fi = INO_FI(inode);
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000905 struct fuse_entry_out outarg;
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000906 int version;
907 int ret;
908
909 ret = fuse_do_lookup(entry->d_parent->d_inode, entry, &outarg,
910 &version);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000911 if (ret)
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000912 return 0;
913
Miklos Szeredia13d9002004-11-02 17:32:03 +0000914 if (outarg.nodeid != fi->nodeid)
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000915 return 0;
916
917 change_attributes(inode, &outarg.attr);
918 inode->i_version = version;
Miklos Szeredi254d5ed2004-03-02 11:11:24 +0000919 entry->d_time = time_to_jiffies(outarg.entry_valid,
920 outarg.entry_valid_nsec);
Miklos Szeredi069c9502004-07-16 16:17:02 +0000921 fi->i_time = time_to_jiffies(outarg.attr_valid,
922 outarg.attr_valid_nsec);
Miklos Szeredi5e5d61f2002-10-24 11:50:33 +0000923 }
924 return 1;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000925}
926
Miklos Szeredif85ab242004-01-07 12:16:45 +0000927#ifdef KERNEL_2_6
928
929#define fuse_mknod _fuse_mknod
930
931static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
932 struct kstat *stat)
933{
934 struct inode *inode = entry->d_inode;
935 int err = fuse_revalidate(entry);
Miklos Szeredic26c14d2004-04-09 17:48:32 +0000936 if (!err)
Miklos Szeredif85ab242004-01-07 12:16:45 +0000937 generic_fillattr(inode, stat);
938
939 return err;
940}
941
942static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
943 struct nameidata *nd)
944{
Miklos Szeredie815c032004-01-19 18:20:49 +0000945 struct inode *inode;
946 int err = fuse_lookup_iget(dir, entry, &inode);
947 if (err)
948 return ERR_PTR(err);
949 return d_splice_alias(inode, entry);
Miklos Szeredif85ab242004-01-07 12:16:45 +0000950}
951
952static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
953 struct nameidata *nd)
954{
955 return _fuse_create(dir, entry, mode);
956}
957
958static int fuse_permission(struct inode *inode, int mask,
959 struct nameidata *nd)
960{
961 return _fuse_permission(inode, mask);
962}
963
964static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
965{
966 return _fuse_dentry_revalidate(entry);
967}
Miklos Szeredi3ed84232004-03-30 15:17:26 +0000968
Miklos Szeredi689f5632004-05-04 08:49:16 +0000969#else /* KERNEL_2_6 */
970
971#define fuse_create _fuse_create
972#define fuse_permission _fuse_permission
973
974static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry)
975{
976 struct inode *inode;
977 struct dentry *alias;
978
979 int err = fuse_lookup_iget(dir, entry, &inode);
980 if (err)
981 return ERR_PTR(err);
982
983 if (inode && S_ISDIR(inode->i_mode) &&
984 (alias = d_find_alias(inode)) != NULL) {
985 dput(alias);
986 iput(inode);
987 printk("fuse: cannot assign an existing directory\n");
988 return ERR_PTR(-EPROTO);
989 }
990
991 d_add(entry, inode);
992 return NULL;
993}
994
995static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
996 int rdev)
997{
Miklos Szerediad051c32004-07-02 09:22:50 +0000998 return _fuse_mknod(dir, entry, mode, rdev);
Miklos Szeredi689f5632004-05-04 08:49:16 +0000999}
1000
1001static int fuse_dentry_revalidate(struct dentry *entry, int flags)
1002{
1003 return _fuse_dentry_revalidate(entry);
1004}
1005#endif /* KERNEL_2_6 */
1006
1007#ifdef HAVE_KERNEL_XATTR
1008
1009#ifdef KERNEL_2_6
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001010static int fuse_setxattr(struct dentry *entry, const char *name,
1011 const void *value, size_t size, int flags)
Miklos Szeredi689f5632004-05-04 08:49:16 +00001012#else
1013static int fuse_setxattr(struct dentry *entry, const char *name,
1014 void *value, size_t size, int flags)
1015#endif
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001016{
1017 struct inode *inode = entry->d_inode;
1018 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredia13d9002004-11-02 17:32:03 +00001019 struct fuse_inode *fi = INO_FI(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001020 struct fuse_req *req;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001021 struct fuse_setxattr_in inarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001022 int err;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001023
Miklos Szeredic26c14d2004-04-09 17:48:32 +00001024 if (size > FUSE_XATTR_SIZE_MAX)
1025 return -E2BIG;
1026
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001027 if (fc->no_setxattr)
1028 return -EOPNOTSUPP;
1029
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001030 req = fuse_get_request(fc);
1031 if (!req)
1032 return -ERESTARTSYS;
1033
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001034 memset(&inarg, 0, sizeof(inarg));
1035 inarg.size = size;
1036 inarg.flags = flags;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001037 req->in.h.opcode = FUSE_SETXATTR;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001038 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001039 req->in.numargs = 3;
1040 req->in.args[0].size = sizeof(inarg);
1041 req->in.args[0].value = &inarg;
1042 req->in.args[1].size = strlen(name) + 1;
1043 req->in.args[1].value = name;
1044 req->in.args[2].size = size;
1045 req->in.args[2].value = value;
1046 request_send(fc, req);
1047 err = req->out.h.error;
1048 if (err == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001049 fc->no_setxattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001050 err = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001051 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001052 fuse_put_request(fc, req);
1053 return err;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001054}
1055
1056static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1057 void *value, size_t size)
1058{
1059 struct inode *inode = entry->d_inode;
1060 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredia13d9002004-11-02 17:32:03 +00001061 struct fuse_inode *fi = INO_FI(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001062 struct fuse_req *req;
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001063 struct fuse_getxattr_in inarg;
1064 struct fuse_getxattr_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001065 ssize_t ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001066
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001067 if (fc->no_getxattr)
1068 return -EOPNOTSUPP;
1069
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001070 req = fuse_get_request(fc);
1071 if (!req)
1072 return -ERESTARTSYS;
1073
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001074 memset(&inarg, 0, sizeof(inarg));
1075 inarg.size = size;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001076 req->in.h.opcode = FUSE_GETXATTR;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001077 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001078 req->in.numargs = 2;
1079 req->in.args[0].size = sizeof(inarg);
1080 req->in.args[0].value = &inarg;
1081 req->in.args[1].size = strlen(name) + 1;
1082 req->in.args[1].value = name;
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001083 /* This is really two different operations rolled into one */
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001084 req->out.numargs = 1;
Miklos Szeredic26c14d2004-04-09 17:48:32 +00001085 if (size) {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001086 req->out.argvar = 1;
1087 req->out.args[0].size = size;
1088 req->out.args[0].value = value;
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001089 } else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001090 req->out.args[0].size = sizeof(outarg);
1091 req->out.args[0].value = &outarg;
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001092 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001093 request_send(fc, req);
1094 ret = req->out.h.error;
1095 if (!ret)
1096 ret = size ? req->out.args[0].size : outarg.size;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001097 else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001098 if (ret == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001099 fc->no_getxattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001100 ret = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001101 }
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001102 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001103 fuse_put_request(fc, req);
1104 return ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001105}
1106
1107static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1108{
1109 struct inode *inode = entry->d_inode;
1110 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredia13d9002004-11-02 17:32:03 +00001111 struct fuse_inode *fi = INO_FI(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001112 struct fuse_req *req;
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001113 struct fuse_getxattr_in inarg;
1114 struct fuse_getxattr_out outarg;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001115 ssize_t ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001116
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001117 if (fc->no_listxattr)
1118 return -EOPNOTSUPP;
1119
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001120 req = fuse_get_request(fc);
1121 if (!req)
1122 return -ERESTARTSYS;
1123
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001124 memset(&inarg, 0, sizeof(inarg));
1125 inarg.size = size;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001126 req->in.h.opcode = FUSE_LISTXATTR;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001127 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001128 req->in.numargs = 1;
1129 req->in.args[0].size = sizeof(inarg);
1130 req->in.args[0].value = &inarg;
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001131 /* This is really two different operations rolled into one */
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001132 req->out.numargs = 1;
Miklos Szeredic26c14d2004-04-09 17:48:32 +00001133 if (size) {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001134 req->out.argvar = 1;
1135 req->out.args[0].size = size;
1136 req->out.args[0].value = list;
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001137 } else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001138 req->out.args[0].size = sizeof(outarg);
1139 req->out.args[0].value = &outarg;
Miklos Szeredi03cebae2004-03-31 10:19:18 +00001140 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001141 request_send(fc, req);
1142 ret = req->out.h.error;
1143 if (!ret)
1144 ret = size ? req->out.args[0].size : outarg.size;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001145 else {
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001146 if (ret == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001147 fc->no_listxattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001148 ret = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001149 }
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001150 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001151 fuse_put_request(fc, req);
1152 return ret;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001153}
1154
1155static int fuse_removexattr(struct dentry *entry, const char *name)
1156{
1157 struct inode *inode = entry->d_inode;
1158 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredia13d9002004-11-02 17:32:03 +00001159 struct fuse_inode *fi = INO_FI(inode);
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001160 struct fuse_req *req;
1161 int err;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001162
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001163 if (fc->no_removexattr)
1164 return -EOPNOTSUPP;
1165
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001166 req = fuse_get_request(fc);
1167 if (!req)
1168 return -ERESTARTSYS;
1169
1170 req->in.h.opcode = FUSE_REMOVEXATTR;
Miklos Szeredia13d9002004-11-02 17:32:03 +00001171 req->in.h.nodeid = fi->nodeid;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001172 req->in.numargs = 1;
1173 req->in.args[0].size = strlen(name) + 1;
1174 req->in.args[0].value = name;
1175 request_send(fc, req);
1176 err = req->out.h.error;
1177 if (err == -ENOSYS) {
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001178 fc->no_removexattr = 1;
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001179 err = -EOPNOTSUPP;
Miklos Szeredi63b8c1c2004-06-03 14:45:04 +00001180 }
Miklos Szeredi7eafcce2004-06-19 22:42:38 +00001181 fuse_put_request(fc, req);
1182 return err;
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001183}
1184
Miklos Szeredi689f5632004-05-04 08:49:16 +00001185#endif
Miklos Szeredif85ab242004-01-07 12:16:45 +00001186
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001187static struct inode_operations fuse_dir_inode_operations =
1188{
Miklos Szeredie8663f32004-01-13 15:33:12 +00001189 .lookup = fuse_lookup,
1190 .create = fuse_create,
1191 .mknod = fuse_mknod,
1192 .mkdir = fuse_mkdir,
1193 .symlink = fuse_symlink,
1194 .unlink = fuse_unlink,
1195 .rmdir = fuse_rmdir,
1196 .rename = fuse_rename,
1197 .link = fuse_link,
1198 .setattr = fuse_setattr,
1199 .permission = fuse_permission,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001200#ifdef KERNEL_2_6
Miklos Szeredie8663f32004-01-13 15:33:12 +00001201 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001202#else
1203 .revalidate = fuse_revalidate,
1204#endif
1205#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001206 .setxattr = fuse_setxattr,
1207 .getxattr = fuse_getxattr,
1208 .listxattr = fuse_listxattr,
1209 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001210#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001211};
1212
1213static struct file_operations fuse_dir_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +00001214 .read = generic_read_dir,
1215 .readdir = fuse_readdir,
1216 .open = fuse_dir_open,
1217 .release = fuse_dir_release,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001218};
1219
1220static struct inode_operations fuse_file_inode_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +00001221 .setattr = fuse_setattr,
1222 .permission = fuse_permission,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001223#ifdef KERNEL_2_6
Miklos Szeredie8663f32004-01-13 15:33:12 +00001224 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001225#else
1226 .revalidate = fuse_revalidate,
1227#endif
1228#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001229 .setxattr = fuse_setxattr,
1230 .getxattr = fuse_getxattr,
1231 .listxattr = fuse_listxattr,
1232 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001233#endif
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001234};
1235
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001236static struct inode_operations fuse_symlink_inode_operations =
1237{
Miklos Szeredie8663f32004-01-13 15:33:12 +00001238 .setattr = fuse_setattr,
1239 .readlink = fuse_readlink,
1240 .follow_link = fuse_follow_link,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001241#ifdef KERNEL_2_6
Miklos Szeredie8663f32004-01-13 15:33:12 +00001242 .getattr = fuse_getattr,
Miklos Szeredi689f5632004-05-04 08:49:16 +00001243#else
1244 .revalidate = fuse_revalidate,
1245#endif
1246#ifdef HAVE_KERNEL_XATTR
Miklos Szeredi3ed84232004-03-30 15:17:26 +00001247 .setxattr = fuse_setxattr,
1248 .getxattr = fuse_getxattr,
1249 .listxattr = fuse_listxattr,
1250 .removexattr = fuse_removexattr,
Miklos Szeredif85ab242004-01-07 12:16:45 +00001251#endif
Miklos Szeredi19dff1b2001-10-30 15:06:52 +00001252};
1253
Miklos Szeredi307242f2004-01-26 11:28:44 +00001254static struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie8663f32004-01-13 15:33:12 +00001255 .d_revalidate = fuse_dentry_revalidate,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001256};
1257
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001258/*
1259 * Local Variables:
1260 * indent-tabs-mode: t
1261 * c-basic-offset: 8
1262 * End:
1263 */