libfuse

passthrough.c
Go to the documentation of this file.
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4 Copyright (C) 2011 Sebastian Pipping <sebastian@pipping.org>
5
6 This program can be distributed under the terms of the GNU GPL.
7 See the file COPYING.
8 */
9
26 #define FUSE_USE_VERSION 31
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #ifdef linux
33 /* For pread()/pwrite()/utimensat() */
34 #define _XOPEN_SOURCE 700
35 #endif
36
37 #include <fuse.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <sys/stat.h>
43 #include <dirent.h>
44 #include <errno.h>
45 #include <sys/time.h>
46 #ifdef HAVE_SETXATTR
47 #include <sys/xattr.h>
48 #endif
49
50 static void *xmp_init(struct fuse_conn_info *conn,
51 struct fuse_config *cfg)
52 {
53 (void) conn;
54 cfg->use_ino = 1;
55
56 /* Pick up changes from lower filesystem right away. This is
57 also necessary for better hardlink support. When the kernel
58 calls the unlink() handler, it does not know the inode of
59 the to-be-removed entry and can therefore not invalidate
60 the cache of the associated inode - resulting in an
61 incorrect st_nlink value being reported for any remaining
62 hardlinks to this inode. */
63 cfg->entry_timeout = 0;
64 cfg->attr_timeout = 0;
65 cfg->negative_timeout = 0;
66
67 return NULL;
68 }
69
70 static int xmp_getattr(const char *path, struct stat *stbuf,
71 struct fuse_file_info *fi)
72 {
73 (void) fi;
74 int res;
75
76 res = lstat(path, stbuf);
77 if (res == -1)
78 return -errno;
79
80 return 0;
81 }
82
83 static int xmp_access(const char *path, int mask)
84 {
85 int res;
86
87 res = access(path, mask);
88 if (res == -1)
89 return -errno;
90
91 return 0;
92 }
93
94 static int xmp_readlink(const char *path, char *buf, size_t size)
95 {
96 int res;
97
98 res = readlink(path, buf, size - 1);
99 if (res == -1)
100 return -errno;
101
102 buf[res] = '\0';
103 return 0;
104 }
105
106
107 static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
108 off_t offset, struct fuse_file_info *fi,
109 enum fuse_readdir_flags flags)
110 {
111 DIR *dp;
112 struct dirent *de;
113
114 (void) offset;
115 (void) fi;
116 (void) flags;
117
118 dp = opendir(path);
119 if (dp == NULL)
120 return -errno;
121
122 while ((de = readdir(dp)) != NULL) {
123 struct stat st;
124 memset(&st, 0, sizeof(st));
125 st.st_ino = de->d_ino;
126 st.st_mode = de->d_type << 12;
127 if (filler(buf, de->d_name, &st, 0, 0))
128 break;
129 }
130
131 closedir(dp);
132 return 0;
133 }
134
135 static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
136 {
137 int res;
138
139 /* On Linux this could just be 'mknod(path, mode, rdev)' but this
140 is more portable */
141 if (S_ISREG(mode)) {
142 res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode);
143 if (res >= 0)
144 res = close(res);
145 } else if (S_ISFIFO(mode))
146 res = mkfifo(path, mode);
147 else
148 res = mknod(path, mode, rdev);
149 if (res == -1)
150 return -errno;
151
152 return 0;
153 }
154
155 static int xmp_mkdir(const char *path, mode_t mode)
156 {
157 int res;
158
159 res = mkdir(path, mode);
160 if (res == -1)
161 return -errno;
162
163 return 0;
164 }
165
166 static int xmp_unlink(const char *path)
167 {
168 int res;
169
170 res = unlink(path);
171 if (res == -1)
172 return -errno;
173
174 return 0;
175 }
176
177 static int xmp_rmdir(const char *path)
178 {
179 int res;
180
181 res = rmdir(path);
182 if (res == -1)
183 return -errno;
184
185 return 0;
186 }
187
188 static int xmp_symlink(const char *from, const char *to)
189 {
190 int res;
191
192 res = symlink(from, to);
193 if (res == -1)
194 return -errno;
195
196 return 0;
197 }
198
199 static int xmp_rename(const char *from, const char *to, unsigned int flags)
200 {
201 int res;
202
203 if (flags)
204 return -EINVAL;
205
206 res = rename(from, to);
207 if (res == -1)
208 return -errno;
209
210 return 0;
211 }
212
213 static int xmp_link(const char *from, const char *to)
214 {
215 int res;
216
217 res = link(from, to);
218 if (res == -1)
219 return -errno;
220
221 return 0;
222 }
223
224 static int xmp_chmod(const char *path, mode_t mode,
225 struct fuse_file_info *fi)
226 {
227 (void) fi;
228 int res;
229
230 res = chmod(path, mode);
231 if (res == -1)
232 return -errno;
233
234 return 0;
235 }
236
237 static int xmp_chown(const char *path, uid_t uid, gid_t gid,
238 struct fuse_file_info *fi)
239 {
240 (void) fi;
241 int res;
242
243 res = lchown(path, uid, gid);
244 if (res == -1)
245 return -errno;
246
247 return 0;
248 }
249
250 static int xmp_truncate(const char *path, off_t size,
251 struct fuse_file_info *fi)
252 {
253 int res;
254
255 if (fi != NULL)
256 res = ftruncate(fi->fh, size);
257 else
258 res = truncate(path, size);
259 if (res == -1)
260 return -errno;
261
262 return 0;
263 }
264
265 #ifdef HAVE_UTIMENSAT
266 static int xmp_utimens(const char *path, const struct timespec ts[2],
267 struct fuse_file_info *fi)
268 {
269 (void) fi;
270 int res;
271
272 /* don't use utime/utimes since they follow symlinks */
273 res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
274 if (res == -1)
275 return -errno;
276
277 return 0;
278 }
279 #endif
280
281 static int xmp_create(const char *path, mode_t mode,
282 struct fuse_file_info *fi)
283 {
284 int res;
285
286 res = open(path, fi->flags, mode);
287 if (res == -1)
288 return -errno;
289
290 fi->fh = res;
291 return 0;
292 }
293
294 static int xmp_open(const char *path, struct fuse_file_info *fi)
295 {
296 int res;
297
298 res = open(path, fi->flags);
299 if (res == -1)
300 return -errno;
301
302 fi->fh = res;
303 return 0;
304 }
305
306 static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
307 struct fuse_file_info *fi)
308 {
309 int fd;
310 int res;
311
312 if(fi == NULL)
313 fd = open(path, O_RDONLY);
314 else
315 fd = fi->fh;
316
317 if (fd == -1)
318 return -errno;
319
320 res = pread(fd, buf, size, offset);
321 if (res == -1)
322 res = -errno;
323
324 if(fi == NULL)
325 close(fd);
326 return res;
327 }
328
329 static int xmp_write(const char *path, const char *buf, size_t size,
330 off_t offset, struct fuse_file_info *fi)
331 {
332 int fd;
333 int res;
334
335 (void) fi;
336 if(fi == NULL)
337 fd = open(path, O_WRONLY);
338 else
339 fd = fi->fh;
340
341 if (fd == -1)
342 return -errno;
343
344 res = pwrite(fd, buf, size, offset);
345 if (res == -1)
346 res = -errno;
347
348 if(fi == NULL)
349 close(fd);
350 return res;
351 }
352
353 static int xmp_statfs(const char *path, struct statvfs *stbuf)
354 {
355 int res;
356
357 res = statvfs(path, stbuf);
358 if (res == -1)
359 return -errno;
360
361 return 0;
362 }
363
364 static int xmp_release(const char *path, struct fuse_file_info *fi)
365 {
366 (void) path;
367 close(fi->fh);
368 return 0;
369 }
370
371 static int xmp_fsync(const char *path, int isdatasync,
372 struct fuse_file_info *fi)
373 {
374 /* Just a stub. This method is optional and can safely be left
375 unimplemented */
376
377 (void) path;
378 (void) isdatasync;
379 (void) fi;
380 return 0;
381 }
382
383 #ifdef HAVE_POSIX_FALLOCATE
384 static int xmp_fallocate(const char *path, int mode,
385 off_t offset, off_t length, struct fuse_file_info *fi)
386 {
387 int fd;
388 int res;
389
390 (void) fi;
391
392 if (mode)
393 return -EOPNOTSUPP;
394
395 if(fi == NULL)
396 fd = open(path, O_WRONLY);
397 else
398 fd = fi->fh;
399
400 if (fd == -1)
401 return -errno;
402
403 res = -posix_fallocate(fd, offset, length);
404
405 if(fi == NULL)
406 close(fd);
407 return res;
408 }
409 #endif
410
411 #ifdef HAVE_SETXATTR
412 /* xattr operations are optional and can safely be left unimplemented */
413 static int xmp_setxattr(const char *path, const char *name, const char *value,
414 size_t size, int flags)
415 {
416 int res = lsetxattr(path, name, value, size, flags);
417 if (res == -1)
418 return -errno;
419 return 0;
420 }
421
422 static int xmp_getxattr(const char *path, const char *name, char *value,
423 size_t size)
424 {
425 int res = lgetxattr(path, name, value, size);
426 if (res == -1)
427 return -errno;
428 return res;
429 }
430
431 static int xmp_listxattr(const char *path, char *list, size_t size)
432 {
433 int res = llistxattr(path, list, size);
434 if (res == -1)
435 return -errno;
436 return res;
437 }
438
439 static int xmp_removexattr(const char *path, const char *name)
440 {
441 int res = lremovexattr(path, name);
442 if (res == -1)
443 return -errno;
444 return 0;
445 }
446 #endif /* HAVE_SETXATTR */
447
448 static struct fuse_operations xmp_oper = {
449 .init = xmp_init,
450 .getattr = xmp_getattr,
451 .access = xmp_access,
452 .readlink = xmp_readlink,
453 .readdir = xmp_readdir,
454 .mknod = xmp_mknod,
455 .mkdir = xmp_mkdir,
456 .symlink = xmp_symlink,
457 .unlink = xmp_unlink,
458 .rmdir = xmp_rmdir,
459 .rename = xmp_rename,
460 .link = xmp_link,
461 .chmod = xmp_chmod,
462 .chown = xmp_chown,
463 .truncate = xmp_truncate,
464 #ifdef HAVE_UTIMENSAT
465 .utimens = xmp_utimens,
466 #endif
467 .open = xmp_open,
468 .create = xmp_create,
469 .read = xmp_read,
470 .write = xmp_write,
471 .statfs = xmp_statfs,
472 .release = xmp_release,
473 .fsync = xmp_fsync,
474 #ifdef HAVE_POSIX_FALLOCATE
475 .fallocate = xmp_fallocate,
476 #endif
477 #ifdef HAVE_SETXATTR
478 .setxattr = xmp_setxattr,
479 .getxattr = xmp_getxattr,
480 .listxattr = xmp_listxattr,
481 .removexattr = xmp_removexattr,
482 #endif
483 };
484
485 int main(int argc, char *argv[])
486 {
487 umask(0);
488 return fuse_main(argc, argv, &xmp_oper, NULL);
489 }
fuse_file_info::fh
uint64_t fh
Definition: fuse_common.h:72
fuse_conn_info
Definition: fuse_common.h:332
fuse_readdir_flags
fuse_readdir_flags
Definition: fuse.h:42
fuse_config::negative_timeout
double negative_timeout
Definition: fuse.h:129
fuse_file_info
Definition: fuse_common.h:37
fuse_operations::init
void *(* init)(struct fuse_conn_info *conn, struct fuse_config *cfg)
Definition: fuse.h:572
fuse_config::use_ino
int use_ino
Definition: fuse.h:190
fuse_operations
Definition: fuse.h:299
fuse_file_info::flags
int flags
Definition: fuse_common.h:39
fuse_config::attr_timeout
double attr_timeout
Definition: fuse.h:135
fuse.h
fuse_fill_dir_t
int(* fuse_fill_dir_t)(void *buf, const char *name, const struct stat *stbuf, off_t off, enum fuse_fill_dir_flags flags)
Definition: fuse.h:82
fuse_config
Definition: fuse.h:93
fuse_config::entry_timeout
double entry_timeout
Definition: fuse.h:119
fuse_main
#define fuse_main(argc, argv, op, private_data)
Definition: fuse.h:829