summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2005-04-03 17:44:54 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2005-04-03 17:44:54 +0000
commit30e093a32e4c9d0ebb803e0cc7e722dc909649ce (patch)
treee921b4b03809945fc6badc4a9004a0550e4781e3
parent91b5e9932f5b2a995d8234ff2c24170db5c78e93 (diff)
downloadfuse-30e093a32e4c9d0ebb803e0cc7e722dc909649ce.tar.gz
-rw-r--r--ChangeLog8
-rw-r--r--Filesystems12
-rw-r--r--configure.in2
-rw-r--r--kernel/configure.ac2
-rw-r--r--lib/Makefile.am3
-rw-r--r--lib/fuse.c108
-rw-r--r--lib/fuse_i.h2
-rw-r--r--lib/fuse_kernel_compat5.h42
8 files changed, 150 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index debe90b..8811780 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2005-04-03 Miklos Szeredi <miklos@szeredi.hu>
+
+ * Released 2.3-pre3
+
+2005-04-03 Miklos Szeredi <miklos@szeredi.hu>
+
+ * Implement backward compatibility with version 5 kernel ABI
+
2005-04-01 Miklos Szeredi <miklos@szeredi.hu>
* Released 2.3-pre2
diff --git a/Filesystems b/Filesystems
index 21d3465..38e30d7 100644
--- a/Filesystems
+++ b/Filesystems
@@ -350,3 +350,15 @@ Homepage: http://search.cpan.org/~dpavlin/Fuse-0.05/
CVS: cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/fuse co -P perl
==============================================================================
+Name: Cddfs
+
+Author: Matthieu Castet
+
+Homepage: http://castet.matthieu.free.fr/cddfs/
+
+Description:
+
+ Cddfs [1] is a file system for fuse that use libparanoia in order to
+ mount your audio cd.
+
+==============================================================================
diff --git a/configure.in b/configure.in
index ac087f2..c29513e 100644
--- a/configure.in
+++ b/configure.in
@@ -1,4 +1,4 @@
-AC_INIT(fuse, 2.3-pre2)
+AC_INIT(fuse, 2.3-pre3)
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(include/config.h)
diff --git a/kernel/configure.ac b/kernel/configure.ac
index c026c10..7dbe029 100644
--- a/kernel/configure.ac
+++ b/kernel/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(fuse-kernel, 2.3-pre2)
+AC_INIT(fuse-kernel, 2.3-pre3)
AC_CONFIG_HEADERS([config.h])
AC_PROG_INSTALL
diff --git a/lib/Makefile.am b/lib/Makefile.am
index b344ef3..3a4a4e6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -7,7 +7,8 @@ libfuse_la_SOURCES = \
fuse_mt.c \
helper.c \
mount.c \
- fuse_i.h
+ fuse_i.h \
+ fuse_kernel_compat5.h
libfuse_la_LDFLAGS = -lpthread -version-number 2:3:0 \
-Wl,--version-script,fuse_versionscript
diff --git a/lib/fuse.c b/lib/fuse.c
index 6a919c9..40230af 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -10,6 +10,7 @@
#include "fuse_i.h"
#include "fuse_compat.h"
#include "fuse_kernel.h"
+#include "fuse_kernel_compat5.h"
#include <stdio.h>
#include <string.h>
@@ -39,7 +40,16 @@
#define FUSE_DEV_OLD "/proc/fs/fuse/dev"
#define FUSE_MAX_PATH 4096
-#define PARAM(inarg) (((char *)(inarg)) + sizeof(*inarg))
+#define PARAM_T(inarg, type) (((char *)(inarg)) + sizeof(type))
+#define PARAM(inarg) PARAM_T(inarg, *(inarg))
+#define PARAM_COMPAT(f, inarg, type) \
+ ((f)->major == 5 ? PARAM_T(inarg, struct type ## _compat5) : PARAM(inarg))
+
+#define MEMBER_COMPAT(f, ptr, memb, type) \
+ ((f)->major == 5 ? &((struct type ## _compat5 *) (ptr))->memb : &ptr->memb)
+
+#define SIZEOF_COMPAT(f, type) \
+ ((f)->major == 5 ? sizeof(struct type ## _compat5) : sizeof(struct type))
#define ENTRY_REVALIDATE_TIME 1 /* sec */
#define ATTR_REVALIDATE_TIME 1 /* sec */
@@ -472,8 +482,35 @@ static int fill_dir5(void *buf, const char *name, int type, ino_t ino,
return db->len > FUSE_NAME_OFFSET ? 0 : 1;
}
-static int fill_dir(struct fuse_dirhandle *dh, const char *name, int type,
- ino_t ino)
+static int fill_dir_compat5(struct fuse_dirhandle *dh, const char *name,
+ int type, ino_t ino)
+{
+ size_t namelen = strlen(name);
+ size_t entsize = sizeof(struct fuse_dirhandle) + namelen + 8;
+ struct fuse_dirent_compat5 *dirent;
+
+ if (namelen > FUSE_NAME_MAX)
+ namelen = FUSE_NAME_MAX;
+
+ dh->contents = realloc(dh->contents, dh->len + entsize);
+ if (dh->contents == NULL)
+ return -ENOMEM;
+
+ dirent = (struct fuse_dirent_compat5 *) (dh->contents + dh->len);
+ memset(dirent, 0, entsize);
+ if ((dh->fuse->flags & FUSE_USE_INO))
+ dirent->ino = ino;
+ else
+ dirent->ino = (unsigned long) -1;
+ dirent->namelen = namelen;
+ strncpy(dirent->name, name, namelen);
+ dirent->type = type;
+ dh->len += FUSE_DIRENT_SIZE_COMPAT5(dirent);
+ return 0;
+}
+
+static int fill_dir_new(struct fuse_dirhandle *dh, const char *name, int type,
+ ino_t ino)
{
size_t namelen = strlen(name);
size_t entsize = sizeof(struct fuse_dirhandle) + namelen + 8;
@@ -500,6 +537,15 @@ static int fill_dir(struct fuse_dirhandle *dh, const char *name, int type,
return 0;
}
+static int fill_dir(struct fuse_dirhandle *dh, const char *name, int type,
+ ino_t ino)
+{
+ if (dh->fuse->major == 5)
+ return fill_dir_compat5(dh, name, type, ino);
+ else
+ return fill_dir_new(dh, name, type, ino);
+}
+
static int send_reply_raw(struct fuse *f, char *outbuf, size_t outsize)
{
int res;
@@ -787,7 +833,7 @@ static void do_setattr(struct fuse *f, struct fuse_in_header *in,
int res;
char *path;
int valid = arg->valid;
- struct fuse_attr *attr = &arg->attr;
+ struct fuse_attr *attr = MEMBER_COMPAT(f, arg, attr, fuse_setattr_in);
struct fuse_attr_out outarg;
res = -ENOENT;
@@ -893,7 +939,7 @@ static void do_mkdir(struct fuse *f, struct fuse_in_header *in,
int res;
int res2;
char *path;
- char *name = PARAM(inarg);
+ char *name = PARAM_COMPAT(f, inarg, fuse_mkdir_in);
struct fuse_entry_out outarg;
res = -ENOENT;
@@ -1101,7 +1147,7 @@ static void do_open(struct fuse *f, struct fuse_in_header *in,
}
pthread_mutex_lock(&f->lock);
- res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
+ res2 = send_reply(f, in, res, &outarg, SIZEOF_COMPAT(f, fuse_open_out));
if(res2 == -ENOENT) {
/* The open syscall was interrupted, so it must be cancelled */
if(f->op.release) {
@@ -1272,7 +1318,7 @@ static void do_write(struct fuse *f, struct fuse_in_header *in,
res = 0;
}
- send_reply(f, in, res, &outarg, sizeof(outarg));
+ send_reply(f, in, res, &outarg, SIZEOF_COMPAT(f, fuse_write_out));
}
static int default_statfs(struct statfs *buf)
@@ -1430,7 +1476,7 @@ static void do_getxattr_size(struct fuse *f, struct fuse_in_header *in,
arg.size = res;
res = 0;
}
- send_reply(f, in, res, &arg, sizeof(arg));
+ send_reply(f, in, res, &arg, SIZEOF_COMPAT(f, fuse_getxattr_out));
}
static void do_getxattr(struct fuse *f, struct fuse_in_header *in,
@@ -1497,7 +1543,7 @@ static void do_listxattr_size(struct fuse *f, struct fuse_in_header *in)
arg.size = res;
res = 0;
}
- send_reply(f, in, res, &arg, sizeof(arg));
+ send_reply(f, in, res, &arg, SIZEOF_COMPAT(f, fuse_getxattr_out));
}
static void do_listxattr(struct fuse *f, struct fuse_in_header *in,
@@ -1530,23 +1576,36 @@ static void do_init(struct fuse *f, struct fuse_in_header *in,
struct fuse_init_in_out *arg)
{
struct fuse_init_in_out outarg;
+
+ if (in->padding == 5) {
+ arg->minor = arg->major;
+ arg->major = in->padding;
+ }
+
if (f->flags & FUSE_DEBUG) {
- printf(" INIT: %u.%u\n", arg->major, arg->minor);
+ printf("INIT: %u.%u\n", arg->major, arg->minor);
fflush(stdout);
}
f->got_init = 1;
if (f->op.init)
f->user_data = f->op.init();
- if (arg->major < 6) {
- fprintf(stderr, "Kernel API version 5 not yet handled\n");
- fuse_exit(f);
- return;
+ if (arg->major == 5) {
+ f->major = 5;
+ f->minor = 1;
+ } else {
+ f->major = FUSE_KERNEL_VERSION;
+ f->minor = FUSE_KERNEL_MINOR_VERSION;
}
-
memset(&outarg, 0, sizeof(outarg));
- outarg.major = FUSE_KERNEL_VERSION;
- outarg.minor = FUSE_KERNEL_MINOR_VERSION;
+ outarg.major = f->major;
+ outarg.minor = f->minor;
+
+ if (f->flags & FUSE_DEBUG) {
+ printf(" INIT: %u.%u\n", outarg.major, outarg.minor);
+ fflush(stdout);
+ }
+
send_reply(f, in, 0, &outarg, sizeof(outarg));
}
@@ -1592,7 +1651,7 @@ static void do_opendir(struct fuse *f, struct fuse_in_header *in,
if (res == 0) {
int res2;
pthread_mutex_lock(&f->lock);
- res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
+ res2 = send_reply(f, in, res, &outarg, SIZEOF_COMPAT(f, fuse_open_out));
if(res2 == -ENOENT) {
/* The opendir syscall was interrupted, so it must be
cancelled */
@@ -1607,7 +1666,7 @@ static void do_opendir(struct fuse *f, struct fuse_in_header *in,
}
free(path);
} else
- send_reply(f, in, 0, &outarg, sizeof(outarg));
+ send_reply(f, in, 0, &outarg, SIZEOF_COMPAT(f, fuse_open_out));
}
static void do_readdir(struct fuse *f, struct fuse_in_header *in,
@@ -1628,7 +1687,7 @@ static void do_readdir(struct fuse *f, struct fuse_in_header *in,
}
buf = outbuf + sizeof(struct fuse_out_header);
- if (f->op.readdir) {
+ if (f->op.readdir && f->major != 5) {
struct fuse_dirbuf db;
struct fuse_file_info fi;
char *path;
@@ -1729,8 +1788,7 @@ static void free_cmd(struct fuse_cmd *cmd)
void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
{
struct fuse_in_header *in = (struct fuse_in_header *) cmd->buf;
- void *inarg = cmd->buf + sizeof(struct fuse_in_header);
- size_t argsize;
+ void *inarg = cmd->buf + SIZEOF_COMPAT(f, fuse_in_header);
struct fuse_context *ctx = fuse_get_context();
fuse_dec_avail(f);
@@ -1754,8 +1812,6 @@ void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
ctx->pid = in->pid;
ctx->private_data = f->user_data;
- argsize = cmd->buflen - sizeof(struct fuse_in_header);
-
switch (in->opcode) {
case FUSE_LOOKUP:
do_lookup(f, in, (char *) inarg);
@@ -1898,7 +1954,7 @@ struct fuse_cmd *fuse_read_cmd(struct fuse *f)
return NULL;
}
in = (struct fuse_in_header *) cmd->buf;
- inarg = cmd->buf + sizeof(struct fuse_in_header);
+ inarg = cmd->buf + SIZEOF_COMPAT(f, fuse_in_header);
res = read(f->fd, cmd->buf, FUSE_MAX_IN);
if (res == -1) {
@@ -1915,7 +1971,7 @@ struct fuse_cmd *fuse_read_cmd(struct fuse *f)
fuse_exit(f);
return NULL;
}
- if ((size_t) res < sizeof(struct fuse_in_header)) {
+ if ((size_t) res < SIZEOF_COMPAT(f, fuse_in_header)) {
free_cmd(cmd);
/* Cannot happen */
fprintf(stderr, "short read on fuse device\n");
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 7ab485d..4a9f04a 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -30,6 +30,8 @@ struct fuse {
volatile int exited;
int got_init;
void *user_data;
+ int major;
+ int minor;
};
struct fuse *fuse_new_common(int fd, const char *opts,
diff --git a/lib/fuse_kernel_compat5.h b/lib/fuse_kernel_compat5.h
new file mode 100644
index 0000000..8edca59
--- /dev/null
+++ b/lib/fuse_kernel_compat5.h
@@ -0,0 +1,42 @@
+struct fuse_mkdir_in_compat5 {
+ __u32 mode;
+};
+
+struct fuse_setattr_in_compat5 {
+ __u32 valid;
+ struct fuse_attr attr;
+};
+
+struct fuse_open_out_compat5 {
+ __u64 fh;
+ __u32 open_flags;
+};
+
+struct fuse_write_out_compat5 {
+ __u32 size;
+};
+
+struct fuse_getxattr_out_compat5 {
+ __u32 size;
+};
+
+struct fuse_in_header_compat5 {
+ __u32 len;
+ __u32 opcode;
+ __u64 unique;
+ __u64 nodeid;
+ __u32 uid;
+ __u32 gid;
+ __u32 pid;
+};
+
+struct fuse_dirent_compat5 {
+ __u64 ino;
+ __u32 namelen;
+ __u32 type;
+ char name[0];
+};
+
+#define FUSE_NAME_OFFSET_COMPAT5 ((unsigned) ((struct fuse_dirent_compat5 *) 0)->name)
+#define FUSE_DIRENT_SIZE_COMPAT5(d) \
+ FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_COMPAT5 + (d)->namelen)