From a431e8615e87f76bf1e0e107223aa4b5f4da2201 Mon Sep 17 00:00:00 2001 From: Colin Date: Tue, 6 Aug 2024 02:14:18 +0000 Subject: [PATCH] port to fuse3 this is only very loosely tested, may be errors --- Makefile.am | 2 +- Makefile.in | 2 +- cache.c | 141 ++++++--------------------------------------------- cache.h | 4 -- configure.ac | 2 +- ftpfs.c | 120 +++++++++++++++---------------------------- 6 files changed, 61 insertions(+), 210 deletions(-) diff --git a/Makefile.am b/Makefile.am index 8fe867c..cd1d9ce 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ DIST_SUBDIRS = $(SUBDIRS) tests LIBICONV = @LIBICONV@ -AM_CPPFLAGS = -DFUSE_USE_VERSION=26 +AM_CPPFLAGS = -DFUSE_USE_VERSION=316 AM_LDFLAGS = $(LIBICONV) bin_PROGRAMS = curlftpfs diff --git a/Makefile.in b/Makefile.in index 033a2c4..85d0c9f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -215,7 +215,7 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = compat doc DIST_SUBDIRS = $(SUBDIRS) tests -AM_CPPFLAGS = -DFUSE_USE_VERSION=26 +AM_CPPFLAGS = -DFUSE_USE_VERSION=316 AM_LDFLAGS = $(LIBICONV) curlftpfs_SOURCES = ftpfs.c @FUSE_OPT_COMPAT_FALSE@curlftpfs_LDADD = libcurlftpfs.a diff --git a/cache.c b/cache.c index 781a87e..53d594b 100644 --- a/cache.c +++ b/cache.c @@ -38,13 +38,6 @@ struct node { time_t valid; }; -struct fuse_cache_dirhandle { - const char *path; - fuse_dirh_t h; - fuse_dirfil_t filler; - GPtrArray *dir; -}; - static void free_node(gpointer node_) { struct node *node = (struct node *) node_; @@ -112,7 +105,7 @@ static void cache_invalidate_dir(const char *path) pthread_mutex_unlock(&cache.lock); } -static void cache_do_rename(const char *from, const char *to) +static void cache_do_rename(const char *from, const char *to, unsigned int flags) { pthread_mutex_lock(&cache.lock); cache_purge(from); @@ -218,11 +211,11 @@ static int cache_get_attr(const char *path, struct stat *stbuf) return err; } -static int cache_getattr(const char *path, struct stat *stbuf) +static int cache_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi) { int err = cache_get_attr(path, stbuf); if (err == -EAGAIN) { - err = cache.next_oper->oper.getattr(path, stbuf); + err = cache.next_oper->oper.getattr(path, stbuf, fi); if (!err) cache_add_attr(path, stbuf); else if (err == -ENOENT) @@ -255,71 +248,6 @@ static int cache_readlink(const char *path, char *buf, size_t size) return err; } -static int cache_dirfill(fuse_cache_dirh_t ch, const char *name, - const struct stat *stbuf) -{ - int err = ch->filler(ch->h, name, 0, 0); - if (!err) { - char *fullpath; - g_ptr_array_add(ch->dir, g_strdup(name)); - fullpath = g_strdup_printf("%s/%s", !ch->path[1] ? "" : ch->path, name); - cache_add_attr(fullpath, stbuf); - g_free(fullpath); - } - return err; -} - -static int cache_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) -{ - struct fuse_cache_dirhandle ch; - int err; - char **dir; - struct node *node; - - pthread_mutex_lock(&cache.lock); - node = cache_lookup(path); - if (node != NULL && node->dir != NULL) { - time_t now = time(NULL); - if (node->dir_valid - now >= 0) { - for(dir = node->dir; *dir != NULL; dir++) - filler(h, *dir, 0, 0); - pthread_mutex_unlock(&cache.lock); - return 0; - } - } - pthread_mutex_unlock(&cache.lock); - - ch.path = path; - ch.h = h; - ch.filler = filler; - ch.dir = g_ptr_array_new(); - err = cache.next_oper->cache_getdir(path, &ch, cache_dirfill); - g_ptr_array_add(ch.dir, NULL); - dir = (char **) ch.dir->pdata; - if (!err) - cache_add_dir(path, dir); - else - g_strfreev(dir); - g_ptr_array_free(ch.dir, FALSE); - return err; -} - -static int cache_unity_dirfill(fuse_cache_dirh_t ch, const char *name, - const struct stat *stbuf) -{ - (void) stbuf; - return ch->filler(ch->h, name, 0, 0); -} - -static int cache_unity_getdir(const char *path, fuse_dirh_t h, - fuse_dirfil_t filler) -{ - struct fuse_cache_dirhandle ch; - ch.h = h; - ch.filler = filler; - return cache.next_oper->cache_getdir(path, &ch, cache_unity_dirfill); -} - static int cache_mknod(const char *path, mode_t mode, dev_t rdev) { int err = cache.next_oper->oper.mknod(path, mode, rdev); @@ -360,11 +288,11 @@ static int cache_symlink(const char *from, const char *to) return err; } -static int cache_rename(const char *from, const char *to) +static int cache_rename(const char *from, const char *to, unsigned int flags) { - int err = cache.next_oper->oper.rename(from, to); + int err = cache.next_oper->oper.rename(from, to, flags); if (!err) - cache_do_rename(from, to); + cache_do_rename(from, to, flags); return err; } @@ -378,33 +306,33 @@ static int cache_link(const char *from, const char *to) return err; } -static int cache_chmod(const char *path, mode_t mode) +static int cache_chmod(const char *path, mode_t mode, struct fuse_file_info* fi) { - int err = cache.next_oper->oper.chmod(path, mode); + int err = cache.next_oper->oper.chmod(path, mode, fi); if (!err) cache_invalidate(path); return err; } -static int cache_chown(const char *path, uid_t uid, gid_t gid) +static int cache_chown(const char *path, uid_t uid, gid_t gid, struct fuse_file_info* fi) { - int err = cache.next_oper->oper.chown(path, uid, gid); + int err = cache.next_oper->oper.chown(path, uid, gid, fi); if (!err) cache_invalidate(path); return err; } -static int cache_truncate(const char *path, off_t size) +static int cache_truncate(const char *path, off_t size, struct fuse_file_info *fi) { - int err = cache.next_oper->oper.truncate(path, size); + int err = cache.next_oper->oper.truncate(path, size, fi); if (!err) cache_invalidate(path); return err; } -static int cache_utime(const char *path, struct utimbuf *buf) +static int cache_utimens(const char *path, struct utimbuf *buf, struct fuse_file_info* fi) { - int err = cache.next_oper->oper.utime(path, buf); + int err = cache.next_oper->oper.utimens(path, buf, fi); if (!err) cache_invalidate(path); return err; @@ -419,7 +347,6 @@ static int cache_write(const char *path, const char *buf, size_t size, return res; } -#if FUSE_VERSION >= 25 static int cache_create(const char *path, mode_t mode, struct fuse_file_info *fi) { @@ -429,39 +356,12 @@ static int cache_create(const char *path, mode_t mode, return err; } -static int cache_ftruncate(const char *path, off_t size, - struct fuse_file_info *fi) -{ - int err = cache.next_oper->oper.ftruncate(path, size, fi); - if (!err) - cache_invalidate(path); - return err; -} - -static int cache_fgetattr(const char *path, struct stat *stbuf, - struct fuse_file_info *fi) -{ - int err = cache_get_attr(path, stbuf); - if (err == -EAGAIN) { - err = cache.next_oper->oper.fgetattr(path, stbuf, fi); - if (!err) - cache_add_attr(path, stbuf); - else if (err == -ENOENT) - cache_add_attr(path, NULL); - } - return err; -} -#endif - static void cache_unity_fill(struct fuse_cache_operations *oper, struct fuse_operations *cache_oper) { -#if FUSE_VERSION >= 23 cache_oper->init = oper->oper.init; -#endif cache_oper->getattr = oper->oper.getattr; cache_oper->readlink = oper->oper.readlink; - cache_oper->getdir = cache_unity_getdir; cache_oper->mknod = oper->oper.mknod; cache_oper->mkdir = oper->oper.mkdir; cache_oper->symlink = oper->oper.symlink; @@ -472,7 +372,7 @@ static void cache_unity_fill(struct fuse_cache_operations *oper, cache_oper->chmod = oper->oper.chmod; cache_oper->chown = oper->oper.chown; cache_oper->truncate = oper->oper.truncate; - cache_oper->utime = oper->oper.utime; + cache_oper->utimens = oper->oper.utimens; cache_oper->open = oper->oper.open; cache_oper->read = oper->oper.read; cache_oper->write = oper->oper.write; @@ -484,11 +384,7 @@ static void cache_unity_fill(struct fuse_cache_operations *oper, cache_oper->getxattr = oper->oper.getxattr; cache_oper->listxattr = oper->oper.listxattr; cache_oper->removexattr = oper->oper.removexattr; -#if FUSE_VERSION >= 25 cache_oper->create = oper->oper.create; - cache_oper->ftruncate = oper->oper.ftruncate; - cache_oper->fgetattr = oper->oper.fgetattr; -#endif } struct fuse_operations *cache_init(struct fuse_cache_operations *oper) @@ -500,7 +396,6 @@ struct fuse_operations *cache_init(struct fuse_cache_operations *oper) if (cache.on) { cache_oper.getattr = oper->oper.getattr ? cache_getattr : NULL; cache_oper.readlink = oper->oper.readlink ? cache_readlink : NULL; - cache_oper.getdir = oper->cache_getdir ? cache_getdir : NULL; cache_oper.mknod = oper->oper.mknod ? cache_mknod : NULL; cache_oper.mkdir = oper->oper.mkdir ? cache_mkdir : NULL; cache_oper.symlink = oper->oper.symlink ? cache_symlink : NULL; @@ -511,13 +406,9 @@ struct fuse_operations *cache_init(struct fuse_cache_operations *oper) cache_oper.chmod = oper->oper.chmod ? cache_chmod : NULL; cache_oper.chown = oper->oper.chown ? cache_chown : NULL; cache_oper.truncate = oper->oper.truncate ? cache_truncate : NULL; - cache_oper.utime = oper->oper.utime ? cache_utime : NULL; + cache_oper.utimens = oper->oper.utimens ? cache_utimens : NULL; cache_oper.write = oper->oper.write ? cache_write : NULL; -#if FUSE_VERSION >= 25 cache_oper.create = oper->oper.create ? cache_create : NULL; - cache_oper.ftruncate = oper->oper.ftruncate ? cache_ftruncate : NULL; - cache_oper.fgetattr = oper->oper.fgetattr ? cache_fgetattr : NULL; -#endif pthread_mutex_init(&cache.lock, NULL); cache.table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_node); diff --git a/cache.h b/cache.h index 73c8c06..6edcff1 100644 --- a/cache.h +++ b/cache.h @@ -12,10 +12,6 @@ #include #include -#ifndef FUSE_VERSION -#define FUSE_VERSION (FUSE_MAJOR_VERSION * 10 + FUSE_MINOR_VERSION) -#endif - #define DEFAULT_CACHE_TIMEOUT 10 #define MAX_CACHE_SIZE 10000 #define MIN_CACHE_CLEAN_INTERVAL 5 diff --git a/configure.ac b/configure.ac index c0373f3..79e6d39 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ AC_PROG_LIBTOOL export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH PKG_CHECK_MODULES(GLIB, [glib-2.0]) -PKG_CHECK_MODULES(FUSE, [fuse >= 2.2]) +PKG_CHECK_MODULES(FUSE, [fuse3 >= 3.16]) LIBCURL_CHECK_CONFIG([yes], [7.17.0], [], [AC_MSG_ERROR(["libcurl not found"])]) if test "$libcurl_protocol_FTP" != yes; then diff --git a/ftpfs.c b/ftpfs.c index adc3661..e9234ee 100644 --- a/ftpfs.c +++ b/ftpfs.c @@ -297,7 +297,7 @@ static int ftpfs_getdir(const char* path, fuse_cache_dirh_t h, return op_return(err, "ftpfs_getdir"); } -static int ftpfs_getattr(const char* path, struct stat* sbuf) { +static int ftpfs_getattr(const char* path, struct stat* sbuf, struct fuse_file_info* fi) { int err; CURLcode curl_res; char* dir_path = get_dir_path(path); @@ -674,7 +674,7 @@ static int create_empty_file(const char * path) } static int ftpfs_mknod(const char* path, mode_t mode, dev_t rdev); -static int ftpfs_chmod(const char* path, mode_t mode); +static int ftpfs_chmod(const char* path, mode_t mode, struct fuse_file_info* fi); static char * flags_to_string(int flags) { @@ -698,13 +698,13 @@ static char * flags_to_string(int flags) static int test_exists(const char* path) { struct stat sbuf; - return ftpfs_getattr(path, &sbuf); + return ftpfs_getattr(path, &sbuf, NULL); } static __off_t test_size(const char* path) { struct stat sbuf; - int err = ftpfs_getattr(path, &sbuf); + int err = ftpfs_getattr(path, &sbuf, NULL); if (err) return err; return sbuf.st_size; @@ -794,7 +794,7 @@ static int ftpfs_open_common(const char* path, mode_t mode, { sem_wait(&fh->ready); /* chmod makes only sense on O_CREAT */ - if (fi->flags & O_CREAT) ftpfs_chmod(path, mode); + if (fi->flags & O_CREAT) ftpfs_chmod(path, mode, fi); sem_post(&fh->data_need); } else @@ -827,12 +827,10 @@ static int ftpfs_open(const char* path, struct fuse_file_info* fi) { return ftpfs_open_common(path, 0, fi); } -#if FUSE_VERSION >= 25 static int ftpfs_create(const char* path, mode_t mode, struct fuse_file_info* fi) { return ftpfs_open_common(path, mode, fi); } -#endif static int ftpfs_read(const char* path, char* rbuf, size_t size, off_t offset, struct fuse_file_info* fi) { @@ -873,12 +871,12 @@ static int ftpfs_mknod(const char* path, mode_t mode, dev_t rdev) { err = create_empty_file(path); if (!err) - ftpfs_chmod(path, mode); + ftpfs_chmod(path, mode, NULL); return op_return(err, "ftpfs_mknod"); } -static int ftpfs_chmod(const char* path, mode_t mode) { +static int ftpfs_chmod(const char* path, mode_t mode, struct fuse_file_info* fi) { int err = 0; // We can only process a subset of the mode - so strip @@ -917,10 +915,10 @@ static int ftpfs_chmod(const char* path, mode_t mode) { return op_return(err, "ftpfs_chmod"); } -static int ftpfs_chown(const char* path, uid_t uid, gid_t gid) { +static int ftpfs_chown(const char* path, uid_t uid, gid_t gid, struct fuse_file_info* fi) { int err = 0; - DEBUG(1, "ftpfs_chown: %d %d\n", (int)uid, (int)gid); + DEBUG(1, "ftpfs_chown: %d %d %u\n", (int)uid, (int)gid, fi); struct curl_slist* header = NULL; char* full_path = get_dir_path(path); @@ -957,25 +955,6 @@ static int ftpfs_chown(const char* path, uid_t uid, gid_t gid) { return op_return(err, "ftpfs_chown"); } -static int ftpfs_truncate(const char* path, off_t offset) { - DEBUG(1, "ftpfs_truncate: %s len=%lld\n", path, offset); - /* we can't use ftpfs_mknod here, because we don't know the right permissions */ - if (offset == 0) return op_return(create_empty_file(path), "ftpfs_truncate"); - - /* fix openoffice problem, truncating exactly to file length */ - - __off_t size = (long long int)test_size(path); - DEBUG(1, "ftpfs_truncate: %s check filesize=%lld\n", path, (long long int)size); - - if (offset == size) - return op_return(0, "ftpfs_ftruncate"); - - DEBUG(1, "ftpfs_truncate problem: %s offset != 0 or filesize=%lld != offset\n", path, (long long int)size); - - - return op_return(-EPERM, "ftpfs_truncate"); -} - static int ftpfs_ftruncate(const char * path , off_t offset, struct fuse_file_info * fi) { DEBUG(1, "ftpfs_ftruncate: %s len=%lld\n", path, offset); @@ -1003,10 +982,32 @@ static int ftpfs_ftruncate(const char * path , off_t offset, struct fuse_file_in return op_return(-EPERM, "ftpfs_ftruncate"); } -static int ftpfs_utime(const char* path, struct utimbuf* time) { +static int ftpfs_truncate(const char* path, off_t offset, struct fuse_file_info* fi) { + if (fi) + return ftpfs_ftruncate(path, offset, fi); + + DEBUG(1, "ftpfs_truncate: %s len=%lld\n", path, offset); + /* we can't use ftpfs_mknod here, because we don't know the right permissions */ + if (offset == 0) return op_return(create_empty_file(path), "ftpfs_truncate"); + + /* fix openoffice problem, truncating exactly to file length */ + + __off_t size = (long long int)test_size(path); + DEBUG(1, "ftpfs_truncate: %s check filesize=%lld\n", path, (long long int)size); + + if (offset == size) + return op_return(0, "ftpfs_ftruncate"); + + DEBUG(1, "ftpfs_truncate problem: %s offset != 0 or filesize=%lld != offset\n", path, (long long int)size); + + + return op_return(-EPERM, "ftpfs_truncate"); +} + +static int ftpfs_utimens(const char* path, struct utimbuf* time, struct fuse_file_info* fi) { (void) path; (void) time; - return op_return(0, "ftpfs_utime"); + return op_return(0, "ftpfs_utimens"); } static int ftpfs_rmdir(const char* path) { @@ -1079,7 +1080,7 @@ static int ftpfs_mkdir(const char* path, mode_t mode) { free(cmd); if (!err) - ftpfs_chmod(path, mode); + ftpfs_chmod(path, mode, NULL); return op_return(err, "ftpfs_mkdir"); } @@ -1221,7 +1222,7 @@ static int ftpfs_flush(const char *path, struct fuse_file_info *fi) { /* check if the resulting file has the correct size this is important, because we use APPE for continuing writing after a premature flush */ - err = ftpfs_getattr(path, &sbuf); + err = ftpfs_getattr(path, &sbuf, fi); if (err) return op_return(err, "ftpfs_flush"); if (sbuf.st_size != fh->pos) @@ -1269,8 +1270,12 @@ static int ftpfs_release(const char* path, struct fuse_file_info* fi) { } -static int ftpfs_rename(const char* from, const char* to) { - DEBUG(1, "ftpfs_rename from %s to %s\n", from, to); +static int ftpfs_rename(const char* from, const char* to, unsigned int flags) { + DEBUG(1, "ftpfs_rename from %s to %s (%u)\n", from, to, flags); + + if(flags != 0) + return -EINVAL; + int err = 0; char* rnfr = g_strdup_printf("RNFR %s", from + 1); char* rnto = g_strdup_printf("RNTO %s", to + 1); @@ -1341,7 +1346,6 @@ static int ftpfs_readlink(const char *path, char *linkbuf, size_t size) { return op_return(0, "ftpfs_readlink"); } -#if FUSE_VERSION >= 25 static int ftpfs_statfs(const char *path, struct statvfs *buf) { (void) path; @@ -1356,21 +1360,6 @@ static int ftpfs_statfs(const char *path, struct statvfs *buf) buf->f_ffree = 999999999; return op_return(0, "ftpfs_statfs"); } -#else -static int ftpfs_statfs(const char *path, struct statfs *buf) -{ - (void) path; - - buf->f_namelen = 255; - buf->f_bsize = ftpfs.blksize; - buf->f_blocks = 999999999 * 2; - buf->f_bfree = 999999999 * 2; - buf->f_bavail = 999999999 * 2; - buf->f_files = 999999999; - buf->f_ffree = 999999999; - return op_return(0, "ftpfs_statfs"); -} -#endif static struct fuse_cache_operations ftpfs_oper = { .oper = { @@ -1386,7 +1375,7 @@ static struct fuse_cache_operations ftpfs_oper = { .chmod = ftpfs_chmod, .chown = ftpfs_chown, .truncate = ftpfs_truncate, - .utime = ftpfs_utime, + .utimens = ftpfs_utimens, .open = ftpfs_open, .flush = ftpfs_flush, .fsync = ftpfs_fsync, @@ -1394,22 +1383,14 @@ static struct fuse_cache_operations ftpfs_oper = { .read = ftpfs_read, .write = ftpfs_write, .statfs = ftpfs_statfs, -#if FUSE_VERSION >= 25 .create = ftpfs_create, - .ftruncate = ftpfs_ftruncate, -// .fgetattr = ftpfs_fgetattr, -#endif }, .cache_getdir = ftpfs_getdir, }; static int curlftpfs_fuse_main(struct fuse_args *args) { -#if FUSE_VERSION >= 26 return fuse_main(args->argc, args->argv, cache_init(&ftpfs_oper), NULL); -#else - return fuse_main(args->argc, args->argv, cache_init(&ftpfs_oper)); -#endif } static int ftpfs_opt_proc(void* data, const char* arg, int key, @@ -1718,23 +1699,6 @@ static void checkpasswd(const char *kind, /* for what purpose */ } } -#if FUSE_VERSION == 25 -static int fuse_opt_insert_arg(struct fuse_args *args, int pos, - const char *arg) -{ - assert(pos <= args->argc); - if (fuse_opt_add_arg(args, arg) == -1) - return -1; - - if (pos != args->argc - 1) { - char *newarg = args->argv[args->argc - 1]; - memmove(&args->argv[pos + 1], &args->argv[pos], - sizeof(char *) * (args->argc - pos - 1)); - args->argv[pos] = newarg; - } - return 0; -} -#endif int main(int argc, char** argv) { int res;