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
12 #define FUSE_USE_VERSION 29
19 # include <linux/fs.h>
20 # include <linux/falloc.h>
21 # include <linux/xattr.h>
22 # define FUSE_PLATFORM_OPTS ",big_writes"
23 # ifdef HAVE_SYS_ACL_H
24 # define TRANSLATE_LINUX_ACLS
27 # define FUSE_PLATFORM_OPTS ""
29 #ifdef TRANSLATE_LINUX_ACLS
32 #include <sys/ioctl.h>
36 #include "ext2fs/ext2fs.h"
37 #include "ext2fs/ext2_fs.h"
39 #include "../version.h"
44 #define _(a) (gettext(a))
46 #define N_(a) gettext_noop(a)
50 #define P_(singular, plural, n) (ngettext(singular, plural, n))
52 #define NLS_CAT_NAME "e2fsprogs"
55 #define LOCALEDIR "/usr/share/locale"
60 #define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural))
63 static ext2_filsys global_fs; /* Try not to use this directly */
68 # define dbg_printf(f, a...) do {printf("FUSE2FS-" f, ## a); \
72 # define dbg_printf(f, a...)
75 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
78 # define SUPPORT_I_FLAGS
83 #ifdef FALLOC_FL_KEEP_SIZE
84 # define FL_KEEP_SIZE_FLAG FALLOC_FL_KEEP_SIZE
85 # define SUPPORT_FALLOCATE
87 # define FL_KEEP_SIZE_FLAG (0)
90 #ifdef FALLOC_FL_PUNCH_HOLE
91 # define FL_PUNCH_HOLE_FLAG FALLOC_FL_PUNCH_HOLE
93 # define FL_PUNCH_HOLE_FLAG (0)
96 errcode_t ext2fs_run_ext3_journal(ext2_filsys *fs);
98 #ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jbd-debug */
99 int journal_enable_debug = -1;
102 /* ACL translation stuff */
103 #ifdef TRANSLATE_LINUX_ACLS
105 * Copied from acl_ea.h in libacl source; ACLs have to be sent to and from fuse
106 * in this format... at least on Linux.
108 #define ACL_EA_ACCESS "system.posix_acl_access"
109 #define ACL_EA_DEFAULT "system.posix_acl_default"
111 #define ACL_EA_VERSION 0x0002
121 #if __GNUC_PREREQ (4, 8)
122 #pragma GCC diagnostic push
123 #pragma GCC diagnostic ignored "-Wpedantic"
125 acl_ea_entry a_entries[0];
126 #if __GNUC_PREREQ (4, 8)
127 #pragma GCC diagnostic pop
131 static inline size_t acl_ea_size(int count)
133 return sizeof(acl_ea_header) + count * sizeof(acl_ea_entry);
136 static inline int acl_ea_count(size_t size)
138 if (size < sizeof(acl_ea_header))
140 size -= sizeof(acl_ea_header);
141 if (size % sizeof(acl_ea_entry))
143 return size / sizeof(acl_ea_entry);
147 * ext4 ACL structures, copied from fs/ext4/acl.h.
149 #define EXT4_ACL_VERSION 0x0001
160 } ext4_acl_entry_short;
166 static inline size_t ext4_acl_size(int count)
169 return sizeof(ext4_acl_header) +
170 count * sizeof(ext4_acl_entry_short);
172 return sizeof(ext4_acl_header) +
173 4 * sizeof(ext4_acl_entry_short) +
174 (count - 4) * sizeof(ext4_acl_entry);
178 static inline int ext4_acl_count(size_t size)
182 size -= sizeof(ext4_acl_header);
183 s = size - 4 * sizeof(ext4_acl_entry_short);
185 if (size % sizeof(ext4_acl_entry_short))
187 return size / sizeof(ext4_acl_entry_short);
189 if (s % sizeof(ext4_acl_entry))
191 return s / sizeof(ext4_acl_entry) + 4;
194 static errcode_t fuse_to_ext4_acl(acl_ea_header *facl, size_t facl_sz,
195 ext4_acl_header **eacl, size_t *eacl_sz)
205 facl_count = acl_ea_count(facl_sz);
206 h_sz = ext4_acl_size(facl_count);
207 if (facl_count < 0 || facl->a_version != ACL_EA_VERSION)
208 return EXT2_ET_INVALID_ARGUMENT;
210 err = ext2fs_get_mem(h_sz, &h);
214 h->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION);
215 hptr = (unsigned char *) (h + 1);
216 for (i = 0, a = facl->a_entries; i < facl_count; i++, a++) {
217 e = (ext4_acl_entry *) hptr;
218 e->e_tag = ext2fs_cpu_to_le16(a->e_tag);
219 e->e_perm = ext2fs_cpu_to_le16(a->e_perm);
224 e->e_id = ext2fs_cpu_to_le32(a->e_id);
225 hptr += sizeof(ext4_acl_entry);
231 hptr += sizeof(ext4_acl_entry_short);
234 err = EXT2_ET_INVALID_ARGUMENT;
247 static errcode_t ext4_to_fuse_acl(acl_ea_header **facl, size_t *facl_sz,
248 ext4_acl_header *eacl, size_t eacl_sz)
258 eacl_count = ext4_acl_count(eacl_sz);
259 f_sz = acl_ea_size(eacl_count);
260 if (eacl_count < 0 ||
261 eacl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION))
262 return EXT2_ET_INVALID_ARGUMENT;
264 err = ext2fs_get_mem(f_sz, &f);
268 f->a_version = ACL_EA_VERSION;
269 hptr = (unsigned char *) (eacl + 1);
270 for (i = 0, a = f->a_entries; i < eacl_count; i++, a++) {
271 e = (ext4_acl_entry *) hptr;
272 a->e_tag = ext2fs_le16_to_cpu(e->e_tag);
273 a->e_perm = ext2fs_le16_to_cpu(e->e_perm);
278 a->e_id = ext2fs_le32_to_cpu(e->e_id);
279 hptr += sizeof(ext4_acl_entry);
285 hptr += sizeof(ext4_acl_entry_short);
288 err = EXT2_ET_INVALID_ARGUMENT;
300 #endif /* TRANSLATE_LINUX_ACLS */
303 * ext2_file_t contains a struct inode, so we can't leave files open.
304 * Use this as a proxy instead.
306 #define FUSE2FS_FILE_MAGIC (0xEF53DEAFUL)
307 struct fuse2fs_file_handle {
313 /* Main program context */
314 #define FUSE2FS_MAGIC (0xEF53DEADUL)
326 int alloc_all_blocks;
328 unsigned int next_generation;
331 #define FUSE2FS_CHECK_MAGIC(fs, ptr, num) do {if ((ptr)->magic != (num)) \
332 return translate_error((fs), 0, EXT2_ET_MAGIC_EXT2_FILE); \
335 #define FUSE2FS_CHECK_CONTEXT(ptr) do {if ((ptr)->magic != FUSE2FS_MAGIC) \
336 return translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC); \
339 static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino,
340 const char *file, int line);
341 #define translate_error(fs, ino, err) __translate_error((fs), (err), (ino), \
353 #define EXT4_EPOCH_BITS 2
354 #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
355 #define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS)
358 * Extended fields will fit into an inode if the filesystem was formatted
359 * with large inodes (-I 256 or larger) and there are not currently any EAs
360 * consuming all of the available space. For new inodes we always reserve
361 * enough space for the kernel's known extended fields, but for inodes
362 * created with an old kernel this might not have been the case. None of
363 * the extended inode fields is critical for correct filesystem operation.
364 * This macro checks if a certain field fits in the inode. Note that
365 * inode-size = GOOD_OLD_INODE_SIZE + i_extra_isize
367 #define EXT4_FITS_IN_INODE(ext4_inode, field) \
368 ((offsetof(typeof(*ext4_inode), field) + \
369 sizeof((ext4_inode)->field)) \
370 <= ((size_t) EXT2_GOOD_OLD_INODE_SIZE + \
371 (ext4_inode)->i_extra_isize)) \
373 static inline __u32 ext4_encode_extra_time(const struct timespec *time)
375 __u32 extra = sizeof(time->tv_sec) > 4 ?
376 ((time->tv_sec - (__s32)time->tv_sec) >> 32) &
378 return extra | (time->tv_nsec << EXT4_EPOCH_BITS);
381 static inline void ext4_decode_extra_time(struct timespec *time, __u32 extra)
383 if (sizeof(time->tv_sec) > 4 && (extra & EXT4_EPOCH_MASK)) {
384 __u64 extra_bits = extra & EXT4_EPOCH_MASK;
386 * Prior to kernel 3.14?, we had a broken decode function,
387 * wherein we effectively did this:
388 * if (extra_bits == 3)
391 time->tv_sec += extra_bits << 32;
393 time->tv_nsec = ((extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
396 #define EXT4_INODE_SET_XTIME(xtime, timespec, raw_inode) \
398 (raw_inode)->xtime = (timespec)->tv_sec; \
399 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
400 (raw_inode)->xtime ## _extra = \
401 ext4_encode_extra_time(timespec); \
404 #define EXT4_EINODE_SET_XTIME(xtime, timespec, raw_inode) \
406 if (EXT4_FITS_IN_INODE(raw_inode, xtime)) \
407 (raw_inode)->xtime = (timespec)->tv_sec; \
408 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
409 (raw_inode)->xtime ## _extra = \
410 ext4_encode_extra_time(timespec); \
413 #define EXT4_INODE_GET_XTIME(xtime, timespec, raw_inode) \
415 (timespec)->tv_sec = (signed)((raw_inode)->xtime); \
416 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
417 ext4_decode_extra_time((timespec), \
418 (raw_inode)->xtime ## _extra); \
420 (timespec)->tv_nsec = 0; \
423 #define EXT4_EINODE_GET_XTIME(xtime, timespec, raw_inode) \
425 if (EXT4_FITS_IN_INODE(raw_inode, xtime)) \
426 (timespec)->tv_sec = \
427 (signed)((raw_inode)->xtime); \
428 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
429 ext4_decode_extra_time((timespec), \
430 raw_inode->xtime ## _extra); \
432 (timespec)->tv_nsec = 0; \
435 static void get_now(struct timespec *now)
437 #ifdef CLOCK_REALTIME
438 if (!clock_gettime(CLOCK_REALTIME, now))
442 now->tv_sec = time(NULL);
446 static void increment_version(struct ext2_inode_large *inode)
450 ver = inode->osd1.linux1.l_i_version;
451 if (EXT4_FITS_IN_INODE(inode, i_version_hi))
452 ver |= (__u64)inode->i_version_hi << 32;
454 inode->osd1.linux1.l_i_version = ver;
455 if (EXT4_FITS_IN_INODE(inode, i_version_hi))
456 inode->i_version_hi = ver >> 32;
459 static void init_times(struct ext2_inode_large *inode)
464 EXT4_INODE_SET_XTIME(i_atime, &now, inode);
465 EXT4_INODE_SET_XTIME(i_ctime, &now, inode);
466 EXT4_INODE_SET_XTIME(i_mtime, &now, inode);
467 EXT4_EINODE_SET_XTIME(i_crtime, &now, inode);
468 increment_version(inode);
471 static int update_ctime(ext2_filsys fs, ext2_ino_t ino,
472 struct ext2_inode_large *pinode)
476 struct ext2_inode_large inode;
480 /* If user already has a inode buffer, just update that */
482 increment_version(pinode);
483 EXT4_INODE_SET_XTIME(i_ctime, &now, pinode);
487 /* Otherwise we have to read-modify-write the inode */
488 memset(&inode, 0, sizeof(inode));
489 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
492 return translate_error(fs, ino, err);
494 increment_version(&inode);
495 EXT4_INODE_SET_XTIME(i_ctime, &now, &inode);
497 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
500 return translate_error(fs, ino, err);
505 static int update_atime(ext2_filsys fs, ext2_ino_t ino)
508 struct ext2_inode_large inode, *pinode;
509 struct timespec atime, mtime, now;
511 if (!(fs->flags & EXT2_FLAG_RW))
513 memset(&inode, 0, sizeof(inode));
514 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
517 return translate_error(fs, ino, err);
520 EXT4_INODE_GET_XTIME(i_atime, &atime, pinode);
521 EXT4_INODE_GET_XTIME(i_mtime, &mtime, pinode);
524 * If atime is newer than mtime and atime hasn't been updated in thirty
525 * seconds, skip the atime update. Same idea as Linux "relatime".
527 if (atime.tv_sec >= mtime.tv_sec && atime.tv_sec >= now.tv_sec - 30)
529 EXT4_INODE_SET_XTIME(i_atime, &now, &inode);
531 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
534 return translate_error(fs, ino, err);
539 static int update_mtime(ext2_filsys fs, ext2_ino_t ino,
540 struct ext2_inode_large *pinode)
543 struct ext2_inode_large inode;
548 EXT4_INODE_SET_XTIME(i_mtime, &now, pinode);
549 EXT4_INODE_SET_XTIME(i_ctime, &now, pinode);
550 increment_version(pinode);
554 memset(&inode, 0, sizeof(inode));
555 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
558 return translate_error(fs, ino, err);
561 EXT4_INODE_SET_XTIME(i_mtime, &now, &inode);
562 EXT4_INODE_SET_XTIME(i_ctime, &now, &inode);
563 increment_version(&inode);
565 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
568 return translate_error(fs, ino, err);
573 static int ext2_file_type(unsigned int mode)
575 if (LINUX_S_ISREG(mode))
576 return EXT2_FT_REG_FILE;
578 if (LINUX_S_ISDIR(mode))
581 if (LINUX_S_ISCHR(mode))
582 return EXT2_FT_CHRDEV;
584 if (LINUX_S_ISBLK(mode))
585 return EXT2_FT_BLKDEV;
587 if (LINUX_S_ISLNK(mode))
588 return EXT2_FT_SYMLINK;
590 if (LINUX_S_ISFIFO(mode))
593 if (LINUX_S_ISSOCK(mode))
599 static int fs_can_allocate(struct fuse2fs *ff, blk64_t num)
601 ext2_filsys fs = ff->fs;
604 dbg_printf("%s: Asking for %llu; alloc_all=%d total=%llu free=%llu "
605 "rsvd=%llu\n", __func__, num, ff->alloc_all_blocks,
606 ext2fs_blocks_count(fs->super),
607 ext2fs_free_blocks_count(fs->super),
608 ext2fs_r_blocks_count(fs->super));
609 if (num > ext2fs_blocks_count(fs->super))
612 if (ff->alloc_all_blocks)
616 * Different meaning for r_blocks -- libext2fs has bugs where the FS
617 * can get corrupted if it totally runs out of blocks. Avoid this
618 * by refusing to allocate any of the reserve blocks to anybody.
620 reserved = ext2fs_r_blocks_count(fs->super);
622 reserved = ext2fs_blocks_count(fs->super) / 10;
623 return ext2fs_free_blocks_count(fs->super) > reserved + num;
626 static int fs_writeable(ext2_filsys fs)
628 return (fs->flags & EXT2_FLAG_RW) && (fs->super->s_error_count == 0);
631 static int check_inum_access(ext2_filsys fs, ext2_ino_t ino, mode_t mask)
633 struct fuse_context *ctxt = fuse_get_context();
634 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
635 struct ext2_inode inode;
639 /* no writing to read-only or broken fs */
640 if ((mask & W_OK) && !fs_writeable(fs))
643 err = ext2fs_read_inode(fs, ino, &inode);
645 return translate_error(fs, ino, err);
646 perms = inode.i_mode & 0777;
648 dbg_printf("access ino=%d mask=e%s%s%s perms=0%o fuid=%d fgid=%d "
649 "uid=%d gid=%d\n", ino,
650 (mask & R_OK ? "r" : ""), (mask & W_OK ? "w" : ""),
651 (mask & X_OK ? "x" : ""), perms, inode_uid(inode),
652 inode_gid(inode), ctxt->uid, ctxt->gid);
654 /* existence check */
660 (inode.i_flags & EXT2_IMMUTABLE_FL))
663 /* Figure out what root's allowed to do */
664 if (ff->fakeroot || ctxt->uid == 0) {
665 /* Non-file access always ok */
666 if (!LINUX_S_ISREG(inode.i_mode))
669 /* R/W access to a file always ok */
673 /* X access to a file ok if a user/group/other can X */
677 /* Trying to execute a file that's not executable. BZZT! */
681 /* allow owner, if perms match */
682 if (inode_uid(inode) == ctxt->uid) {
683 if ((mask & (perms >> 6)) == mask)
688 /* allow group, if perms match */
689 if (inode_gid(inode) == ctxt->gid) {
690 if ((mask & (perms >> 3)) == mask)
695 /* otherwise check other */
696 if ((mask & perms) == mask)
701 static void op_destroy(void *p EXT2FS_ATTR((unused)))
703 struct fuse_context *ctxt = fuse_get_context();
704 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
708 if (ff->magic != FUSE2FS_MAGIC) {
709 translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC);
713 dbg_printf("%s: dev=%s\n", __func__, fs->device_name);
714 if (fs->flags & EXT2_FLAG_RW) {
715 fs->super->s_state |= EXT2_VALID_FS;
716 if (fs->super->s_error_count)
717 fs->super->s_state |= EXT2_ERROR_FS;
718 ext2fs_mark_super_dirty(fs);
719 err = ext2fs_set_gdt_csum(fs);
721 translate_error(fs, 0, err);
723 err = ext2fs_flush2(fs, 0);
725 translate_error(fs, 0, err);
729 static void *op_init(struct fuse_conn_info *conn)
731 struct fuse_context *ctxt = fuse_get_context();
732 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
736 if (ff->magic != FUSE2FS_MAGIC) {
737 translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC);
741 dbg_printf("%s: dev=%s\n", __func__, fs->device_name);
742 #ifdef FUSE_CAP_IOCTL_DIR
743 conn->want |= FUSE_CAP_IOCTL_DIR;
745 if (fs->flags & EXT2_FLAG_RW) {
746 fs->super->s_mnt_count++;
747 fs->super->s_mtime = time(NULL);
748 fs->super->s_state &= ~EXT2_VALID_FS;
749 ext2fs_mark_super_dirty(fs);
750 err = ext2fs_flush2(fs, 0);
752 translate_error(fs, 0, err);
757 static blkcnt_t blocks_from_inode(ext2_filsys fs,
758 struct ext2_inode_large *inode)
763 if (ext2fs_has_feature_huge_file(fs->super))
764 b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
766 if (!ext2fs_has_feature_huge_file(fs->super) ||
767 !(inode->i_flags & EXT4_HUGE_FILE_FL))
768 b *= fs->blocksize / 512;
769 b *= EXT2FS_CLUSTER_RATIO(fs);
774 static int stat_inode(ext2_filsys fs, ext2_ino_t ino, struct stat *statbuf)
776 struct ext2_inode_large inode;
782 memset(&inode, 0, sizeof(inode));
783 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
786 return translate_error(fs, ino, err);
788 memcpy(&fakedev, fs->super->s_uuid, sizeof(fakedev));
789 statbuf->st_dev = fakedev;
790 statbuf->st_ino = ino;
791 statbuf->st_mode = inode.i_mode;
792 statbuf->st_nlink = inode.i_links_count;
793 statbuf->st_uid = inode_uid(inode);
794 statbuf->st_gid = inode_gid(inode);
795 statbuf->st_size = EXT2_I_SIZE(&inode);
796 statbuf->st_blksize = fs->blocksize;
797 statbuf->st_blocks = blocks_from_inode(fs, &inode);
798 EXT4_INODE_GET_XTIME(i_atime, &tv, &inode);
799 statbuf->st_atime = tv.tv_sec;
800 EXT4_INODE_GET_XTIME(i_mtime, &tv, &inode);
801 statbuf->st_mtime = tv.tv_sec;
802 EXT4_INODE_GET_XTIME(i_ctime, &tv, &inode);
803 statbuf->st_ctime = tv.tv_sec;
804 if (LINUX_S_ISCHR(inode.i_mode) ||
805 LINUX_S_ISBLK(inode.i_mode)) {
806 if (inode.i_block[0])
807 statbuf->st_rdev = inode.i_block[0];
809 statbuf->st_rdev = inode.i_block[1];
815 static int op_getattr(const char *path, struct stat *statbuf)
817 struct fuse_context *ctxt = fuse_get_context();
818 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
824 FUSE2FS_CHECK_CONTEXT(ff);
826 dbg_printf("%s: path=%s\n", __func__, path);
827 pthread_mutex_lock(&ff->bfl);
828 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
830 ret = translate_error(fs, 0, err);
833 ret = stat_inode(fs, ino, statbuf);
835 pthread_mutex_unlock(&ff->bfl);
839 static int op_readlink(const char *path, char *buf, size_t len)
841 struct fuse_context *ctxt = fuse_get_context();
842 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
846 struct ext2_inode inode;
851 FUSE2FS_CHECK_CONTEXT(ff);
853 dbg_printf("%s: path=%s\n", __func__, path);
854 pthread_mutex_lock(&ff->bfl);
855 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
856 if (err || ino == 0) {
857 ret = translate_error(fs, 0, err);
861 err = ext2fs_read_inode(fs, ino, &inode);
863 ret = translate_error(fs, ino, err);
867 if (!LINUX_S_ISLNK(inode.i_mode)) {
873 if (inode.i_size < len)
875 if (ext2fs_is_fast_symlink(&inode))
876 memcpy(buf, (char *)inode.i_block, len);
878 /* big/inline symlink */
880 err = ext2fs_file_open(fs, ino, 0, &file);
882 ret = translate_error(fs, ino, err);
886 err = ext2fs_file_read(file, buf, len, &got);
887 if (err || got != len) {
888 ext2fs_file_close(file);
889 ret = translate_error(fs, ino, err);
894 err = ext2fs_file_close(file);
898 ret = translate_error(fs, ino, err);
904 if (fs_writeable(fs)) {
905 ret = update_atime(fs, ino);
911 pthread_mutex_unlock(&ff->bfl);
915 static int op_mknod(const char *path, mode_t mode, dev_t dev)
917 struct fuse_context *ctxt = fuse_get_context();
918 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
920 ext2_ino_t parent, child;
925 struct ext2_inode_large inode;
928 FUSE2FS_CHECK_CONTEXT(ff);
930 dbg_printf("%s: path=%s mode=0%o dev=0x%x\n", __func__, path, mode,
932 temp_path = strdup(path);
937 node_name = strrchr(temp_path, '/');
946 pthread_mutex_lock(&ff->bfl);
947 if (!fs_can_allocate(ff, 2)) {
952 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
955 ret = translate_error(fs, 0, err);
959 ret = check_inum_access(fs, parent, W_OK);
965 if (LINUX_S_ISCHR(mode))
966 filetype = EXT2_FT_CHRDEV;
967 else if (LINUX_S_ISBLK(mode))
968 filetype = EXT2_FT_BLKDEV;
969 else if (LINUX_S_ISFIFO(mode))
970 filetype = EXT2_FT_FIFO;
971 else if (LINUX_S_ISSOCK(mode))
972 filetype = EXT2_FT_SOCK;
978 err = ext2fs_new_inode(fs, parent, mode, 0, &child);
980 ret = translate_error(fs, 0, err);
984 dbg_printf("%s: create ino=%d/name=%s in dir=%d\n", __func__, child,
986 err = ext2fs_link(fs, parent, node_name, child, filetype);
987 if (err == EXT2_ET_DIR_NO_SPACE) {
988 err = ext2fs_expand_dir(fs, parent);
990 ret = translate_error(fs, parent, err);
994 err = ext2fs_link(fs, parent, node_name, child,
998 ret = translate_error(fs, parent, err);
1002 ret = update_mtime(fs, parent, NULL);
1006 memset(&inode, 0, sizeof(inode));
1007 inode.i_mode = mode;
1010 inode.i_block[1] = dev;
1012 inode.i_block[0] = dev;
1013 inode.i_links_count = 1;
1014 inode.i_extra_isize = sizeof(struct ext2_inode_large) -
1015 EXT2_GOOD_OLD_INODE_SIZE;
1016 inode.i_uid = ctxt->uid;
1017 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
1018 inode.i_gid = ctxt->gid;
1019 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
1021 err = ext2fs_write_new_inode(fs, child, (struct ext2_inode *)&inode);
1023 ret = translate_error(fs, child, err);
1027 inode.i_generation = ff->next_generation++;
1029 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
1032 ret = translate_error(fs, child, err);
1036 ext2fs_inode_alloc_stats2(fs, child, 1, 0);
1039 pthread_mutex_unlock(&ff->bfl);
1045 static int op_mkdir(const char *path, mode_t mode)
1047 struct fuse_context *ctxt = fuse_get_context();
1048 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1050 ext2_ino_t parent, child;
1054 struct ext2_inode_large inode;
1060 FUSE2FS_CHECK_CONTEXT(ff);
1062 dbg_printf("%s: path=%s mode=0%o\n", __func__, path, mode);
1063 temp_path = strdup(path);
1068 node_name = strrchr(temp_path, '/');
1077 pthread_mutex_lock(&ff->bfl);
1078 if (!fs_can_allocate(ff, 1)) {
1083 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1086 ret = translate_error(fs, 0, err);
1090 ret = check_inum_access(fs, parent, W_OK);
1094 /* Is the parent dir sgid? */
1095 err = ext2fs_read_inode_full(fs, parent, (struct ext2_inode *)&inode,
1098 ret = translate_error(fs, parent, err);
1101 parent_sgid = inode.i_mode & S_ISGID;
1105 err = ext2fs_mkdir(fs, parent, 0, node_name);
1106 if (err == EXT2_ET_DIR_NO_SPACE) {
1107 err = ext2fs_expand_dir(fs, parent);
1109 ret = translate_error(fs, parent, err);
1113 err = ext2fs_mkdir(fs, parent, 0, node_name);
1116 ret = translate_error(fs, parent, err);
1120 ret = update_mtime(fs, parent, NULL);
1124 /* Still have to update the uid/gid of the dir */
1125 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1128 ret = translate_error(fs, 0, err);
1131 dbg_printf("%s: created ino=%d/path=%s in dir=%d\n", __func__, child,
1134 memset(&inode, 0, sizeof(inode));
1135 err = ext2fs_read_inode_full(fs, child, (struct ext2_inode *)&inode,
1138 ret = translate_error(fs, child, err);
1142 inode.i_uid = ctxt->uid;
1143 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
1144 inode.i_gid = ctxt->gid;
1145 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
1146 inode.i_mode = LINUX_S_IFDIR | (mode & ~(S_ISUID | fs->umask)) |
1148 inode.i_generation = ff->next_generation++;
1150 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
1153 ret = translate_error(fs, child, err);
1157 /* Rewrite the directory block checksum, having set i_generation */
1158 if ((inode.i_flags & EXT4_INLINE_DATA_FL) ||
1159 !ext2fs_has_feature_metadata_csum(fs->super))
1161 err = ext2fs_new_dir_block(fs, child, parent, &block);
1163 ret = translate_error(fs, child, err);
1166 err = ext2fs_bmap2(fs, child, (struct ext2_inode *)&inode, NULL, 0, 0,
1169 ret = translate_error(fs, child, err);
1172 err = ext2fs_write_dir_block4(fs, blk, block, 0, child);
1174 ret = translate_error(fs, child, err);
1179 ext2fs_free_mem(&block);
1181 pthread_mutex_unlock(&ff->bfl);
1187 static int unlink_file_by_name(ext2_filsys fs, const char *path)
1191 char *filename = strdup(path);
1195 base_name = strrchr(filename, '/');
1197 *base_name++ = '\0';
1198 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, filename,
1202 return translate_error(fs, 0, err);
1205 dir = EXT2_ROOT_INO;
1206 base_name = filename;
1209 ret = check_inum_access(fs, dir, W_OK);
1215 dbg_printf("%s: unlinking name=%s from dir=%d\n", __func__,
1217 err = ext2fs_unlink(fs, dir, base_name, 0, 0);
1220 return translate_error(fs, dir, err);
1222 return update_mtime(fs, dir, NULL);
1225 static int remove_inode(struct fuse2fs *ff, ext2_ino_t ino)
1227 ext2_filsys fs = ff->fs;
1229 struct ext2_inode_large inode;
1232 memset(&inode, 0, sizeof(inode));
1233 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1236 ret = translate_error(fs, ino, err);
1239 dbg_printf("%s: put ino=%d links=%d\n", __func__, ino,
1240 inode.i_links_count);
1242 switch (inode.i_links_count) {
1244 return 0; /* XXX: already done? */
1246 inode.i_links_count--;
1247 inode.i_dtime = fs->now ? fs->now : time(0);
1250 inode.i_links_count--;
1253 ret = update_ctime(fs, ino, &inode);
1257 if (inode.i_links_count)
1260 /* Nobody holds this file; free its blocks! */
1261 err = ext2fs_free_ext_attr(fs, ino, &inode);
1265 if (ext2fs_inode_has_valid_blocks2(fs, (struct ext2_inode *)&inode)) {
1266 err = ext2fs_punch(fs, ino, (struct ext2_inode *)&inode, NULL,
1269 ret = translate_error(fs, ino, err);
1274 ext2fs_inode_alloc_stats2(fs, ino, -1,
1275 LINUX_S_ISDIR(inode.i_mode));
1278 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
1281 ret = translate_error(fs, ino, err);
1288 static int __op_unlink(struct fuse2fs *ff, const char *path)
1290 ext2_filsys fs = ff->fs;
1295 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1297 ret = translate_error(fs, 0, err);
1301 ret = unlink_file_by_name(fs, path);
1305 ret = remove_inode(ff, ino);
1312 static int op_unlink(const char *path)
1314 struct fuse_context *ctxt = fuse_get_context();
1315 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1318 FUSE2FS_CHECK_CONTEXT(ff);
1319 pthread_mutex_lock(&ff->bfl);
1320 ret = __op_unlink(ff, path);
1321 pthread_mutex_unlock(&ff->bfl);
1330 static int rmdir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
1331 int entry EXT2FS_ATTR((unused)),
1332 struct ext2_dir_entry *dirent,
1333 int offset EXT2FS_ATTR((unused)),
1334 int blocksize EXT2FS_ATTR((unused)),
1335 char *buf EXT2FS_ATTR((unused)),
1338 struct rd_struct *rds = (struct rd_struct *) private;
1340 if (dirent->inode == 0)
1342 if (((dirent->name_len & 0xFF) == 1) && (dirent->name[0] == '.'))
1344 if (((dirent->name_len & 0xFF) == 2) && (dirent->name[0] == '.') &&
1345 (dirent->name[1] == '.')) {
1346 rds->parent = dirent->inode;
1353 static int __op_rmdir(struct fuse2fs *ff, const char *path)
1355 ext2_filsys fs = ff->fs;
1358 struct ext2_inode_large inode;
1359 struct rd_struct rds;
1362 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &child);
1364 ret = translate_error(fs, 0, err);
1367 dbg_printf("%s: rmdir path=%s ino=%d\n", __func__, path, child);
1372 err = ext2fs_dir_iterate2(fs, child, 0, 0, rmdir_proc, &rds);
1374 ret = translate_error(fs, child, err);
1378 if (rds.empty == 0) {
1383 ret = unlink_file_by_name(fs, path);
1386 /* Directories have to be "removed" twice. */
1387 ret = remove_inode(ff, child);
1390 ret = remove_inode(ff, child);
1395 dbg_printf("%s: decr dir=%d link count\n", __func__,
1397 err = ext2fs_read_inode_full(fs, rds.parent,
1398 (struct ext2_inode *)&inode,
1401 ret = translate_error(fs, rds.parent, err);
1404 if (inode.i_links_count > 1)
1405 inode.i_links_count--;
1406 ret = update_mtime(fs, rds.parent, &inode);
1409 err = ext2fs_write_inode_full(fs, rds.parent,
1410 (struct ext2_inode *)&inode,
1413 ret = translate_error(fs, rds.parent, err);
1422 static int op_rmdir(const char *path)
1424 struct fuse_context *ctxt = fuse_get_context();
1425 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1428 FUSE2FS_CHECK_CONTEXT(ff);
1429 pthread_mutex_lock(&ff->bfl);
1430 ret = __op_rmdir(ff, path);
1431 pthread_mutex_unlock(&ff->bfl);
1435 static int op_symlink(const char *src, const char *dest)
1437 struct fuse_context *ctxt = fuse_get_context();
1438 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1440 ext2_ino_t parent, child;
1444 struct ext2_inode_large inode;
1447 FUSE2FS_CHECK_CONTEXT(ff);
1449 dbg_printf("%s: symlink %s to %s\n", __func__, src, dest);
1450 temp_path = strdup(dest);
1455 node_name = strrchr(temp_path, '/');
1464 pthread_mutex_lock(&ff->bfl);
1465 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1469 ret = translate_error(fs, 0, err);
1473 ret = check_inum_access(fs, parent, W_OK);
1478 /* Create symlink */
1479 err = ext2fs_symlink(fs, parent, 0, node_name, src);
1480 if (err == EXT2_ET_DIR_NO_SPACE) {
1481 err = ext2fs_expand_dir(fs, parent);
1483 ret = translate_error(fs, parent, err);
1487 err = ext2fs_symlink(fs, parent, 0, node_name, src);
1490 ret = translate_error(fs, parent, err);
1494 /* Update parent dir's mtime */
1495 ret = update_mtime(fs, parent, NULL);
1499 /* Still have to update the uid/gid of the symlink */
1500 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1503 ret = translate_error(fs, 0, err);
1506 dbg_printf("%s: symlinking ino=%d/name=%s to dir=%d\n", __func__,
1507 child, node_name, parent);
1509 memset(&inode, 0, sizeof(inode));
1510 err = ext2fs_read_inode_full(fs, child, (struct ext2_inode *)&inode,
1513 ret = translate_error(fs, child, err);
1517 inode.i_uid = ctxt->uid;
1518 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
1519 inode.i_gid = ctxt->gid;
1520 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
1521 inode.i_generation = ff->next_generation++;
1523 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
1526 ret = translate_error(fs, child, err);
1530 pthread_mutex_unlock(&ff->bfl);
1536 struct update_dotdot {
1537 ext2_ino_t new_dotdot;
1540 static int update_dotdot_helper(ext2_ino_t dir EXT2FS_ATTR((unused)),
1541 int entry EXT2FS_ATTR((unused)),
1542 struct ext2_dir_entry *dirent,
1543 int offset EXT2FS_ATTR((unused)),
1544 int blocksize EXT2FS_ATTR((unused)),
1545 char *buf EXT2FS_ATTR((unused)),
1548 struct update_dotdot *ud = priv_data;
1550 if (ext2fs_dirent_name_len(dirent) == 2 &&
1551 dirent->name[0] == '.' && dirent->name[1] == '.') {
1552 dirent->inode = ud->new_dotdot;
1553 return DIRENT_CHANGED | DIRENT_ABORT;
1559 static int op_rename(const char *from, const char *to)
1561 struct fuse_context *ctxt = fuse_get_context();
1562 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1565 ext2_ino_t from_ino, to_ino, to_dir_ino, from_dir_ino;
1566 char *temp_to = NULL, *temp_from = NULL;
1568 struct ext2_inode inode;
1569 struct update_dotdot ud;
1572 FUSE2FS_CHECK_CONTEXT(ff);
1574 dbg_printf("%s: renaming %s to %s\n", __func__, from, to);
1575 pthread_mutex_lock(&ff->bfl);
1576 if (!fs_can_allocate(ff, 5)) {
1581 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, from, &from_ino);
1582 if (err || from_ino == 0) {
1583 ret = translate_error(fs, 0, err);
1587 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, to, &to_ino);
1588 if (err && err != EXT2_ET_FILE_NOT_FOUND) {
1589 ret = translate_error(fs, 0, err);
1593 if (err == EXT2_ET_FILE_NOT_FOUND)
1596 /* Already the same file? */
1597 if (to_ino != 0 && to_ino == from_ino) {
1602 temp_to = strdup(to);
1608 temp_from = strdup(from);
1614 /* Find parent dir of the source and check write access */
1615 cp = strrchr(temp_from, '/');
1623 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_from,
1627 ret = translate_error(fs, 0, err);
1630 if (from_dir_ino == 0) {
1635 ret = check_inum_access(fs, from_dir_ino, W_OK);
1639 /* Find parent dir of the destination and check write access */
1640 cp = strrchr(temp_to, '/');
1648 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_to,
1652 ret = translate_error(fs, 0, err);
1655 if (to_dir_ino == 0) {
1660 ret = check_inum_access(fs, to_dir_ino, W_OK);
1664 /* If the target exists, unlink it first */
1666 err = ext2fs_read_inode(fs, to_ino, &inode);
1668 ret = translate_error(fs, to_ino, err);
1672 dbg_printf("%s: unlinking %s ino=%d\n", __func__,
1673 LINUX_S_ISDIR(inode.i_mode) ? "dir" : "file",
1675 if (LINUX_S_ISDIR(inode.i_mode))
1676 ret = __op_rmdir(ff, to);
1678 ret = __op_unlink(ff, to);
1683 /* Get ready to do the move */
1684 err = ext2fs_read_inode(fs, from_ino, &inode);
1686 ret = translate_error(fs, from_ino, err);
1690 /* Link in the new file */
1691 dbg_printf("%s: linking ino=%d/path=%s to dir=%d\n", __func__,
1692 from_ino, cp + 1, to_dir_ino);
1693 err = ext2fs_link(fs, to_dir_ino, cp + 1, from_ino,
1694 ext2_file_type(inode.i_mode));
1695 if (err == EXT2_ET_DIR_NO_SPACE) {
1696 err = ext2fs_expand_dir(fs, to_dir_ino);
1698 ret = translate_error(fs, to_dir_ino, err);
1702 err = ext2fs_link(fs, to_dir_ino, cp + 1, from_ino,
1703 ext2_file_type(inode.i_mode));
1706 ret = translate_error(fs, to_dir_ino, err);
1710 /* Update '..' pointer if dir */
1711 err = ext2fs_read_inode(fs, from_ino, &inode);
1713 ret = translate_error(fs, from_ino, err);
1717 if (LINUX_S_ISDIR(inode.i_mode)) {
1718 ud.new_dotdot = to_dir_ino;
1719 dbg_printf("%s: updating .. entry for dir=%d\n", __func__,
1721 err = ext2fs_dir_iterate2(fs, from_ino, 0, NULL,
1722 update_dotdot_helper, &ud);
1724 ret = translate_error(fs, from_ino, err);
1728 /* Decrease from_dir_ino's links_count */
1729 dbg_printf("%s: moving linkcount from dir=%d to dir=%d\n",
1730 __func__, from_dir_ino, to_dir_ino);
1731 err = ext2fs_read_inode(fs, from_dir_ino, &inode);
1733 ret = translate_error(fs, from_dir_ino, err);
1736 inode.i_links_count--;
1737 err = ext2fs_write_inode(fs, from_dir_ino, &inode);
1739 ret = translate_error(fs, from_dir_ino, err);
1743 /* Increase to_dir_ino's links_count */
1744 err = ext2fs_read_inode(fs, to_dir_ino, &inode);
1746 ret = translate_error(fs, to_dir_ino, err);
1749 inode.i_links_count++;
1750 err = ext2fs_write_inode(fs, to_dir_ino, &inode);
1752 ret = translate_error(fs, to_dir_ino, err);
1757 /* Update timestamps */
1758 ret = update_ctime(fs, from_ino, NULL);
1762 ret = update_mtime(fs, to_dir_ino, NULL);
1766 /* Remove the old file */
1767 ret = unlink_file_by_name(fs, from);
1771 /* Flush the whole mess out */
1772 err = ext2fs_flush2(fs, 0);
1774 ret = translate_error(fs, 0, err);
1780 pthread_mutex_unlock(&ff->bfl);
1784 static int op_link(const char *src, const char *dest)
1786 struct fuse_context *ctxt = fuse_get_context();
1787 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1792 ext2_ino_t parent, ino;
1793 struct ext2_inode_large inode;
1796 FUSE2FS_CHECK_CONTEXT(ff);
1798 dbg_printf("%s: src=%s dest=%s\n", __func__, src, dest);
1799 temp_path = strdup(dest);
1804 node_name = strrchr(temp_path, '/');
1813 pthread_mutex_lock(&ff->bfl);
1814 if (!fs_can_allocate(ff, 2)) {
1819 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1827 ret = check_inum_access(fs, parent, W_OK);
1832 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, src, &ino);
1833 if (err || ino == 0) {
1834 ret = translate_error(fs, 0, err);
1838 memset(&inode, 0, sizeof(inode));
1839 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1842 ret = translate_error(fs, ino, err);
1846 inode.i_links_count++;
1847 ret = update_ctime(fs, ino, &inode);
1851 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
1854 ret = translate_error(fs, ino, err);
1858 dbg_printf("%s: linking ino=%d/name=%s to dir=%d\n", __func__, ino,
1860 err = ext2fs_link(fs, parent, node_name, ino,
1861 ext2_file_type(inode.i_mode));
1862 if (err == EXT2_ET_DIR_NO_SPACE) {
1863 err = ext2fs_expand_dir(fs, parent);
1865 ret = translate_error(fs, parent, err);
1869 err = ext2fs_link(fs, parent, node_name, ino,
1870 ext2_file_type(inode.i_mode));
1873 ret = translate_error(fs, parent, err);
1877 ret = update_mtime(fs, parent, NULL);
1882 pthread_mutex_unlock(&ff->bfl);
1888 static int op_chmod(const char *path, mode_t mode)
1890 struct fuse_context *ctxt = fuse_get_context();
1891 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1895 struct ext2_inode_large inode;
1898 FUSE2FS_CHECK_CONTEXT(ff);
1900 pthread_mutex_lock(&ff->bfl);
1901 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1903 ret = translate_error(fs, 0, err);
1906 dbg_printf("%s: path=%s mode=0%o ino=%d\n", __func__, path, mode, ino);
1908 memset(&inode, 0, sizeof(inode));
1909 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1912 ret = translate_error(fs, ino, err);
1916 if (!ff->fakeroot && ctxt->uid != 0 && ctxt->uid != inode_uid(inode)) {
1922 * XXX: We should really check that the inode gid is not in /any/
1923 * of the user's groups, but FUSE only tells us about the primary
1926 if (!ff->fakeroot && ctxt->uid != 0 && ctxt->gid != inode_gid(inode))
1929 inode.i_mode &= ~0xFFF;
1930 inode.i_mode |= mode & 0xFFF;
1931 ret = update_ctime(fs, ino, &inode);
1935 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
1938 ret = translate_error(fs, ino, err);
1943 pthread_mutex_unlock(&ff->bfl);
1947 static int op_chown(const char *path, uid_t owner, gid_t group)
1949 struct fuse_context *ctxt = fuse_get_context();
1950 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1954 struct ext2_inode_large inode;
1957 FUSE2FS_CHECK_CONTEXT(ff);
1959 pthread_mutex_lock(&ff->bfl);
1960 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1962 ret = translate_error(fs, 0, err);
1965 dbg_printf("%s: path=%s owner=%d group=%d ino=%d\n", __func__,
1966 path, owner, group, ino);
1968 memset(&inode, 0, sizeof(inode));
1969 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1972 ret = translate_error(fs, ino, err);
1976 /* FUSE seems to feed us ~0 to mean "don't change" */
1977 if (owner != (uid_t) ~0) {
1978 /* Only root gets to change UID. */
1979 if (!ff->fakeroot && ctxt->uid != 0 &&
1980 !(inode_uid(inode) == ctxt->uid && owner == ctxt->uid)) {
1984 inode.i_uid = owner;
1985 ext2fs_set_i_uid_high(inode, owner >> 16);
1988 if (group != (gid_t) ~0) {
1989 /* Only root or the owner get to change GID. */
1990 if (!ff->fakeroot && ctxt->uid != 0 &&
1991 inode_uid(inode) != ctxt->uid) {
1996 /* XXX: We /should/ check group membership but FUSE */
1997 inode.i_gid = group;
1998 ext2fs_set_i_gid_high(inode, group >> 16);
2001 ret = update_ctime(fs, ino, &inode);
2005 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
2008 ret = translate_error(fs, ino, err);
2013 pthread_mutex_unlock(&ff->bfl);
2017 static int op_truncate(const char *path, off_t len)
2019 struct fuse_context *ctxt = fuse_get_context();
2020 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2027 FUSE2FS_CHECK_CONTEXT(ff);
2029 pthread_mutex_lock(&ff->bfl);
2030 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2031 if (err || ino == 0) {
2032 ret = translate_error(fs, 0, err);
2035 dbg_printf("%s: ino=%d len=%jd\n", __func__, ino, len);
2037 ret = check_inum_access(fs, ino, W_OK);
2041 err = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &file);
2043 ret = translate_error(fs, ino, err);
2047 err = ext2fs_file_set_size2(file, len);
2049 ret = translate_error(fs, ino, err);
2054 err = ext2fs_file_close(file);
2058 ret = translate_error(fs, ino, err);
2062 ret = update_mtime(fs, ino, NULL);
2065 pthread_mutex_unlock(&ff->bfl);
2070 static void detect_linux_executable_open(int kernel_flags, int *access_check,
2071 int *e2fs_open_flags)
2074 * On Linux, execve will bleed __FMODE_EXEC into the file mode flags,
2075 * and FUSE is more than happy to let that slip through.
2077 if (kernel_flags & 0x20) {
2078 *access_check = X_OK;
2079 *e2fs_open_flags &= ~EXT2_FILE_WRITE;
2083 static void detect_linux_executable_open(int kernel_flags, int *access_check,
2084 int *e2fs_open_flags)
2088 #endif /* __linux__ */
2090 static int __op_open(struct fuse2fs *ff, const char *path,
2091 struct fuse_file_info *fp)
2093 ext2_filsys fs = ff->fs;
2095 struct fuse2fs_file_handle *file;
2096 int check = 0, ret = 0;
2098 dbg_printf("%s: path=%s\n", __func__, path);
2099 err = ext2fs_get_mem(sizeof(*file), &file);
2101 return translate_error(fs, 0, err);
2102 file->magic = FUSE2FS_FILE_MAGIC;
2104 file->open_flags = 0;
2105 switch (fp->flags & O_ACCMODE) {
2111 file->open_flags |= EXT2_FILE_WRITE;
2114 check = R_OK | W_OK;
2115 file->open_flags |= EXT2_FILE_WRITE;
2119 detect_linux_executable_open(fp->flags, &check, &file->open_flags);
2121 if (fp->flags & O_CREAT)
2122 file->open_flags |= EXT2_FILE_CREATE;
2124 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &file->ino);
2125 if (err || file->ino == 0) {
2126 ret = translate_error(fs, 0, err);
2129 dbg_printf("%s: ino=%d\n", __func__, file->ino);
2131 ret = check_inum_access(fs, file->ino, check);
2134 * In a regular (Linux) fs driver, the kernel will open
2135 * binaries for reading if the user has --x privileges (i.e.
2136 * execute without read). Since the kernel doesn't have any
2137 * way to tell us if it's opening a file via execve, we'll
2138 * just assume that allowing access is ok if asking for ro mode
2139 * fails but asking for x mode succeeds. Of course we can
2140 * also employ undocumented hacks (see above).
2142 if (check == R_OK) {
2143 ret = check_inum_access(fs, file->ino, X_OK);
2149 fp->fh = (uintptr_t)file;
2153 ext2fs_free_mem(&file);
2157 static int op_open(const char *path, struct fuse_file_info *fp)
2159 struct fuse_context *ctxt = fuse_get_context();
2160 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2163 FUSE2FS_CHECK_CONTEXT(ff);
2164 pthread_mutex_lock(&ff->bfl);
2165 ret = __op_open(ff, path, fp);
2166 pthread_mutex_unlock(&ff->bfl);
2170 static int op_read(const char *path EXT2FS_ATTR((unused)), char *buf,
2171 size_t len, off_t offset,
2172 struct fuse_file_info *fp)
2174 struct fuse_context *ctxt = fuse_get_context();
2175 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2176 struct fuse2fs_file_handle *fh =
2177 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2181 unsigned int got = 0;
2184 FUSE2FS_CHECK_CONTEXT(ff);
2186 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2187 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino, offset,
2189 pthread_mutex_lock(&ff->bfl);
2190 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
2192 ret = translate_error(fs, fh->ino, err);
2196 err = ext2fs_file_llseek(efp, offset, SEEK_SET, NULL);
2198 ret = translate_error(fs, fh->ino, err);
2202 err = ext2fs_file_read(efp, buf, len, &got);
2204 ret = translate_error(fs, fh->ino, err);
2209 err = ext2fs_file_close(efp);
2213 ret = translate_error(fs, fh->ino, err);
2217 if (fs_writeable(fs)) {
2218 ret = update_atime(fs, fh->ino);
2223 pthread_mutex_unlock(&ff->bfl);
2224 return got ? (int) got : ret;
2227 static int op_write(const char *path EXT2FS_ATTR((unused)),
2228 const char *buf, size_t len, off_t offset,
2229 struct fuse_file_info *fp)
2231 struct fuse_context *ctxt = fuse_get_context();
2232 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2233 struct fuse2fs_file_handle *fh =
2234 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2238 unsigned int got = 0;
2241 FUSE2FS_CHECK_CONTEXT(ff);
2243 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2244 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino, offset,
2246 pthread_mutex_lock(&ff->bfl);
2247 if (!fs_writeable(fs)) {
2252 if (!fs_can_allocate(ff, len / fs->blocksize)) {
2257 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
2259 ret = translate_error(fs, fh->ino, err);
2263 err = ext2fs_file_llseek(efp, offset, SEEK_SET, NULL);
2265 ret = translate_error(fs, fh->ino, err);
2269 err = ext2fs_file_write(efp, buf, len, &got);
2271 ret = translate_error(fs, fh->ino, err);
2275 err = ext2fs_file_flush(efp);
2278 ret = translate_error(fs, fh->ino, err);
2283 err = ext2fs_file_close(efp);
2287 ret = translate_error(fs, fh->ino, err);
2291 ret = update_mtime(fs, fh->ino, NULL);
2296 pthread_mutex_unlock(&ff->bfl);
2297 return got ? (int) got : ret;
2300 static int op_release(const char *path EXT2FS_ATTR((unused)),
2301 struct fuse_file_info *fp)
2303 struct fuse_context *ctxt = fuse_get_context();
2304 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2305 struct fuse2fs_file_handle *fh =
2306 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2311 FUSE2FS_CHECK_CONTEXT(ff);
2313 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2314 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
2315 pthread_mutex_lock(&ff->bfl);
2316 if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) {
2317 err = ext2fs_flush2(fs, EXT2_FLAG_FLUSH_NO_SYNC);
2319 ret = translate_error(fs, fh->ino, err);
2322 pthread_mutex_unlock(&ff->bfl);
2324 ext2fs_free_mem(&fh);
2329 static int op_fsync(const char *path EXT2FS_ATTR((unused)),
2330 int datasync EXT2FS_ATTR((unused)),
2331 struct fuse_file_info *fp)
2333 struct fuse_context *ctxt = fuse_get_context();
2334 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2335 struct fuse2fs_file_handle *fh =
2336 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2341 FUSE2FS_CHECK_CONTEXT(ff);
2343 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2344 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
2345 /* For now, flush everything, even if it's slow */
2346 pthread_mutex_lock(&ff->bfl);
2347 if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) {
2348 err = ext2fs_flush2(fs, 0);
2350 ret = translate_error(fs, fh->ino, err);
2352 pthread_mutex_unlock(&ff->bfl);
2357 static int op_statfs(const char *path EXT2FS_ATTR((unused)),
2358 struct statvfs *buf)
2360 struct fuse_context *ctxt = fuse_get_context();
2361 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2364 blk64_t overhead, reserved, free;
2366 FUSE2FS_CHECK_CONTEXT(ff);
2368 dbg_printf("%s: path=%s\n", __func__, path);
2369 buf->f_bsize = fs->blocksize;
2375 overhead = fs->desc_blocks +
2376 fs->group_desc_count *
2377 (fs->inode_blocks_per_group + 2);
2378 reserved = ext2fs_r_blocks_count(fs->super);
2380 reserved = ext2fs_blocks_count(fs->super) / 10;
2381 free = ext2fs_free_blocks_count(fs->super);
2383 buf->f_blocks = ext2fs_blocks_count(fs->super) - overhead;
2384 buf->f_bfree = free;
2385 if (free < reserved)
2388 buf->f_bavail = free - reserved;
2389 buf->f_files = fs->super->s_inodes_count;
2390 buf->f_ffree = fs->super->s_free_inodes_count;
2391 buf->f_favail = fs->super->s_free_inodes_count;
2392 f = (uint64_t *)fs->super->s_uuid;
2398 if (fs->flags & EXT2_FLAG_RW)
2399 buf->f_flag |= ST_RDONLY;
2400 buf->f_namemax = EXT2_NAME_LEN;
2405 typedef errcode_t (*xattr_xlate_get)(void **cooked_buf, size_t *cooked_sz,
2406 const void *raw_buf, size_t raw_sz);
2407 typedef errcode_t (*xattr_xlate_set)(const void *cooked_buf, size_t cooked_sz,
2408 const void **raw_buf, size_t *raw_sz);
2409 struct xattr_translate {
2411 xattr_xlate_get get;
2412 xattr_xlate_set set;
2415 #define XATTR_TRANSLATOR(p, g, s) \
2417 .get = (xattr_xlate_get)(g), \
2418 .set = (xattr_xlate_set)(s)}
2420 static struct xattr_translate xattr_translators[] = {
2421 #ifdef TRANSLATE_LINUX_ACLS
2422 XATTR_TRANSLATOR(ACL_EA_ACCESS, ext4_to_fuse_acl, fuse_to_ext4_acl),
2423 XATTR_TRANSLATOR(ACL_EA_DEFAULT, ext4_to_fuse_acl, fuse_to_ext4_acl),
2425 XATTR_TRANSLATOR(NULL, NULL, NULL),
2427 #undef XATTR_TRANSLATOR
2429 static int op_getxattr(const char *path, const char *key, char *value,
2432 struct fuse_context *ctxt = fuse_get_context();
2433 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2435 struct ext2_xattr_handle *h;
2436 struct xattr_translate *xt;
2443 FUSE2FS_CHECK_CONTEXT(ff);
2445 pthread_mutex_lock(&ff->bfl);
2446 if (!ext2fs_has_feature_xattr(fs->super)) {
2451 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2452 if (err || ino == 0) {
2453 ret = translate_error(fs, 0, err);
2456 dbg_printf("%s: ino=%d\n", __func__, ino);
2458 ret = check_inum_access(fs, ino, R_OK);
2462 err = ext2fs_xattrs_open(fs, ino, &h);
2464 ret = translate_error(fs, ino, err);
2468 err = ext2fs_xattrs_read(h);
2470 ret = translate_error(fs, ino, err);
2474 err = ext2fs_xattr_get(h, key, &ptr, &plen);
2476 ret = translate_error(fs, ino, err);
2480 for (xt = xattr_translators; xt->prefix != NULL; xt++) {
2481 if (strncmp(key, xt->prefix, strlen(xt->prefix)) == 0) {
2482 err = xt->get(&cptr, &clen, ptr, plen);
2485 ext2fs_free_mem(&ptr);
2493 } else if (len < plen) {
2496 memcpy(value, ptr, plen);
2501 ext2fs_free_mem(&ptr);
2503 err = ext2fs_xattrs_close(&h);
2505 ret = translate_error(fs, ino, err);
2507 pthread_mutex_unlock(&ff->bfl);
2512 static int count_buffer_space(char *name, char *value EXT2FS_ATTR((unused)),
2513 size_t value_len EXT2FS_ATTR((unused)),
2516 unsigned int *x = data;
2518 *x = *x + strlen(name) + 1;
2522 static int copy_names(char *name, char *value EXT2FS_ATTR((unused)),
2523 size_t value_len EXT2FS_ATTR((unused)), void *data)
2527 strncpy(*b, name, strlen(name));
2528 *b = *b + strlen(name) + 1;
2533 static int op_listxattr(const char *path, char *names, size_t len)
2535 struct fuse_context *ctxt = fuse_get_context();
2536 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2538 struct ext2_xattr_handle *h;
2544 FUSE2FS_CHECK_CONTEXT(ff);
2546 pthread_mutex_lock(&ff->bfl);
2547 if (!ext2fs_has_feature_xattr(fs->super)) {
2552 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2553 if (err || ino == 0) {
2554 ret = translate_error(fs, ino, err);
2557 dbg_printf("%s: ino=%d\n", __func__, ino);
2559 ret = check_inum_access(fs, ino, R_OK);
2563 err = ext2fs_xattrs_open(fs, ino, &h);
2565 ret = translate_error(fs, ino, err);
2569 err = ext2fs_xattrs_read(h);
2571 ret = translate_error(fs, ino, err);
2575 /* Count buffer space needed for names */
2577 err = ext2fs_xattrs_iterate(h, count_buffer_space, &bufsz);
2579 ret = translate_error(fs, ino, err);
2586 } else if (len < bufsz) {
2591 /* Copy names out */
2592 memset(names, 0, len);
2593 err = ext2fs_xattrs_iterate(h, copy_names, &names);
2595 ret = translate_error(fs, ino, err);
2600 err = ext2fs_xattrs_close(&h);
2602 ret = translate_error(fs, ino, err);
2604 pthread_mutex_unlock(&ff->bfl);
2609 static int op_setxattr(const char *path EXT2FS_ATTR((unused)),
2610 const char *key, const char *value,
2611 size_t len, int flags EXT2FS_ATTR((unused)))
2613 struct fuse_context *ctxt = fuse_get_context();
2614 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2616 struct ext2_xattr_handle *h;
2617 struct xattr_translate *xt;
2624 FUSE2FS_CHECK_CONTEXT(ff);
2626 pthread_mutex_lock(&ff->bfl);
2627 if (!ext2fs_has_feature_xattr(fs->super)) {
2632 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2633 if (err || ino == 0) {
2634 ret = translate_error(fs, 0, err);
2637 dbg_printf("%s: ino=%d\n", __func__, ino);
2639 ret = check_inum_access(fs, ino, W_OK);
2640 if (ret == -EACCES) {
2646 err = ext2fs_xattrs_open(fs, ino, &h);
2648 ret = translate_error(fs, ino, err);
2652 err = ext2fs_xattrs_read(h);
2654 ret = translate_error(fs, ino, err);
2660 for (xt = xattr_translators; xt->prefix != NULL; xt++) {
2661 if (strncmp(key, xt->prefix, strlen(xt->prefix)) == 0) {
2662 err = xt->set(value, len, &cvalue, &clen);
2668 err = ext2fs_xattr_set(h, key, cvalue, clen);
2670 ret = translate_error(fs, ino, err);
2674 ret = update_ctime(fs, ino, NULL);
2676 if (cvalue != value)
2677 ext2fs_free_mem(&cvalue);
2679 err = ext2fs_xattrs_close(&h);
2681 ret = translate_error(fs, ino, err);
2683 pthread_mutex_unlock(&ff->bfl);
2688 static int op_removexattr(const char *path, const char *key)
2690 struct fuse_context *ctxt = fuse_get_context();
2691 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2693 struct ext2_xattr_handle *h;
2698 FUSE2FS_CHECK_CONTEXT(ff);
2700 pthread_mutex_lock(&ff->bfl);
2701 if (!ext2fs_has_feature_xattr(fs->super)) {
2706 if (!fs_can_allocate(ff, 1)) {
2711 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2712 if (err || ino == 0) {
2713 ret = translate_error(fs, 0, err);
2716 dbg_printf("%s: ino=%d\n", __func__, ino);
2718 ret = check_inum_access(fs, ino, W_OK);
2722 err = ext2fs_xattrs_open(fs, ino, &h);
2724 ret = translate_error(fs, ino, err);
2728 err = ext2fs_xattrs_read(h);
2730 ret = translate_error(fs, ino, err);
2734 err = ext2fs_xattr_remove(h, key);
2736 ret = translate_error(fs, ino, err);
2740 ret = update_ctime(fs, ino, NULL);
2742 err = ext2fs_xattrs_close(&h);
2744 ret = translate_error(fs, ino, err);
2746 pthread_mutex_unlock(&ff->bfl);
2751 struct readdir_iter {
2753 fuse_fill_dir_t func;
2756 static int op_readdir_iter(ext2_ino_t dir EXT2FS_ATTR((unused)),
2757 int entry EXT2FS_ATTR((unused)),
2758 struct ext2_dir_entry *dirent,
2759 int offset EXT2FS_ATTR((unused)),
2760 int blocksize EXT2FS_ATTR((unused)),
2761 char *buf EXT2FS_ATTR((unused)), void *data)
2763 struct readdir_iter *i = data;
2764 char namebuf[EXT2_NAME_LEN + 1];
2767 memcpy(namebuf, dirent->name, dirent->name_len & 0xFF);
2768 namebuf[dirent->name_len & 0xFF] = 0;
2769 ret = i->func(i->buf, namebuf, NULL, 0);
2771 return DIRENT_ABORT;
2776 static int op_readdir(const char *path EXT2FS_ATTR((unused)),
2777 void *buf, fuse_fill_dir_t fill_func,
2778 off_t offset EXT2FS_ATTR((unused)),
2779 struct fuse_file_info *fp)
2781 struct fuse_context *ctxt = fuse_get_context();
2782 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2783 struct fuse2fs_file_handle *fh =
2784 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2787 struct readdir_iter i;
2790 FUSE2FS_CHECK_CONTEXT(ff);
2792 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2793 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
2794 pthread_mutex_lock(&ff->bfl);
2797 err = ext2fs_dir_iterate2(fs, fh->ino, 0, NULL, op_readdir_iter, &i);
2799 ret = translate_error(fs, fh->ino, err);
2803 if (fs_writeable(fs)) {
2804 ret = update_atime(fs, fh->ino);
2809 pthread_mutex_unlock(&ff->bfl);
2813 static int op_access(const char *path, int mask)
2815 struct fuse_context *ctxt = fuse_get_context();
2816 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2822 FUSE2FS_CHECK_CONTEXT(ff);
2824 dbg_printf("%s: path=%s mask=0x%x\n", __func__, path, mask);
2825 pthread_mutex_lock(&ff->bfl);
2826 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2827 if (err || ino == 0) {
2828 ret = translate_error(fs, 0, err);
2832 ret = check_inum_access(fs, ino, mask);
2837 pthread_mutex_unlock(&ff->bfl);
2841 static int op_create(const char *path, mode_t mode, struct fuse_file_info *fp)
2843 struct fuse_context *ctxt = fuse_get_context();
2844 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2846 ext2_ino_t parent, child;
2851 struct ext2_inode_large inode;
2854 FUSE2FS_CHECK_CONTEXT(ff);
2856 dbg_printf("%s: path=%s mode=0%o\n", __func__, path, mode);
2857 temp_path = strdup(path);
2862 node_name = strrchr(temp_path, '/');
2871 pthread_mutex_lock(&ff->bfl);
2872 if (!fs_can_allocate(ff, 1)) {
2877 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
2880 ret = translate_error(fs, 0, err);
2884 ret = check_inum_access(fs, parent, W_OK);
2890 filetype = ext2_file_type(mode);
2892 err = ext2fs_new_inode(fs, parent, mode, 0, &child);
2894 ret = translate_error(fs, parent, err);
2898 dbg_printf("%s: creating ino=%d/name=%s in dir=%d\n", __func__, child,
2900 err = ext2fs_link(fs, parent, node_name, child, filetype);
2901 if (err == EXT2_ET_DIR_NO_SPACE) {
2902 err = ext2fs_expand_dir(fs, parent);
2904 ret = translate_error(fs, parent, err);
2908 err = ext2fs_link(fs, parent, node_name, child,
2912 ret = translate_error(fs, parent, err);
2916 ret = update_mtime(fs, parent, NULL);
2920 memset(&inode, 0, sizeof(inode));
2921 inode.i_mode = mode;
2922 inode.i_links_count = 1;
2923 inode.i_extra_isize = sizeof(struct ext2_inode_large) -
2924 EXT2_GOOD_OLD_INODE_SIZE;
2925 inode.i_uid = ctxt->uid;
2926 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
2927 inode.i_gid = ctxt->gid;
2928 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
2929 if (ext2fs_has_feature_extents(fs->super)) {
2930 ext2_extent_handle_t handle;
2932 inode.i_flags &= ~EXT4_EXTENTS_FL;
2933 ret = ext2fs_extent_open2(fs, child,
2934 (struct ext2_inode *)&inode, &handle);
2937 ext2fs_extent_free(handle);
2940 err = ext2fs_write_new_inode(fs, child, (struct ext2_inode *)&inode);
2942 ret = translate_error(fs, child, err);
2946 inode.i_generation = ff->next_generation++;
2948 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
2951 ret = translate_error(fs, child, err);
2955 ext2fs_inode_alloc_stats2(fs, child, 1, 0);
2957 ret = __op_open(ff, path, fp);
2961 pthread_mutex_unlock(&ff->bfl);
2967 static int op_ftruncate(const char *path EXT2FS_ATTR((unused)),
2968 off_t len, struct fuse_file_info *fp)
2970 struct fuse_context *ctxt = fuse_get_context();
2971 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2972 struct fuse2fs_file_handle *fh =
2973 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2979 FUSE2FS_CHECK_CONTEXT(ff);
2981 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2982 dbg_printf("%s: ino=%d len=%jd\n", __func__, fh->ino, len);
2983 pthread_mutex_lock(&ff->bfl);
2984 if (!fs_writeable(fs)) {
2989 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
2991 ret = translate_error(fs, fh->ino, err);
2995 err = ext2fs_file_set_size2(efp, len);
2997 ret = translate_error(fs, fh->ino, err);
3002 err = ext2fs_file_close(efp);
3006 ret = translate_error(fs, fh->ino, err);
3010 ret = update_mtime(fs, fh->ino, NULL);
3015 pthread_mutex_unlock(&ff->bfl);
3019 static int op_fgetattr(const char *path EXT2FS_ATTR((unused)),
3020 struct stat *statbuf,
3021 struct fuse_file_info *fp)
3023 struct fuse_context *ctxt = fuse_get_context();
3024 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3026 struct fuse2fs_file_handle *fh =
3027 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3030 FUSE2FS_CHECK_CONTEXT(ff);
3032 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3033 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3034 pthread_mutex_lock(&ff->bfl);
3035 ret = stat_inode(fs, fh->ino, statbuf);
3036 pthread_mutex_unlock(&ff->bfl);
3041 static int op_utimens(const char *path, const struct timespec ctv[2])
3043 struct fuse_context *ctxt = fuse_get_context();
3044 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3045 struct timespec tv[2];
3049 struct ext2_inode_large inode;
3052 FUSE2FS_CHECK_CONTEXT(ff);
3054 pthread_mutex_lock(&ff->bfl);
3055 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
3057 ret = translate_error(fs, 0, err);
3060 dbg_printf("%s: ino=%d\n", __func__, ino);
3062 ret = check_inum_access(fs, ino, W_OK);
3066 memset(&inode, 0, sizeof(inode));
3067 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
3070 ret = translate_error(fs, ino, err);
3077 if (tv[0].tv_nsec == UTIME_NOW)
3079 if (tv[1].tv_nsec == UTIME_NOW)
3081 #endif /* UTIME_NOW */
3083 if (tv[0].tv_nsec != UTIME_OMIT)
3084 EXT4_INODE_SET_XTIME(i_atime, tv, &inode);
3085 if (tv[1].tv_nsec != UTIME_OMIT)
3086 EXT4_INODE_SET_XTIME(i_mtime, tv + 1, &inode);
3087 #endif /* UTIME_OMIT */
3088 ret = update_ctime(fs, ino, &inode);
3092 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
3095 ret = translate_error(fs, ino, err);
3100 pthread_mutex_unlock(&ff->bfl);
3104 #ifdef SUPPORT_I_FLAGS
3105 static int ioctl_getflags(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3109 struct ext2_inode_large inode;
3111 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3112 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3113 memset(&inode, 0, sizeof(inode));
3114 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3117 return translate_error(fs, fh->ino, err);
3119 *(__u32 *)data = inode.i_flags & EXT2_FL_USER_VISIBLE;
3123 #define FUSE2FS_MODIFIABLE_IFLAGS \
3124 (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL | EXT2_NODUMP_FL | \
3125 EXT2_NOATIME_FL | EXT3_JOURNAL_DATA_FL | EXT2_DIRSYNC_FL | \
3128 static int ioctl_setflags(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3132 struct ext2_inode_large inode;
3134 __u32 flags = *(__u32 *)data;
3135 struct fuse_context *ctxt = fuse_get_context();
3136 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3138 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3139 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3140 memset(&inode, 0, sizeof(inode));
3141 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3144 return translate_error(fs, fh->ino, err);
3146 if (!ff->fakeroot && ctxt->uid != 0 && inode_uid(inode) != ctxt->uid)
3149 if ((inode.i_flags ^ flags) & ~FUSE2FS_MODIFIABLE_IFLAGS)
3152 inode.i_flags = (inode.i_flags & ~FUSE2FS_MODIFIABLE_IFLAGS) |
3153 (flags & FUSE2FS_MODIFIABLE_IFLAGS);
3155 ret = update_ctime(fs, fh->ino, &inode);
3159 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3162 return translate_error(fs, fh->ino, err);
3167 static int ioctl_getversion(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3171 struct ext2_inode_large inode;
3173 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3174 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3175 memset(&inode, 0, sizeof(inode));
3176 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3179 return translate_error(fs, fh->ino, err);
3181 *(__u32 *)data = inode.i_generation;
3185 static int ioctl_setversion(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3189 struct ext2_inode_large inode;
3191 __u32 generation = *(__u32 *)data;
3192 struct fuse_context *ctxt = fuse_get_context();
3193 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3195 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3196 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3197 memset(&inode, 0, sizeof(inode));
3198 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3201 return translate_error(fs, fh->ino, err);
3203 if (!ff->fakeroot && ctxt->uid != 0 && inode_uid(inode) != ctxt->uid)
3206 inode.i_generation = generation;
3208 ret = update_ctime(fs, fh->ino, &inode);
3212 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3215 return translate_error(fs, fh->ino, err);
3219 #endif /* SUPPORT_I_FLAGS */
3222 static int ioctl_fitrim(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3225 struct fstrim_range *fr = data;
3226 blk64_t start, end, max_blocks, b, cleared;
3229 start = fr->start / fs->blocksize;
3230 end = (fr->start + fr->len - 1) / fs->blocksize;
3231 dbg_printf("%s: start=%llu end=%llu\n", __func__, start, end);
3233 if (start < fs->super->s_first_data_block)
3234 start = fs->super->s_first_data_block;
3235 if (start >= ext2fs_blocks_count(fs->super))
3236 start = ext2fs_blocks_count(fs->super) - 1;
3238 if (end < fs->super->s_first_data_block)
3239 end = fs->super->s_first_data_block;
3240 if (end >= ext2fs_blocks_count(fs->super))
3241 end = ext2fs_blocks_count(fs->super) - 1;
3244 max_blocks = 2048ULL * 1024 * 1024 / fs->blocksize;
3247 while (start <= end) {
3248 err = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
3249 start, end, &start);
3253 return translate_error(fs, fh->ino, err);
3255 b = start + max_blocks < end ? start + max_blocks : end;
3256 err = ext2fs_find_first_set_block_bitmap2(fs->block_map,
3258 if (err && err != ENOENT)
3259 return translate_error(fs, fh->ino, err);
3260 if (b - start >= fr->minlen) {
3261 err = io_channel_discard(fs->io, start, b - start);
3263 return translate_error(fs, fh->ino, err);
3264 cleared += b - start;
3265 fr->len = cleared * fs->blocksize;
3274 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
3275 static int op_ioctl(const char *path EXT2FS_ATTR((unused)), int cmd,
3276 void *arg EXT2FS_ATTR((unused)),
3277 struct fuse_file_info *fp,
3278 unsigned int flags EXT2FS_ATTR((unused)), void *data)
3280 struct fuse_context *ctxt = fuse_get_context();
3281 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3282 struct fuse2fs_file_handle *fh =
3283 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3287 FUSE2FS_CHECK_CONTEXT(ff);
3289 pthread_mutex_lock(&ff->bfl);
3290 switch ((unsigned long) cmd) {
3291 #ifdef SUPPORT_I_FLAGS
3292 case EXT2_IOC_GETFLAGS:
3293 ret = ioctl_getflags(fs, fh, data);
3295 case EXT2_IOC_SETFLAGS:
3296 ret = ioctl_setflags(fs, fh, data);
3298 case EXT2_IOC_GETVERSION:
3299 ret = ioctl_getversion(fs, fh, data);
3301 case EXT2_IOC_SETVERSION:
3302 ret = ioctl_setversion(fs, fh, data);
3307 ret = ioctl_fitrim(fs, fh, data);
3311 dbg_printf("%s: Unknown ioctl %d\n", __func__, cmd);
3314 pthread_mutex_unlock(&ff->bfl);
3318 #endif /* FUSE 28 */
3320 static int op_bmap(const char *path, size_t blocksize EXT2FS_ATTR((unused)),
3323 struct fuse_context *ctxt = fuse_get_context();
3324 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3330 FUSE2FS_CHECK_CONTEXT(ff);
3332 pthread_mutex_lock(&ff->bfl);
3333 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
3335 ret = translate_error(fs, 0, err);
3338 dbg_printf("%s: ino=%d blk=%"PRIu64"\n", __func__, ino, *idx);
3340 err = ext2fs_bmap2(fs, ino, NULL, NULL, 0, *idx, 0, (blk64_t *)idx);
3342 ret = translate_error(fs, ino, err);
3347 pthread_mutex_unlock(&ff->bfl);
3351 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3352 # ifdef SUPPORT_FALLOCATE
3353 static int fallocate_helper(struct fuse_file_info *fp, int mode, off_t offset,
3356 struct fuse_context *ctxt = fuse_get_context();
3357 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3358 struct fuse2fs_file_handle *fh =
3359 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3361 struct ext2_inode_large inode;
3367 FUSE2FS_CHECK_CONTEXT(ff);
3369 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3370 start = offset / fs->blocksize;
3371 end = (offset + len - 1) / fs->blocksize;
3372 dbg_printf("%s: ino=%d mode=0x%x start=%jd end=%llu\n", __func__,
3373 fh->ino, mode, offset / fs->blocksize, end);
3374 if (!fs_can_allocate(ff, len / fs->blocksize))
3377 memset(&inode, 0, sizeof(inode));
3378 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3382 fsize = EXT2_I_SIZE(&inode);
3384 /* Allocate a bunch of blocks */
3385 flags = (mode & FL_KEEP_SIZE_FLAG ? 0 :
3386 EXT2_FALLOCATE_INIT_BEYOND_EOF);
3387 err = ext2fs_fallocate(fs, flags, fh->ino,
3388 (struct ext2_inode *)&inode,
3389 ~0ULL, start, end - start + 1);
3390 if (err && err != EXT2_ET_BLOCK_ALLOC_FAIL)
3391 return translate_error(fs, fh->ino, err);
3394 if (!(mode & FL_KEEP_SIZE_FLAG)) {
3395 if ((__u64) offset + len > fsize) {
3396 err = ext2fs_inode_size_set(fs,
3397 (struct ext2_inode *)&inode,
3400 return translate_error(fs, fh->ino, err);
3404 err = update_mtime(fs, fh->ino, &inode);
3408 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3411 return translate_error(fs, fh->ino, err);
3416 static errcode_t clean_block_middle(ext2_filsys fs, ext2_ino_t ino,
3417 struct ext2_inode_large *inode, off_t offset,
3418 off_t len, char **buf)
3425 residue = offset % fs->blocksize;
3430 err = ext2fs_get_mem(fs->blocksize, buf);
3435 err = ext2fs_bmap2(fs, ino, (struct ext2_inode *)inode, *buf, 0,
3436 offset / fs->blocksize, &retflags, &blk);
3439 if (!blk || (retflags & BMAP_RET_UNINIT))
3442 err = io_channel_read_blk(fs->io, blk, 1, *buf);
3446 memset(*buf + residue, 0, len);
3448 return io_channel_write_blk(fs->io, blk, 1, *buf);
3451 static errcode_t clean_block_edge(ext2_filsys fs, ext2_ino_t ino,
3452 struct ext2_inode_large *inode, off_t offset,
3453 int clean_before, char **buf)
3460 residue = offset % fs->blocksize;
3465 err = ext2fs_get_mem(fs->blocksize, buf);
3470 err = ext2fs_bmap2(fs, ino, (struct ext2_inode *)inode, *buf, 0,
3471 offset / fs->blocksize, &retflags, &blk);
3475 err = io_channel_read_blk(fs->io, blk, 1, *buf);
3478 if (!blk || (retflags & BMAP_RET_UNINIT))
3482 memset(*buf, 0, residue);
3484 memset(*buf + residue, 0, fs->blocksize - residue);
3486 return io_channel_write_blk(fs->io, blk, 1, *buf);
3489 static int punch_helper(struct fuse_file_info *fp, int mode, off_t offset,
3492 struct fuse_context *ctxt = fuse_get_context();
3493 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3494 struct fuse2fs_file_handle *fh =
3495 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3497 struct ext2_inode_large inode;
3502 FUSE2FS_CHECK_CONTEXT(ff);
3504 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3505 dbg_printf("%s: offset=%jd len=%jd\n", __func__, offset, len);
3507 /* kernel ext4 punch requires this flag to be set */
3508 if (!(mode & FL_KEEP_SIZE_FLAG))
3511 /* Punch out a bunch of blocks */
3512 start = (offset + fs->blocksize - 1) / fs->blocksize;
3513 end = (offset + len - fs->blocksize) / fs->blocksize;
3514 dbg_printf("%s: ino=%d mode=0x%x start=%llu end=%llu\n", __func__,
3515 fh->ino, mode, start, end);
3517 memset(&inode, 0, sizeof(inode));
3518 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3521 return translate_error(fs, fh->ino, err);
3523 /* Zero everything before the first block and after the last block */
3524 if ((offset / fs->blocksize) == ((offset + len) / fs->blocksize))
3525 err = clean_block_middle(fs, fh->ino, &inode, offset,
3528 err = clean_block_edge(fs, fh->ino, &inode, offset, 0, &buf);
3530 err = clean_block_edge(fs, fh->ino, &inode,
3531 offset + len, 1, &buf);
3534 ext2fs_free_mem(&buf);
3536 return translate_error(fs, fh->ino, err);
3538 /* Unmap full blocks in the middle */
3540 err = ext2fs_punch(fs, fh->ino, (struct ext2_inode *)&inode,
3543 return translate_error(fs, fh->ino, err);
3546 err = update_mtime(fs, fh->ino, &inode);
3550 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3553 return translate_error(fs, fh->ino, err);
3558 static int op_fallocate(const char *path EXT2FS_ATTR((unused)), int mode,
3559 off_t offset, off_t len,
3560 struct fuse_file_info *fp)
3562 struct fuse_context *ctxt = fuse_get_context();
3563 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3564 ext2_filsys fs = ff->fs;
3567 /* Catch unknown flags */
3568 if (mode & ~(FL_PUNCH_HOLE_FLAG | FL_KEEP_SIZE_FLAG))
3571 pthread_mutex_lock(&ff->bfl);
3572 if (!fs_writeable(fs)) {
3576 if (mode & FL_PUNCH_HOLE_FLAG)
3577 ret = punch_helper(fp, mode, offset, len);
3579 ret = fallocate_helper(fp, mode, offset, len);
3581 pthread_mutex_unlock(&ff->bfl);
3585 # endif /* SUPPORT_FALLOCATE */
3586 #endif /* FUSE 29 */
3588 static struct fuse_operations fs_ops = {
3590 .destroy = op_destroy,
3591 .getattr = op_getattr,
3592 .readlink = op_readlink,
3595 .unlink = op_unlink,
3597 .symlink = op_symlink,
3598 .rename = op_rename,
3602 .truncate = op_truncate,
3606 .statfs = op_statfs,
3607 .release = op_release,
3609 .setxattr = op_setxattr,
3610 .getxattr = op_getxattr,
3611 .listxattr = op_listxattr,
3612 .removexattr = op_removexattr,
3614 .readdir = op_readdir,
3615 .releasedir = op_release,
3616 .fsyncdir = op_fsync,
3617 .access = op_access,
3618 .create = op_create,
3619 .ftruncate = op_ftruncate,
3620 .fgetattr = op_fgetattr,
3621 .utimens = op_utimens,
3622 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3623 # if defined(UTIME_NOW) || defined(UTIME_OMIT)
3624 .flag_utime_omit_ok = 1,
3632 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
3634 .flag_nullpath_ok = 1,
3636 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3638 # ifdef SUPPORT_FALLOCATE
3639 .fallocate = op_fallocate,
3644 static int get_random_bytes(void *p, size_t sz)
3649 fd = open("/dev/urandom", O_RDONLY);
3651 perror("/dev/urandom");
3655 r = read(fd, p, sz);
3658 return (size_t) r == sz;
3667 #define FUSE2FS_OPT(t, p, v) { t, offsetof(struct fuse2fs, p), v }
3669 static struct fuse_opt fuse2fs_opts[] = {
3670 FUSE2FS_OPT("ro", ro, 1),
3671 FUSE2FS_OPT("errors=panic", panic_on_error, 1),
3672 FUSE2FS_OPT("minixdf", minixdf, 1),
3673 FUSE2FS_OPT("fakeroot", fakeroot, 1),
3674 FUSE2FS_OPT("fuse2fs_debug", debug, 1),
3675 FUSE2FS_OPT("no_default_opts", no_default_opts, 1),
3677 FUSE_OPT_KEY("-V", FUSE2FS_VERSION),
3678 FUSE_OPT_KEY("--version", FUSE2FS_VERSION),
3679 FUSE_OPT_KEY("-h", FUSE2FS_HELP),
3680 FUSE_OPT_KEY("--help", FUSE2FS_HELP),
3681 FUSE_OPT_KEY("--helpfull", FUSE2FS_HELPFULL),
3686 static int fuse2fs_opt_proc(void *data, const char *arg,
3687 int key, struct fuse_args *outargs)
3689 struct fuse2fs *ff = data;
3692 case FUSE_OPT_KEY_NONOPT:
3694 ff->device = strdup(arg);
3699 case FUSE2FS_HELPFULL:
3701 "usage: %s device/image mountpoint [options]\n"
3703 "general options:\n"
3704 " -o opt,[opt...] mount options\n"
3705 " -h --help print help\n"
3706 " -V --version print version\n"
3708 "fuse2fs options:\n"
3709 " -o ro read-only mount\n"
3710 " -o errors=panic dump core on error\n"
3711 " -o minixdf minix-style df\n"
3712 " -o fakeroot pretend to be root for permission checks\n"
3713 " -o no_default_opts do not include default fuse options\n"
3714 " -o fuse2fs_debug enable fuse2fs debugging\n"
3717 if (key == FUSE2FS_HELPFULL) {
3718 fuse_opt_add_arg(outargs, "-ho");
3719 fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL);
3721 fprintf(stderr, "Try --helpfull to get a list of "
3722 "all flags, including the FUSE options.\n");
3726 case FUSE2FS_VERSION:
3727 fprintf(stderr, "fuse2fs %s (%s)\n", E2FSPROGS_VERSION,
3729 fuse_opt_add_arg(outargs, "--version");
3730 fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL);
3736 int main(int argc, char *argv[])
3738 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
3739 struct fuse2fs fctx;
3742 char extra_args[BUFSIZ];
3743 int ret = 0, flags = EXT2_FLAG_64BITS | EXT2_FLAG_EXCLUSIVE;
3745 memset(&fctx, 0, sizeof(fctx));
3746 fctx.magic = FUSE2FS_MAGIC;
3748 fuse_opt_parse(&args, &fctx, fuse2fs_opts, fuse2fs_opt_proc);
3749 if (fctx.device == NULL) {
3750 fprintf(stderr, "Missing ext4 device/image\n");
3751 fprintf(stderr, "See '%s -h' for usage\n", argv[0]);
3756 printf("%s", _("Mounting read-only.\n"));
3759 setlocale(LC_MESSAGES, "");
3760 setlocale(LC_CTYPE, "");
3761 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
3762 textdomain(NLS_CAT_NAME);
3763 set_com_err_gettext(gettext);
3765 add_error_table(&et_ext2_error_table);
3767 /* Set up error logging */
3768 logfile = getenv("FUSE2FS_LOGFILE");
3770 fctx.err_fp = fopen(logfile, "a");
3776 fctx.err_fp = stderr;
3778 /* Will we allow users to allocate every last block? */
3779 if (getenv("FUSE2FS_ALLOC_ALL_BLOCKS")) {
3780 printf(_("%s: Allowing users to allocate all blocks. "
3781 "This is dangerous!\n"), fctx.device);
3782 fctx.alloc_all_blocks = 1;
3785 /* Start up the fs (while we still can use stdout) */
3788 flags |= EXT2_FLAG_RW;
3789 err = ext2fs_open2(fctx.device, NULL, flags, 0, 0, unix_io_manager,
3792 printf(_("%s: %s.\n"), fctx.device, error_message(err));
3793 printf(_("Please run e2fsck -fy %s.\n"), fctx.device);
3796 fctx.fs = global_fs;
3797 global_fs->priv_data = &fctx;
3801 if (ext2fs_has_feature_journal_needs_recovery(global_fs->super)) {
3803 printf(_("%s: recovering journal\n"), fctx.device);
3804 err = ext2fs_run_ext3_journal(&global_fs);
3806 printf(_("%s: %s.\n"), fctx.device,
3807 error_message(err));
3808 printf(_("Please run e2fsck -fy %s.\n"),
3812 ext2fs_clear_feature_journal_needs_recovery(global_fs->super);
3813 ext2fs_mark_super_dirty(global_fs);
3815 printf("%s", _("Journal needs recovery; running "
3816 "`e2fsck -E journal_only' is required.\n"));
3822 if (ext2fs_has_feature_journal(global_fs->super))
3823 printf(_("%s: Writing to the journal is not supported.\n"),
3825 err = ext2fs_read_inode_bitmap(global_fs);
3827 translate_error(global_fs, 0, err);
3830 err = ext2fs_read_block_bitmap(global_fs);
3832 translate_error(global_fs, 0, err);
3837 if (!(global_fs->super->s_state & EXT2_VALID_FS))
3838 printf("%s", _("Warning: Mounting unchecked fs, running e2fsck "
3839 "is recommended.\n"));
3840 if (global_fs->super->s_max_mnt_count > 0 &&
3841 global_fs->super->s_mnt_count >= global_fs->super->s_max_mnt_count)
3842 printf("%s", _("Warning: Maximal mount count reached, running "
3843 "e2fsck is recommended.\n"));
3844 if (global_fs->super->s_checkinterval > 0 &&
3845 (time_t) (global_fs->super->s_lastcheck +
3846 global_fs->super->s_checkinterval) <= time(0))
3847 printf("%s", _("Warning: Check time reached; running e2fsck "
3848 "is recommended.\n"));
3849 if (global_fs->super->s_last_orphan)
3851 _("Orphans detected; running e2fsck is recommended.\n"));
3853 if (global_fs->super->s_state & EXT2_ERROR_FS) {
3855 _("Errors detected; running e2fsck is required.\n"));
3859 /* Initialize generation counter */
3860 get_random_bytes(&fctx.next_generation, sizeof(unsigned int));
3862 /* Set up default fuse parameters */
3863 snprintf(extra_args, BUFSIZ, "-okernel_cache,subtype=ext4,use_ino,"
3864 "fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS,
3866 if (fctx.no_default_opts == 0)
3867 fuse_opt_add_arg(&args, extra_args);
3869 if (fctx.fakeroot) {
3870 #ifdef HAVE_MOUNT_NODEV
3871 fuse_opt_add_arg(&args,"-onodev");
3873 #ifdef HAVE_MOUNT_NOSUID
3874 fuse_opt_add_arg(&args,"-onosuid");
3881 printf("fuse arguments:");
3882 for (i = 0; i < args.argc; i++)
3883 printf(" '%s'", args.argv[i]);
3887 pthread_mutex_init(&fctx.bfl, NULL);
3888 fuse_main(args.argc, args.argv, &fs_ops, &fctx);
3889 pthread_mutex_destroy(&fctx.bfl);
3894 err = ext2fs_close(global_fs);
3896 com_err(argv[0], err, "while closing fs");
3902 static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino,
3903 const char *file, int line)
3905 struct timespec now;
3907 struct fuse2fs *ff = fs->priv_data;
3910 /* Translate ext2 error to unix error code */
3911 if (err < EXT2_ET_BASE)
3912 goto no_translation;
3914 case EXT2_ET_NO_MEMORY:
3915 case EXT2_ET_TDB_ERR_OOM:
3918 case EXT2_ET_INVALID_ARGUMENT:
3919 case EXT2_ET_LLSEEK_FAILED:
3922 case EXT2_ET_NO_DIRECTORY:
3925 case EXT2_ET_FILE_NOT_FOUND:
3928 case EXT2_ET_DIR_NO_SPACE:
3931 case EXT2_ET_TOOSMALL:
3932 case EXT2_ET_BLOCK_ALLOC_FAIL:
3933 case EXT2_ET_INODE_ALLOC_FAIL:
3934 case EXT2_ET_EA_NO_SPACE:
3937 case EXT2_ET_SYMLINK_LOOP:
3940 case EXT2_ET_FILE_TOO_BIG:
3943 case EXT2_ET_TDB_ERR_EXISTS:
3944 case EXT2_ET_FILE_EXISTS:
3947 case EXT2_ET_MMP_FAILED:
3948 case EXT2_ET_MMP_FSCK_ON:
3951 case EXT2_ET_EA_KEY_NOT_FOUND:
3958 /* Sometimes fuse returns a garbage file handle pointer to us... */
3959 case EXT2_ET_MAGIC_EXT2_FILE:
3962 case EXT2_ET_UNIMPLEMENTED:
3976 fprintf(ff->err_fp, "FUSE2FS (%s): %s (inode #%d) at %s:%d.\n",
3977 fs->device_name ? fs->device_name : "???",
3978 error_message(err), ino, file, line);
3980 fprintf(ff->err_fp, "FUSE2FS (%s): %s at %s:%d.\n",
3981 fs->device_name ? fs->device_name : "???",
3982 error_message(err), file, line);
3985 /* Make a note in the error log */
3987 fs->super->s_last_error_time = now.tv_sec;
3988 fs->super->s_last_error_ino = ino;
3989 fs->super->s_last_error_line = line;
3990 fs->super->s_last_error_block = err; /* Yeah... */
3991 strncpy((char *)fs->super->s_last_error_func, file,
3992 sizeof(fs->super->s_last_error_func));
3993 if (fs->super->s_first_error_time == 0) {
3994 fs->super->s_first_error_time = now.tv_sec;
3995 fs->super->s_first_error_ino = ino;
3996 fs->super->s_first_error_line = line;
3997 fs->super->s_first_error_block = err;
3998 strncpy((char *)fs->super->s_first_error_func, file,
3999 sizeof(fs->super->s_first_error_func));
4002 fs->super->s_error_count++;
4003 ext2fs_mark_super_dirty(fs);
4005 if (ff->panic_on_error)