Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 130 additions & 20 deletions archivemount.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,22 @@
#define _XOPEN_SOURCE 500
#endif

#define FUSE_USE_VERSION 26
#define MAXBUF 4096

#define BLOCK_SIZE 10240

#include "config.h"

#ifdef HAVE_FUSE2
#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <fuse/fuse_lowlevel.h>
#elif defined(HAVE_FUSE3)
#define FUSE_USE_VERSION 30
#include <fuse.h>
#else
#error No fuse version defined
#endif
#include <fuse_opt.h>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -1544,7 +1551,7 @@ _ar_getsizeraw(const char *path)
}

static int
_ar_getattr(const char *path, struct stat *stbuf)
_ar_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
{
NODE *node;
int ret;
Expand All @@ -1558,7 +1565,7 @@ _ar_getattr(const char *path, struct stat *stbuf)
if (archive_entry_hardlink(node->entry)) {
/* a hardlink, recurse into it */
ret = _ar_getattr(archive_entry_hardlink(
node->entry), stbuf);
node->entry), stbuf, fi);
return ret;
}
if (options.formatraw && ! node->child) {
Expand Down Expand Up @@ -1596,15 +1603,24 @@ _ar_getattr(const char *path, struct stat *stbuf)
}

static int
#ifdef HAVE_FUSE3
ar_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
#else
ar_getattr(const char *path, struct stat *stbuf)
#endif
{
//log("ar_getattr called, path: '%s'", path);
int ret = pthread_mutex_lock(&lock);
if (ret) {
log("failed to get lock: %s\n", strerror(ret));
return -EIO;
} else {
ret = _ar_getattr(path, stbuf);
ret = _ar_getattr(path, stbuf,
#ifdef HAVE_FUSE3
fi);
#else
NULL);
#endif
pthread_mutex_unlock(&lock);
}
return ret;
Expand Down Expand Up @@ -1863,7 +1879,7 @@ ar_link(const char *from, const char *to)
return -EEXIST;
}
/* extract originals stat info */
_ar_getattr(from, &st);
_ar_getattr(from, &st, NULL);
/* build new node */
if ((node = init_node()) == NULL) {
pthread_mutex_unlock(&lock);
Expand Down Expand Up @@ -1932,7 +1948,7 @@ ar_link(const char *from, const char *to)
}

static int
_ar_truncate(const char *path, off_t size)
_ar_truncate(const char *path, off_t size, struct fuse_file_info *fi)
{
NODE *node;
char *location;
Expand All @@ -1951,12 +1967,12 @@ _ar_truncate(const char *path, off_t size)
if (archive_entry_hardlink(node->entry)) {
/* file is a hardlink, recurse into it */
return _ar_truncate(archive_entry_hardlink(
node->entry), size);
node->entry), size, fi);
}
if (archive_entry_symlink(node->entry)) {
/* file is a symlink, recurse into it */
return _ar_truncate(archive_entry_symlink(
node->entry), size);
node->entry), size, fi);
}
if (node->location) {
/* open existing temp file */
Expand Down Expand Up @@ -2054,12 +2070,22 @@ _ar_truncate(const char *path, off_t size)
}

static int
#ifdef HAVE_FUSE3
ar_truncate(const char *path, off_t size, struct fuse_file_info *fi)
#else
ar_truncate(const char *path, off_t size)
#endif
{
int ret;
log("ar_truncate called, path '%s'", path);
pthread_mutex_lock(&lock);
ret = _ar_truncate(path, size);
ret = _ar_truncate(path, size,
#ifdef HAVE_FUSE3
fi
#else
NULL
#endif
);
pthread_mutex_unlock(&lock);
return ret;
}
Expand Down Expand Up @@ -2319,7 +2345,7 @@ ar_unlink(const char *path)
}

