+2005-11-11 Miklos Szeredi <miklos@szeredi.hu>
+
+ * Use 64bit type for file handle, so the full range supported by
+ the kernel interface is available to applications
+
2005-11-10 Miklos Szeredi <miklos@szeredi.hu>
* Moved mountpoint argument checking from fuse_parse_cmdline() to
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 = (DIR *) fi->fh;
+ DIR *dp = get_dirp(fi);
struct dirent *de;
(void) path;
static int xmp_releasedir(const char *path, struct fuse_file_info *fi)
{
- DIR *dp = (DIR *) fi->fh;
+ DIR *dp = get_dirp(fi);
(void) path;
closedir(dp);
return 0;
struct fuse_file_info *);
/** Just a placeholder, don't set */
- void (*statfs_old) (void);
+ /** Get file system statistics
+ *
+ * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored
+ *
+ * Replaced 'struct statfs' parameter with 'struct statvfs' in
+ * version 2.5
+ */
+ int (*statfs) (const char *, struct statvfs *);
/** Possibly flush cached data
*
* Introduced in version 2.5
*/
int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
-
- /** Get file system statistics
- *
- * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored
- *
- * Replaced 'struct statfs' parameter with 'struct statvfs' in
- * version 2.5
- */
- int (*statfs) (const char *, struct statvfs *);
};
/** Extra context that may be needed by some filesystems
# undef fuse_main
# if FUSE_USE_VERSION == 22
# define FUSE_MINOR_VERSION 4
-# define fuse_main fuse_main_compat22
+# 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_operations fuse_operations_compat22
+# define fuse_file_info fuse_file_info_compat22
# else
# define fuse_dirfil_t fuse_dirfil_t_compat
# define __fuse_read_cmd fuse_read_cmd
#ifndef _FUSE_COMMON_H_
#define _FUSE_COMMON_H_
+#include <stdint.h>
+
/** Major version of FUSE library interface */
#define FUSE_MAJOR_VERSION 2
extern "C" {
#endif
-/** Information about open files */
+/**
+ * Information about open files
+ *
+ * Changed in version 2.5
+ */
struct fuse_file_info {
/** Open flags. Available in open() and release() */
int flags;
- /** File handle. May be filled in by filesystem in open().
- Available in all other file operations */
- unsigned long fh;
+ /** Old file handle, don't use */
+ unsigned long fh_old;
/** In case of a write operation indicates if this was caused by a
writepage */
/** Can be filled in by open, to indicate, that cached file data
need not be invalidated. Introduced in version 2.4 */
unsigned int keep_cache : 1;
+
+ /** Padding. Do not use*/
+ unsigned int padding : 30;
+
+ /** File handle. May be filled in by filesystem in open().
+ Available in all other file operations */
+ uint64_t fh;
};
/*
#include <sys/statfs.h>
+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_compat22 {
int (*getattr) (const char *, struct stat *);
int (*readlink) (const char *, char *, size_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 (*open) (const char *, struct fuse_file_info_compat22 *);
+ int (*read) (const char *, char *, size_t, off_t,
+ struct fuse_file_info_compat22 *);
int (*write) (const char *, const char *, size_t, off_t,
- struct fuse_file_info *);
+ struct fuse_file_info_compat22 *);
int (*statfs) (const char *, struct statfs *);
- 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 (*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 (*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 (*opendir) (const char *, struct fuse_file_info_compat22 *);
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 *);
+ struct fuse_file_info_compat22 *);
+ int (*releasedir) (const char *, struct fuse_file_info_compat22 *);
+ int (*fsyncdir) (const char *, int, struct fuse_file_info_compat22 *);
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 *);
- void (*statfs_new) (void);
};
-static inline int fuse_main_compat22(int argc, char *argv[],
- const struct fuse_operations_compat22 *op)
-{
- return fuse_main_real(argc, argv, (const struct fuse_operations *) op,
- sizeof(*op));
-}
+struct fuse *fuse_new_compat22(int fd, const char *opts,
+ const struct fuse_operations_compat22 *op,
+ size_t op_size);
+
+struct fuse *fuse_setup_compat22(int argc, char *argv[],
+ const struct fuse_operations_compat22 *op,
+ size_t op_size, char **mountpoint,
+ int *multithreaded, int *fd);
+int fuse_main_real_compat22(int argc, char *argv[],
+ const struct fuse_operations_compat22 *op,
+ size_t op_size);
typedef int (*fuse_dirfil_t_compat) (fuse_dirh_t h, const char *name, int type);
struct fuse_operations_compat2 {
* ----------------------------------------------------------- */
#if FUSE_USE_VERSION == 24
-#include <sys/statfs.h>
-
-int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf);
-
+#include "fuse_lowlevel_compat.h"
#undef FUSE_MINOR_VERSION
#define FUSE_MINOR_VERSION 4
+#define fuse_file_info fuse_file_info_compat
#define fuse_reply_statfs fuse_reply_statfs_compat
+#define fuse_reply_open fuse_reply_open_compat
#elif FUSE_USE_VERSION < 25
# error Compatibility with low level API version other than 24 not supported
--- /dev/null
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+
+ 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! */
+
+#include <sys/statfs.h>
+
+struct fuse_file_info_compat {
+ int flags;
+ unsigned long fh;
+ int writepage;
+ unsigned int direct_io : 1;
+ unsigned int keep_cache : 1;
+};
+
+int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf);
+
+int fuse_reply_open_compat(fuse_req_t req,
+ const struct fuse_file_info_compat *fi);
#include <limits.h>
#include <errno.h>
#include <assert.h>
-#include <stdint.h>
#include <pthread.h>
#include <sys/param.h>
#include <sys/uio.h>
unsigned size;
unsigned needlen;
int filled;
- unsigned long fh;
+ uint64_t fh;
int error;
fuse_ino_t nodeid;
};
{
struct node *node = get_node_nocheck(f, nodeid);
if (!node) {
- fprintf(stderr, "fuse internal error: node %lu not found\n",
- nodeid);
+ fprintf(stderr, "fuse internal error: node %llu not found\n",
+ (unsigned long long) nodeid);
abort();
}
return node;
node->parent = 0;
return;
}
- fprintf(stderr, "fuse internal error: unable to unhash node: %lu\n",
- node->nodeid);
+ fprintf(stderr, "fuse internal error: unable to unhash node: %llu\n",
+ (unsigned long long) node->nodeid);
abort();
}
}
static void delete_node(struct fuse *f, struct node *node)
{
if (f->flags & FUSE_DEBUG) {
- printf("delete: %lu\n", node->nodeid);
+ printf("delete: %llu\n", (unsigned long long) node->nodeid);
fflush(stdout);
}
assert(!node->name);
{
struct fuse *f = req_fuse(req);
if (f->flags & FUSE_DEBUG) {
- printf("FORGET %lu/%lu\n", ino, nlookup);
+ printf("FORGET %llu/%lu\n", (unsigned long long) ino, nlookup);
fflush(stdout);
}
forget_node(f, ino, nlookup);
err = f->op.create(path, mode, fi);
if (!err) {
if (f->flags & FUSE_DEBUG) {
- printf("CREATE[%lu] flags: 0x%x %s\n", fi->fh, fi->flags,
- path);
+ printf("CREATE[%llu] flags: 0x%x %s\n",
+ (unsigned long long) fi->fh, fi->flags, path);
fflush(stdout);
}
err = lookup_path(f, parent, name, path, &e, fi);
if (path != NULL) {
if (!f->compat)
err = f->op.open(path, fi);
- else
+ else if (f->compat == 22) {
+ struct fuse_file_info_compat22 tmp;
+ memcpy(&tmp, fi, sizeof(tmp));
+ err = ((struct fuse_operations_compat22 *) &f->op)->open(path, &tmp);
+ memcpy(fi, &tmp, sizeof(tmp));
+ fi->fh = tmp.fh;
+ } else
err = ((struct fuse_operations_compat2 *) &f->op)->open(path, fi->flags);
}
}
if (!err) {
if (f->flags & FUSE_DEBUG) {
- printf("OPEN[%lu] flags: 0x%x\n", fi->fh, fi->flags);
+ printf("OPEN[%llu] flags: 0x%x\n", (unsigned long long) fi->fh,
+ fi->flags);
fflush(stdout);
}
if (fuse_reply_open(req, fi) == -ENOENT) {
/* The open syscall was interrupted, so it must be cancelled */
if(f->op.release && path != NULL) {
- if (!f->compat)
+ if (!f->compat || f->compat >= 22)
f->op.release(path, fi);
else
((struct fuse_operations_compat2 *) &f->op)->release(path, fi->flags);
path = get_path(f, ino);
if (path != NULL) {
if (f->flags & FUSE_DEBUG) {
- printf("READ[%lu] %u bytes from %llu\n", fi->fh, size, off);
+ printf("READ[%llu] %u bytes from %llu\n",
+ (unsigned long long) fi->fh, size, off);
fflush(stdout);
}
if (res >= 0) {
if (f->flags & FUSE_DEBUG) {
- printf(" READ[%lu] %u bytes\n", fi->fh, res);
+ printf(" READ[%llu] %u bytes\n", (unsigned long long) fi->fh,
+ res);
fflush(stdout);
}
if ((size_t) res > size)
path = get_path(f, ino);
if (path != NULL) {
if (f->flags & FUSE_DEBUG) {
- printf("WRITE%s[%lu] %u bytes to %llu\n",
- fi->writepage ? "PAGE" : "", fi->fh, size, off);
+ printf("WRITE%s[%llu] %u bytes to %llu\n",
+ fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
+ size, off);
fflush(stdout);
}
if (res >= 0) {
if (f->flags & FUSE_DEBUG) {
- printf(" WRITE%s[%lu] %u bytes\n",
- fi->writepage ? "PAGE" : "", fi->fh, res);
+ printf(" WRITE%s[%llu] %u bytes\n",
+ fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
+ res);
fflush(stdout);
}
if ((size_t) res > size)
path = get_path(f, ino);
if (path != NULL) {
if (f->flags & FUSE_DEBUG) {
- printf("FLUSH[%lu]\n", fi->fh);
+ printf("FLUSH[%llu]\n", (unsigned long long) fi->fh);
fflush(stdout);
}
err = -ENOSYS;
pthread_rwlock_rdlock(&f->tree_lock);
path = get_path(f, ino);
if (f->flags & FUSE_DEBUG) {
- printf("RELEASE[%lu] flags: 0x%x\n", fi->fh, fi->flags);
+ printf("RELEASE[%llu] flags: 0x%x\n", (unsigned long long) fi->fh,
+ fi->flags);
fflush(stdout);
}
if (f->op.release) {
- if (!f->compat)
+ if (!f->compat || f->compat >= 22)
f->op.release(path ? path : "-", fi);
else if (path)
((struct fuse_operations_compat2 *) &f->op)->release(path, fi->flags);
path = get_path(f, ino);
if (path != NULL) {
if (f->flags & FUSE_DEBUG) {
- printf("FSYNC[%lu]\n", fi->fh);
+ printf("FSYNC[%llu]\n", (unsigned long long) fi->fh);
fflush(stdout);
}
err = -ENOSYS;
static struct fuse_dirhandle *get_dirhandle(const struct fuse_file_info *llfi,
struct fuse_file_info *fi)
{
- struct fuse_dirhandle *dh = (struct fuse_dirhandle *) llfi->fh;
+ struct fuse_dirhandle *dh = (struct fuse_dirhandle *) (uintptr_t) llfi->fh;
memset(fi, 0, sizeof(struct fuse_file_info));
fi->fh = dh->fh;
return dh;
dh->nodeid = ino;
mutex_init(&dh->lock);
- llfi->fh = (unsigned long) dh;
+ llfi->fh = (uintptr_t) dh;
if (f->op.opendir) {
struct fuse_file_info fi;
pthread_rwlock_rdlock(&f->tree_lock);
path = get_path(f, ino);
if (path != NULL) {
- err = f->op.opendir(path, &fi);
- dh->fh = fi.fh;
+ if (!f->compat) {
+ err = f->op.opendir(path, &fi);
+ dh->fh = fi.fh;
+ } else {
+ struct fuse_file_info_compat22 tmp;
+ memcpy(&tmp, &fi, sizeof(tmp));
+ err = ((struct fuse_operations_compat22 *) &f->op)->opendir(path, &tmp);
+ dh->fh = tmp.fh;
+ }
}
if (!err) {
pthread_mutex_lock(&f->lock);
memset(&buf, 0, sizeof(buf));
if (f->op.statfs) {
- err = f->op.statfs("/", &buf);
- } else if (f->op.statfs_old) {
- if (!f->compat || f->compat > 11) {
+ if (!f->compat) {
+ err = f->op.statfs("/", &buf);
+ } else if (f->compat > 11) {
struct statfs oldbuf;
err = ((struct fuse_operations_compat22 *) &f->op)->statfs("/", &oldbuf);
if (!err)
return fuse_new_common(fd, opts, op, op_size, 0);
}
+struct fuse *fuse_new_compat22(int fd, const char *opts,
+ const struct fuse_operations_compat22 *op,
+ size_t op_size)
+{
+ return fuse_new_common(fd, opts, (struct fuse_operations *) op,
+ op_size, 22);
+}
+
struct fuse *fuse_new_compat2(int fd, const char *opts,
const struct fuse_operations_compat2 *op)
{
__asm__(".symver fuse_read_cmd,__fuse_read_cmd@");
__asm__(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@");
__asm__(".symver fuse_new_compat2,fuse_new@");
+__asm__(".symver fuse_new_compat22,fuse_new@FUSE_2.2");
#include <config.h>
#include "fuse_lowlevel.h"
+#include "fuse_lowlevel_compat.h"
#include "fuse_kernel.h"
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
-#include <stdint.h>
#include <sys/statfs.h>
#define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
arg->open_flags |= FOPEN_KEEP_CACHE;
}
+static void fill_open_compat(struct fuse_open_out *arg,
+ const struct fuse_file_info_compat *f)
+{
+ arg->fh = f->fh;
+ if (f->direct_io)
+ arg->open_flags |= FOPEN_DIRECT_IO;
+ if (f->keep_cache)
+ arg->open_flags |= FOPEN_KEEP_CACHE;
+}
+
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
{
struct fuse_entry_out arg;
return send_reply_ok(req, &arg, sizeof(arg));
}
+int fuse_reply_open_compat(fuse_req_t req,
+ const struct fuse_file_info_compat *f)
+{
+ struct fuse_open_out arg;
+
+ memset(&arg, 0, sizeof(arg));
+ fill_open_compat(&arg, f);
+ return send_reply_ok(req, &arg, sizeof(arg));
+}
+
int fuse_reply_write(fuse_req_t req, size_t count)
{
struct fuse_write_out arg;
memset(&fi_store, 0, sizeof(fi_store));
fi = &fi_store;
fi->fh = arg->fh;
+ fi->fh_old = fi->fh;
}
req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
} else
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
+ fi.fh_old = fi.fh;
req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
} else
fuse_reply_err(req, ENOSYS);
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
+ fi.fh_old = fi.fh;
fi.writepage = arg->write_flags & 1;
if (req->f->op.write)
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
+ fi.fh_old = fi.fh;
if (req->f->op.flush)
req->f->op.flush(req, nodeid, &fi);
memset(&fi, 0, sizeof(fi));
fi.flags = arg->flags;
fi.fh = arg->fh;
+ fi.fh_old = fi.fh;
if (req->f->op.release)
req->f->op.release(req, nodeid, &fi);
memset(&fi, 0, sizeof(fi));
fi.fh = inarg->fh;
+ fi.fh_old = fi.fh;
if (req->f->op.fsync)
req->f->op.fsync(req, nodeid, inarg->fsync_flags & 1, &fi);
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
+ fi.fh_old = fi.fh;
if (req->f->op.readdir)
req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
memset(&fi, 0, sizeof(fi));
fi.flags = arg->flags;
fi.fh = arg->fh;
+ fi.fh_old = fi.fh;
if (req->f->op.releasedir)
req->f->op.releasedir(req, nodeid, &fi);
memset(&fi, 0, sizeof(fi));
fi.fh = inarg->fh;
+ fi.fh_old = fi.fh;
if (req->f->op.fsyncdir)
req->f->op.fsyncdir(req, nodeid, inarg->fsync_flags & 1, &fi);
free(f);
}
-
struct fuse_session *fuse_lowlevel_new(const char *opts,
const struct fuse_lowlevel_ops *op,
size_t op_size, void *userdata)
}
__asm__(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");
+__asm__(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
fuse_main;
fuse_main_compat1;
fuse_main_compat2;
- fuse_main_real;
fuse_mount;
fuse_mount_compat1;
- fuse_new;
fuse_new_compat1;
fuse_new_compat2;
fuse_process_cmd;
fuse_read_cmd;
fuse_set_getcontext_func;
- fuse_setup;
fuse_setup_compat2;
fuse_teardown;
fuse_unmount;
fuse_reply_entry;
fuse_reply_err;
fuse_reply_none;
- fuse_reply_open;
fuse_reply_readlink;
fuse_reply_write;
fuse_reply_xattr;
FUSE_2.5 {
global:
- fuse_reply_statfs;
+ fuse_main_real;
+ fuse_main_real_compat22;
+ fuse_new;
+ fuse_new_compat22;
fuse_reply_create;
+ fuse_reply_open;
+ fuse_reply_open_compat;
+ fuse_reply_statfs;
fuse_reply_statfs_compat;
+ fuse_setup;
+ fuse_setup_compat22;
local:
*;
multithreaded, fd, 0);
}
+struct fuse *fuse_setup_compat22(int argc, char *argv[],
+ const struct fuse_operations_compat22 *op,
+ size_t op_size, char **mountpoint,
+ int *multithreaded, int *fd)
+{
+ return fuse_setup_common(argc, argv, (struct fuse_operations *) op,
+ op_size, mountpoint, multithreaded, fd, 22);
+}
+
struct fuse *fuse_setup_compat2(int argc, char *argv[],
const struct fuse_operations_compat2 *op,
char **mountpoint, int *multithreaded,
return fuse_main_common(argc, argv, op, op_size, 0);
}
+int fuse_main_real_compat22(int argc, char *argv[],
+ const struct fuse_operations_compat22 *op,
+ size_t op_size)
+{
+ return fuse_main_common(argc, argv, (struct fuse_operations *) op,
+ op_size, 22);
+}
+
#undef fuse_main
int fuse_main(void)
{
}
__asm__(".symver fuse_setup_compat2,__fuse_setup@");
+__asm__(".symver fuse_setup_compat22,fuse_setup@FUSE_2.2");
__asm__(".symver fuse_teardown,__fuse_teardown@");
__asm__(".symver fuse_main_compat2,fuse_main@");
+__asm__(".symver fuse_main_real_compat22,fuse_main_real@FUSE_2.2");