2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
5 This program can be distributed under the terms of the GNU GPL.
8 gcc -Wall `pkg-config fuse --cflags --libs` -lulockmgr fusexmp_fh.c -o fusexmp_fh
11 #define FUSE_USE_VERSION 26
30 #include <sys/xattr.h>
33 static int xmp_getattr(const char *path
, struct stat
*stbuf
)
37 res
= lstat(path
, stbuf
);
44 static int xmp_fgetattr(const char *path
, struct stat
*stbuf
,
45 struct fuse_file_info
*fi
)
51 res
= fstat(fi
->fh
, stbuf
);
58 static int xmp_access(const char *path
, int mask
)
62 res
= access(path
, mask
);
69 static int xmp_readlink(const char *path
, char *buf
, size_t size
)
73 res
= readlink(path
, buf
, size
- 1);
87 static int xmp_opendir(const char *path
, struct fuse_file_info
*fi
)
90 struct xmp_dirp
*d
= malloc(sizeof(struct xmp_dirp
));
94 d
->dp
= opendir(path
);
103 fi
->fh
= (unsigned long) d
;
107 static inline struct xmp_dirp
*get_dirp(struct fuse_file_info
*fi
)
109 return (struct xmp_dirp
*) (uintptr_t) fi
->fh
;
112 static int xmp_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
113 off_t offset
, struct fuse_file_info
*fi
)
115 struct xmp_dirp
*d
= get_dirp(fi
);
118 if (offset
!= d
->offset
) {
119 seekdir(d
->dp
, offset
);
128 d
->entry
= readdir(d
->dp
);
133 memset(&st
, 0, sizeof(st
));
134 st
.st_ino
= d
->entry
->d_ino
;
135 st
.st_mode
= d
->entry
->d_type
<< 12;
136 nextoff
= telldir(d
->dp
);
137 if (filler(buf
, d
->entry
->d_name
, &st
, nextoff
))
147 static int xmp_releasedir(const char *path
, struct fuse_file_info
*fi
)
149 struct xmp_dirp
*d
= get_dirp(fi
);
156 static int xmp_mknod(const char *path
, mode_t mode
, dev_t rdev
)
161 res
= mkfifo(path
, mode
);
163 res
= mknod(path
, mode
, rdev
);
170 static int xmp_mkdir(const char *path
, mode_t mode
)
174 res
= mkdir(path
, mode
);
181 static int xmp_unlink(const char *path
)
192 static int xmp_rmdir(const char *path
)
203 static int xmp_symlink(const char *from
, const char *to
)
207 res
= symlink(from
, to
);
214 static int xmp_rename(const char *from
, const char *to
)
218 res
= rename(from
, to
);
225 static int xmp_link(const char *from
, const char *to
)
229 res
= link(from
, to
);
236 static int xmp_chmod(const char *path
, mode_t mode
)
240 res
= chmod(path
, mode
);
247 static int xmp_chown(const char *path
, uid_t uid
, gid_t gid
)
251 res
= lchown(path
, uid
, gid
);
258 static int xmp_truncate(const char *path
, off_t size
)
262 res
= truncate(path
, size
);
269 static int xmp_ftruncate(const char *path
, off_t size
,
270 struct fuse_file_info
*fi
)
276 res
= ftruncate(fi
->fh
, size
);
283 static int xmp_utimens(const char *path
, const struct timespec ts
[2])
286 struct timeval tv
[2];
288 tv
[0].tv_sec
= ts
[0].tv_sec
;
289 tv
[0].tv_usec
= ts
[0].tv_nsec
/ 1000;
290 tv
[1].tv_sec
= ts
[1].tv_sec
;
291 tv
[1].tv_usec
= ts
[1].tv_nsec
/ 1000;
293 res
= utimes(path
, tv
);
300 static int xmp_create(const char *path
, mode_t mode
, struct fuse_file_info
*fi
)
304 fd
= open(path
, fi
->flags
, mode
);
312 static int xmp_open(const char *path
, struct fuse_file_info
*fi
)
316 fd
= open(path
, fi
->flags
);
324 static int xmp_read(const char *path
, char *buf
, size_t size
, off_t offset
,
325 struct fuse_file_info
*fi
)
330 res
= pread(fi
->fh
, buf
, size
, offset
);
337 static int xmp_write(const char *path
, const char *buf
, size_t size
,
338 off_t offset
, struct fuse_file_info
*fi
)
343 res
= pwrite(fi
->fh
, buf
, size
, offset
);
350 static int xmp_statfs(const char *path
, struct statvfs
*stbuf
)
354 res
= statvfs(path
, stbuf
);
361 static int xmp_flush(const char *path
, struct fuse_file_info
*fi
)
366 /* This is called from every close on an open file, so call the
367 close on the underlying filesystem. But since flush may be
368 called multiple times for an open file, this must not really
369 close the file. This is important if used on a network
370 filesystem like NFS which flush the data/metadata on close() */
371 res
= close(dup(fi
->fh
));
378 static int xmp_release(const char *path
, struct fuse_file_info
*fi
)
386 static int xmp_fsync(const char *path
, int isdatasync
,
387 struct fuse_file_info
*fi
)
392 #ifndef HAVE_FDATASYNC
396 res
= fdatasync(fi
->fh
);
407 /* xattr operations are optional and can safely be left unimplemented */
408 static int xmp_setxattr(const char *path
, const char *name
, const char *value
,
409 size_t size
, int flags
)
411 int res
= lsetxattr(path
, name
, value
, size
, flags
);
417 static int xmp_getxattr(const char *path
, const char *name
, char *value
,
420 int res
= lgetxattr(path
, name
, value
, size
);
426 static int xmp_listxattr(const char *path
, char *list
, size_t size
)
428 int res
= llistxattr(path
, list
, size
);
434 static int xmp_removexattr(const char *path
, const char *name
)
436 int res
= lremovexattr(path
, name
);
441 #endif /* HAVE_SETXATTR */
443 static int xmp_lock(const char *path
, struct fuse_file_info
*fi
, int cmd
,
448 return ulockmgr_op(fi
->fh
, cmd
, lock
, &fi
->lock_owner
,
449 sizeof(fi
->lock_owner
));
452 static struct fuse_operations xmp_oper
= {
453 .getattr
= xmp_getattr
,
454 .fgetattr
= xmp_fgetattr
,
455 .access
= xmp_access
,
456 .readlink
= xmp_readlink
,
457 .opendir
= xmp_opendir
,
458 .readdir
= xmp_readdir
,
459 .releasedir
= xmp_releasedir
,
462 .symlink
= xmp_symlink
,
463 .unlink
= xmp_unlink
,
465 .rename
= xmp_rename
,
469 .truncate
= xmp_truncate
,
470 .ftruncate
= xmp_ftruncate
,
471 .utimens
= xmp_utimens
,
472 .create
= xmp_create
,
476 .statfs
= xmp_statfs
,
478 .release
= xmp_release
,
481 .setxattr
= xmp_setxattr
,
482 .getxattr
= xmp_getxattr
,
483 .listxattr
= xmp_listxattr
,
484 .removexattr
= xmp_removexattr
,
488 .flag_nullpath_ok
= 1,
491 int main(int argc
, char *argv
[])
494 return fuse_main(argc
, argv
, &xmp_oper
, NULL
);