static int
_ar_chmod(const char *path, mode_t mode)
_ar_chmod(const char *path, mode_t mode, struct fuse_file_info *fi)
{
NODE *node;

Expand All @@ -2333,11 +2359,11 @@ _ar_chmod(const char *path, mode_t mode)
}
if (archive_entry_hardlink(node->entry)) {
/* file is a hardlink, recurse into it */
return _ar_chmod(archive_entry_hardlink(node->entry), mode);
return _ar_chmod(archive_entry_hardlink(node->entry), mode, fi);
}
if (archive_entry_symlink(node->entry)) {
/* file is a symlink, recurse into it */
return _ar_chmod(archive_entry_symlink(node->entry), mode);
return _ar_chmod(archive_entry_symlink(node->entry), mode, fi);
}
#ifdef __APPLE__
/* Make sure the full mode, including file type information, is used */
Expand All @@ -2349,18 +2375,28 @@ _ar_chmod(const char *path, mode_t mode)
}

static int
#ifdef HAVE_FUSE3
ar_chmod(const char *path, mode_t mode, struct fuse_file_info *fi)
#else
ar_chmod(const char *path, mode_t mode)
#endif
{
log("ar_chmod called, path '%s', mode: %o", path, mode);
int ret;
pthread_mutex_lock(&lock);
ret = _ar_chmod(path, mode);
ret = _ar_chmod(path, mode,
#ifdef HAVE_FUSE3
fi
#else
NULL
#endif
);
pthread_mutex_unlock(&lock);
return ret;
}

static int
_ar_chown(const char *path, uid_t uid, gid_t gid)
_ar_chown(const char *path, uid_t uid, gid_t gid, struct fuse_file_info *fi)
{
NODE *node;

Expand All @@ -2375,7 +2411,7 @@ _ar_chown(const char *path, uid_t uid, gid_t gid)
if (archive_entry_hardlink(node->entry)) {
/* file is a hardlink, recurse into it */
return _ar_chown(archive_entry_hardlink(node->entry),
uid, gid);
uid, gid, NULL);
}
/* changing ownership of symlinks is allowed, however */
archive_entry_set_uid(node->entry, uid);
Expand All @@ -2385,16 +2421,65 @@ _ar_chown(const char *path, uid_t uid, gid_t gid)
}

static int
#ifdef HAVE_FUSE3
ar_chown(const char *path, uid_t uid, gid_t gid, struct fuse_file_info *fi)
#else
ar_chown(const char *path, uid_t uid, gid_t gid)
#endif
{
log("ar_chown called, %s", path);
int ret;
pthread_mutex_lock(&lock);
ret = _ar_chown(path, uid, gid);
ret = _ar_chown(path, uid, gid,
#ifdef HAVE_FUSE3
fi
#else
NULL
#endif
);
pthread_mutex_unlock(&lock);
return ret;
}

#ifdef HAVE_FUSE3
static int
_ar_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi)
{
NODE *node;

log("_ar_utimens called, %s", path);
if (! archiveWriteable || options.readonly) {
return -EROFS;
}
node = get_node_for_path(root, path);
if (! node) {
return -ENOENT;
}
if (archive_entry_hardlink(node->entry)) {
/* file is a hardlink, recurse into it */
return _ar_utimens(archive_entry_hardlink(node->entry), tv, fi);
}
if (archive_entry_symlink(node->entry)) {
/* file is a symlink, recurse into it */
return _ar_utimens(archive_entry_symlink(node->entry), tv, fi);
}
archive_entry_set_mtime(node->entry, tv[0].tv_sec, tv[0].tv_nsec);
archive_entry_set_atime(node->entry, tv[1].tv_sec, tv[1].tv_nsec);
archiveModified = 1;
return 0;
}

int
ar_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi)
{
log("ar_utimens called, %s", path);
int ret;
pthread_mutex_lock(&lock);
ret = _ar_utimens(path, tv, fi);
pthread_mutex_unlock(&lock);
return ret;
}
#else
static int
_ar_utime(const char *path, struct utimbuf *buf)
{
Expand Down Expand Up @@ -2432,7 +2517,7 @@ ar_utime(const char *path, struct utimbuf *buf)
pthread_mutex_unlock(&lock);
return ret;
}

