2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4 Copyright (C) 2011 Sebastian Pipping <sebastian@pipping.org>
6 This program can be distributed under the terms of the GNU GPL.
9 gcc -Wall fusexmp.c `pkg-config fuse --cflags --libs` -o fusexmp
12 #define FUSE_USE_VERSION 30
19 /* For pread()/pwrite()/utimensat() */
20 #define _XOPEN_SOURCE 700
33 #include <sys/xattr.h>
36 static int xmp_getattr(const char *path
, struct stat
*stbuf
)
40 res
= lstat(path
, stbuf
);
47 static int xmp_access(const char *path
, int mask
)
51 res
= access(path
, mask
);
58 static int xmp_readlink(const char *path
, char *buf
, size_t size
)
62 res
= readlink(path
, buf
, size
- 1);
71 static int xmp_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
72 off_t offset
, struct fuse_file_info
*fi
)
84 while ((de
= readdir(dp
)) != NULL
) {
86 memset(&st
, 0, sizeof(st
));
87 st
.st_ino
= de
->d_ino
;
88 st
.st_mode
= de
->d_type
<< 12;
89 if (filler(buf
, de
->d_name
, &st
, 0))
97 static int xmp_mknod(const char *path
, mode_t mode
, dev_t rdev
)
101 /* On Linux this could just be 'mknod(path, mode, rdev)' but this
104 res
= open(path
, O_CREAT
| O_EXCL
| O_WRONLY
, mode
);
107 } else if (S_ISFIFO(mode
))
108 res
= mkfifo(path
, mode
);
110 res
= mknod(path
, mode
, rdev
);
117 static int xmp_mkdir(const char *path
, mode_t mode
)
121 res
= mkdir(path
, mode
);
128 static int xmp_unlink(const char *path
)
139 static int xmp_rmdir(const char *path
)
150 static int xmp_symlink(const char *from
, const char *to
)
154 res
= symlink(from
, to
);
161 static int xmp_rename(const char *from
, const char *to
)
165 res
= rename(from
, to
);
172 static int xmp_link(const char *from
, const char *to
)
176 res
= link(from
, to
);
183 static int xmp_chmod(const char *path
, mode_t mode
)
187 res
= chmod(path
, mode
);
194 static int xmp_chown(const char *path
, uid_t uid
, gid_t gid
)
198 res
= lchown(path
, uid
, gid
);
205 static int xmp_truncate(const char *path
, off_t size
)
209 res
= truncate(path
, size
);
216 #ifdef HAVE_UTIMENSAT
217 static int xmp_utimens(const char *path
, const struct timespec ts
[2])
221 /* don't use utime/utimes since they follow symlinks */
222 res
= utimensat(0, path
, ts
, AT_SYMLINK_NOFOLLOW
);
230 static int xmp_open(const char *path
, struct fuse_file_info
*fi
)
234 res
= open(path
, fi
->flags
);
242 static int xmp_read(const char *path
, char *buf
, size_t size
, off_t offset
,
243 struct fuse_file_info
*fi
)
249 fd
= open(path
, O_RDONLY
);
253 res
= pread(fd
, buf
, size
, offset
);
261 static int xmp_write(const char *path
, const char *buf
, size_t size
,
262 off_t offset
, struct fuse_file_info
*fi
)
268 fd
= open(path
, O_WRONLY
);
272 res
= pwrite(fd
, buf
, size
, offset
);
280 static int xmp_statfs(const char *path
, struct statvfs
*stbuf
)
284 res
= statvfs(path
, stbuf
);
291 static int xmp_release(const char *path
, struct fuse_file_info
*fi
)
293 /* Just a stub. This method is optional and can safely be left
301 static int xmp_fsync(const char *path
, int isdatasync
,
302 struct fuse_file_info
*fi
)
304 /* Just a stub. This method is optional and can safely be left
313 #ifdef HAVE_POSIX_FALLOCATE
314 static int xmp_fallocate(const char *path
, int mode
,
315 off_t offset
, off_t length
, struct fuse_file_info
*fi
)
325 fd
= open(path
, O_WRONLY
);
329 res
= -posix_fallocate(fd
, offset
, length
);
337 /* xattr operations are optional and can safely be left unimplemented */
338 static int xmp_setxattr(const char *path
, const char *name
, const char *value
,
339 size_t size
, int flags
)
341 int res
= lsetxattr(path
, name
, value
, size
, flags
);
347 static int xmp_getxattr(const char *path
, const char *name
, char *value
,
350 int res
= lgetxattr(path
, name
, value
, size
);
356 static int xmp_listxattr(const char *path
, char *list
, size_t size
)
358 int res
= llistxattr(path
, list
, size
);
364 static int xmp_removexattr(const char *path
, const char *name
)
366 int res
= lremovexattr(path
, name
);
371 #endif /* HAVE_SETXATTR */
373 static struct fuse_operations xmp_oper
= {
374 .getattr
= xmp_getattr
,
375 .access
= xmp_access
,
376 .readlink
= xmp_readlink
,
377 .readdir
= xmp_readdir
,
380 .symlink
= xmp_symlink
,
381 .unlink
= xmp_unlink
,
383 .rename
= xmp_rename
,
387 .truncate
= xmp_truncate
,
388 #ifdef HAVE_UTIMENSAT
389 .utimens
= xmp_utimens
,
394 .statfs
= xmp_statfs
,
395 .release
= xmp_release
,
397 #ifdef HAVE_POSIX_FALLOCATE
398 .fallocate
= xmp_fallocate
,
401 .setxattr
= xmp_setxattr
,
402 .getxattr
= xmp_getxattr
,
403 .listxattr
= xmp_listxattr
,
404 .removexattr
= xmp_removexattr
,
408 int main(int argc
, char *argv
[])
411 return fuse_main(argc
, argv
, &xmp_oper
, NULL
);