# include <linux/fs.h>
# include <linux/falloc.h>
# include <linux/xattr.h>
-# define FUSE_PLATFORM_OPTS ",nonempty,big_writes"
+# define FUSE_PLATFORM_OPTS ",big_writes"
# ifdef HAVE_SYS_ACL_H
# define TRANSLATE_LINUX_ACLS
# endif
typedef struct {
u_int32_t a_version;
+#if __GNUC_PREREQ (4, 8)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
acl_ea_entry a_entries[0];
+#if __GNUC_PREREQ (4, 8)
+#pragma GCC diagnostic pop
+#endif
} acl_ea_header;
static inline size_t acl_ea_size(int count)
int no_default_opts;
int panic_on_error;
int minixdf;
+ int fakeroot;
int alloc_all_blocks;
FILE *err_fp;
unsigned int next_generation;
static int check_inum_access(ext2_filsys fs, ext2_ino_t ino, mode_t mask)
{
struct fuse_context *ctxt = fuse_get_context();
+ struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
struct ext2_inode inode;
mode_t perms;
errcode_t err;
return -EACCES;
/* Figure out what root's allowed to do */
- if (ctxt->uid == 0) {
+ if (ff->fakeroot || ctxt->uid == 0) {
/* Non-file access always ok */
if (!LINUX_S_ISREG(inode.i_mode))
return 0;
len--;
if (inode.i_size < len)
len = inode.i_size;
- if (ext2fs_inode_data_blocks2(fs, &inode) ||
- (inode.i_flags & EXT4_INLINE_DATA_FL)) {
+ if (ext2fs_is_fast_symlink(&inode))
+ memcpy(buf, (char *)inode.i_block, len);
+ else {
/* big/inline symlink */
err = ext2fs_file_open(fs, ino, 0, &file);
ret = translate_error(fs, ino, err);
goto out;
}
- } else
- /* inline symlink */
- memcpy(buf, (char *)inode.i_block, len);
+ }
buf[len] = 0;
if (fs_writeable(fs)) {
goto out;
}
- if (ctxt->uid != 0 && ctxt->uid != inode.i_uid) {
+ if (!ff->fakeroot && ctxt->uid != 0 && ctxt->uid != inode.i_uid) {
ret = -EPERM;
goto out;
}
* of the user's groups, but FUSE only tells us about the primary
* group.
*/
- if (ctxt->uid != 0 && ctxt->gid != inode.i_gid)
+ if (!ff->fakeroot && ctxt->uid != 0 && ctxt->gid != inode.i_gid)
mode &= ~S_ISGID;
inode.i_mode &= ~0xFFF;
/* FUSE seems to feed us ~0 to mean "don't change" */
if (owner != (uid_t) ~0) {
/* Only root gets to change UID. */
- if (ctxt->uid != 0 &&
+ if (!ff->fakeroot && ctxt->uid != 0 &&
!(inode.i_uid == ctxt->uid && owner == ctxt->uid)) {
ret = -EPERM;
goto out;
if (group != (gid_t) ~0) {
/* Only root or the owner get to change GID. */
- if (ctxt->uid != 0 && inode.i_uid != ctxt->uid) {
+ if (!ff->fakeroot && ctxt->uid != 0 && inode.i_uid != ctxt->uid) {
ret = -EPERM;
goto out;
}
goto out3;
}
- err = ext2fs_xattrs_write(h);
- if (err) {
- ret = translate_error(fs, ino, err);
- goto out3;
- }
-
ret = update_ctime(fs, ino, NULL);
out3:
if (cvalue != value)
goto out2;
}
- err = ext2fs_xattrs_write(h);
- if (err) {
- ret = translate_error(fs, ino, err);
- goto out2;
- }
-
ret = update_ctime(fs, ino, NULL);
out2:
err = ext2fs_xattrs_close(&h);
int ret;
__u32 flags = *(__u32 *)data;
struct fuse_context *ctxt = fuse_get_context();
+ struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
dbg_printf("%s: ino=%d\n", __func__, fh->ino);
if (err)
return translate_error(fs, fh->ino, err);
- if (ctxt->uid != 0 && inode.i_uid != ctxt->uid)
+ if (!ff->fakeroot && ctxt->uid != 0 && inode.i_uid != ctxt->uid)
return -EPERM;
if ((inode.i_flags ^ flags) & ~FUSE2FS_MODIFIABLE_IFLAGS)
int ret;
__u32 generation = *(__u32 *)data;
struct fuse_context *ctxt = fuse_get_context();
+ struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
dbg_printf("%s: ino=%d\n", __func__, fh->ino);
if (err)
return translate_error(fs, fh->ino, err);
- if (ctxt->uid != 0 && inode.i_uid != ctxt->uid)
+ if (!ff->fakeroot && ctxt->uid != 0 && inode.i_uid != ctxt->uid)
return -EPERM;
inode.i_generation = generation;
FUSE2FS_OPT("ro", ro, 1),
FUSE2FS_OPT("errors=panic", panic_on_error, 1),
FUSE2FS_OPT("minixdf", minixdf, 1),
+ FUSE2FS_OPT("fakeroot", fakeroot, 1),
FUSE2FS_OPT("fuse2fs_debug", debug, 1),
FUSE2FS_OPT("no_default_opts", no_default_opts, 1),
" -o ro read-only mount\n"
" -o errors=panic dump core on error\n"
" -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 fuse2fs_debug enable fuse2fs debugging\n"
"\n",
fctx.err_fp = fopen(logfile, "a");
if (!fctx.err_fp) {
perror(logfile);
- goto out_nofs;
+ goto out;
}
} else
fctx.err_fp = stderr;
if (err) {
printf(_("%s: %s.\n"), fctx.device, error_message(err));
printf(_("Please run e2fsck -fy %s.\n"), fctx.device);
- goto out_nofs;
+ goto out;
}
fctx.fs = global_fs;
global_fs->priv_data = &fctx;
ret = 3;
+
if (ext2fs_has_feature_journal_needs_recovery(global_fs->super)) {
if (!fctx.ro) {
printf(_("%s: recovering journal\n"), fctx.device);
/* Set up default fuse parameters */
snprintf(extra_args, BUFSIZ, "-okernel_cache,subtype=ext4,use_ino,"
"fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS,
- argv[1]);
+ fctx.device);
if (fctx.no_default_opts == 0)
fuse_opt_add_arg(&args, extra_args);
+ if (fctx.fakeroot) {
+#ifdef HAVE_MOUNT_NODEV
+ fuse_opt_add_arg(&args,"-onodev");
+#endif
+#ifdef HAVE_MOUNT_NOSUID
+ fuse_opt_add_arg(&args,"-onosuid");
+#endif
+ }
+
if (fctx.debug) {
int i;
ret = 0;
out:
- err = ext2fs_close(global_fs);
- if (err)
- com_err(argv[0], err, "while closing fs");
- global_fs = NULL;
-out_nofs:
-
+ if (global_fs) {
+ err = ext2fs_close(global_fs);
+ if (err)
+ com_err(argv[0], err, "while closing fs");
+ global_fs = NULL;
+ }
return ret;
}