#endif
static int
ar_statfs(const char *path, struct statvfs *stbuf)
{
Expand All @@ -2456,7 +2541,11 @@ ar_statfs(const char *path, struct statvfs *stbuf)
}

static int
#ifdef HAVE_FUSE3
ar_rename(const char *from, const char *to, unsigned int flags)
#else
ar_rename(const char *from, const char *to)
#endif
{
NODE *from_node;
int ret = 0;
Expand Down Expand Up @@ -2599,9 +2688,20 @@ ar_release(const char *path, struct fuse_file_info *fi)
return 0;
}

#ifdef HAVE_FUSE3
#define DIR_FILLER(F,B,N,S,O) F(B,N,S,O,FUSE_FILL_DIR_PLUS)
#else
#define DIR_FILLER(F,B,N,S,O) F(B,N,S,O)
#endif

static int
#ifdef HAVE_FUSE3
ar_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi, enum fuse_readdir_flags flags)
#else
ar_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
#endif
{
NODE *node;
(void) offset;
Expand All @@ -2620,8 +2720,8 @@ ar_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
return -ENOENT;
}

filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
DIR_FILLER(filler, buf, ".", NULL, 0);
DIR_FILLER(filler, buf, "..", NULL, 0);

node = node->child;

Expand All @@ -2645,7 +2745,7 @@ ar_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
st_copy.st_blocks = (st_copy.st_size + 511) / 512;
st_copy.st_blksize = 4096;

if (filler(buf, node->basename, &st_copy, 0)) {
if (DIR_FILLER(filler, buf, node->basename, &st_copy, 0)) {
pthread_mutex_unlock(&lock);
return -ENOMEM;
}
Expand Down Expand Up @@ -2742,7 +2842,11 @@ static struct fuse_operations ar_oper = {
.chmod = ar_chmod,
.chown = ar_chown,
.truncate = ar_truncate,
#ifdef HAVE_FUSE3
.utimens = ar_utimens,
#else
.utime = ar_utime,
#endif
.open = ar_open,
.read = ar_read,
.write = ar_write,
Expand Down Expand Up @@ -2912,6 +3016,11 @@ main(int argc, char **argv)
*/
fuse_opt_add_arg(&args, "-s");

#ifdef HAVE_FUSE3
/* now do the real mount */
int fuse_ret;
fuse_ret = fuse_main(args.argc, args.argv, &ar_oper, NULL);
#else
#if FUSE_VERSION >= 26
{
struct fuse *fuse;
Expand Down Expand Up @@ -2980,6 +3089,7 @@ main(int argc, char **argv)
int fuse_ret;
fuse_ret = fuse_main(args.argc, args.argv, &ar_oper, NULL);
}
#endif
#endif

/* go back to saved dir */
Expand Down
8 changes: 6 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ AC_SUBST(RELEASE_DATE)

# Check for libfuse
PKG_CHECK_EXISTS(fuse)
PKG_CHECK_MODULES([FUSE], [fuse >= 2.6],,
AC_MSG_ERROR([libfuse>=2.6 not found.
PKG_CHECK_MODULES([FUSE], [fuse >= 2.6],
AC_DEFINE([HAVE_FUSE2], [], [Need to use the fuse 2.6 API]),
PKG_CHECK_MODULES([FUSE], [fuse3 >= 3],
AC_DEFINE([HAVE_FUSE3], [], [Need to use the fuse 3.0 API]),
AC_MSG_ERROR([libfuse>=2.6 not found.

If libfuse is installed then perhaps you should set
the PKG_CONFIG_PATH=/dir/containing/fuse.pc environment
variable]))
)
AC_SUBST([FUSE_LIBS])
AC_SUBST([FUSE_CFLAGS])

Expand Down