2 * fuse2fs.c - FUSE server for e2fsprogs.
4 * Copyright (C) 2014 Oracle.
7 * This file may be redistributed under the terms of the GNU Public
11 #define _FILE_OFFSET_BITS 64
18 # include <linux/fs.h>
19 # include <linux/falloc.h>
20 # include <linux/xattr.h>
21 # ifdef HAVE_SYS_ACL_H
22 # define TRANSLATE_LINUX_ACLS
25 #ifdef TRANSLATE_LINUX_ACLS
28 #include <sys/ioctl.h>
32 #include "ext2fs/ext2fs.h"
33 #include "ext2fs/ext2_fs.h"
34 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
35 # define FUSE_PLATFORM_OPTS ""
38 # define FUSE_PLATFORM_OPTS ",use_ino,big_writes"
40 # define FUSE_PLATFORM_OPTS ",use_ino"
44 #include "../version.h"
49 #define _(a) (gettext(a))
51 #define N_(a) gettext_noop(a)
55 #define P_(singular, plural, n) (ngettext(singular, plural, n))
57 #define NLS_CAT_NAME "e2fsprogs"
60 #define LOCALEDIR "/usr/share/locale"
65 #define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural))
68 static ext2_filsys global_fs; /* Try not to use this directly */
73 # define dbg_printf(f, a...) do {printf("FUSE2FS-" f, ## a); \
77 # define dbg_printf(f, a...)
80 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
83 # define SUPPORT_I_FLAGS
88 #ifdef FALLOC_FL_KEEP_SIZE
89 # define FL_KEEP_SIZE_FLAG FALLOC_FL_KEEP_SIZE
90 # define SUPPORT_FALLOCATE
92 # define FL_KEEP_SIZE_FLAG (0)
95 #ifdef FALLOC_FL_PUNCH_HOLE
96 # define FL_PUNCH_HOLE_FLAG FALLOC_FL_PUNCH_HOLE
98 # define FL_PUNCH_HOLE_FLAG (0)
101 errcode_t ext2fs_run_ext3_journal(ext2_filsys *fs);
103 #ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jbd-debug */
104 int journal_enable_debug = -1;
107 /* ACL translation stuff */
108 #ifdef TRANSLATE_LINUX_ACLS
110 * Copied from acl_ea.h in libacl source; ACLs have to be sent to and from fuse
111 * in this format... at least on Linux.
113 #define ACL_EA_ACCESS "system.posix_acl_access"
114 #define ACL_EA_DEFAULT "system.posix_acl_default"
116 #define ACL_EA_VERSION 0x0002
126 #if __GNUC_PREREQ (4, 8)
127 #pragma GCC diagnostic push
128 #pragma GCC diagnostic ignored "-Wpedantic"
130 acl_ea_entry a_entries[0];
131 #if __GNUC_PREREQ (4, 8)
132 #pragma GCC diagnostic pop
136 static inline size_t acl_ea_size(int count)
138 return sizeof(acl_ea_header) + count * sizeof(acl_ea_entry);
141 static inline int acl_ea_count(size_t size)
143 if (size < sizeof(acl_ea_header))
145 size -= sizeof(acl_ea_header);
146 if (size % sizeof(acl_ea_entry))
148 return size / sizeof(acl_ea_entry);
152 * ext4 ACL structures, copied from fs/ext4/acl.h.
154 #define EXT4_ACL_VERSION 0x0001
165 } ext4_acl_entry_short;
171 static inline size_t ext4_acl_size(int count)
174 return sizeof(ext4_acl_header) +
175 count * sizeof(ext4_acl_entry_short);
177 return sizeof(ext4_acl_header) +
178 4 * sizeof(ext4_acl_entry_short) +
179 (count - 4) * sizeof(ext4_acl_entry);
183 static inline int ext4_acl_count(size_t size)
187 size -= sizeof(ext4_acl_header);
188 s = size - 4 * sizeof(ext4_acl_entry_short);
190 if (size % sizeof(ext4_acl_entry_short))
192 return size / sizeof(ext4_acl_entry_short);
194 if (s % sizeof(ext4_acl_entry))
196 return s / sizeof(ext4_acl_entry) + 4;
199 static errcode_t fuse_to_ext4_acl(acl_ea_header *facl, size_t facl_sz,
200 ext4_acl_header **eacl, size_t *eacl_sz)
210 facl_count = acl_ea_count(facl_sz);
211 h_sz = ext4_acl_size(facl_count);
212 if (facl_count < 0 || facl->a_version != ACL_EA_VERSION)
213 return EXT2_ET_INVALID_ARGUMENT;
215 err = ext2fs_get_mem(h_sz, &h);
219 h->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION);
220 hptr = (unsigned char *) (h + 1);
221 for (i = 0, a = facl->a_entries; i < facl_count; i++, a++) {
222 e = (ext4_acl_entry *) hptr;
223 e->e_tag = ext2fs_cpu_to_le16(a->e_tag);
224 e->e_perm = ext2fs_cpu_to_le16(a->e_perm);
229 e->e_id = ext2fs_cpu_to_le32(a->e_id);
230 hptr += sizeof(ext4_acl_entry);
236 hptr += sizeof(ext4_acl_entry_short);
239 err = EXT2_ET_INVALID_ARGUMENT;
252 static errcode_t ext4_to_fuse_acl(acl_ea_header **facl, size_t *facl_sz,
253 ext4_acl_header *eacl, size_t eacl_sz)
263 eacl_count = ext4_acl_count(eacl_sz);
264 f_sz = acl_ea_size(eacl_count);
265 if (eacl_count < 0 ||
266 eacl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION))
267 return EXT2_ET_INVALID_ARGUMENT;
269 err = ext2fs_get_mem(f_sz, &f);
273 f->a_version = ACL_EA_VERSION;
274 hptr = (unsigned char *) (eacl + 1);
275 for (i = 0, a = f->a_entries; i < eacl_count; i++, a++) {
276 e = (ext4_acl_entry *) hptr;
277 a->e_tag = ext2fs_le16_to_cpu(e->e_tag);
278 a->e_perm = ext2fs_le16_to_cpu(e->e_perm);
283 a->e_id = ext2fs_le32_to_cpu(e->e_id);
284 hptr += sizeof(ext4_acl_entry);
290 hptr += sizeof(ext4_acl_entry_short);
293 err = EXT2_ET_INVALID_ARGUMENT;
305 #endif /* TRANSLATE_LINUX_ACLS */
308 * ext2_file_t contains a struct inode, so we can't leave files open.
309 * Use this as a proxy instead.
311 #define FUSE2FS_FILE_MAGIC (0xEF53DEAFUL)
312 struct fuse2fs_file_handle {
318 /* Main program context */
319 #define FUSE2FS_MAGIC (0xEF53DEADUL)
331 int alloc_all_blocks;
333 unsigned long offset;
335 unsigned int next_generation;
338 #define FUSE2FS_CHECK_MAGIC(fs, ptr, num) do {if ((ptr)->magic != (num)) \
339 return translate_error((fs), 0, EXT2_ET_MAGIC_EXT2_FILE); \
342 #define FUSE2FS_CHECK_CONTEXT(ptr) do {if ((ptr)->magic != FUSE2FS_MAGIC) \
343 return translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC); \
346 static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino,
347 const char *file, int line);
348 #define translate_error(fs, ino, err) __translate_error((fs), (err), (ino), \
360 #define EXT4_EPOCH_BITS 2
361 #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
362 #define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS)
365 * Extended fields will fit into an inode if the filesystem was formatted
366 * with large inodes (-I 256 or larger) and there are not currently any EAs
367 * consuming all of the available space. For new inodes we always reserve
368 * enough space for the kernel's known extended fields, but for inodes
369 * created with an old kernel this might not have been the case. None of
370 * the extended inode fields is critical for correct filesystem operation.
371 * This macro checks if a certain field fits in the inode. Note that
372 * inode-size = GOOD_OLD_INODE_SIZE + i_extra_isize
374 #define EXT4_FITS_IN_INODE(ext4_inode, field) \
375 ((offsetof(typeof(*ext4_inode), field) + \
376 sizeof((ext4_inode)->field)) \
377 <= ((size_t) EXT2_GOOD_OLD_INODE_SIZE + \
378 (ext4_inode)->i_extra_isize)) \
380 static inline __u32 ext4_encode_extra_time(const struct timespec *time)
382 __u32 extra = sizeof(time->tv_sec) > 4 ?
383 ((time->tv_sec - (__s32)time->tv_sec) >> 32) &
385 return extra | (time->tv_nsec << EXT4_EPOCH_BITS);
388 static inline void ext4_decode_extra_time(struct timespec *time, __u32 extra)
390 if (sizeof(time->tv_sec) > 4 && (extra & EXT4_EPOCH_MASK)) {
391 __u64 extra_bits = extra & EXT4_EPOCH_MASK;
393 * Prior to kernel 3.14?, we had a broken decode function,
394 * wherein we effectively did this:
395 * if (extra_bits == 3)
398 time->tv_sec += extra_bits << 32;
400 time->tv_nsec = ((extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
403 #define EXT4_INODE_SET_XTIME(xtime, timespec, raw_inode) \
405 (raw_inode)->xtime = (timespec)->tv_sec; \
406 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
407 (raw_inode)->xtime ## _extra = \
408 ext4_encode_extra_time(timespec); \
411 #define EXT4_EINODE_SET_XTIME(xtime, timespec, raw_inode) \
413 if (EXT4_FITS_IN_INODE(raw_inode, xtime)) \
414 (raw_inode)->xtime = (timespec)->tv_sec; \
415 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
416 (raw_inode)->xtime ## _extra = \
417 ext4_encode_extra_time(timespec); \
420 #define EXT4_INODE_GET_XTIME(xtime, timespec, raw_inode) \
422 (timespec)->tv_sec = (signed)((raw_inode)->xtime); \
423 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
424 ext4_decode_extra_time((timespec), \
425 (raw_inode)->xtime ## _extra); \
427 (timespec)->tv_nsec = 0; \
430 #define EXT4_EINODE_GET_XTIME(xtime, timespec, raw_inode) \
432 if (EXT4_FITS_IN_INODE(raw_inode, xtime)) \
433 (timespec)->tv_sec = \
434 (signed)((raw_inode)->xtime); \
435 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
436 ext4_decode_extra_time((timespec), \
437 raw_inode->xtime ## _extra); \
439 (timespec)->tv_nsec = 0; \
442 static void get_now(struct timespec *now)
444 #ifdef CLOCK_REALTIME
445 if (!clock_gettime(CLOCK_REALTIME, now))
449 now->tv_sec = time(NULL);
453 static void increment_version(struct ext2_inode_large *inode)
457 ver = inode->osd1.linux1.l_i_version;
458 if (EXT4_FITS_IN_INODE(inode, i_version_hi))
459 ver |= (__u64)inode->i_version_hi << 32;
461 inode->osd1.linux1.l_i_version = ver;
462 if (EXT4_FITS_IN_INODE(inode, i_version_hi))
463 inode->i_version_hi = ver >> 32;
466 static void init_times(struct ext2_inode_large *inode)
471 EXT4_INODE_SET_XTIME(i_atime, &now, inode);
472 EXT4_INODE_SET_XTIME(i_ctime, &now, inode);
473 EXT4_INODE_SET_XTIME(i_mtime, &now, inode);
474 EXT4_EINODE_SET_XTIME(i_crtime, &now, inode);
475 increment_version(inode);
478 static int update_ctime(ext2_filsys fs, ext2_ino_t ino,
479 struct ext2_inode_large *pinode)
483 struct ext2_inode_large inode;
487 /* If user already has a inode buffer, just update that */
489 increment_version(pinode);
490 EXT4_INODE_SET_XTIME(i_ctime, &now, pinode);
494 /* Otherwise we have to read-modify-write the inode */
495 memset(&inode, 0, sizeof(inode));
496 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
499 return translate_error(fs, ino, err);
501 increment_version(&inode);
502 EXT4_INODE_SET_XTIME(i_ctime, &now, &inode);
504 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
507 return translate_error(fs, ino, err);
512 static int update_atime(ext2_filsys fs, ext2_ino_t ino)
515 struct ext2_inode_large inode, *pinode;
516 struct timespec atime, mtime, now;
518 if (!(fs->flags & EXT2_FLAG_RW))
520 memset(&inode, 0, sizeof(inode));
521 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
524 return translate_error(fs, ino, err);
527 EXT4_INODE_GET_XTIME(i_atime, &atime, pinode);
528 EXT4_INODE_GET_XTIME(i_mtime, &mtime, pinode);
531 * If atime is newer than mtime and atime hasn't been updated in thirty
532 * seconds, skip the atime update. Same idea as Linux "relatime".
534 if (atime.tv_sec >= mtime.tv_sec && atime.tv_sec >= now.tv_sec - 30)
536 EXT4_INODE_SET_XTIME(i_atime, &now, &inode);
538 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
541 return translate_error(fs, ino, err);
546 static int update_mtime(ext2_filsys fs, ext2_ino_t ino,
547 struct ext2_inode_large *pinode)
550 struct ext2_inode_large inode;
555 EXT4_INODE_SET_XTIME(i_mtime, &now, pinode);
556 EXT4_INODE_SET_XTIME(i_ctime, &now, pinode);
557 increment_version(pinode);
561 memset(&inode, 0, sizeof(inode));
562 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
565 return translate_error(fs, ino, err);
568 EXT4_INODE_SET_XTIME(i_mtime, &now, &inode);
569 EXT4_INODE_SET_XTIME(i_ctime, &now, &inode);
570 increment_version(&inode);
572 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
575 return translate_error(fs, ino, err);
580 static int ext2_file_type(unsigned int mode)
582 if (LINUX_S_ISREG(mode))
583 return EXT2_FT_REG_FILE;
585 if (LINUX_S_ISDIR(mode))
588 if (LINUX_S_ISCHR(mode))
589 return EXT2_FT_CHRDEV;
591 if (LINUX_S_ISBLK(mode))
592 return EXT2_FT_BLKDEV;
594 if (LINUX_S_ISLNK(mode))
595 return EXT2_FT_SYMLINK;
597 if (LINUX_S_ISFIFO(mode))
600 if (LINUX_S_ISSOCK(mode))
606 static int fs_can_allocate(struct fuse2fs *ff, blk64_t num)
608 ext2_filsys fs = ff->fs;
611 dbg_printf("%s: Asking for %llu; alloc_all=%d total=%llu free=%llu "
612 "rsvd=%llu\n", __func__, num, ff->alloc_all_blocks,
613 ext2fs_blocks_count(fs->super),
614 ext2fs_free_blocks_count(fs->super),
615 ext2fs_r_blocks_count(fs->super));
616 if (num > ext2fs_blocks_count(fs->super))
619 if (ff->alloc_all_blocks)
623 * Different meaning for r_blocks -- libext2fs has bugs where the FS
624 * can get corrupted if it totally runs out of blocks. Avoid this
625 * by refusing to allocate any of the reserve blocks to anybody.
627 reserved = ext2fs_r_blocks_count(fs->super);
629 reserved = ext2fs_blocks_count(fs->super) / 10;
630 return ext2fs_free_blocks_count(fs->super) > reserved + num;
633 static int fs_writeable(ext2_filsys fs)
635 return (fs->flags & EXT2_FLAG_RW) && (fs->super->s_error_count == 0);
638 static int check_inum_access(ext2_filsys fs, ext2_ino_t ino, mode_t mask)
640 struct fuse_context *ctxt = fuse_get_context();
641 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
642 struct ext2_inode inode;
646 /* no writing to read-only or broken fs */
647 if ((mask & W_OK) && !fs_writeable(fs))
650 err = ext2fs_read_inode(fs, ino, &inode);
652 return translate_error(fs, ino, err);
653 perms = inode.i_mode & 0777;
655 dbg_printf("access ino=%d mask=e%s%s%s perms=0%o fuid=%d fgid=%d "
656 "uid=%d gid=%d\n", ino,
657 (mask & R_OK ? "r" : ""), (mask & W_OK ? "w" : ""),
658 (mask & X_OK ? "x" : ""), perms, inode_uid(inode),
659 inode_gid(inode), ctxt->uid, ctxt->gid);
661 /* existence check */
667 (inode.i_flags & EXT2_IMMUTABLE_FL))
670 /* Figure out what root's allowed to do */
671 if (ff->fakeroot || ctxt->uid == 0) {
672 /* Non-file access always ok */
673 if (!LINUX_S_ISREG(inode.i_mode))
676 /* R/W access to a file always ok */
680 /* X access to a file ok if a user/group/other can X */
684 /* Trying to execute a file that's not executable. BZZT! */
688 /* allow owner, if perms match */
689 if (inode_uid(inode) == ctxt->uid) {
690 if ((mask & (perms >> 6)) == mask)
695 /* allow group, if perms match */
696 if (inode_gid(inode) == ctxt->gid) {
697 if ((mask & (perms >> 3)) == mask)
702 /* otherwise check other */
703 if ((mask & perms) == mask)
708 static void op_destroy(void *p EXT2FS_ATTR((unused)))
710 struct fuse_context *ctxt = fuse_get_context();
711 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
715 if (ff->magic != FUSE2FS_MAGIC) {
716 translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC);
720 dbg_printf("%s: dev=%s\n", __func__, fs->device_name);
721 if (fs->flags & EXT2_FLAG_RW) {
722 fs->super->s_state |= EXT2_VALID_FS;
723 if (fs->super->s_error_count)
724 fs->super->s_state |= EXT2_ERROR_FS;
725 ext2fs_mark_super_dirty(fs);
726 err = ext2fs_set_gdt_csum(fs);
728 translate_error(fs, 0, err);
730 err = ext2fs_flush2(fs, 0);
732 translate_error(fs, 0, err);
736 static void *op_init(struct fuse_conn_info *conn
737 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
738 , struct fuse_config *cfg EXT2FS_ATTR((unused))
742 struct fuse_context *ctxt = fuse_get_context();
743 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
747 if (ff->magic != FUSE2FS_MAGIC) {
748 translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC);
752 dbg_printf("%s: dev=%s\n", __func__, fs->device_name);
753 #ifdef FUSE_CAP_IOCTL_DIR
754 conn->want |= FUSE_CAP_IOCTL_DIR;
756 if (fs->flags & EXT2_FLAG_RW) {
757 fs->super->s_mnt_count++;
758 ext2fs_set_tstamp(fs->super, s_mtime, time(NULL));
759 fs->super->s_state &= ~EXT2_VALID_FS;
760 ext2fs_mark_super_dirty(fs);
761 err = ext2fs_flush2(fs, 0);
763 translate_error(fs, 0, err);
768 static int stat_inode(ext2_filsys fs, ext2_ino_t ino, struct stat *statbuf)
770 struct ext2_inode_large inode;
776 memset(&inode, 0, sizeof(inode));
777 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
780 return translate_error(fs, ino, err);
782 memcpy(&fakedev, fs->super->s_uuid, sizeof(fakedev));
783 statbuf->st_dev = fakedev;
784 statbuf->st_ino = ino;
785 statbuf->st_mode = inode.i_mode;
786 statbuf->st_nlink = inode.i_links_count;
787 statbuf->st_uid = inode_uid(inode);
788 statbuf->st_gid = inode_gid(inode);
789 statbuf->st_size = EXT2_I_SIZE(&inode);
790 statbuf->st_blksize = fs->blocksize;
791 statbuf->st_blocks = ext2fs_get_stat_i_blocks(fs,
792 (struct ext2_inode *)&inode);
793 EXT4_INODE_GET_XTIME(i_atime, &tv, &inode);
794 statbuf->st_atime = tv.tv_sec;
795 EXT4_INODE_GET_XTIME(i_mtime, &tv, &inode);
796 statbuf->st_mtime = tv.tv_sec;
797 EXT4_INODE_GET_XTIME(i_ctime, &tv, &inode);
798 statbuf->st_ctime = tv.tv_sec;
799 if (LINUX_S_ISCHR(inode.i_mode) ||
800 LINUX_S_ISBLK(inode.i_mode)) {
801 if (inode.i_block[0])
802 statbuf->st_rdev = inode.i_block[0];
804 statbuf->st_rdev = inode.i_block[1];
810 static int op_getattr(const char *path, struct stat *statbuf
811 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
812 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
816 struct fuse_context *ctxt = fuse_get_context();
817 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
823 FUSE2FS_CHECK_CONTEXT(ff);
825 dbg_printf("%s: path=%s\n", __func__, path);
826 pthread_mutex_lock(&ff->bfl);
827 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
829 ret = translate_error(fs, 0, err);
832 ret = stat_inode(fs, ino, statbuf);
834 pthread_mutex_unlock(&ff->bfl);
838 static int op_readlink(const char *path, char *buf, size_t len)
840 struct fuse_context *ctxt = fuse_get_context();
841 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
845 struct ext2_inode inode;
850 FUSE2FS_CHECK_CONTEXT(ff);
852 dbg_printf("%s: path=%s\n", __func__, path);
853 pthread_mutex_lock(&ff->bfl);
854 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
855 if (err || ino == 0) {
856 ret = translate_error(fs, 0, err);
860 err = ext2fs_read_inode(fs, ino, &inode);
862 ret = translate_error(fs, ino, err);
866 if (!LINUX_S_ISLNK(inode.i_mode)) {
872 if (inode.i_size < len)
874 if (ext2fs_is_fast_symlink(&inode))
875 memcpy(buf, (char *)inode.i_block, len);
877 /* big/inline symlink */
879 err = ext2fs_file_open(fs, ino, 0, &file);
881 ret = translate_error(fs, ino, err);
885 err = ext2fs_file_read(file, buf, len, &got);
886 if (err || got != len) {
887 ext2fs_file_close(file);
888 ret = translate_error(fs, ino, err);
893 err = ext2fs_file_close(file);
897 ret = translate_error(fs, ino, err);
903 if (fs_writeable(fs)) {
904 ret = update_atime(fs, ino);
910 pthread_mutex_unlock(&ff->bfl);
914 static int op_mknod(const char *path, mode_t mode, dev_t dev)
916 struct fuse_context *ctxt = fuse_get_context();
917 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
919 ext2_ino_t parent, child;
924 struct ext2_inode_large inode;
927 FUSE2FS_CHECK_CONTEXT(ff);
929 dbg_printf("%s: path=%s mode=0%o dev=0x%x\n", __func__, path, mode,
931 temp_path = strdup(path);
936 node_name = strrchr(temp_path, '/');
945 pthread_mutex_lock(&ff->bfl);
946 if (!fs_can_allocate(ff, 2)) {
951 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
954 ret = translate_error(fs, 0, err);
958 ret = check_inum_access(fs, parent, W_OK);
964 if (LINUX_S_ISCHR(mode))
965 filetype = EXT2_FT_CHRDEV;
966 else if (LINUX_S_ISBLK(mode))
967 filetype = EXT2_FT_BLKDEV;
968 else if (LINUX_S_ISFIFO(mode))
969 filetype = EXT2_FT_FIFO;
970 else if (LINUX_S_ISSOCK(mode))
971 filetype = EXT2_FT_SOCK;
977 err = ext2fs_new_inode(fs, parent, mode, 0, &child);
979 ret = translate_error(fs, 0, err);
983 dbg_printf("%s: create ino=%d/name=%s in dir=%d\n", __func__, child,
985 err = ext2fs_link(fs, parent, node_name, child, filetype);
986 if (err == EXT2_ET_DIR_NO_SPACE) {
987 err = ext2fs_expand_dir(fs, parent);
989 ret = translate_error(fs, parent, err);
993 err = ext2fs_link(fs, parent, node_name, child,
997 ret = translate_error(fs, parent, err);
1001 ret = update_mtime(fs, parent, NULL);
1005 memset(&inode, 0, sizeof(inode));
1006 inode.i_mode = mode;
1009 inode.i_block[1] = dev;
1011 inode.i_block[0] = dev;
1012 inode.i_links_count = 1;
1013 inode.i_extra_isize = sizeof(struct ext2_inode_large) -
1014 EXT2_GOOD_OLD_INODE_SIZE;
1015 inode.i_uid = ctxt->uid;
1016 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
1017 inode.i_gid = ctxt->gid;
1018 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
1020 err = ext2fs_write_new_inode(fs, child, (struct ext2_inode *)&inode);
1022 ret = translate_error(fs, child, err);
1026 inode.i_generation = ff->next_generation++;
1028 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
1031 ret = translate_error(fs, child, err);
1035 ext2fs_inode_alloc_stats2(fs, child, 1, 0);
1038 pthread_mutex_unlock(&ff->bfl);
1044 static int op_mkdir(const char *path, mode_t mode)
1046 struct fuse_context *ctxt = fuse_get_context();
1047 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1049 ext2_ino_t parent, child;
1053 struct ext2_inode_large inode;
1059 FUSE2FS_CHECK_CONTEXT(ff);
1061 dbg_printf("%s: path=%s mode=0%o\n", __func__, path, mode);
1062 temp_path = strdup(path);
1067 node_name = strrchr(temp_path, '/');
1076 pthread_mutex_lock(&ff->bfl);
1077 if (!fs_can_allocate(ff, 1)) {
1082 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1085 ret = translate_error(fs, 0, err);
1089 ret = check_inum_access(fs, parent, W_OK);
1093 /* Is the parent dir sgid? */
1094 err = ext2fs_read_inode_full(fs, parent, (struct ext2_inode *)&inode,
1097 ret = translate_error(fs, parent, err);
1100 parent_sgid = inode.i_mode & S_ISGID;
1104 err = ext2fs_mkdir(fs, parent, 0, node_name);
1105 if (err == EXT2_ET_DIR_NO_SPACE) {
1106 err = ext2fs_expand_dir(fs, parent);
1108 ret = translate_error(fs, parent, err);
1112 err = ext2fs_mkdir(fs, parent, 0, node_name);
1115 ret = translate_error(fs, parent, err);
1119 ret = update_mtime(fs, parent, NULL);
1123 /* Still have to update the uid/gid of the dir */
1124 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1127 ret = translate_error(fs, 0, err);
1130 dbg_printf("%s: created ino=%d/path=%s in dir=%d\n", __func__, child,
1133 memset(&inode, 0, sizeof(inode));
1134 err = ext2fs_read_inode_full(fs, child, (struct ext2_inode *)&inode,
1137 ret = translate_error(fs, child, err);
1141 inode.i_uid = ctxt->uid;
1142 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
1143 inode.i_gid = ctxt->gid;
1144 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
1145 inode.i_mode = LINUX_S_IFDIR | (mode & ~S_ISUID) |
1147 inode.i_generation = ff->next_generation++;
1149 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
1152 ret = translate_error(fs, child, err);
1156 /* Rewrite the directory block checksum, having set i_generation */
1157 if ((inode.i_flags & EXT4_INLINE_DATA_FL) ||
1158 !ext2fs_has_feature_metadata_csum(fs->super))
1160 err = ext2fs_new_dir_block(fs, child, parent, &block);
1162 ret = translate_error(fs, child, err);
1165 err = ext2fs_bmap2(fs, child, (struct ext2_inode *)&inode, NULL, 0, 0,
1168 ret = translate_error(fs, child, err);
1171 err = ext2fs_write_dir_block4(fs, blk, block, 0, child);
1173 ret = translate_error(fs, child, err);
1178 ext2fs_free_mem(&block);
1180 pthread_mutex_unlock(&ff->bfl);
1186 static int unlink_file_by_name(ext2_filsys fs, const char *path)
1190 char *filename = strdup(path);
1194 base_name = strrchr(filename, '/');
1196 *base_name++ = '\0';
1197 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, filename,
1201 return translate_error(fs, 0, err);
1204 dir = EXT2_ROOT_INO;
1205 base_name = filename;
1208 ret = check_inum_access(fs, dir, W_OK);
1214 dbg_printf("%s: unlinking name=%s from dir=%d\n", __func__,
1216 err = ext2fs_unlink(fs, dir, base_name, 0, 0);
1219 return translate_error(fs, dir, err);
1221 return update_mtime(fs, dir, NULL);
1224 static int remove_inode(struct fuse2fs *ff, ext2_ino_t ino)
1226 ext2_filsys fs = ff->fs;
1228 struct ext2_inode_large inode;
1231 memset(&inode, 0, sizeof(inode));
1232 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1235 ret = translate_error(fs, ino, err);
1238 dbg_printf("%s: put ino=%d links=%d\n", __func__, ino,
1239 inode.i_links_count);
1241 switch (inode.i_links_count) {
1243 return 0; /* XXX: already done? */
1245 inode.i_links_count--;
1246 ext2fs_set_dtime(fs, EXT2_INODE(&inode));
1249 inode.i_links_count--;
1252 ret = update_ctime(fs, ino, &inode);
1256 if (inode.i_links_count)
1259 /* Nobody holds this file; free its blocks! */
1260 err = ext2fs_free_ext_attr(fs, ino, &inode);
1264 if (ext2fs_inode_has_valid_blocks2(fs, (struct ext2_inode *)&inode)) {
1265 err = ext2fs_punch(fs, ino, (struct ext2_inode *)&inode, NULL,
1268 ret = translate_error(fs, ino, err);
1273 ext2fs_inode_alloc_stats2(fs, ino, -1,
1274 LINUX_S_ISDIR(inode.i_mode));
1277 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
1280 ret = translate_error(fs, ino, err);
1287 static int __op_unlink(struct fuse2fs *ff, const char *path)
1289 ext2_filsys fs = ff->fs;
1294 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1296 ret = translate_error(fs, 0, err);
1300 ret = unlink_file_by_name(fs, path);
1304 ret = remove_inode(ff, ino);
1311 static int op_unlink(const char *path)
1313 struct fuse_context *ctxt = fuse_get_context();
1314 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1317 FUSE2FS_CHECK_CONTEXT(ff);
1318 pthread_mutex_lock(&ff->bfl);
1319 ret = __op_unlink(ff, path);
1320 pthread_mutex_unlock(&ff->bfl);
1329 static int rmdir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
1330 int entry EXT2FS_ATTR((unused)),
1331 struct ext2_dir_entry *dirent,
1332 int offset EXT2FS_ATTR((unused)),
1333 int blocksize EXT2FS_ATTR((unused)),
1334 char *buf EXT2FS_ATTR((unused)),
1337 struct rd_struct *rds = (struct rd_struct *) private;
1339 if (dirent->inode == 0)
1341 if (((dirent->name_len & 0xFF) == 1) && (dirent->name[0] == '.'))
1343 if (((dirent->name_len & 0xFF) == 2) && (dirent->name[0] == '.') &&
1344 (dirent->name[1] == '.')) {
1345 rds->parent = dirent->inode;
1352 static int __op_rmdir(struct fuse2fs *ff, const char *path)
1354 ext2_filsys fs = ff->fs;
1357 struct ext2_inode_large inode;
1358 struct rd_struct rds;
1361 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &child);
1363 ret = translate_error(fs, 0, err);
1366 dbg_printf("%s: rmdir path=%s ino=%d\n", __func__, path, child);
1371 err = ext2fs_dir_iterate2(fs, child, 0, 0, rmdir_proc, &rds);
1373 ret = translate_error(fs, child, err);
1377 if (rds.empty == 0) {
1382 ret = unlink_file_by_name(fs, path);
1385 /* Directories have to be "removed" twice. */
1386 ret = remove_inode(ff, child);
1389 ret = remove_inode(ff, child);
1394 dbg_printf("%s: decr dir=%d link count\n", __func__,
1396 err = ext2fs_read_inode_full(fs, rds.parent,
1397 (struct ext2_inode *)&inode,
1400 ret = translate_error(fs, rds.parent, err);
1403 if (inode.i_links_count > 1)
1404 inode.i_links_count--;
1405 ret = update_mtime(fs, rds.parent, &inode);
1408 err = ext2fs_write_inode_full(fs, rds.parent,
1409 (struct ext2_inode *)&inode,
1412 ret = translate_error(fs, rds.parent, err);
1421 static int op_rmdir(const char *path)
1423 struct fuse_context *ctxt = fuse_get_context();
1424 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1427 FUSE2FS_CHECK_CONTEXT(ff);
1428 pthread_mutex_lock(&ff->bfl);
1429 ret = __op_rmdir(ff, path);
1430 pthread_mutex_unlock(&ff->bfl);
1434 static int op_symlink(const char *src, const char *dest)
1436 struct fuse_context *ctxt = fuse_get_context();
1437 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1439 ext2_ino_t parent, child;
1443 struct ext2_inode_large inode;
1446 FUSE2FS_CHECK_CONTEXT(ff);
1448 dbg_printf("%s: symlink %s to %s\n", __func__, src, dest);
1449 temp_path = strdup(dest);
1454 node_name = strrchr(temp_path, '/');
1463 pthread_mutex_lock(&ff->bfl);
1464 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1468 ret = translate_error(fs, 0, err);
1472 ret = check_inum_access(fs, parent, W_OK);
1477 /* Create symlink */
1478 err = ext2fs_symlink(fs, parent, 0, node_name, src);
1479 if (err == EXT2_ET_DIR_NO_SPACE) {
1480 err = ext2fs_expand_dir(fs, parent);
1482 ret = translate_error(fs, parent, err);
1486 err = ext2fs_symlink(fs, parent, 0, node_name, src);
1489 ret = translate_error(fs, parent, err);
1493 /* Update parent dir's mtime */
1494 ret = update_mtime(fs, parent, NULL);
1498 /* Still have to update the uid/gid of the symlink */
1499 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1502 ret = translate_error(fs, 0, err);
1505 dbg_printf("%s: symlinking ino=%d/name=%s to dir=%d\n", __func__,
1506 child, node_name, parent);
1508 memset(&inode, 0, sizeof(inode));
1509 err = ext2fs_read_inode_full(fs, child, (struct ext2_inode *)&inode,
1512 ret = translate_error(fs, child, err);
1516 inode.i_uid = ctxt->uid;
1517 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
1518 inode.i_gid = ctxt->gid;
1519 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
1520 inode.i_generation = ff->next_generation++;
1522 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
1525 ret = translate_error(fs, child, err);
1529 pthread_mutex_unlock(&ff->bfl);
1535 struct update_dotdot {
1536 ext2_ino_t new_dotdot;
1539 static int update_dotdot_helper(ext2_ino_t dir EXT2FS_ATTR((unused)),
1540 int entry EXT2FS_ATTR((unused)),
1541 struct ext2_dir_entry *dirent,
1542 int offset EXT2FS_ATTR((unused)),
1543 int blocksize EXT2FS_ATTR((unused)),
1544 char *buf EXT2FS_ATTR((unused)),
1547 struct update_dotdot *ud = priv_data;
1549 if (ext2fs_dirent_name_len(dirent) == 2 &&
1550 dirent->name[0] == '.' && dirent->name[1] == '.') {
1551 dirent->inode = ud->new_dotdot;
1552 return DIRENT_CHANGED | DIRENT_ABORT;
1558 static int op_rename(const char *from, const char *to
1559 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1560 , unsigned int flags EXT2FS_ATTR((unused))
1564 struct fuse_context *ctxt = fuse_get_context();
1565 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1568 ext2_ino_t from_ino, to_ino, to_dir_ino, from_dir_ino;
1569 char *temp_to = NULL, *temp_from = NULL;
1571 struct ext2_inode inode;
1572 struct update_dotdot ud;
1575 FUSE2FS_CHECK_CONTEXT(ff);
1577 dbg_printf("%s: renaming %s to %s\n", __func__, from, to);
1578 pthread_mutex_lock(&ff->bfl);
1579 if (!fs_can_allocate(ff, 5)) {
1584 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, from, &from_ino);
1585 if (err || from_ino == 0) {
1586 ret = translate_error(fs, 0, err);
1590 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, to, &to_ino);
1591 if (err && err != EXT2_ET_FILE_NOT_FOUND) {
1592 ret = translate_error(fs, 0, err);
1596 if (err == EXT2_ET_FILE_NOT_FOUND)
1599 /* Already the same file? */
1600 if (to_ino != 0 && to_ino == from_ino) {
1605 temp_to = strdup(to);
1611 temp_from = strdup(from);
1617 /* Find parent dir of the source and check write access */
1618 cp = strrchr(temp_from, '/');
1626 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_from,
1630 ret = translate_error(fs, 0, err);
1633 if (from_dir_ino == 0) {
1638 ret = check_inum_access(fs, from_dir_ino, W_OK);
1642 /* Find parent dir of the destination and check write access */
1643 cp = strrchr(temp_to, '/');
1651 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_to,
1655 ret = translate_error(fs, 0, err);
1658 if (to_dir_ino == 0) {
1663 ret = check_inum_access(fs, to_dir_ino, W_OK);
1667 /* If the target exists, unlink it first */
1669 err = ext2fs_read_inode(fs, to_ino, &inode);
1671 ret = translate_error(fs, to_ino, err);
1675 dbg_printf("%s: unlinking %s ino=%d\n", __func__,
1676 LINUX_S_ISDIR(inode.i_mode) ? "dir" : "file",
1678 if (LINUX_S_ISDIR(inode.i_mode))
1679 ret = __op_rmdir(ff, to);
1681 ret = __op_unlink(ff, to);
1686 /* Get ready to do the move */
1687 err = ext2fs_read_inode(fs, from_ino, &inode);
1689 ret = translate_error(fs, from_ino, err);
1693 /* Link in the new file */
1694 dbg_printf("%s: linking ino=%d/path=%s to dir=%d\n", __func__,
1695 from_ino, cp + 1, to_dir_ino);
1696 err = ext2fs_link(fs, to_dir_ino, cp + 1, from_ino,
1697 ext2_file_type(inode.i_mode));
1698 if (err == EXT2_ET_DIR_NO_SPACE) {
1699 err = ext2fs_expand_dir(fs, to_dir_ino);
1701 ret = translate_error(fs, to_dir_ino, err);
1705 err = ext2fs_link(fs, to_dir_ino, cp + 1, from_ino,
1706 ext2_file_type(inode.i_mode));
1709 ret = translate_error(fs, to_dir_ino, err);
1713 /* Update '..' pointer if dir */
1714 err = ext2fs_read_inode(fs, from_ino, &inode);
1716 ret = translate_error(fs, from_ino, err);
1720 if (LINUX_S_ISDIR(inode.i_mode)) {
1721 ud.new_dotdot = to_dir_ino;
1722 dbg_printf("%s: updating .. entry for dir=%d\n", __func__,
1724 err = ext2fs_dir_iterate2(fs, from_ino, 0, NULL,
1725 update_dotdot_helper, &ud);
1727 ret = translate_error(fs, from_ino, err);
1731 /* Decrease from_dir_ino's links_count */
1732 dbg_printf("%s: moving linkcount from dir=%d to dir=%d\n",
1733 __func__, from_dir_ino, to_dir_ino);
1734 err = ext2fs_read_inode(fs, from_dir_ino, &inode);
1736 ret = translate_error(fs, from_dir_ino, err);
1739 inode.i_links_count--;
1740 err = ext2fs_write_inode(fs, from_dir_ino, &inode);
1742 ret = translate_error(fs, from_dir_ino, err);
1746 /* Increase to_dir_ino's links_count */
1747 err = ext2fs_read_inode(fs, to_dir_ino, &inode);
1749 ret = translate_error(fs, to_dir_ino, err);
1752 inode.i_links_count++;
1753 err = ext2fs_write_inode(fs, to_dir_ino, &inode);
1755 ret = translate_error(fs, to_dir_ino, err);
1760 /* Update timestamps */
1761 ret = update_ctime(fs, from_ino, NULL);
1765 ret = update_mtime(fs, to_dir_ino, NULL);
1769 /* Remove the old file */
1770 ret = unlink_file_by_name(fs, from);
1774 /* Flush the whole mess out */
1775 err = ext2fs_flush2(fs, 0);
1777 ret = translate_error(fs, 0, err);
1783 pthread_mutex_unlock(&ff->bfl);
1787 static int op_link(const char *src, const char *dest)
1789 struct fuse_context *ctxt = fuse_get_context();
1790 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1795 ext2_ino_t parent, ino;
1796 struct ext2_inode_large inode;
1799 FUSE2FS_CHECK_CONTEXT(ff);
1801 dbg_printf("%s: src=%s dest=%s\n", __func__, src, dest);
1802 temp_path = strdup(dest);
1807 node_name = strrchr(temp_path, '/');
1816 pthread_mutex_lock(&ff->bfl);
1817 if (!fs_can_allocate(ff, 2)) {
1822 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1830 ret = check_inum_access(fs, parent, W_OK);
1835 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, src, &ino);
1836 if (err || ino == 0) {
1837 ret = translate_error(fs, 0, err);
1841 memset(&inode, 0, sizeof(inode));
1842 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1845 ret = translate_error(fs, ino, err);
1849 inode.i_links_count++;
1850 ret = update_ctime(fs, ino, &inode);
1854 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
1857 ret = translate_error(fs, ino, err);
1861 dbg_printf("%s: linking ino=%d/name=%s to dir=%d\n", __func__, ino,
1863 err = ext2fs_link(fs, parent, node_name, ino,
1864 ext2_file_type(inode.i_mode));
1865 if (err == EXT2_ET_DIR_NO_SPACE) {
1866 err = ext2fs_expand_dir(fs, parent);
1868 ret = translate_error(fs, parent, err);
1872 err = ext2fs_link(fs, parent, node_name, ino,
1873 ext2_file_type(inode.i_mode));
1876 ret = translate_error(fs, parent, err);
1880 ret = update_mtime(fs, parent, NULL);
1885 pthread_mutex_unlock(&ff->bfl);
1891 static int op_chmod(const char *path, mode_t mode
1892 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1893 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
1897 struct fuse_context *ctxt = fuse_get_context();
1898 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1902 struct ext2_inode_large inode;
1905 FUSE2FS_CHECK_CONTEXT(ff);
1907 pthread_mutex_lock(&ff->bfl);
1908 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1910 ret = translate_error(fs, 0, err);
1913 dbg_printf("%s: path=%s mode=0%o ino=%d\n", __func__, path, mode, ino);
1915 memset(&inode, 0, sizeof(inode));
1916 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1919 ret = translate_error(fs, ino, err);
1923 if (!ff->fakeroot && ctxt->uid != 0 && ctxt->uid != inode_uid(inode)) {
1929 * XXX: We should really check that the inode gid is not in /any/
1930 * of the user's groups, but FUSE only tells us about the primary
1933 if (!ff->fakeroot && ctxt->uid != 0 && ctxt->gid != inode_gid(inode))
1936 inode.i_mode &= ~0xFFF;
1937 inode.i_mode |= mode & 0xFFF;
1938 ret = update_ctime(fs, ino, &inode);
1942 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
1945 ret = translate_error(fs, ino, err);
1950 pthread_mutex_unlock(&ff->bfl);
1954 static int op_chown(const char *path, uid_t owner, gid_t group
1955 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1956 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
1960 struct fuse_context *ctxt = fuse_get_context();
1961 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1965 struct ext2_inode_large inode;
1968 FUSE2FS_CHECK_CONTEXT(ff);
1970 pthread_mutex_lock(&ff->bfl);
1971 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1973 ret = translate_error(fs, 0, err);
1976 dbg_printf("%s: path=%s owner=%d group=%d ino=%d\n", __func__,
1977 path, owner, group, ino);
1979 memset(&inode, 0, sizeof(inode));
1980 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1983 ret = translate_error(fs, ino, err);
1987 /* FUSE seems to feed us ~0 to mean "don't change" */
1988 if (owner != (uid_t) ~0) {
1989 /* Only root gets to change UID. */
1990 if (!ff->fakeroot && ctxt->uid != 0 &&
1991 !(inode_uid(inode) == ctxt->uid && owner == ctxt->uid)) {
1995 inode.i_uid = owner;
1996 ext2fs_set_i_uid_high(inode, owner >> 16);
1999 if (group != (gid_t) ~0) {
2000 /* Only root or the owner get to change GID. */
2001 if (!ff->fakeroot && ctxt->uid != 0 &&
2002 inode_uid(inode) != ctxt->uid) {
2007 /* XXX: We /should/ check group membership but FUSE */
2008 inode.i_gid = group;
2009 ext2fs_set_i_gid_high(inode, group >> 16);
2012 ret = update_ctime(fs, ino, &inode);
2016 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
2019 ret = translate_error(fs, ino, err);
2024 pthread_mutex_unlock(&ff->bfl);
2028 static int op_truncate(const char *path, off_t len
2029 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
2030 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
2034 struct fuse_context *ctxt = fuse_get_context();
2035 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2042 FUSE2FS_CHECK_CONTEXT(ff);
2044 pthread_mutex_lock(&ff->bfl);
2045 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2046 if (err || ino == 0) {
2047 ret = translate_error(fs, 0, err);
2050 dbg_printf("%s: ino=%d len=%jd\n", __func__, ino, len);
2052 ret = check_inum_access(fs, ino, W_OK);
2056 err = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &file);
2058 ret = translate_error(fs, ino, err);
2062 err = ext2fs_file_set_size2(file, len);
2064 ret = translate_error(fs, ino, err);
2069 err = ext2fs_file_close(file);
2073 ret = translate_error(fs, ino, err);
2077 ret = update_mtime(fs, ino, NULL);
2080 pthread_mutex_unlock(&ff->bfl);
2085 static void detect_linux_executable_open(int kernel_flags, int *access_check,
2086 int *e2fs_open_flags)
2089 * On Linux, execve will bleed __FMODE_EXEC into the file mode flags,
2090 * and FUSE is more than happy to let that slip through.
2092 if (kernel_flags & 0x20) {
2093 *access_check = X_OK;
2094 *e2fs_open_flags &= ~EXT2_FILE_WRITE;
2098 static void detect_linux_executable_open(int kernel_flags, int *access_check,
2099 int *e2fs_open_flags)
2103 #endif /* __linux__ */
2105 static int __op_open(struct fuse2fs *ff, const char *path,
2106 struct fuse_file_info *fp)
2108 ext2_filsys fs = ff->fs;
2110 struct fuse2fs_file_handle *file;
2111 int check = 0, ret = 0;
2113 dbg_printf("%s: path=%s\n", __func__, path);
2114 err = ext2fs_get_mem(sizeof(*file), &file);
2116 return translate_error(fs, 0, err);
2117 file->magic = FUSE2FS_FILE_MAGIC;
2119 file->open_flags = 0;
2120 switch (fp->flags & O_ACCMODE) {
2126 file->open_flags |= EXT2_FILE_WRITE;
2129 check = R_OK | W_OK;
2130 file->open_flags |= EXT2_FILE_WRITE;
2134 detect_linux_executable_open(fp->flags, &check, &file->open_flags);
2136 if (fp->flags & O_CREAT)
2137 file->open_flags |= EXT2_FILE_CREATE;
2139 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &file->ino);
2140 if (err || file->ino == 0) {
2141 ret = translate_error(fs, 0, err);
2144 dbg_printf("%s: ino=%d\n", __func__, file->ino);
2146 ret = check_inum_access(fs, file->ino, check);
2149 * In a regular (Linux) fs driver, the kernel will open
2150 * binaries for reading if the user has --x privileges (i.e.
2151 * execute without read). Since the kernel doesn't have any
2152 * way to tell us if it's opening a file via execve, we'll
2153 * just assume that allowing access is ok if asking for ro mode
2154 * fails but asking for x mode succeeds. Of course we can
2155 * also employ undocumented hacks (see above).
2157 if (check == R_OK) {
2158 ret = check_inum_access(fs, file->ino, X_OK);
2164 fp->fh = (uintptr_t)file;
2168 ext2fs_free_mem(&file);
2172 static int op_open(const char *path, struct fuse_file_info *fp)
2174 struct fuse_context *ctxt = fuse_get_context();
2175 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2178 FUSE2FS_CHECK_CONTEXT(ff);
2179 pthread_mutex_lock(&ff->bfl);
2180 ret = __op_open(ff, path, fp);
2181 pthread_mutex_unlock(&ff->bfl);
2185 static int op_read(const char *path EXT2FS_ATTR((unused)), char *buf,
2186 size_t len, off_t offset,
2187 struct fuse_file_info *fp)
2189 struct fuse_context *ctxt = fuse_get_context();
2190 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2191 struct fuse2fs_file_handle *fh =
2192 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2196 unsigned int got = 0;
2199 FUSE2FS_CHECK_CONTEXT(ff);
2201 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2202 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino, offset,
2204 pthread_mutex_lock(&ff->bfl);
2205 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
2207 ret = translate_error(fs, fh->ino, err);
2211 err = ext2fs_file_llseek(efp, offset, SEEK_SET, NULL);
2213 ret = translate_error(fs, fh->ino, err);
2217 err = ext2fs_file_read(efp, buf, len, &got);
2219 ret = translate_error(fs, fh->ino, err);
2224 err = ext2fs_file_close(efp);
2228 ret = translate_error(fs, fh->ino, err);
2232 if (fs_writeable(fs)) {
2233 ret = update_atime(fs, fh->ino);
2238 pthread_mutex_unlock(&ff->bfl);
2239 return got ? (int) got : ret;
2242 static int op_write(const char *path EXT2FS_ATTR((unused)),
2243 const char *buf, size_t len, off_t offset,
2244 struct fuse_file_info *fp)
2246 struct fuse_context *ctxt = fuse_get_context();
2247 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2248 struct fuse2fs_file_handle *fh =
2249 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2253 unsigned int got = 0;
2256 FUSE2FS_CHECK_CONTEXT(ff);
2258 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2259 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino, offset,
2261 pthread_mutex_lock(&ff->bfl);
2262 if (!fs_writeable(fs)) {
2267 if (!fs_can_allocate(ff, len / fs->blocksize)) {
2272 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
2274 ret = translate_error(fs, fh->ino, err);
2278 err = ext2fs_file_llseek(efp, offset, SEEK_SET, NULL);
2280 ret = translate_error(fs, fh->ino, err);
2284 err = ext2fs_file_write(efp, buf, len, &got);
2286 ret = translate_error(fs, fh->ino, err);
2290 err = ext2fs_file_flush(efp);
2293 ret = translate_error(fs, fh->ino, err);
2298 err = ext2fs_file_close(efp);
2302 ret = translate_error(fs, fh->ino, err);
2306 ret = update_mtime(fs, fh->ino, NULL);
2311 pthread_mutex_unlock(&ff->bfl);
2312 return got ? (int) got : ret;
2315 static int op_release(const char *path EXT2FS_ATTR((unused)),
2316 struct fuse_file_info *fp)
2318 struct fuse_context *ctxt = fuse_get_context();
2319 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2320 struct fuse2fs_file_handle *fh =
2321 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2326 FUSE2FS_CHECK_CONTEXT(ff);
2328 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2329 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
2330 pthread_mutex_lock(&ff->bfl);
2331 if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) {
2332 err = ext2fs_flush2(fs, EXT2_FLAG_FLUSH_NO_SYNC);
2334 ret = translate_error(fs, fh->ino, err);
2337 pthread_mutex_unlock(&ff->bfl);
2339 ext2fs_free_mem(&fh);
2344 static int op_fsync(const char *path EXT2FS_ATTR((unused)),
2345 int datasync EXT2FS_ATTR((unused)),
2346 struct fuse_file_info *fp)
2348 struct fuse_context *ctxt = fuse_get_context();
2349 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2350 struct fuse2fs_file_handle *fh =
2351 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2356 FUSE2FS_CHECK_CONTEXT(ff);
2358 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2359 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
2360 /* For now, flush everything, even if it's slow */
2361 pthread_mutex_lock(&ff->bfl);
2362 if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) {
2363 err = ext2fs_flush2(fs, 0);
2365 ret = translate_error(fs, fh->ino, err);
2367 pthread_mutex_unlock(&ff->bfl);
2372 static int op_statfs(const char *path EXT2FS_ATTR((unused)),
2373 struct statvfs *buf)
2375 struct fuse_context *ctxt = fuse_get_context();
2376 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2379 blk64_t overhead, reserved, free;
2381 FUSE2FS_CHECK_CONTEXT(ff);
2383 dbg_printf("%s: path=%s\n", __func__, path);
2384 buf->f_bsize = fs->blocksize;
2390 overhead = fs->desc_blocks +
2391 (blk64_t)fs->group_desc_count *
2392 (fs->inode_blocks_per_group + 2);
2393 reserved = ext2fs_r_blocks_count(fs->super);
2395 reserved = ext2fs_blocks_count(fs->super) / 10;
2396 free = ext2fs_free_blocks_count(fs->super);
2398 buf->f_blocks = ext2fs_blocks_count(fs->super) - overhead;
2399 buf->f_bfree = free;
2400 if (free < reserved)
2403 buf->f_bavail = free - reserved;
2404 buf->f_files = fs->super->s_inodes_count;
2405 buf->f_ffree = fs->super->s_free_inodes_count;
2406 buf->f_favail = fs->super->s_free_inodes_count;
2407 f = (uint64_t *)fs->super->s_uuid;
2413 if (fs->flags & EXT2_FLAG_RW)
2414 buf->f_flag |= ST_RDONLY;
2415 buf->f_namemax = EXT2_NAME_LEN;
2420 typedef errcode_t (*xattr_xlate_get)(void **cooked_buf, size_t *cooked_sz,
2421 const void *raw_buf, size_t raw_sz);
2422 typedef errcode_t (*xattr_xlate_set)(const void *cooked_buf, size_t cooked_sz,
2423 const void **raw_buf, size_t *raw_sz);
2424 struct xattr_translate {
2426 xattr_xlate_get get;
2427 xattr_xlate_set set;
2430 #define XATTR_TRANSLATOR(p, g, s) \
2432 .get = (xattr_xlate_get)(g), \
2433 .set = (xattr_xlate_set)(s)}
2435 static struct xattr_translate xattr_translators[] = {
2436 #ifdef TRANSLATE_LINUX_ACLS
2437 XATTR_TRANSLATOR(ACL_EA_ACCESS, ext4_to_fuse_acl, fuse_to_ext4_acl),
2438 XATTR_TRANSLATOR(ACL_EA_DEFAULT, ext4_to_fuse_acl, fuse_to_ext4_acl),
2440 XATTR_TRANSLATOR(NULL, NULL, NULL),
2442 #undef XATTR_TRANSLATOR
2444 static int op_getxattr(const char *path, const char *key, char *value,
2447 struct fuse_context *ctxt = fuse_get_context();
2448 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2450 struct ext2_xattr_handle *h;
2451 struct xattr_translate *xt;
2458 FUSE2FS_CHECK_CONTEXT(ff);
2460 pthread_mutex_lock(&ff->bfl);
2461 if (!ext2fs_has_feature_xattr(fs->super)) {
2466 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2467 if (err || ino == 0) {
2468 ret = translate_error(fs, 0, err);
2471 dbg_printf("%s: ino=%d\n", __func__, ino);
2473 ret = check_inum_access(fs, ino, R_OK);
2477 err = ext2fs_xattrs_open(fs, ino, &h);
2479 ret = translate_error(fs, ino, err);
2483 err = ext2fs_xattrs_read(h);
2485 ret = translate_error(fs, ino, err);
2489 err = ext2fs_xattr_get(h, key, &ptr, &plen);
2491 ret = translate_error(fs, ino, err);
2495 for (xt = xattr_translators; xt->prefix != NULL; xt++) {
2496 if (strncmp(key, xt->prefix, strlen(xt->prefix)) == 0) {
2497 err = xt->get(&cptr, &clen, ptr, plen);
2500 ext2fs_free_mem(&ptr);
2508 } else if (len < plen) {
2511 memcpy(value, ptr, plen);
2516 ext2fs_free_mem(&ptr);
2518 err = ext2fs_xattrs_close(&h);
2520 ret = translate_error(fs, ino, err);
2522 pthread_mutex_unlock(&ff->bfl);
2527 static int count_buffer_space(char *name, char *value EXT2FS_ATTR((unused)),
2528 size_t value_len EXT2FS_ATTR((unused)),
2529 ext2_ino_t inode_num EXT2FS_ATTR((unused)),
2532 unsigned int *x = data;
2534 *x = *x + strlen(name) + 1;
2538 static int copy_names(char *name, char *value EXT2FS_ATTR((unused)),
2539 size_t value_len EXT2FS_ATTR((unused)),
2540 ext2_ino_t inode_num EXT2FS_ATTR((unused)),
2544 size_t name_len = strlen(name);
2546 memcpy(*b, name, name_len + 1);
2547 *b = *b + name_len + 1;
2552 static int op_listxattr(const char *path, char *names, size_t len)
2554 struct fuse_context *ctxt = fuse_get_context();
2555 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2557 struct ext2_xattr_handle *h;
2563 FUSE2FS_CHECK_CONTEXT(ff);
2565 pthread_mutex_lock(&ff->bfl);
2566 if (!ext2fs_has_feature_xattr(fs->super)) {
2571 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2572 if (err || ino == 0) {
2573 ret = translate_error(fs, ino, err);
2576 dbg_printf("%s: ino=%d\n", __func__, ino);
2578 ret = check_inum_access(fs, ino, R_OK);
2582 err = ext2fs_xattrs_open(fs, ino, &h);
2584 ret = translate_error(fs, ino, err);
2588 err = ext2fs_xattrs_read(h);
2590 ret = translate_error(fs, ino, err);
2594 /* Count buffer space needed for names */
2596 err = ext2fs_xattrs_iterate(h, count_buffer_space, &bufsz);
2598 ret = translate_error(fs, ino, err);
2605 } else if (len < bufsz) {
2610 /* Copy names out */
2611 memset(names, 0, len);
2612 err = ext2fs_xattrs_iterate(h, copy_names, &names);
2614 ret = translate_error(fs, ino, err);
2619 err = ext2fs_xattrs_close(&h);
2621 ret = translate_error(fs, ino, err);
2623 pthread_mutex_unlock(&ff->bfl);
2628 static int op_setxattr(const char *path EXT2FS_ATTR((unused)),
2629 const char *key, const char *value,
2630 size_t len, int flags EXT2FS_ATTR((unused)))
2632 struct fuse_context *ctxt = fuse_get_context();
2633 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2635 struct ext2_xattr_handle *h;
2636 struct xattr_translate *xt;
2643 FUSE2FS_CHECK_CONTEXT(ff);
2645 pthread_mutex_lock(&ff->bfl);
2646 if (!ext2fs_has_feature_xattr(fs->super)) {
2651 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2652 if (err || ino == 0) {
2653 ret = translate_error(fs, 0, err);
2656 dbg_printf("%s: ino=%d\n", __func__, ino);
2658 ret = check_inum_access(fs, ino, W_OK);
2659 if (ret == -EACCES) {
2665 err = ext2fs_xattrs_open(fs, ino, &h);
2667 ret = translate_error(fs, ino, err);
2671 err = ext2fs_xattrs_read(h);
2673 ret = translate_error(fs, ino, err);
2679 for (xt = xattr_translators; xt->prefix != NULL; xt++) {
2680 if (strncmp(key, xt->prefix, strlen(xt->prefix)) == 0) {
2681 err = xt->set(value, len, &cvalue, &clen);
2687 err = ext2fs_xattr_set(h, key, cvalue, clen);
2689 ret = translate_error(fs, ino, err);
2693 ret = update_ctime(fs, ino, NULL);
2695 if (cvalue != value)
2696 ext2fs_free_mem(&cvalue);
2698 err = ext2fs_xattrs_close(&h);
2700 ret = translate_error(fs, ino, err);
2702 pthread_mutex_unlock(&ff->bfl);
2707 static int op_removexattr(const char *path, const char *key)
2709 struct fuse_context *ctxt = fuse_get_context();
2710 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2712 struct ext2_xattr_handle *h;
2717 FUSE2FS_CHECK_CONTEXT(ff);
2719 pthread_mutex_lock(&ff->bfl);
2720 if (!ext2fs_has_feature_xattr(fs->super)) {
2725 if (!fs_can_allocate(ff, 1)) {
2730 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2731 if (err || ino == 0) {
2732 ret = translate_error(fs, 0, err);
2735 dbg_printf("%s: ino=%d\n", __func__, ino);
2737 ret = check_inum_access(fs, ino, W_OK);
2741 err = ext2fs_xattrs_open(fs, ino, &h);
2743 ret = translate_error(fs, ino, err);
2747 err = ext2fs_xattrs_read(h);
2749 ret = translate_error(fs, ino, err);
2753 err = ext2fs_xattr_remove(h, key);
2755 ret = translate_error(fs, ino, err);
2759 ret = update_ctime(fs, ino, NULL);
2761 err = ext2fs_xattrs_close(&h);
2763 ret = translate_error(fs, ino, err);
2765 pthread_mutex_unlock(&ff->bfl);
2770 struct readdir_iter {
2772 fuse_fill_dir_t func;
2775 static int op_readdir_iter(ext2_ino_t dir EXT2FS_ATTR((unused)),
2776 int entry EXT2FS_ATTR((unused)),
2777 struct ext2_dir_entry *dirent,
2778 int offset EXT2FS_ATTR((unused)),
2779 int blocksize EXT2FS_ATTR((unused)),
2780 char *buf EXT2FS_ATTR((unused)), void *data)
2782 struct readdir_iter *i = data;
2783 char namebuf[EXT2_NAME_LEN + 1];
2786 memcpy(namebuf, dirent->name, dirent->name_len & 0xFF);
2787 namebuf[dirent->name_len & 0xFF] = 0;
2788 ret = i->func(i->buf, namebuf, NULL, 0
2789 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
2794 return DIRENT_ABORT;
2799 static int op_readdir(const char *path EXT2FS_ATTR((unused)),
2800 void *buf, fuse_fill_dir_t fill_func,
2801 off_t offset EXT2FS_ATTR((unused)),
2802 struct fuse_file_info *fp
2803 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
2804 , enum fuse_readdir_flags flags EXT2FS_ATTR((unused))
2808 struct fuse_context *ctxt = fuse_get_context();
2809 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2810 struct fuse2fs_file_handle *fh =
2811 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2814 struct readdir_iter i;
2817 FUSE2FS_CHECK_CONTEXT(ff);
2819 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2820 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
2821 pthread_mutex_lock(&ff->bfl);
2824 err = ext2fs_dir_iterate2(fs, fh->ino, 0, NULL, op_readdir_iter, &i);
2826 ret = translate_error(fs, fh->ino, err);
2830 if (fs_writeable(fs)) {
2831 ret = update_atime(fs, fh->ino);
2836 pthread_mutex_unlock(&ff->bfl);
2840 static int op_access(const char *path, int mask)
2842 struct fuse_context *ctxt = fuse_get_context();
2843 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2849 FUSE2FS_CHECK_CONTEXT(ff);
2851 dbg_printf("%s: path=%s mask=0x%x\n", __func__, path, mask);
2852 pthread_mutex_lock(&ff->bfl);
2853 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2854 if (err || ino == 0) {
2855 ret = translate_error(fs, 0, err);
2859 ret = check_inum_access(fs, ino, mask);
2864 pthread_mutex_unlock(&ff->bfl);
2868 static int op_create(const char *path, mode_t mode, struct fuse_file_info *fp)
2870 struct fuse_context *ctxt = fuse_get_context();
2871 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2873 ext2_ino_t parent, child;
2878 struct ext2_inode_large inode;
2881 FUSE2FS_CHECK_CONTEXT(ff);
2883 dbg_printf("%s: path=%s mode=0%o\n", __func__, path, mode);
2884 temp_path = strdup(path);
2889 node_name = strrchr(temp_path, '/');
2898 pthread_mutex_lock(&ff->bfl);
2899 if (!fs_can_allocate(ff, 1)) {
2904 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
2907 ret = translate_error(fs, 0, err);
2911 ret = check_inum_access(fs, parent, W_OK);
2917 filetype = ext2_file_type(mode);
2919 err = ext2fs_new_inode(fs, parent, mode, 0, &child);
2921 ret = translate_error(fs, parent, err);
2925 dbg_printf("%s: creating ino=%d/name=%s in dir=%d\n", __func__, child,
2927 err = ext2fs_link(fs, parent, node_name, child, filetype);
2928 if (err == EXT2_ET_DIR_NO_SPACE) {
2929 err = ext2fs_expand_dir(fs, parent);
2931 ret = translate_error(fs, parent, err);
2935 err = ext2fs_link(fs, parent, node_name, child,
2939 ret = translate_error(fs, parent, err);
2943 ret = update_mtime(fs, parent, NULL);
2947 memset(&inode, 0, sizeof(inode));
2948 inode.i_mode = mode;
2949 inode.i_links_count = 1;
2950 inode.i_extra_isize = sizeof(struct ext2_inode_large) -
2951 EXT2_GOOD_OLD_INODE_SIZE;
2952 inode.i_uid = ctxt->uid;
2953 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
2954 inode.i_gid = ctxt->gid;
2955 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
2956 if (ext2fs_has_feature_extents(fs->super)) {
2957 ext2_extent_handle_t handle;
2959 inode.i_flags &= ~EXT4_EXTENTS_FL;
2960 ret = ext2fs_extent_open2(fs, child,
2961 (struct ext2_inode *)&inode, &handle);
2964 ext2fs_extent_free(handle);
2967 err = ext2fs_write_new_inode(fs, child, (struct ext2_inode *)&inode);
2969 ret = translate_error(fs, child, err);
2973 inode.i_generation = ff->next_generation++;
2975 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
2978 ret = translate_error(fs, child, err);
2982 ext2fs_inode_alloc_stats2(fs, child, 1, 0);
2984 ret = __op_open(ff, path, fp);
2988 pthread_mutex_unlock(&ff->bfl);
2994 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
2995 static int op_ftruncate(const char *path EXT2FS_ATTR((unused)),
2996 off_t len, struct fuse_file_info *fp)
2998 struct fuse_context *ctxt = fuse_get_context();
2999 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3000 struct fuse2fs_file_handle *fh =
3001 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3007 FUSE2FS_CHECK_CONTEXT(ff);
3009 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3010 dbg_printf("%s: ino=%d len=%jd\n", __func__, fh->ino, len);
3011 pthread_mutex_lock(&ff->bfl);
3012 if (!fs_writeable(fs)) {
3017 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
3019 ret = translate_error(fs, fh->ino, err);
3023 err = ext2fs_file_set_size2(efp, len);
3025 ret = translate_error(fs, fh->ino, err);
3030 err = ext2fs_file_close(efp);
3034 ret = translate_error(fs, fh->ino, err);
3038 ret = update_mtime(fs, fh->ino, NULL);
3043 pthread_mutex_unlock(&ff->bfl);
3047 static int op_fgetattr(const char *path EXT2FS_ATTR((unused)),
3048 struct stat *statbuf,
3049 struct fuse_file_info *fp)
3051 struct fuse_context *ctxt = fuse_get_context();
3052 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3054 struct fuse2fs_file_handle *fh =
3055 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3058 FUSE2FS_CHECK_CONTEXT(ff);
3060 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3061 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3062 pthread_mutex_lock(&ff->bfl);
3063 ret = stat_inode(fs, fh->ino, statbuf);
3064 pthread_mutex_unlock(&ff->bfl);
3068 #endif /* FUSE_VERSION < FUSE_MAKE_VERSION(3, 0) */
3070 static int op_utimens(const char *path, const struct timespec ctv[2]
3071 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
3072 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
3076 struct fuse_context *ctxt = fuse_get_context();
3077 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3078 struct timespec tv[2];
3082 struct ext2_inode_large inode;
3085 FUSE2FS_CHECK_CONTEXT(ff);
3087 pthread_mutex_lock(&ff->bfl);
3088 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
3090 ret = translate_error(fs, 0, err);
3093 dbg_printf("%s: ino=%d\n", __func__, ino);
3095 ret = check_inum_access(fs, ino, W_OK);
3099 memset(&inode, 0, sizeof(inode));
3100 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
3103 ret = translate_error(fs, ino, err);
3110 if (tv[0].tv_nsec == UTIME_NOW)
3112 if (tv[1].tv_nsec == UTIME_NOW)
3114 #endif /* UTIME_NOW */
3116 if (tv[0].tv_nsec != UTIME_OMIT)
3117 EXT4_INODE_SET_XTIME(i_atime, tv, &inode);
3118 if (tv[1].tv_nsec != UTIME_OMIT)
3119 EXT4_INODE_SET_XTIME(i_mtime, tv + 1, &inode);
3120 #endif /* UTIME_OMIT */
3121 ret = update_ctime(fs, ino, &inode);
3125 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
3128 ret = translate_error(fs, ino, err);
3133 pthread_mutex_unlock(&ff->bfl);
3137 #ifdef SUPPORT_I_FLAGS
3138 static int ioctl_getflags(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3142 struct ext2_inode_large inode;
3144 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3145 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3146 memset(&inode, 0, sizeof(inode));
3147 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3150 return translate_error(fs, fh->ino, err);
3152 *(__u32 *)data = inode.i_flags & EXT2_FL_USER_VISIBLE;
3156 #define FUSE2FS_MODIFIABLE_IFLAGS \
3157 (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL | EXT2_NODUMP_FL | \
3158 EXT2_NOATIME_FL | EXT3_JOURNAL_DATA_FL | EXT2_DIRSYNC_FL | \
3161 static int ioctl_setflags(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3165 struct ext2_inode_large inode;
3167 __u32 flags = *(__u32 *)data;
3168 struct fuse_context *ctxt = fuse_get_context();
3169 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3171 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3172 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3173 memset(&inode, 0, sizeof(inode));
3174 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3177 return translate_error(fs, fh->ino, err);
3179 if (!ff->fakeroot && ctxt->uid != 0 && inode_uid(inode) != ctxt->uid)
3182 if ((inode.i_flags ^ flags) & ~FUSE2FS_MODIFIABLE_IFLAGS)
3185 inode.i_flags = (inode.i_flags & ~FUSE2FS_MODIFIABLE_IFLAGS) |
3186 (flags & FUSE2FS_MODIFIABLE_IFLAGS);
3188 ret = update_ctime(fs, fh->ino, &inode);
3192 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3195 return translate_error(fs, fh->ino, err);
3200 static int ioctl_getversion(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3204 struct ext2_inode_large inode;
3206 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3207 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3208 memset(&inode, 0, sizeof(inode));
3209 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3212 return translate_error(fs, fh->ino, err);
3214 *(__u32 *)data = inode.i_generation;
3218 static int ioctl_setversion(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3222 struct ext2_inode_large inode;
3224 __u32 generation = *(__u32 *)data;
3225 struct fuse_context *ctxt = fuse_get_context();
3226 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3228 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3229 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3230 memset(&inode, 0, sizeof(inode));
3231 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3234 return translate_error(fs, fh->ino, err);
3236 if (!ff->fakeroot && ctxt->uid != 0 && inode_uid(inode) != ctxt->uid)
3239 inode.i_generation = generation;
3241 ret = update_ctime(fs, fh->ino, &inode);
3245 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3248 return translate_error(fs, fh->ino, err);
3252 #endif /* SUPPORT_I_FLAGS */
3255 static int ioctl_fitrim(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3258 struct fstrim_range *fr = data;
3259 blk64_t start, end, max_blocks, b, cleared;
3262 start = fr->start / fs->blocksize;
3263 end = (fr->start + fr->len - 1) / fs->blocksize;
3264 dbg_printf("%s: start=%llu end=%llu\n", __func__, start, end);
3266 if (start < fs->super->s_first_data_block)
3267 start = fs->super->s_first_data_block;
3268 if (start >= ext2fs_blocks_count(fs->super))
3269 start = ext2fs_blocks_count(fs->super) - 1;
3271 if (end < fs->super->s_first_data_block)
3272 end = fs->super->s_first_data_block;
3273 if (end >= ext2fs_blocks_count(fs->super))
3274 end = ext2fs_blocks_count(fs->super) - 1;
3277 max_blocks = 2048ULL * 1024 * 1024 / fs->blocksize;
3280 while (start <= end) {
3281 err = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
3282 start, end, &start);
3286 return translate_error(fs, fh->ino, err);
3288 b = start + max_blocks < end ? start + max_blocks : end;
3289 err = ext2fs_find_first_set_block_bitmap2(fs->block_map,
3291 if (err && err != ENOENT)
3292 return translate_error(fs, fh->ino, err);
3293 if (b - start >= fr->minlen) {
3294 err = io_channel_discard(fs->io, start, b - start);
3296 return translate_error(fs, fh->ino, err);
3297 cleared += b - start;
3298 fr->len = cleared * fs->blocksize;
3307 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
3308 static int op_ioctl(const char *path EXT2FS_ATTR((unused)),
3309 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
3314 void *arg EXT2FS_ATTR((unused)),
3315 struct fuse_file_info *fp,
3316 unsigned int flags EXT2FS_ATTR((unused)), void *data)
3318 struct fuse_context *ctxt = fuse_get_context();
3319 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3320 struct fuse2fs_file_handle *fh =
3321 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3325 FUSE2FS_CHECK_CONTEXT(ff);
3327 pthread_mutex_lock(&ff->bfl);
3328 switch ((unsigned long) cmd) {
3329 #ifdef SUPPORT_I_FLAGS
3330 case EXT2_IOC_GETFLAGS:
3331 ret = ioctl_getflags(fs, fh, data);
3333 case EXT2_IOC_SETFLAGS:
3334 ret = ioctl_setflags(fs, fh, data);
3336 case EXT2_IOC_GETVERSION:
3337 ret = ioctl_getversion(fs, fh, data);
3339 case EXT2_IOC_SETVERSION:
3340 ret = ioctl_setversion(fs, fh, data);
3345 ret = ioctl_fitrim(fs, fh, data);
3349 dbg_printf("%s: Unknown ioctl %d\n", __func__, cmd);
3352 pthread_mutex_unlock(&ff->bfl);
3356 #endif /* FUSE 28 */
3358 static int op_bmap(const char *path, size_t blocksize EXT2FS_ATTR((unused)),
3361 struct fuse_context *ctxt = fuse_get_context();
3362 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3368 FUSE2FS_CHECK_CONTEXT(ff);
3370 pthread_mutex_lock(&ff->bfl);
3371 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
3373 ret = translate_error(fs, 0, err);
3376 dbg_printf("%s: ino=%d blk=%"PRIu64"\n", __func__, ino, *idx);
3378 err = ext2fs_bmap2(fs, ino, NULL, NULL, 0, *idx, 0, (blk64_t *)idx);
3380 ret = translate_error(fs, ino, err);
3385 pthread_mutex_unlock(&ff->bfl);
3389 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3390 # ifdef SUPPORT_FALLOCATE
3391 static int fallocate_helper(struct fuse_file_info *fp, int mode, off_t offset,
3394 struct fuse_context *ctxt = fuse_get_context();
3395 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3396 struct fuse2fs_file_handle *fh =
3397 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3399 struct ext2_inode_large inode;
3405 FUSE2FS_CHECK_CONTEXT(ff);
3407 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3408 start = offset / fs->blocksize;
3409 end = (offset + len - 1) / fs->blocksize;
3410 dbg_printf("%s: ino=%d mode=0x%x start=%jd end=%llu\n", __func__,
3411 fh->ino, mode, offset / fs->blocksize, end);
3412 if (!fs_can_allocate(ff, len / fs->blocksize))
3415 memset(&inode, 0, sizeof(inode));
3416 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3420 fsize = EXT2_I_SIZE(&inode);
3422 /* Allocate a bunch of blocks */
3423 flags = (mode & FL_KEEP_SIZE_FLAG ? 0 :
3424 EXT2_FALLOCATE_INIT_BEYOND_EOF);
3425 err = ext2fs_fallocate(fs, flags, fh->ino,
3426 (struct ext2_inode *)&inode,
3427 ~0ULL, start, end - start + 1);
3428 if (err && err != EXT2_ET_BLOCK_ALLOC_FAIL)
3429 return translate_error(fs, fh->ino, err);
3432 if (!(mode & FL_KEEP_SIZE_FLAG)) {
3433 if ((__u64) offset + len > fsize) {
3434 err = ext2fs_inode_size_set(fs,
3435 (struct ext2_inode *)&inode,
3438 return translate_error(fs, fh->ino, err);
3442 err = update_mtime(fs, fh->ino, &inode);
3446 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3449 return translate_error(fs, fh->ino, err);
3454 static errcode_t clean_block_middle(ext2_filsys fs, ext2_ino_t ino,
3455 struct ext2_inode_large *inode, off_t offset,
3456 off_t len, char **buf)
3463 residue = offset % fs->blocksize;
3468 err = ext2fs_get_mem(fs->blocksize, buf);
3473 err = ext2fs_bmap2(fs, ino, (struct ext2_inode *)inode, *buf, 0,
3474 offset / fs->blocksize, &retflags, &blk);
3477 if (!blk || (retflags & BMAP_RET_UNINIT))
3480 err = io_channel_read_blk(fs->io, blk, 1, *buf);
3484 memset(*buf + residue, 0, len);
3486 return io_channel_write_blk(fs->io, blk, 1, *buf);
3489 static errcode_t clean_block_edge(ext2_filsys fs, ext2_ino_t ino,
3490 struct ext2_inode_large *inode, off_t offset,
3491 int clean_before, char **buf)
3498 residue = offset % fs->blocksize;
3503 err = ext2fs_get_mem(fs->blocksize, buf);
3508 err = ext2fs_bmap2(fs, ino, (struct ext2_inode *)inode, *buf, 0,
3509 offset / fs->blocksize, &retflags, &blk);
3513 err = io_channel_read_blk(fs->io, blk, 1, *buf);
3516 if (!blk || (retflags & BMAP_RET_UNINIT))
3520 memset(*buf, 0, residue);
3522 memset(*buf + residue, 0, fs->blocksize - residue);
3524 return io_channel_write_blk(fs->io, blk, 1, *buf);
3527 static int punch_helper(struct fuse_file_info *fp, int mode, off_t offset,
3530 struct fuse_context *ctxt = fuse_get_context();
3531 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3532 struct fuse2fs_file_handle *fh =
3533 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3535 struct ext2_inode_large inode;
3540 FUSE2FS_CHECK_CONTEXT(ff);
3542 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3543 dbg_printf("%s: offset=%jd len=%jd\n", __func__, offset, len);
3545 /* kernel ext4 punch requires this flag to be set */
3546 if (!(mode & FL_KEEP_SIZE_FLAG))
3549 /* Punch out a bunch of blocks */
3550 start = (offset + fs->blocksize - 1) / fs->blocksize;
3551 end = (offset + len - fs->blocksize) / fs->blocksize;
3552 dbg_printf("%s: ino=%d mode=0x%x start=%llu end=%llu\n", __func__,
3553 fh->ino, mode, start, end);
3555 memset(&inode, 0, sizeof(inode));
3556 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3559 return translate_error(fs, fh->ino, err);
3561 /* Zero everything before the first block and after the last block */
3562 if ((offset / fs->blocksize) == ((offset + len) / fs->blocksize))
3563 err = clean_block_middle(fs, fh->ino, &inode, offset,
3566 err = clean_block_edge(fs, fh->ino, &inode, offset, 0, &buf);
3568 err = clean_block_edge(fs, fh->ino, &inode,
3569 offset + len, 1, &buf);
3572 ext2fs_free_mem(&buf);
3574 return translate_error(fs, fh->ino, err);
3576 /* Unmap full blocks in the middle */
3578 err = ext2fs_punch(fs, fh->ino, (struct ext2_inode *)&inode,
3581 return translate_error(fs, fh->ino, err);
3584 err = update_mtime(fs, fh->ino, &inode);
3588 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3591 return translate_error(fs, fh->ino, err);
3596 static int op_fallocate(const char *path EXT2FS_ATTR((unused)), int mode,
3597 off_t offset, off_t len,
3598 struct fuse_file_info *fp)
3600 struct fuse_context *ctxt = fuse_get_context();
3601 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3602 ext2_filsys fs = ff->fs;
3605 /* Catch unknown flags */
3606 if (mode & ~(FL_PUNCH_HOLE_FLAG | FL_KEEP_SIZE_FLAG))
3609 pthread_mutex_lock(&ff->bfl);
3610 if (!fs_writeable(fs)) {
3614 if (mode & FL_PUNCH_HOLE_FLAG)
3615 ret = punch_helper(fp, mode, offset, len);
3617 ret = fallocate_helper(fp, mode, offset, len);
3619 pthread_mutex_unlock(&ff->bfl);
3623 # endif /* SUPPORT_FALLOCATE */
3624 #endif /* FUSE 29 */
3626 static struct fuse_operations fs_ops = {
3628 .destroy = op_destroy,
3629 .getattr = op_getattr,
3630 .readlink = op_readlink,
3633 .unlink = op_unlink,
3635 .symlink = op_symlink,
3636 .rename = op_rename,
3640 .truncate = op_truncate,
3644 .statfs = op_statfs,
3645 .release = op_release,
3647 .setxattr = op_setxattr,
3648 .getxattr = op_getxattr,
3649 .listxattr = op_listxattr,
3650 .removexattr = op_removexattr,
3652 .readdir = op_readdir,
3653 .releasedir = op_release,
3654 .fsyncdir = op_fsync,
3655 .access = op_access,
3656 .create = op_create,
3657 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
3658 .ftruncate = op_ftruncate,
3659 .fgetattr = op_fgetattr,
3661 .utimens = op_utimens,
3662 #if (FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)) && (FUSE_VERSION < FUSE_MAKE_VERSION(3, 0))
3663 # if defined(UTIME_NOW) || defined(UTIME_OMIT)
3664 .flag_utime_omit_ok = 1,
3672 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
3674 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
3675 .flag_nullpath_ok = 1,
3678 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3679 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
3682 # ifdef SUPPORT_FALLOCATE
3683 .fallocate = op_fallocate,
3688 static int get_random_bytes(void *p, size_t sz)
3693 fd = open("/dev/urandom", O_RDONLY);
3695 perror("/dev/urandom");
3699 r = read(fd, p, sz);
3702 return (size_t) r == sz;
3711 #define FUSE2FS_OPT(t, p, v) { t, offsetof(struct fuse2fs, p), v }
3713 static struct fuse_opt fuse2fs_opts[] = {
3714 FUSE2FS_OPT("ro", ro, 1),
3715 FUSE2FS_OPT("errors=panic", panic_on_error, 1),
3716 FUSE2FS_OPT("minixdf", minixdf, 1),
3717 FUSE2FS_OPT("fakeroot", fakeroot, 1),
3718 FUSE2FS_OPT("fuse2fs_debug", debug, 1),
3719 FUSE2FS_OPT("no_default_opts", no_default_opts, 1),
3720 FUSE2FS_OPT("norecovery", norecovery, 1),
3721 FUSE2FS_OPT("offset=%lu", offset, 0),
3723 FUSE_OPT_KEY("-V", FUSE2FS_VERSION),
3724 FUSE_OPT_KEY("--version", FUSE2FS_VERSION),
3725 FUSE_OPT_KEY("-h", FUSE2FS_HELP),
3726 FUSE_OPT_KEY("--help", FUSE2FS_HELP),
3727 FUSE_OPT_KEY("--helpfull", FUSE2FS_HELPFULL),
3732 static int fuse2fs_opt_proc(void *data, const char *arg,
3733 int key, struct fuse_args *outargs)
3735 struct fuse2fs *ff = data;
3738 case FUSE_OPT_KEY_NONOPT:
3740 ff->device = strdup(arg);
3745 case FUSE2FS_HELPFULL:
3747 "usage: %s device/image mountpoint [options]\n"
3749 "general options:\n"
3750 " -o opt,[opt...] mount options\n"
3751 " -h --help print help\n"
3752 " -V --version print version\n"
3754 "fuse2fs options:\n"
3755 " -o ro read-only mount\n"
3756 " -o errors=panic dump core on error\n"
3757 " -o minixdf minix-style df\n"
3758 " -o fakeroot pretend to be root for permission checks\n"
3759 " -o no_default_opts do not include default fuse options\n"
3760 " -o offset=<bytes> similar to mount -o offset=<bytes>, mount the partition starting at <bytes>\n"
3761 " -o norecovery don't replay the journal (implies ro)\n"
3762 " -o fuse2fs_debug enable fuse2fs debugging\n"
3765 if (key == FUSE2FS_HELPFULL) {
3766 fuse_opt_add_arg(outargs, "-ho");
3767 fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL);
3769 fprintf(stderr, "Try --helpfull to get a list of "
3770 "all flags, including the FUSE options.\n");
3774 case FUSE2FS_VERSION:
3775 fprintf(stderr, "fuse2fs %s (%s)\n", E2FSPROGS_VERSION,
3777 fuse_opt_add_arg(outargs, "--version");
3778 fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL);
3784 int main(int argc, char *argv[])
3786 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
3787 struct fuse2fs fctx;
3790 char extra_args[BUFSIZ];
3792 int flags = EXT2_FLAG_64BITS | EXT2_FLAG_THREADS | EXT2_FLAG_EXCLUSIVE;
3794 memset(&fctx, 0, sizeof(fctx));
3795 fctx.magic = FUSE2FS_MAGIC;
3797 fuse_opt_parse(&args, &fctx, fuse2fs_opts, fuse2fs_opt_proc);
3798 if (fctx.device == NULL) {
3799 fprintf(stderr, "Missing ext4 device/image\n");
3800 fprintf(stderr, "See '%s -h' for usage\n", argv[0]);
3804 if (fctx.norecovery)
3807 printf("%s", _("Mounting read-only.\n"));
3810 setlocale(LC_MESSAGES, "");
3811 setlocale(LC_CTYPE, "");
3812 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
3813 textdomain(NLS_CAT_NAME);
3814 set_com_err_gettext(gettext);
3816 add_error_table(&et_ext2_error_table);
3818 /* Set up error logging */
3819 logfile = getenv("FUSE2FS_LOGFILE");
3821 fctx.err_fp = fopen(logfile, "a");
3827 fctx.err_fp = stderr;
3829 /* Will we allow users to allocate every last block? */
3830 if (getenv("FUSE2FS_ALLOC_ALL_BLOCKS")) {
3831 printf(_("%s: Allowing users to allocate all blocks. "
3832 "This is dangerous!\n"), fctx.device);
3833 fctx.alloc_all_blocks = 1;
3836 /* Start up the fs (while we still can use stdout) */
3839 flags |= EXT2_FLAG_RW;
3841 sprintf(options, "offset=%lu", fctx.offset);
3842 err = ext2fs_open2(fctx.device, options, flags, 0, 0, unix_io_manager,
3845 printf(_("%s: %s.\n"), fctx.device, error_message(err));
3846 printf(_("Please run e2fsck -fy %s.\n"), fctx.device);
3849 fctx.fs = global_fs;
3850 global_fs->priv_data = &fctx;
3854 if (ext2fs_has_feature_journal_needs_recovery(global_fs->super)) {
3855 if (fctx.norecovery) {
3856 printf(_("%s: mounting read-only without "
3857 "recovering journal\n"),
3859 } else if (!fctx.ro) {
3860 printf(_("%s: recovering journal\n"), fctx.device);
3861 err = ext2fs_run_ext3_journal(&global_fs);
3863 printf(_("%s: %s.\n"), fctx.device,
3864 error_message(err));
3865 printf(_("Please run e2fsck -fy %s.\n"),
3869 ext2fs_clear_feature_journal_needs_recovery(global_fs->super);
3870 ext2fs_mark_super_dirty(global_fs);
3872 printf("%s", _("Journal needs recovery; running "
3873 "`e2fsck -E journal_only' is required.\n"));
3879 if (ext2fs_has_feature_journal(global_fs->super))
3880 printf(_("%s: Writing to the journal is not supported.\n"),
3882 err = ext2fs_read_inode_bitmap(global_fs);
3884 translate_error(global_fs, 0, err);
3887 err = ext2fs_read_block_bitmap(global_fs);
3889 translate_error(global_fs, 0, err);
3894 if (!(global_fs->super->s_state & EXT2_VALID_FS))
3895 printf("%s", _("Warning: Mounting unchecked fs, running e2fsck "
3896 "is recommended.\n"));
3897 if (global_fs->super->s_max_mnt_count > 0 &&
3898 global_fs->super->s_mnt_count >= global_fs->super->s_max_mnt_count)
3899 printf("%s", _("Warning: Maximal mount count reached, running "
3900 "e2fsck is recommended.\n"));
3901 if (global_fs->super->s_checkinterval > 0 &&
3902 (time_t) (global_fs->super->s_lastcheck +
3903 global_fs->super->s_checkinterval) <= time(0))
3904 printf("%s", _("Warning: Check time reached; running e2fsck "
3905 "is recommended.\n"));
3906 if (global_fs->super->s_last_orphan)
3908 _("Orphans detected; running e2fsck is recommended.\n"));
3910 if (global_fs->super->s_state & EXT2_ERROR_FS) {
3912 _("Errors detected; running e2fsck is required.\n"));
3916 /* Initialize generation counter */
3917 get_random_bytes(&fctx.next_generation, sizeof(unsigned int));
3919 /* Set up default fuse parameters */
3920 snprintf(extra_args, BUFSIZ, "-okernel_cache,subtype=ext4,"
3921 "fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS,
3923 if (fctx.no_default_opts == 0)
3924 fuse_opt_add_arg(&args, extra_args);
3926 if (fctx.fakeroot) {
3927 #ifdef HAVE_MOUNT_NODEV
3928 fuse_opt_add_arg(&args,"-onodev");
3930 #ifdef HAVE_MOUNT_NOSUID
3931 fuse_opt_add_arg(&args,"-onosuid");
3938 printf("fuse arguments:");
3939 for (i = 0; i < args.argc; i++)
3940 printf(" '%s'", args.argv[i]);
3944 pthread_mutex_init(&fctx.bfl, NULL);
3945 fuse_main(args.argc, args.argv, &fs_ops, &fctx);
3946 pthread_mutex_destroy(&fctx.bfl);
3951 err = ext2fs_close(global_fs);
3953 com_err(argv[0], err, "while closing fs");
3959 static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino,
3960 const char *file, int line)
3962 struct timespec now;
3964 struct fuse2fs *ff = fs->priv_data;
3967 /* Translate ext2 error to unix error code */
3968 if (err < EXT2_ET_BASE)
3969 goto no_translation;
3971 case EXT2_ET_NO_MEMORY:
3972 case EXT2_ET_TDB_ERR_OOM:
3975 case EXT2_ET_INVALID_ARGUMENT:
3976 case EXT2_ET_LLSEEK_FAILED:
3979 case EXT2_ET_NO_DIRECTORY:
3982 case EXT2_ET_FILE_NOT_FOUND:
3985 case EXT2_ET_DIR_NO_SPACE:
3988 case EXT2_ET_TOOSMALL:
3989 case EXT2_ET_BLOCK_ALLOC_FAIL:
3990 case EXT2_ET_INODE_ALLOC_FAIL:
3991 case EXT2_ET_EA_NO_SPACE:
3994 case EXT2_ET_SYMLINK_LOOP:
3997 case EXT2_ET_FILE_TOO_BIG:
4000 case EXT2_ET_TDB_ERR_EXISTS:
4001 case EXT2_ET_FILE_EXISTS:
4004 case EXT2_ET_MMP_FAILED:
4005 case EXT2_ET_MMP_FSCK_ON:
4008 case EXT2_ET_EA_KEY_NOT_FOUND:
4015 /* Sometimes fuse returns a garbage file handle pointer to us... */
4016 case EXT2_ET_MAGIC_EXT2_FILE:
4019 case EXT2_ET_UNIMPLEMENTED:
4033 fprintf(ff->err_fp, "FUSE2FS (%s): %s (inode #%d) at %s:%d.\n",
4034 fs->device_name ? fs->device_name : "???",
4035 error_message(err), ino, file, line);
4037 fprintf(ff->err_fp, "FUSE2FS (%s): %s at %s:%d.\n",
4038 fs->device_name ? fs->device_name : "???",
4039 error_message(err), file, line);
4042 /* Make a note in the error log */
4044 ext2fs_set_tstamp(fs->super, s_last_error_time, now.tv_sec);
4045 fs->super->s_last_error_ino = ino;
4046 fs->super->s_last_error_line = line;
4047 fs->super->s_last_error_block = err; /* Yeah... */
4048 strncpy((char *)fs->super->s_last_error_func, file,
4049 sizeof(fs->super->s_last_error_func));
4050 if (ext2fs_get_tstamp(fs->super, s_first_error_time) == 0) {
4051 ext2fs_set_tstamp(fs->super, s_first_error_time, now.tv_sec);
4052 fs->super->s_first_error_ino = ino;
4053 fs->super->s_first_error_line = line;
4054 fs->super->s_first_error_block = err;
4055 strncpy((char *)fs->super->s_first_error_func, file,
4056 sizeof(fs->super->s_first_error_func));
4059 fs->super->s_error_count++;
4060 ext2fs_mark_super_dirty(fs);
4062 if (ff->panic_on_error)