From 3f5e67633de9c07f99967edf00bf9a3efdc65f62 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Sat, 23 Mar 2013 14:21:25 +0100 Subject: Synchronize headers, examples and version script with FUSE 2.6.5 Update the headers from FUSE 2.6.5, import the examples and update the version script. This temporarly breaks compilation. * configure.ac (AC_CONFIG_FILES): Add example-26/Makefile. * example-26/.gitignore: New file. * example-26/Makefile.am: Likewise. * example-26/fusexmp.c: Likewise. * example-26/fusexmp_fh.c: Likewise. * example-26/hello.c: Likewise. * example-26/hello_ll.c: Likewise. * example-26/null.c: Likewise. * include/Makefile.am (fuseinclude_HEADERS): Add fuse_common_compat.h. * include/fuse.h: Update from FUSE 2.6.5. * include/fuse_common.h: Likewise. * include/fuse_compat.h: Likewise. * include/fuse_opt.h: Likewise. * include/fuse_common_compat.h: Import from FUSE 2.6.5. * Update from FUSE 2.6.5. --- configure.ac | 3 +- example-26/.gitignore | 4 + example-26/Makefile.am | 12 ++ example-26/fusexmp.c | 383 ++++++++++++++++++++++++++++++++++++ example-26/fusexmp_fh.c | 458 +++++++++++++++++++++++++++++++++++++++++++ example-26/hello.c | 98 +++++++++ example-26/hello_ll.c | 180 +++++++++++++++++ example-26/null.c | 92 +++++++++ include/Makefile.am | 1 + include/fuse.h | 204 ++++++++++++------- include/fuse_common.h | 122 +++++++++++- include/fuse_common_compat.h | 27 +++ include/fuse_compat.h | 90 ++++++--- include/fuse_opt.h | 35 +++- src/fuse_versionscript | 40 +++- 15 files changed, 1643 insertions(+), 106 deletions(-) create mode 100644 example-26/.gitignore create mode 100644 example-26/Makefile.am create mode 100644 example-26/fusexmp.c create mode 100644 example-26/fusexmp_fh.c create mode 100644 example-26/hello.c create mode 100644 example-26/hello_ll.c create mode 100644 example-26/null.c create mode 100644 include/fuse_common_compat.h diff --git a/configure.ac b/configure.ac index fc670fa1a..54c0298d6 100644 --- a/configure.ac +++ b/configure.ac @@ -41,5 +41,6 @@ CFLAGS="$CFLAGS -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W -ggdb" AC_CONFIG_FILES([fuse.pc Makefile] [include/Makefile src/Makefile] - [example-25/Makefile]) + [example-25/Makefile + example-26/Makefile]) AC_OUTPUT diff --git a/example-26/.gitignore b/example-26/.gitignore new file mode 100644 index 000000000..929ddf159 --- /dev/null +++ b/example-26/.gitignore @@ -0,0 +1,4 @@ +fusexmp +fusexmp_fh +hello +null diff --git a/example-26/Makefile.am b/example-26/Makefile.am new file mode 100644 index 000000000..5b0c03d05 --- /dev/null +++ b/example-26/Makefile.am @@ -0,0 +1,12 @@ +## Process this file with automake to produce Makefile.in + +noinst_PROGRAMS = fusexmp fusexmp_fh null hello +# low-level api not supported: hello_ll + +fusexmp_SOURCES = fusexmp.c +fusexmp_fh_SOURCES = fusexmp_fh.c +null_SOURCES = null.c +hello_SOURCES = hello.c + +LDADD = ../src/libfuse.la +AM_CPPFLAGS = -DFUSE_USE_VERSION=26 -I$(top_srcdir) -I$(top_srcdir)/include diff --git a/example-26/fusexmp.c b/example-26/fusexmp.c new file mode 100644 index 000000000..b086235c2 --- /dev/null +++ b/example-26/fusexmp.c @@ -0,0 +1,383 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + gcc -Wall `pkg-config fuse --cflags --libs` fusexmp.c -o fusexmp +*/ + +#define FUSE_USE_VERSION 26 + +#include + +#ifdef linux +/* For pread()/pwrite() */ +#define _XOPEN_SOURCE 500 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SETXATTR +#include +#endif + +static int xmp_getattr(const char *path, struct stat *stbuf) +{ + int res; + + res = lstat(path, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_access(const char *path, int mask) +{ + int res; + + res = access(path, mask); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_readlink(const char *path, char *buf, size_t size) +{ + int res; + + res = readlink(path, buf, size - 1); + if (res == -1) + return -errno; + + buf[res] = '\0'; + return 0; +} + + +static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi) +{ + DIR *dp; + struct dirent *de; + + (void) offset; + (void) fi; + + dp = opendir(path); + if (dp == NULL) + return -errno; + + while ((de = readdir(dp)) != NULL) { + struct stat st; + memset(&st, 0, sizeof(st)); + st.st_ino = de->d_ino; + st.st_mode = de->d_type << 12; + if (filler(buf, de->d_name, &st, 0)) + break; + } + + closedir(dp); + return 0; +} + +static int xmp_mknod(const char *path, mode_t mode, dev_t rdev) +{ + int res; + + /* On Linux this could just be 'mknod(path, mode, rdev)' but this + is more portable */ + if (S_ISREG(mode)) { + res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode); + if (res >= 0) + res = close(res); + } else if (S_ISFIFO(mode)) + res = mkfifo(path, mode); + else + res = mknod(path, mode, rdev); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_mkdir(const char *path, mode_t mode) +{ + int res; + + res = mkdir(path, mode); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_unlink(const char *path) +{ + int res; + + res = unlink(path); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_rmdir(const char *path) +{ + int res; + + res = rmdir(path); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_symlink(const char *from, const char *to) +{ + int res; + + res = symlink(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_rename(const char *from, const char *to) +{ + int res; + + res = rename(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_link(const char *from, const char *to) +{ + int res; + + res = link(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_chmod(const char *path, mode_t mode) +{ + int res; + + res = chmod(path, mode); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_chown(const char *path, uid_t uid, gid_t gid) +{ + int res; + + res = lchown(path, uid, gid); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_truncate(const char *path, off_t size) +{ + int res; + + res = truncate(path, size); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_utimens(const char *path, const struct timespec ts[2]) +{ + int res; + struct timeval tv[2]; + + tv[0].tv_sec = ts[0].tv_sec; + tv[0].tv_usec = ts[0].tv_nsec / 1000; + tv[1].tv_sec = ts[1].tv_sec; + tv[1].tv_usec = ts[1].tv_nsec / 1000; + + res = utimes(path, tv); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_open(const char *path, struct fuse_file_info *fi) +{ + int res; + + res = open(path, fi->flags); + if (res == -1) + return -errno; + + close(res); + return 0; +} + +static int xmp_read(const char *path, char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + int fd; + int res; + + (void) fi; + fd = open(path, O_RDONLY); + if (fd == -1) + return -errno; + + res = pread(fd, buf, size, offset); + if (res == -1) + res = -errno; + + close(fd); + return res; +} + +static int xmp_write(const char *path, const char *buf, size_t size, + off_t offset, struct fuse_file_info *fi) +{ + int fd; + int res; + + (void) fi; + fd = open(path, O_WRONLY); + if (fd == -1) + return -errno; + + res = pwrite(fd, buf, size, offset); + if (res == -1) + res = -errno; + + close(fd); + return res; +} + +static int xmp_statfs(const char *path, struct statvfs *stbuf) +{ + int res; + + res = statvfs(path, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_release(const char *path, struct fuse_file_info *fi) +{ + /* Just a stub. This method is optional and can safely be left + unimplemented */ + + (void) path; + (void) fi; + return 0; +} + +static int xmp_fsync(const char *path, int isdatasync, + struct fuse_file_info *fi) +{ + /* Just a stub. This method is optional and can safely be left + unimplemented */ + + (void) path; + (void) isdatasync; + (void) fi; + return 0; +} + +#ifdef HAVE_SETXATTR +/* xattr operations are optional and can safely be left unimplemented */ +static int xmp_setxattr(const char *path, const char *name, const char *value, + size_t size, int flags) +{ + int res = lsetxattr(path, name, value, size, flags); + if (res == -1) + return -errno; + return 0; +} + +static int xmp_getxattr(const char *path, const char *name, char *value, + size_t size) +{ + int res = lgetxattr(path, name, value, size); + if (res == -1) + return -errno; + return res; +} + +static int xmp_listxattr(const char *path, char *list, size_t size) +{ + int res = llistxattr(path, list, size); + if (res == -1) + return -errno; + return res; +} + +static int xmp_removexattr(const char *path, const char *name) +{ + int res = lremovexattr(path, name); + if (res == -1) + return -errno; + return 0; +} +#endif /* HAVE_SETXATTR */ + +static struct fuse_operations xmp_oper = { + .getattr = xmp_getattr, + .access = xmp_access, + .readlink = xmp_readlink, + .readdir = xmp_readdir, + .mknod = xmp_mknod, + .mkdir = xmp_mkdir, + .symlink = xmp_symlink, + .unlink = xmp_unlink, + .rmdir = xmp_rmdir, + .rename = xmp_rename, + .link = xmp_link, + .chmod = xmp_chmod, + .chown = xmp_chown, + .truncate = xmp_truncate, + .utimens = xmp_utimens, + .open = xmp_open, + .read = xmp_read, + .write = xmp_write, + .statfs = xmp_statfs, + .release = xmp_release, + .fsync = xmp_fsync, +#ifdef HAVE_SETXATTR + .setxattr = xmp_setxattr, + .getxattr = xmp_getxattr, + .listxattr = xmp_listxattr, + .removexattr= xmp_removexattr, +#endif +}; + +int main(int argc, char *argv[]) +{ + umask(0); + return fuse_main(argc, argv, &xmp_oper, NULL); +} diff --git a/example-26/fusexmp_fh.c b/example-26/fusexmp_fh.c new file mode 100644 index 000000000..f8c1ed482 --- /dev/null +++ b/example-26/fusexmp_fh.c @@ -0,0 +1,458 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + gcc -Wall `pkg-config fuse --cflags --libs` -lulockmgr fusexmp_fh.c -o fusexmp_fh +*/ + +#define FUSE_USE_VERSION 26 + +#include + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SETXATTR +#include +#endif + +static int xmp_getattr(const char *path, struct stat *stbuf) +{ + int res; + + res = lstat(path, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_fgetattr(const char *path, struct stat *stbuf, + struct fuse_file_info *fi) +{ + int res; + + (void) path; + + res = fstat(fi->fh, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_access(const char *path, int mask) +{ + int res; + + res = access(path, mask); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_readlink(const char *path, char *buf, size_t size) +{ + int res; + + res = readlink(path, buf, size - 1); + if (res == -1) + return -errno; + + buf[res] = '\0'; + return 0; +} + +static int xmp_opendir(const char *path, struct fuse_file_info *fi) +{ + DIR *dp = opendir(path); + if (dp == NULL) + return -errno; + + fi->fh = (unsigned long) dp; + return 0; +} + +static inline DIR *get_dirp(struct fuse_file_info *fi) +{ + return (DIR *) (uintptr_t) fi->fh; +} + +static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi) +{ + DIR *dp = get_dirp(fi); + struct dirent *de; + + (void) path; + seekdir(dp, offset); + while ((de = readdir(dp)) != NULL) { + struct stat st; + memset(&st, 0, sizeof(st)); + st.st_ino = de->d_ino; + st.st_mode = de->d_type << 12; + if (filler(buf, de->d_name, &st, telldir(dp))) + break; + } + + return 0; +} + +static int xmp_releasedir(const char *path, struct fuse_file_info *fi) +{ + DIR *dp = get_dirp(fi); + (void) path; + closedir(dp); + return 0; +} + +static int xmp_mknod(const char *path, mode_t mode, dev_t rdev) +{ + int res; + + if (S_ISFIFO(mode)) + res = mkfifo(path, mode); + else + res = mknod(path, mode, rdev); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_mkdir(const char *path, mode_t mode) +{ + int res; + + res = mkdir(path, mode); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_unlink(const char *path) +{ + int res; + + res = unlink(path); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_rmdir(const char *path) +{ + int res; + + res = rmdir(path); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_symlink(const char *from, const char *to) +{ + int res; + + res = symlink(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_rename(const char *from, const char *to) +{ + int res; + + res = rename(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_link(const char *from, const char *to) +{ + int res; + + res = link(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_chmod(const char *path, mode_t mode) +{ + int res; + + res = chmod(path, mode); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_chown(const char *path, uid_t uid, gid_t gid) +{ + int res; + + res = lchown(path, uid, gid); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_truncate(const char *path, off_t size) +{ + int res; + + res = truncate(path, size); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_ftruncate(const char *path, off_t size, + struct fuse_file_info *fi) +{ + int res; + + (void) path; + + res = ftruncate(fi->fh, size); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_utimens(const char *path, const struct timespec ts[2]) +{ + int res; + struct timeval tv[2]; + + tv[0].tv_sec = ts[0].tv_sec; + tv[0].tv_usec = ts[0].tv_nsec / 1000; + tv[1].tv_sec = ts[1].tv_sec; + tv[1].tv_usec = ts[1].tv_nsec / 1000; + + res = utimes(path, tv); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_create(const char *path, mode_t mode, struct fuse_file_info *fi) +{ + int fd; + + fd = open(path, fi->flags, mode); + if (fd == -1) + return -errno; + + fi->fh = fd; + return 0; +} + +static int xmp_open(const char *path, struct fuse_file_info *fi) +{ + int fd; + + fd = open(path, fi->flags); + if (fd == -1) + return -errno; + + fi->fh = fd; + return 0; +} + +static int xmp_read(const char *path, char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + int res; + + (void) path; + res = pread(fi->fh, buf, size, offset); + if (res == -1) + res = -errno; + + return res; +} + +static int xmp_write(const char *path, const char *buf, size_t size, + off_t offset, struct fuse_file_info *fi) +{ + int res; + + (void) path; + res = pwrite(fi->fh, buf, size, offset); + if (res == -1) + res = -errno; + + return res; +} + +static int xmp_statfs(const char *path, struct statvfs *stbuf) +{ + int res; + + res = statvfs(path, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_flush(const char *path, struct fuse_file_info *fi) +{ + int res; + + (void) path; + /* This is called from every close on an open file, so call the + close on the underlying filesystem. But since flush may be + called multiple times for an open file, this must not really + close the file. This is important if used on a network + filesystem like NFS which flush the data/metadata on close() */ + res = close(dup(fi->fh)); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_release(const char *path, struct fuse_file_info *fi) +{ + (void) path; + close(fi->fh); + + return 0; +} + +static int xmp_fsync(const char *path, int isdatasync, + struct fuse_file_info *fi) +{ + int res; + (void) path; + +#ifndef HAVE_FDATASYNC + (void) isdatasync; +#else + if (isdatasync) + res = fdatasync(fi->fh); + else +#endif + res = fsync(fi->fh); + if (res == -1) + return -errno; + + return 0; +} + +#ifdef HAVE_SETXATTR +/* xattr operations are optional and can safely be left unimplemented */ +static int xmp_setxattr(const char *path, const char *name, const char *value, + size_t size, int flags) +{ + int res = lsetxattr(path, name, value, size, flags); + if (res == -1) + return -errno; + return 0; +} + +static int xmp_getxattr(const char *path, const char *name, char *value, + size_t size) +{ + int res = lgetxattr(path, name, value, size); + if (res == -1) + return -errno; + return res; +} + +static int xmp_listxattr(const char *path, char *list, size_t size) +{ + int res = llistxattr(path, list, size); + if (res == -1) + return -errno; + return res; +} + +static int xmp_removexattr(const char *path, const char *name) +{ + int res = lremovexattr(path, name); + if (res == -1) + return -errno; + return 0; +} +#endif /* HAVE_SETXATTR */ + +static int xmp_lock(const char *path, struct fuse_file_info *fi, int cmd, + struct flock *lock) +{ + (void) path; + + return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner, + sizeof(fi->lock_owner)); +} + +static struct fuse_operations xmp_oper = { + .getattr = xmp_getattr, + .fgetattr = xmp_fgetattr, + .access = xmp_access, + .readlink = xmp_readlink, + .opendir = xmp_opendir, + .readdir = xmp_readdir, + .releasedir = xmp_releasedir, + .mknod = xmp_mknod, + .mkdir = xmp_mkdir, + .symlink = xmp_symlink, + .unlink = xmp_unlink, + .rmdir = xmp_rmdir, + .rename = xmp_rename, + .link = xmp_link, + .chmod = xmp_chmod, + .chown = xmp_chown, + .truncate = xmp_truncate, + .ftruncate = xmp_ftruncate, + .utimens = xmp_utimens, + .create = xmp_create, + .open = xmp_open, + .read = xmp_read, + .write = xmp_write, + .statfs = xmp_statfs, + .flush = xmp_flush, + .release = xmp_release, + .fsync = xmp_fsync, +#ifdef HAVE_SETXATTR + .setxattr = xmp_setxattr, + .getxattr = xmp_getxattr, + .listxattr = xmp_listxattr, + .removexattr= xmp_removexattr, +#endif + .lock = xmp_lock, +}; + +int main(int argc, char *argv[]) +{ + umask(0); + return fuse_main(argc, argv, &xmp_oper, NULL); +} diff --git a/example-26/hello.c b/example-26/hello.c new file mode 100644 index 000000000..7a1cdb59e --- /dev/null +++ b/example-26/hello.c @@ -0,0 +1,98 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + gcc -Wall `pkg-config fuse --cflags --libs` hello.c -o hello +*/ + +#define FUSE_USE_VERSION 26 + +#include +#include +#include +#include +#include + +static const char *hello_str = "Hello World!\n"; +static const char *hello_path = "/hello"; + +static int hello_getattr(const char *path, struct stat *stbuf) +{ + int res = 0; + + memset(stbuf, 0, sizeof(struct stat)); + if(strcmp(path, "/") == 0) { + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 2; + } + else if(strcmp(path, hello_path) == 0) { + stbuf->st_mode = S_IFREG | 0444; + stbuf->st_nlink = 1; + stbuf->st_size = strlen(hello_str); + } + else + res = -ENOENT; + + return res; +} + +static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi) +{ + (void) offset; + (void) fi; + + if(strcmp(path, "/") != 0) + return -ENOENT; + + filler(buf, ".", NULL, 0); + filler(buf, "..", NULL, 0); + filler(buf, hello_path + 1, NULL, 0); + + return 0; +} + +static int hello_open(const char *path, struct fuse_file_info *fi) +{ + if(strcmp(path, hello_path) != 0) + return -ENOENT; + + if((fi->flags & 3) != O_RDONLY) + return -EACCES; + + return 0; +} + +static int hello_read(const char *path, char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + size_t len; + (void) fi; + if(strcmp(path, hello_path) != 0) + return -ENOENT; + + len = strlen(hello_str); + if (offset < len) { + if (offset + size > len) + size = len - offset; + memcpy(buf, hello_str + offset, size); + } else + size = 0; + + return size; +} + +static struct fuse_operations hello_oper = { + .getattr = hello_getattr, + .readdir = hello_readdir, + .open = hello_open, + .read = hello_read, +}; + +int main(int argc, char *argv[]) +{ + return fuse_main(argc, argv, &hello_oper, NULL); +} diff --git a/example-26/hello_ll.c b/example-26/hello_ll.c new file mode 100644 index 000000000..934e9a720 --- /dev/null +++ b/example-26/hello_ll.c @@ -0,0 +1,180 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + gcc -Wall `pkg-config fuse --cflags --libs` hello_ll.c -o hello_ll +*/ + +#define FUSE_USE_VERSION 26 + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *hello_str = "Hello World!\n"; +static const char *hello_name = "hello"; + +static int hello_stat(fuse_ino_t ino, struct stat *stbuf) +{ + stbuf->st_ino = ino; + switch (ino) { + case 1: + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 2; + break; + + case 2: + stbuf->st_mode = S_IFREG | 0444; + stbuf->st_nlink = 1; + stbuf->st_size = strlen(hello_str); + break; + + default: + return -1; + } + return 0; +} + +static void hello_ll_getattr(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) +{ + struct stat stbuf; + + (void) fi; + + memset(&stbuf, 0, sizeof(stbuf)); + if (hello_stat(ino, &stbuf) == -1) + fuse_reply_err(req, ENOENT); + else + fuse_reply_attr(req, &stbuf, 1.0); +} + +static void hello_ll_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) +{ + struct fuse_entry_param e; + + if (parent != 1 || strcmp(name, hello_name) != 0) + fuse_reply_err(req, ENOENT); + else { + memset(&e, 0, sizeof(e)); + e.ino = 2; + e.attr_timeout = 1.0; + e.entry_timeout = 1.0; + hello_stat(e.ino, &e.attr); + + fuse_reply_entry(req, &e); + } +} + +struct dirbuf { + char *p; + size_t size; +}; + +static void dirbuf_add(fuse_req_t req, struct dirbuf *b, const char *name, + fuse_ino_t ino) +{ + struct stat stbuf; + size_t oldsize = b->size; + b->size += fuse_add_direntry(req, NULL, 0, name, NULL, 0); + b->p = (char *) realloc(b->p, b->size); + memset(&stbuf, 0, sizeof(stbuf)); + stbuf.st_ino = ino; + fuse_add_direntry(req, b->p + oldsize, b->size - oldsize, name, &stbuf, + b->size); +} + +#define min(x, y) ((x) < (y) ? (x) : (y)) + +static int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize, + off_t off, size_t maxsize) +{ + if (off < bufsize) + return fuse_reply_buf(req, buf + off, min(bufsize - off, maxsize)); + else + return fuse_reply_buf(req, NULL, 0); +} + +static void hello_ll_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, + off_t off, struct fuse_file_info *fi) +{ + (void) fi; + + if (ino != 1) + fuse_reply_err(req, ENOTDIR); + else { + struct dirbuf b; + + memset(&b, 0, sizeof(b)); + dirbuf_add(req, &b, ".", 1); + dirbuf_add(req, &b, "..", 1); + dirbuf_add(req, &b, hello_name, 2); + reply_buf_limited(req, b.p, b.size, off, size); + free(b.p); + } +} + +static void hello_ll_open(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) +{ + if (ino != 2) + fuse_reply_err(req, EISDIR); + else if ((fi->flags & 3) != O_RDONLY) + fuse_reply_err(req, EACCES); + else + fuse_reply_open(req, fi); +} + +static void hello_ll_read(fuse_req_t req, fuse_ino_t ino, size_t size, + off_t off, struct fuse_file_info *fi) +{ + (void) fi; + + assert(ino == 2); + reply_buf_limited(req, hello_str, strlen(hello_str), off, size); +} + +static struct fuse_lowlevel_ops hello_ll_oper = { + .lookup = hello_ll_lookup, + .getattr = hello_ll_getattr, + .readdir = hello_ll_readdir, + .open = hello_ll_open, + .read = hello_ll_read, +}; + +int main(int argc, char *argv[]) +{ + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + struct fuse_chan *ch; + char *mountpoint; + int err = -1; + + if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1 && + (ch = fuse_mount(mountpoint, &args)) != NULL) { + struct fuse_session *se; + + se = fuse_lowlevel_new(&args, &hello_ll_oper, sizeof(hello_ll_oper), + NULL); + if (se != NULL) { + if (fuse_set_signal_handlers(se) != -1) { + fuse_session_add_chan(se, ch); + err = fuse_session_loop(se); + fuse_remove_signal_handlers(se); + fuse_session_remove_chan(ch); + } + fuse_session_destroy(se); + } + fuse_unmount(mountpoint, ch); + } + fuse_opt_free_args(&args); + + return err ? 1 : 0; +} diff --git a/example-26/null.c b/example-26/null.c new file mode 100644 index 000000000..1ab6573a4 --- /dev/null +++ b/example-26/null.c @@ -0,0 +1,92 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + gcc -Wall `pkg-config fuse --cflags --libs` null.c -o null +*/ + +#define FUSE_USE_VERSION 26 + +#include +#include +#include +#include +#include + +static int null_getattr(const char *path, struct stat *stbuf) +{ + if(strcmp(path, "/") != 0) + return -ENOENT; + + stbuf->st_mode = S_IFREG | 0644; + stbuf->st_nlink = 1; + stbuf->st_uid = getuid(); + stbuf->st_gid = getgid(); + stbuf->st_size = (1ULL << 32); /* 4G */ + stbuf->st_blocks = 0; + stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = time(NULL); + + return 0; +} + +static int null_truncate(const char *path, off_t size) +{ + (void) size; + + if(strcmp(path, "/") != 0) + return -ENOENT; + + return 0; +} + +static int null_open(const char *path, struct fuse_file_info *fi) +{ + (void) fi; + + if(strcmp(path, "/") != 0) + return -ENOENT; + + return 0; +} + +static int null_read(const char *path, char *buf, size_t size, + off_t offset, struct fuse_file_info *fi) +{ + (void) buf; + (void) offset; + (void) fi; + + if(strcmp(path, "/") != 0) + return -ENOENT; + + return size; +} + +static int null_write(const char *path, const char *buf, size_t size, + off_t offset, struct fuse_file_info *fi) +{ + (void) buf; + (void) offset; + (void) fi; + + if(strcmp(path, "/") != 0) + return -ENOENT; + + return size; +} + +static struct fuse_operations null_oper = { + .getattr = null_getattr, + .truncate = null_truncate, + .open = null_open, + .read = null_read, + .write = null_write, +}; + +int main(int argc, char *argv[]) +{ + return fuse_main(argc, argv, &null_oper, NULL); +} diff --git a/include/Makefile.am b/include/Makefile.am index 56cc45ddf..f8391207a 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -8,6 +8,7 @@ fuseinclude_HEADERS = \ fuse.h \ fuse_opt.h \ fuse_common.h \ + fuse_common_compat.h \ fuse_compat.h include_HEADERS = old/fuse.h diff --git a/include/fuse.h b/include/fuse.h index eb41c75ec..83b6f213c 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -12,9 +12,9 @@ /* This file defines the library interface of FUSE */ /* IMPORTANT: you should define FUSE_USE_VERSION before including this - header. To use the newest API define it to 25 (recommended for any - new application), to use the old API define it to 21 (default) or - 22, to use the even older 1.X API define it to 11. */ + header. To use the newest API define it to 26 (recommended for any + new application), to use the old API define it to 21 (default) 22 + or 25, to use the even older 1.X API define it to 11. */ #ifndef FUSE_USE_VERSION #define FUSE_USE_VERSION 21 @@ -22,10 +22,12 @@ #include "fuse_common.h" +#include +#include +#include #include #include #include -#include #ifdef __cplusplus extern "C" { @@ -67,9 +69,9 @@ typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type, * * All methods are optional, but some are essential for a useful * filesystem (e.g. getattr). Open, flush, release, fsync, opendir, - * releasedir, fsyncdir, access, create, ftruncate, fgetattr, init and - * destroy are special purpose methods, without which a full featured - * filesystem can still be implemented. + * releasedir, fsyncdir, access, create, ftruncate, fgetattr, lock, + * init and destroy are special purpose methods, without which a full + * featured filesystem can still be implemented. */ struct fuse_operations { /** Get file attributes. @@ -95,8 +97,9 @@ struct fuse_operations { /** Create a file node * - * There is no create() operation, mknod() will be called for - * creation of all non-directory, non-symlink nodes. + * If the filesystem doesn't define a create() operation, mknod() + * will be called for creation of all non-directory, non-symlink + * nodes. */ int (*mknod) (const char *, mode_t, dev_t); @@ -127,7 +130,10 @@ struct fuse_operations { /** Change the size of a file */ int (*truncate) (const char *, off_t); - /** Change the access and/or modification times of a file */ + /** Change the access and/or modification times of a file + * + * Deprecated, use utimes() instead. + */ int (*utime) (const char *, struct utimbuf *); /** File open operation @@ -166,7 +172,6 @@ struct fuse_operations { int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *); - /** Just a placeholder, don't set */ /** Get file system statistics * * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored @@ -294,8 +299,9 @@ struct fuse_operations { * destroy() method. * * Introduced in version 2.3 + * Changed in version 2.6 */ - void *(*init) (void); + void *(*init) (struct fuse_conn_info *conn); /** * Clean up filesystem @@ -360,6 +366,59 @@ struct fuse_operations { * Introduced in version 2.5 */ int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *); + + /** + * Perform POSIX file locking operation + * + * The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW. + * + * For the meaning of fields in 'struct flock' see the man page + * for fcntl(2). The l_whence field will always be set to + * SEEK_SET. + * + * For checking lock ownership, the 'fuse_file_info->owner' + * argument must be used. + * + * For F_GETLK operation, the library will first check currently + * held locks, and if a conflicting lock is found it will return + * information without calling this method. This ensures, that + * for local locks the l_pid field is correctly filled in. The + * results may not be accurate in case of race conditions and in + * the presence of hard links, but it's unlikly that an + * application would rely on accurate GETLK results in these + * cases. If a conflicting lock is not found, this method will be + * called, and the filesystem may fill out l_pid by a meaningful + * value, or it may leave this field zero. + * + * For F_SETLK and F_SETLKW the l_pid field will be set to the pid + * of the process performing the locking operation. + * + * Note: if this method is not implemented, the kernel will still + * allow file locking to work locally. Hence it is only + * interesting for network filesystems and similar. + * + * Introduced in version 2.6 + */ + int (*lock) (const char *, struct fuse_file_info *, int cmd, + struct flock *); + + /** + * Change the access and modification times of a file with + * nanosecond resolution + * + * Introduced in version 2.6 + */ + int (*utimens) (const char *, const struct timespec tv[2]); + + /** + * Map block index within file to block index within device + * + * Note: This makes sense only for block device backed filesystems + * mounted with the 'blkdev' option + * + * Introduced in version 2.6 + */ + int (*bmap) (const char *, size_t blocksize, uint64_t *idx); }; /** Extra context that may be needed by some filesystems @@ -404,13 +463,15 @@ struct fuse_context { * @param argc the argument counter passed to the main() function * @param argv the argument vector passed to the main() function * @param op the file system operation + * @param user_data user data set in context for init() method * @return 0 on success, nonzero on failure */ /* -int fuse_main(int argc, char *argv[], const struct fuse_operations *op); +int fuse_main(int argc, char *argv[], const struct fuse_operations *op, + void *user_data); */ -#define fuse_main(argc, argv, op) \ - fuse_main_real(argc, argv, op, sizeof(*(op))) +#define fuse_main(argc, argv, op, user_data) \ + fuse_main_real(argc, argv, op, sizeof(*(op)), user_data) /* ----------------------------------------------------------- * * More detailed API * @@ -419,19 +480,24 @@ int fuse_main(int argc, char *argv[], const struct fuse_operations *op); /** * Create a new FUSE filesystem. * - * @param fd the control file descriptor + * @param ch the communication channel * @param args argument vector * @param op the operations * @param op_size the size of the fuse_operations structure + * @param user_data user data set in context for init() method * @return the created FUSE handle */ -struct fuse *fuse_new(int fd, struct fuse_args *args, - const struct fuse_operations *op, size_t op_size); +struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, + const struct fuse_operations *op, size_t op_size, + void *user_data); /** * Destroy the FUSE handle. * - * The filesystem is not unmounted. + * The communication channel attached to the handle is also destroyed. + * + * NOTE: This function does not unmount the filesystem. If this is + * needed, call fuse_unmount() before calling this function. * * @param f the FUSE handle */ @@ -476,11 +542,18 @@ int fuse_loop_mt(struct fuse *f); * The context is only valid for the duration of a filesystem * operation, and thus must not be stored and used later. * - * @param f the FUSE handle * @return the context */ struct fuse_context *fuse_get_context(void); +/** + * Check if a request has already been interrupted + * + * @param req request handle + * @return 1 if the request has been interrupted, 0 otherwise + */ +int fuse_interrupted(void); + /** * Obsolete, doesn't do anything * @@ -497,22 +570,26 @@ int fuse_is_lib_option(const char *opt); * Do not call this directly, use fuse_main() */ int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, - size_t op_size); + size_t op_size, void *user_data); /* ----------------------------------------------------------- * * Advanced API for event handling, don't worry about this... * * ----------------------------------------------------------- */ +/* NOTE: the following functions are deprecated, and will be removed + from the 3.0 API. Use the lowlevel session functions instead */ + /** Function type used to process commands */ typedef void (*fuse_processor_t)(struct fuse *, struct fuse_cmd *, void *); /** This is the part of fuse_main() before the event loop */ struct fuse *fuse_setup(int argc, char *argv[], const struct fuse_operations *op, size_t op_size, - char **mountpoint, int *multithreaded, int *fd); + char **mountpoint, int *multithreaded, + void *user_data); /** This is the part of fuse_main() after the event loop */ -void fuse_teardown(struct fuse *fuse, int fd, char *mountpoint); +void fuse_teardown(struct fuse *fuse, char *mountpoint); /** Read a single command. If none are read, return NULL */ struct fuse_cmd *fuse_read_cmd(struct fuse *f); @@ -528,68 +605,59 @@ int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data); called */ int fuse_exited(struct fuse *f); -/** Set function which can be used to get the current context */ +/** This function is obsolete and implemented as a no-op */ void fuse_set_getcontext_func(struct fuse_context *(*func)(void)); +/** Get session from fuse object */ +struct fuse_session *fuse_get_session(struct fuse *f); + /* ----------------------------------------------------------- * * Compatibility stuff * * ----------------------------------------------------------- */ -#ifndef __FreeBSD__ - -#if FUSE_USE_VERSION == 22 || FUSE_USE_VERSION == 21 || FUSE_USE_VERSION == 11 +#if FUSE_USE_VERSION < 26 # include "fuse_compat.h" -# undef FUSE_MINOR_VERSION # undef fuse_main -# if FUSE_USE_VERSION == 22 -# define FUSE_MINOR_VERSION 4 +# if FUSE_USE_VERSION == 25 +# define fuse_main(argc, argv, op) \ + fuse_main_real_compat25(argc, argv, op, sizeof(*(op))) +# define fuse_new fuse_new_compat25 +# define fuse_setup fuse_setup_compat25 +# define fuse_teardown fuse_teardown_compat22 +# define fuse_operations fuse_operations_compat25 +# elif FUSE_USE_VERSION == 22 # define fuse_main(argc, argv, op) \ fuse_main_real_compat22(argc, argv, op, sizeof(*(op))) # define fuse_new fuse_new_compat22 # define fuse_setup fuse_setup_compat22 +# define fuse_teardown fuse_teardown_compat22 # define fuse_operations fuse_operations_compat22 -# define fuse_file_info fuse_file_info_compat22 -# define fuse_mount fuse_mount_compat22 +# define fuse_file_info fuse_file_info_compat +# elif FUSE_USE_VERSION == 24 +# error Compatibility with high-level API version 24 not supported # else -# define fuse_dirfil_t fuse_dirfil_t_compat -# define __fuse_read_cmd fuse_read_cmd -# define __fuse_process_cmd fuse_process_cmd -# define __fuse_loop_mt fuse_loop_mt_proc -# if FUSE_USE_VERSION == 21 -# define FUSE_MINOR_VERSION 1 -# define fuse_operations fuse_operations_compat2 -# define fuse_main fuse_main_compat2 -# define fuse_new fuse_new_compat2 -# define __fuse_setup fuse_setup_compat2 -# define __fuse_teardown fuse_teardown -# define __fuse_exited fuse_exited -# define __fuse_set_getcontext_func fuse_set_getcontext_func -# define fuse_mount fuse_mount_compat22 -# else -# warning Compatibility with API version 11 is deprecated -# undef FUSE_MAJOR_VERSION -# define FUSE_MAJOR_VERSION 1 -# define FUSE_MINOR_VERSION 1 -# define fuse_statfs fuse_statfs_compat1 -# define fuse_operations fuse_operations_compat1 -# define fuse_main fuse_main_compat1 -# define fuse_new fuse_new_compat1 -# define fuse_mount fuse_mount_compat1 -# define FUSE_DEBUG FUSE_DEBUG_COMPAT1 -# endif +# define fuse_dirfil_t fuse_dirfil_t_compat +# define __fuse_read_cmd fuse_read_cmd +# define __fuse_process_cmd fuse_process_cmd +# define __fuse_loop_mt fuse_loop_mt_proc +# if FUSE_USE_VERSION == 21 +# define fuse_operations fuse_operations_compat2 +# define fuse_main fuse_main_compat2 +# define fuse_new fuse_new_compat2 +# define __fuse_setup fuse_setup_compat2 +# define __fuse_teardown fuse_teardown_compat22 +# define __fuse_exited fuse_exited +# define __fuse_set_getcontext_func fuse_set_getcontext_func +# else +# define fuse_statfs fuse_statfs_compat1 +# define fuse_operations fuse_operations_compat1 +# define fuse_main fuse_main_compat1 +# define fuse_new fuse_new_compat1 +# define FUSE_DEBUG FUSE_DEBUG_COMPAT1 +# endif # endif -#elif FUSE_USE_VERSION < 25 -# error Compatibility with API version other than 21, 22 and 11 not supported #endif -#else /* __FreeBSD__ */ - -#if FUSE_USE_VERSION < 25 -# error On FreeBSD API version 25 or greater must be used -#endif - -#endif /* __FreeBSD__ */ - #ifdef __cplusplus } #endif diff --git a/include/fuse_common.h b/include/fuse_common.h index 0f35ea62b..8dc7bc25a 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -20,7 +20,7 @@ #define FUSE_MAJOR_VERSION 2 /** Minor version of FUSE library interface */ -#define FUSE_MINOR_VERSION 5 +#define FUSE_MINOR_VERSION 6 #define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min)) #define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION) @@ -58,14 +58,64 @@ struct fuse_file_info { need not be invalidated. Introduced in version 2.4 */ unsigned int keep_cache : 1; + /** Indicates a flush operation. Set in flush operation, also + maybe set in highlevel lock operation and lowlevel release + operation. Introduced in version 2.6 */ + unsigned int flush : 1; + /** Padding. Do not use*/ - unsigned int padding : 30; + unsigned int padding : 29; /** File handle. May be filled in by filesystem in open(). Available in all other file operations */ uint64_t fh; + + /** Lock owner id. Available in locking operations and flush */ + uint64_t lock_owner; }; +/** + * Connection information, passed to the ->init() method + * + * Some of the elements are read-write, these can be changed to + * indicate the value requested by the filesystem. The requested + * value must usually be smaller than the indicated value. + */ +struct fuse_conn_info { + /** + * Major version of the protocol (read-only) + */ + unsigned proto_major; + + /** + * Minor version of the protocol (read-only) + */ + unsigned proto_minor; + + /** + * Is asynchronous read supported (read-write) + */ + unsigned async_read; + + /** + * Maximum size of the write buffer + */ + unsigned max_write; + + /** + * Maximum readahead + */ + unsigned max_readahead; + + /** + * For future use. + */ + unsigned reserved[27]; +}; + +struct fuse_session; +struct fuse_chan; + /** * Create a FUSE mountpoint * @@ -74,16 +124,17 @@ struct fuse_file_info { * * @param mountpoint the mount point path * @param args argument vector - * @return the control file descriptor on success, -1 on failure + * @return the communication channel on success, NULL on failure */ -int fuse_mount(const char *mountpoint, struct fuse_args *args); +struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args); /** * Umount a FUSE mountpoint * * @param mountpoint the mount point path + * @param ch the communication channel */ -void fuse_unmount(const char *mountpoint); +void fuse_unmount(const char *mountpoint, struct fuse_chan *ch); /** * Parse common options @@ -110,6 +161,67 @@ int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint, int *multithreaded, int *foreground); +int fuse_daemonize(int foreground); + +/* ----------------------------------------------------------- * + * Signal handling * + * ----------------------------------------------------------- */ + +/** + * Exit session on HUP, TERM and INT signals and ignore PIPE signal + * + * Stores session in a global variable. May only be called once per + * process until fuse_remove_signal_handlers() is called. + * + * @param se the session to exit + * @return 0 on success, -1 on failure + */ +int fuse_set_signal_handlers(struct fuse_session *se); + +/** + * Restore default signal handlers + * + * Resets global session. After this fuse_set_signal_handlers() may + * be called again. + * + * @param se the same session as given in fuse_set_signal_handlers() + */ +void fuse_remove_signal_handlers(struct fuse_session *se); + +/* ----------------------------------------------------------- * + * Compatibility stuff * + * ----------------------------------------------------------- */ + +#if FUSE_USE_VERSION < 26 +# ifdef __FreeBSD__ +# if FUSE_USE_VERSION < 25 +# error On FreeBSD API version 25 or greater must be used +# endif +# endif +# include "fuse_common_compat.h" +# undef FUSE_MINOR_VERSION +# undef fuse_main +# define fuse_unmount fuse_unmount_compat22 +# if FUSE_USE_VERSION == 25 +# define FUSE_MINOR_VERSION 5 +# define fuse_mount fuse_mount_compat25 +# elif FUSE_USE_VERSION == 24 || FUSE_USE_VERSION == 22 +# define FUSE_MINOR_VERSION 4 +# define fuse_mount fuse_mount_compat22 +# elif FUSE_USE_VERSION == 21 +# define FUSE_MINOR_VERSION 1 +# define fuse_mount fuse_mount_compat22 +# elif FUSE_USE_VERSION == 11 +# warning Compatibility with API version 11 is deprecated +# undef FUSE_MAJOR_VERSION +# define FUSE_MAJOR_VERSION 1 +# define FUSE_MINOR_VERSION 1 +# define fuse_mount fuse_mount_compat1 +# else +# error Compatibility with API version other than 21, 22, 24, 25 and 11 not supported +# endif +#endif + #ifdef __cplusplus } #endif diff --git a/include/fuse_common_compat.h b/include/fuse_common_compat.h new file mode 100644 index 000000000..60ca944cd --- /dev/null +++ b/include/fuse_common_compat.h @@ -0,0 +1,27 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPL. + See the file COPYING.LIB. +*/ + +/* these definitions provide source compatibility to prior versions. + Do not include this file directly! */ + +struct fuse_file_info_compat { + int flags; + unsigned long fh; + int writepage; + unsigned int direct_io : 1; + unsigned int keep_cache : 1; +}; + +int fuse_mount_compat25(const char *mountpoint, struct fuse_args *args); + +int fuse_mount_compat22(const char *mountpoint, const char *opts); + +int fuse_mount_compat1(const char *mountpoint, const char *args[]); + +void fuse_unmount_compat22(const char *mountpoint); + diff --git a/include/fuse_compat.h b/include/fuse_compat.h index 220ef0752..b67f30e00 100644 --- a/include/fuse_compat.h +++ b/include/fuse_compat.h @@ -9,16 +9,64 @@ /* these definitions provide source compatibility to prior versions. Do not include this file directly! */ -#include - -struct fuse_file_info_compat22 { - int flags; - unsigned long fh; - int writepage; - unsigned int direct_io : 1; - unsigned int keep_cache : 1; +struct fuse_operations_compat25 { + int (*getattr) (const char *, struct stat *); + int (*readlink) (const char *, char *, size_t); + int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t); + int (*mknod) (const char *, mode_t, dev_t); + int (*mkdir) (const char *, mode_t); + int (*unlink) (const char *); + int (*rmdir) (const char *); + int (*symlink) (const char *, const char *); + int (*rename) (const char *, const char *); + int (*link) (const char *, const char *); + int (*chmod) (const char *, mode_t); + int (*chown) (const char *, uid_t, gid_t); + int (*truncate) (const char *, off_t); + int (*utime) (const char *, struct utimbuf *); + int (*open) (const char *, struct fuse_file_info *); + int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *); + int (*write) (const char *, const char *, size_t, off_t, + struct fuse_file_info *); + int (*statfs) (const char *, struct statvfs *); + int (*flush) (const char *, struct fuse_file_info *); + int (*release) (const char *, struct fuse_file_info *); + int (*fsync) (const char *, int, struct fuse_file_info *); + int (*setxattr) (const char *, const char *, const char *, size_t, int); + int (*getxattr) (const char *, const char *, char *, size_t); + int (*listxattr) (const char *, char *, size_t); + int (*removexattr) (const char *, const char *); + int (*opendir) (const char *, struct fuse_file_info *); + int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, + struct fuse_file_info *); + int (*releasedir) (const char *, struct fuse_file_info *); + int (*fsyncdir) (const char *, int, struct fuse_file_info *); + void *(*init) (void); + void (*destroy) (void *); + int (*access) (const char *, int); + int (*create) (const char *, mode_t, struct fuse_file_info *); + int (*ftruncate) (const char *, off_t, struct fuse_file_info *); + int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *); }; +struct fuse *fuse_new_compat25(int fd, struct fuse_args *args, + const struct fuse_operations_compat25 *op, + size_t op_size); + +int fuse_main_real_compat25(int argc, char *argv[], + const struct fuse_operations_compat25 *op, + size_t op_size); + +struct fuse *fuse_setup_compat25(int argc, char *argv[], + const struct fuse_operations_compat25 *op, + size_t op_size, char **mountpoint, + int *multithreaded, int *fd); + +void fuse_teardown_compat22(struct fuse *fuse, int fd, char *mountpoint); + +#ifndef __FreeBSD__ +#include + struct fuse_operations_compat22 { int (*getattr) (const char *, struct stat *); int (*readlink) (const char *, char *, size_t); @@ -34,24 +82,24 @@ struct fuse_operations_compat22 { int (*chown) (const char *, uid_t, gid_t); int (*truncate) (const char *, off_t); int (*utime) (const char *, struct utimbuf *); - int (*open) (const char *, struct fuse_file_info_compat22 *); + int (*open) (const char *, struct fuse_file_info_compat *); int (*read) (const char *, char *, size_t, off_t, - struct fuse_file_info_compat22 *); + struct fuse_file_info_compat *); int (*write) (const char *, const char *, size_t, off_t, - struct fuse_file_info_compat22 *); + struct fuse_file_info_compat *); int (*statfs) (const char *, struct statfs *); - int (*flush) (const char *, struct fuse_file_info_compat22 *); - int (*release) (const char *, struct fuse_file_info_compat22 *); - int (*fsync) (const char *, int, struct fuse_file_info_compat22 *); + int (*flush) (const char *, struct fuse_file_info_compat *); + int (*release) (const char *, struct fuse_file_info_compat *); + int (*fsync) (const char *, int, struct fuse_file_info_compat *); int (*setxattr) (const char *, const char *, const char *, size_t, int); int (*getxattr) (const char *, const char *, char *, size_t); int (*listxattr) (const char *, char *, size_t); int (*removexattr) (const char *, const char *); - int (*opendir) (const char *, struct fuse_file_info_compat22 *); + int (*opendir) (const char *, struct fuse_file_info_compat *); int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, - struct fuse_file_info_compat22 *); - int (*releasedir) (const char *, struct fuse_file_info_compat22 *); - int (*fsyncdir) (const char *, int, struct fuse_file_info_compat22 *); + struct fuse_file_info_compat *); + int (*releasedir) (const char *, struct fuse_file_info_compat *); + int (*fsyncdir) (const char *, int, struct fuse_file_info_compat *); void *(*init) (void); void (*destroy) (void *); }; @@ -69,8 +117,6 @@ int fuse_main_real_compat22(int argc, char *argv[], const struct fuse_operations_compat22 *op, size_t op_size); -int fuse_mount_compat22(const char *mountpoint, const char *opts); - typedef int (*fuse_dirfil_t_compat) (fuse_dirh_t h, const char *name, int type); struct fuse_operations_compat2 { int (*getattr) (const char *, struct stat *); @@ -140,8 +186,8 @@ struct fuse_operations_compat1 { #define FUSE_DEBUG_COMPAT1 (1 << 1) -int fuse_mount_compat1(const char *mountpoint, const char *args[]); - struct fuse *fuse_new_compat1(int fd, int flags, const struct fuse_operations_compat1 *op); void fuse_main_compat1(int argc, char *argv[], const struct fuse_operations_compat1 *op); + +#endif /* __FreeBSD__ */ diff --git a/include/fuse_opt.h b/include/fuse_opt.h index 2988902f2..cbe9b7b8f 100644 --- a/include/fuse_opt.h +++ b/include/fuse_opt.h @@ -2,8 +2,8 @@ FUSE: Filesystem in Userspace Copyright (C) 2001-2006 Miklos Szeredi - This program can be distributed under the terms of the GNU GPL. - See the file COPYING. + This program can be distributed under the terms of the GNU LGPL. + See the file COPYING.LIB. */ #ifndef _FUSE_OPT_H_ @@ -132,6 +132,22 @@ struct fuse_args { */ #define FUSE_OPT_KEY_NONOPT -2 +/** + * Special key value for options to keep + * + * Argument is not passed to processing function, but behave as if the + * processing function returned 1 + */ +#define FUSE_OPT_KEY_KEEP -3 + +/** + * Special key value for options to discard + * + * Argument is not passed to processing function, but behave as if the + * processing function returned zero + */ +#define FUSE_OPT_KEY_DISCARD -4 + /** * Processing function * @@ -201,6 +217,21 @@ int fuse_opt_add_opt(char **opts, const char *opt); */ int fuse_opt_add_arg(struct fuse_args *args, const char *arg); +/** + * Add an argument at the specified position in a NULL terminated + * argument vector + * + * Adds the argument to the N-th position. This is useful for adding + * options at the beggining of the array which must not come after the + * special '--' option. + * + * @param args is the structure containing the current argument list + * @param pos is the position at which to add the argument + * @param arg is the new argument to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg); + /** * Free the contents of argument list * diff --git a/src/fuse_versionscript b/src/fuse_versionscript index 95e0d8708..5722a5b0a 100644 --- a/src/fuse_versionscript +++ b/src/fuse_versionscript @@ -24,8 +24,6 @@ FUSE_2.2 { fuse_read_cmd; fuse_set_getcontext_func; fuse_setup_compat2; - fuse_teardown; - fuse_unmount; }; FUSE_2.4 { @@ -66,18 +64,15 @@ FUSE_2.4 { FUSE_2.5 { global: - fuse_lowlevel_new; fuse_lowlevel_new_compat; - fuse_main_real; fuse_main_real_compat22; - fuse_mount; fuse_mount_compat22; - fuse_new; fuse_new_compat22; fuse_opt_parse; fuse_opt_add_opt; fuse_opt_add_arg; fuse_opt_free_args; + fuse_opt_insert_arg; fuse_opt_match; fuse_parse_cmdline; fuse_remove_signal_handlers; @@ -86,10 +81,39 @@ FUSE_2.5 { fuse_reply_open_compat; fuse_reply_statfs; fuse_reply_statfs_compat; - fuse_setup; fuse_setup_compat22; fuse_set_signal_handlers; +} FUSE_2.4; + +FUSE_2.6 { + global: + fuse_add_direntry; + fuse_chan_new; + fuse_chan_new_compat24; + fuse_chan_recv; + fuse_daemonize; + fuse_get_session; + fuse_interrupted; + fuse_lowlevel_new; + fuse_lowlevel_new_compat25; + fuse_main_real; + fuse_main_real_compat25; + fuse_mount; + fuse_mount_compat25; + fuse_new; + fuse_new_compat25; + fuse_opt_insert_arg; + fuse_reply_lock; + fuse_req_interrupt_func; + fuse_req_interrupted; + fuse_session_remove_chan; + fuse_setup; + fuse_setup_compat25; + fuse_teardown; + fuse_teardown_compat22; + fuse_unmount; + fuse_unmount_compat22; local: *; -} FUSE_2.4; +} FUSE_2.5; -- cgit v1.2.3