* %End-Header%
*/
#define _FILE_OFFSET_BITS 64
-#define FUSE_USE_VERSION 29
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
# include <linux/fs.h>
# include <linux/falloc.h>
# include <linux/xattr.h>
-# define FUSE_PLATFORM_OPTS ",big_writes"
# ifdef HAVE_SYS_ACL_H
# define TRANSLATE_LINUX_ACLS
# endif
-#else
-# define FUSE_PLATFORM_OPTS ""
#endif
#ifdef TRANSLATE_LINUX_ACLS
# include <sys/acl.h>
#include <inttypes.h>
#include "ext2fs/ext2fs.h"
#include "ext2fs/ext2_fs.h"
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+# define FUSE_PLATFORM_OPTS ""
+#else
+# ifdef __linux__
+# define FUSE_PLATFORM_OPTS ",use_ino,big_writes"
+# else
+# define FUSE_PLATFORM_OPTS ",use_ino"
+# endif
+#endif
#include "../version.h"
int minixdf;
int fakeroot;
int alloc_all_blocks;
+ int norecovery;
+ unsigned long offset;
FILE *err_fp;
unsigned int next_generation;
};
}
}
-static void *op_init(struct fuse_conn_info *conn)
+static void *op_init(struct fuse_conn_info *conn
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_config *cfg EXT2FS_ATTR((unused))
+#endif
+ )
{
struct fuse_context *ctxt = fuse_get_context();
struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
#endif
if (fs->flags & EXT2_FLAG_RW) {
fs->super->s_mnt_count++;
- fs->super->s_mtime = time(NULL);
+ ext2fs_set_tstamp(fs->super, s_mtime, time(NULL));
fs->super->s_state &= ~EXT2_VALID_FS;
ext2fs_mark_super_dirty(fs);
err = ext2fs_flush2(fs, 0);
return ff;
}
-static blkcnt_t blocks_from_inode(ext2_filsys fs,
- struct ext2_inode_large *inode)
-{
- blkcnt_t b;
-
- b = inode->i_blocks;
- if (ext2fs_has_feature_huge_file(fs->super))
- b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
-
- if (!ext2fs_has_feature_huge_file(fs->super) ||
- !(inode->i_flags & EXT4_HUGE_FILE_FL))
- b *= fs->blocksize / 512;
- b *= EXT2FS_CLUSTER_RATIO(fs);
-
- return b;
-}
-
static int stat_inode(ext2_filsys fs, ext2_ino_t ino, struct stat *statbuf)
{
struct ext2_inode_large inode;
statbuf->st_gid = inode_gid(inode);
statbuf->st_size = EXT2_I_SIZE(&inode);
statbuf->st_blksize = fs->blocksize;
- statbuf->st_blocks = blocks_from_inode(fs, &inode);
+ statbuf->st_blocks = ext2fs_get_stat_i_blocks(fs,
+ (struct ext2_inode *)&inode);
EXT4_INODE_GET_XTIME(i_atime, &tv, &inode);
statbuf->st_atime = tv.tv_sec;
EXT4_INODE_GET_XTIME(i_mtime, &tv, &inode);
return ret;
}
-static int op_getattr(const char *path, struct stat *statbuf)
+static int op_getattr(const char *path, struct stat *statbuf
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_file_info *fi EXT2FS_ATTR((unused))
+#endif
+ )
{
struct fuse_context *ctxt = fuse_get_context();
struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
inode.i_gid = ctxt->gid;
ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
- inode.i_mode = LINUX_S_IFDIR | (mode & ~(S_ISUID | fs->umask)) |
+ inode.i_mode = LINUX_S_IFDIR | (mode & ~S_ISUID) |
parent_sgid;
inode.i_generation = ff->next_generation++;
return 0; /* XXX: already done? */
case 1:
inode.i_links_count--;
- inode.i_dtime = fs->now ? fs->now : time(0);
+ ext2fs_set_dtime(fs, EXT2_INODE(&inode));
break;
default:
inode.i_links_count--;
return 0;
}
-static int op_rename(const char *from, const char *to)
+static int op_rename(const char *from, const char *to
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , unsigned int flags EXT2FS_ATTR((unused))
+#endif
+ )
{
struct fuse_context *ctxt = fuse_get_context();
struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
return ret;
}
-static int op_chmod(const char *path, mode_t mode)
+static int op_chmod(const char *path, mode_t mode
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_file_info *fi EXT2FS_ATTR((unused))
+#endif
+ )
{
struct fuse_context *ctxt = fuse_get_context();
struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
return ret;
}
-static int op_chown(const char *path, uid_t owner, gid_t group)
+static int op_chown(const char *path, uid_t owner, gid_t group
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_file_info *fi EXT2FS_ATTR((unused))
+#endif
+ )
{
struct fuse_context *ctxt = fuse_get_context();
struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
return ret;
}
-static int op_truncate(const char *path, off_t len)
+static int op_truncate(const char *path, off_t len
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_file_info *fi EXT2FS_ATTR((unused))
+#endif
+ )
{
struct fuse_context *ctxt = fuse_get_context();
struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
overhead = 0;
else
overhead = fs->desc_blocks +
- fs->group_desc_count *
+ (blk64_t)fs->group_desc_count *
(fs->inode_blocks_per_group + 2);
reserved = ext2fs_r_blocks_count(fs->super);
if (!reserved)
size_t value_len EXT2FS_ATTR((unused)), void *data)
{
char **b = data;
+ size_t name_len = strlen(name);
- strncpy(*b, name, strlen(name));
- *b = *b + strlen(name) + 1;
+ memcpy(*b, name, name_len + 1);
+ *b = *b + name_len + 1;
return 0;
}
memcpy(namebuf, dirent->name, dirent->name_len & 0xFF);
namebuf[dirent->name_len & 0xFF] = 0;
- ret = i->func(i->buf, namebuf, NULL, 0);
+ ret = i->func(i->buf, namebuf, NULL, 0
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , 0
+#endif
+ );
if (ret)
return DIRENT_ABORT;
static int op_readdir(const char *path EXT2FS_ATTR((unused)),
void *buf, fuse_fill_dir_t fill_func,
off_t offset EXT2FS_ATTR((unused)),
- struct fuse_file_info *fp)
+ struct fuse_file_info *fp
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , enum fuse_readdir_flags flags EXT2FS_ATTR((unused))
+#endif
+ )
{
struct fuse_context *ctxt = fuse_get_context();
struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
return ret;
}
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
static int op_ftruncate(const char *path EXT2FS_ATTR((unused)),
off_t len, struct fuse_file_info *fp)
{
return ret;
}
+#endif /* FUSE_VERSION < FUSE_MAKE_VERSION(3, 0) */
-static int op_utimens(const char *path, const struct timespec ctv[2])
+static int op_utimens(const char *path, const struct timespec ctv[2]
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_file_info *fi EXT2FS_ATTR((unused))
+#endif
+ )
{
struct fuse_context *ctxt = fuse_get_context();
struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
#endif /* FITRIM */
#if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
-static int op_ioctl(const char *path EXT2FS_ATTR((unused)), int cmd,
+static int op_ioctl(const char *path EXT2FS_ATTR((unused)),
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ unsigned int cmd,
+#else
+ int cmd,
+#endif
void *arg EXT2FS_ATTR((unused)),
struct fuse_file_info *fp,
unsigned int flags EXT2FS_ATTR((unused)), void *data)
.fsyncdir = op_fsync,
.access = op_access,
.create = op_create,
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
.ftruncate = op_ftruncate,
.fgetattr = op_fgetattr,
+#endif
.utimens = op_utimens,
-#if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
+#if (FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)) && (FUSE_VERSION < FUSE_MAKE_VERSION(3, 0))
# if defined(UTIME_NOW) || defined(UTIME_OMIT)
.flag_utime_omit_ok = 1,
# endif
#endif
#if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
.ioctl = op_ioctl,
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
.flag_nullpath_ok = 1,
#endif
+#endif
#if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
.flag_nopath = 1,
+#endif
# ifdef SUPPORT_FALLOCATE
.fallocate = op_fallocate,
# endif
FUSE2FS_OPT("fakeroot", fakeroot, 1),
FUSE2FS_OPT("fuse2fs_debug", debug, 1),
FUSE2FS_OPT("no_default_opts", no_default_opts, 1),
+ FUSE2FS_OPT("norecovery", norecovery, 1),
+ FUSE2FS_OPT("offset=%lu", offset, 0),
FUSE_OPT_KEY("-V", FUSE2FS_VERSION),
FUSE_OPT_KEY("--version", FUSE2FS_VERSION),
" -o minixdf minix-style df\n"
" -o fakeroot pretend to be root for permission checks\n"
" -o no_default_opts do not include default fuse options\n"
+ " -o offset=<bytes> similar to mount -o offset=<bytes>, mount the partition starting at <bytes>\n"
+ " -o norecovery don't replay the journal (implies ro)\n"
" -o fuse2fs_debug enable fuse2fs debugging\n"
"\n",
outargs->argv[0]);
errcode_t err;
char *logfile;
char extra_args[BUFSIZ];
- int ret = 0, flags = EXT2_FLAG_64BITS | EXT2_FLAG_EXCLUSIVE;
+ int ret = 0;
+ int flags = EXT2_FLAG_64BITS | EXT2_FLAG_THREADS | EXT2_FLAG_EXCLUSIVE;
memset(&fctx, 0, sizeof(fctx));
fctx.magic = FUSE2FS_MAGIC;
exit(1);
}
+ if (fctx.norecovery)
+ fctx.ro = 1;
if (fctx.ro)
printf("%s", _("Mounting read-only.\n"));
ret = 2;
if (!fctx.ro)
flags |= EXT2_FLAG_RW;
- err = ext2fs_open2(fctx.device, NULL, flags, 0, 0, unix_io_manager,
+ char options[50];
+ sprintf(options, "offset=%lu", fctx.offset);
+ err = ext2fs_open2(fctx.device, options, flags, 0, 0, unix_io_manager,
&global_fs);
if (err) {
printf(_("%s: %s.\n"), fctx.device, error_message(err));
ret = 3;
if (ext2fs_has_feature_journal_needs_recovery(global_fs->super)) {
- if (!fctx.ro) {
+ if (fctx.norecovery) {
+ printf(_("%s: mounting read-only without "
+ "recovering journal\n"),
+ fctx.device);
+ } else if (!fctx.ro) {
printf(_("%s: recovering journal\n"), fctx.device);
err = ext2fs_run_ext3_journal(&global_fs);
if (err) {
get_random_bytes(&fctx.next_generation, sizeof(unsigned int));
/* Set up default fuse parameters */
- snprintf(extra_args, BUFSIZ, "-okernel_cache,subtype=ext4,use_ino,"
+ snprintf(extra_args, BUFSIZ, "-okernel_cache,subtype=ext4,"
"fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS,
fctx.device);
if (fctx.no_default_opts == 0)
/* Make a note in the error log */
get_now(&now);
- fs->super->s_last_error_time = now.tv_sec;
+ ext2fs_set_tstamp(fs->super, s_last_error_time, now.tv_sec);
fs->super->s_last_error_ino = ino;
fs->super->s_last_error_line = line;
fs->super->s_last_error_block = err; /* Yeah... */
strncpy((char *)fs->super->s_last_error_func, file,
sizeof(fs->super->s_last_error_func));
- if (fs->super->s_first_error_time == 0) {
- fs->super->s_first_error_time = now.tv_sec;
+ if (ext2fs_get_tstamp(fs->super, s_first_error_time) == 0) {
+ ext2fs_set_tstamp(fs->super, s_first_error_time, now.tv_sec);
fs->super->s_first_error_ino = ino;
fs->super->s_first_error_line = line;
fs->super->s_first_error_block = err;