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
17 # include <linux/fs.h>
18 # include <linux/falloc.h>
19 # include <linux/xattr.h>
20 # ifdef HAVE_SYS_ACL_H
21 # define TRANSLATE_LINUX_ACLS
24 #ifdef TRANSLATE_LINUX_ACLS
27 #include <sys/ioctl.h>
31 #include "ext2fs/ext2fs.h"
32 #include "ext2fs/ext2_fs.h"
33 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
34 # define FUSE_PLATFORM_OPTS ""
37 # define FUSE_PLATFORM_OPTS ",use_ino,big_writes"
39 # define FUSE_PLATFORM_OPTS ",use_ino"
43 #include "../version.h"
48 #define _(a) (gettext(a))
50 #define N_(a) gettext_noop(a)
54 #define P_(singular, plural, n) (ngettext(singular, plural, n))
56 #define NLS_CAT_NAME "e2fsprogs"
59 #define LOCALEDIR "/usr/share/locale"
64 #define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural))
67 static ext2_filsys global_fs; /* Try not to use this directly */
72 # define dbg_printf(f, a...) do {printf("FUSE2FS-" f, ## a); \
76 # define dbg_printf(f, a...)
79 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
82 # define SUPPORT_I_FLAGS
87 #ifdef FALLOC_FL_KEEP_SIZE
88 # define FL_KEEP_SIZE_FLAG FALLOC_FL_KEEP_SIZE
89 # define SUPPORT_FALLOCATE
91 # define FL_KEEP_SIZE_FLAG (0)
94 #ifdef FALLOC_FL_PUNCH_HOLE
95 # define FL_PUNCH_HOLE_FLAG FALLOC_FL_PUNCH_HOLE
97 # define FL_PUNCH_HOLE_FLAG (0)
100 errcode_t ext2fs_run_ext3_journal(ext2_filsys *fs);
102 #ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jbd-debug */
103 int journal_enable_debug = -1;
106 /* ACL translation stuff */
107 #ifdef TRANSLATE_LINUX_ACLS
109 * Copied from acl_ea.h in libacl source; ACLs have to be sent to and from fuse
110 * in this format... at least on Linux.
112 #define ACL_EA_ACCESS "system.posix_acl_access"
113 #define ACL_EA_DEFAULT "system.posix_acl_default"
115 #define ACL_EA_VERSION 0x0002
125 #if __GNUC_PREREQ (4, 8)
126 #pragma GCC diagnostic push
127 #pragma GCC diagnostic ignored "-Wpedantic"
129 acl_ea_entry a_entries[0];
130 #if __GNUC_PREREQ (4, 8)
131 #pragma GCC diagnostic pop
135 static inline size_t acl_ea_size(int count)
137 return sizeof(acl_ea_header) + count * sizeof(acl_ea_entry);
140 static inline int acl_ea_count(size_t size)
142 if (size < sizeof(acl_ea_header))
144 size -= sizeof(acl_ea_header);
145 if (size % sizeof(acl_ea_entry))
147 return size / sizeof(acl_ea_entry);
151 * ext4 ACL structures, copied from fs/ext4/acl.h.
153 #define EXT4_ACL_VERSION 0x0001
164 } ext4_acl_entry_short;
170 static inline size_t ext4_acl_size(int count)
173 return sizeof(ext4_acl_header) +
174 count * sizeof(ext4_acl_entry_short);
176 return sizeof(ext4_acl_header) +
177 4 * sizeof(ext4_acl_entry_short) +
178 (count - 4) * sizeof(ext4_acl_entry);
182 static inline int ext4_acl_count(size_t size)
186 size -= sizeof(ext4_acl_header);
187 s = size - 4 * sizeof(ext4_acl_entry_short);
189 if (size % sizeof(ext4_acl_entry_short))
191 return size / sizeof(ext4_acl_entry_short);
193 if (s % sizeof(ext4_acl_entry))
195 return s / sizeof(ext4_acl_entry) + 4;
198 static errcode_t fuse_to_ext4_acl(acl_ea_header *facl, size_t facl_sz,
199 ext4_acl_header **eacl, size_t *eacl_sz)
209 facl_count = acl_ea_count(facl_sz);
210 h_sz = ext4_acl_size(facl_count);
211 if (facl_count < 0 || facl->a_version != ACL_EA_VERSION)
212 return EXT2_ET_INVALID_ARGUMENT;
214 err = ext2fs_get_mem(h_sz, &h);
218 h->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION);
219 hptr = (unsigned char *) (h + 1);
220 for (i = 0, a = facl->a_entries; i < facl_count; i++, a++) {
221 e = (ext4_acl_entry *) hptr;
222 e->e_tag = ext2fs_cpu_to_le16(a->e_tag);
223 e->e_perm = ext2fs_cpu_to_le16(a->e_perm);
228 e->e_id = ext2fs_cpu_to_le32(a->e_id);
229 hptr += sizeof(ext4_acl_entry);
235 hptr += sizeof(ext4_acl_entry_short);
238 err = EXT2_ET_INVALID_ARGUMENT;
251 static errcode_t ext4_to_fuse_acl(acl_ea_header **facl, size_t *facl_sz,
252 ext4_acl_header *eacl, size_t eacl_sz)
262 eacl_count = ext4_acl_count(eacl_sz);
263 f_sz = acl_ea_size(eacl_count);
264 if (eacl_count < 0 ||
265 eacl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION))
266 return EXT2_ET_INVALID_ARGUMENT;
268 err = ext2fs_get_mem(f_sz, &f);
272 f->a_version = ACL_EA_VERSION;
273 hptr = (unsigned char *) (eacl + 1);
274 for (i = 0, a = f->a_entries; i < eacl_count; i++, a++) {
275 e = (ext4_acl_entry *) hptr;
276 a->e_tag = ext2fs_le16_to_cpu(e->e_tag);
277 a->e_perm = ext2fs_le16_to_cpu(e->e_perm);
282 a->e_id = ext2fs_le32_to_cpu(e->e_id);
283 hptr += sizeof(ext4_acl_entry);
289 hptr += sizeof(ext4_acl_entry_short);
292 err = EXT2_ET_INVALID_ARGUMENT;
304 #endif /* TRANSLATE_LINUX_ACLS */
307 * ext2_file_t contains a struct inode, so we can't leave files open.
308 * Use this as a proxy instead.
310 #define FUSE2FS_FILE_MAGIC (0xEF53DEAFUL)
311 struct fuse2fs_file_handle {
317 /* Main program context */
318 #define FUSE2FS_MAGIC (0xEF53DEADUL)
330 int alloc_all_blocks;
332 unsigned long offset;
334 unsigned int next_generation;
337 #define FUSE2FS_CHECK_MAGIC(fs, ptr, num) do {if ((ptr)->magic != (num)) \
338 return translate_error((fs), 0, EXT2_ET_MAGIC_EXT2_FILE); \
341 #define FUSE2FS_CHECK_CONTEXT(ptr) do {if ((ptr)->magic != FUSE2FS_MAGIC) \
342 return translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC); \
345 static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino,
346 const char *file, int line);
347 #define translate_error(fs, ino, err) __translate_error((fs), (err), (ino), \
359 #define EXT4_EPOCH_BITS 2
360 #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
361 #define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS)
364 * Extended fields will fit into an inode if the filesystem was formatted
365 * with large inodes (-I 256 or larger) and there are not currently any EAs
366 * consuming all of the available space. For new inodes we always reserve
367 * enough space for the kernel's known extended fields, but for inodes
368 * created with an old kernel this might not have been the case. None of
369 * the extended inode fields is critical for correct filesystem operation.
370 * This macro checks if a certain field fits in the inode. Note that
371 * inode-size = GOOD_OLD_INODE_SIZE + i_extra_isize
373 #define EXT4_FITS_IN_INODE(ext4_inode, field) \
374 ((offsetof(typeof(*ext4_inode), field) + \
375 sizeof((ext4_inode)->field)) \
376 <= ((size_t) EXT2_GOOD_OLD_INODE_SIZE + \
377 (ext4_inode)->i_extra_isize)) \
379 static inline __u32 ext4_encode_extra_time(const struct timespec *time)
381 __u32 extra = sizeof(time->tv_sec) > 4 ?
382 ((time->tv_sec - (__s32)time->tv_sec) >> 32) &
384 return extra | (time->tv_nsec << EXT4_EPOCH_BITS);
387 static inline void ext4_decode_extra_time(struct timespec *time, __u32 extra)
389 if (sizeof(time->tv_sec) > 4 && (extra & EXT4_EPOCH_MASK)) {
390 __u64 extra_bits = extra & EXT4_EPOCH_MASK;
392 * Prior to kernel 3.14?, we had a broken decode function,
393 * wherein we effectively did this:
394 * if (extra_bits == 3)
397 time->tv_sec += extra_bits << 32;
399 time->tv_nsec = ((extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
402 #define EXT4_INODE_SET_XTIME(xtime, timespec, raw_inode) \
404 (raw_inode)->xtime = (timespec)->tv_sec; \
405 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
406 (raw_inode)->xtime ## _extra = \
407 ext4_encode_extra_time(timespec); \
410 #define EXT4_EINODE_SET_XTIME(xtime, timespec, raw_inode) \
412 if (EXT4_FITS_IN_INODE(raw_inode, xtime)) \
413 (raw_inode)->xtime = (timespec)->tv_sec; \
414 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
415 (raw_inode)->xtime ## _extra = \
416 ext4_encode_extra_time(timespec); \
419 #define EXT4_INODE_GET_XTIME(xtime, timespec, raw_inode) \
421 (timespec)->tv_sec = (signed)((raw_inode)->xtime); \
422 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
423 ext4_decode_extra_time((timespec), \
424 (raw_inode)->xtime ## _extra); \
426 (timespec)->tv_nsec = 0; \
429 #define EXT4_EINODE_GET_XTIME(xtime, timespec, raw_inode) \
431 if (EXT4_FITS_IN_INODE(raw_inode, xtime)) \
432 (timespec)->tv_sec = \
433 (signed)((raw_inode)->xtime); \
434 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
435 ext4_decode_extra_time((timespec), \
436 raw_inode->xtime ## _extra); \
438 (timespec)->tv_nsec = 0; \
441 static void get_now(struct timespec *now)
443 #ifdef CLOCK_REALTIME
444 if (!clock_gettime(CLOCK_REALTIME, now))
448 now->tv_sec = time(NULL);
452 static void increment_version(struct ext2_inode_large *inode)
456 ver = inode->osd1.linux1.l_i_version;
457 if (EXT4_FITS_IN_INODE(inode, i_version_hi))
458 ver |= (__u64)inode->i_version_hi << 32;
460 inode->osd1.linux1.l_i_version = ver;
461 if (EXT4_FITS_IN_INODE(inode, i_version_hi))
462 inode->i_version_hi = ver >> 32;
465 static void init_times(struct ext2_inode_large *inode)
470 EXT4_INODE_SET_XTIME(i_atime, &now, inode);
471 EXT4_INODE_SET_XTIME(i_ctime, &now, inode);
472 EXT4_INODE_SET_XTIME(i_mtime, &now, inode);
473 EXT4_EINODE_SET_XTIME(i_crtime, &now, inode);
474 increment_version(inode);
477 static int update_ctime(ext2_filsys fs, ext2_ino_t ino,
478 struct ext2_inode_large *pinode)
482 struct ext2_inode_large inode;
486 /* If user already has a inode buffer, just update that */
488 increment_version(pinode);
489 EXT4_INODE_SET_XTIME(i_ctime, &now, pinode);
493 /* Otherwise we have to read-modify-write the inode */
494 memset(&inode, 0, sizeof(inode));
495 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
498 return translate_error(fs, ino, err);
500 increment_version(&inode);
501 EXT4_INODE_SET_XTIME(i_ctime, &now, &inode);
503 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
506 return translate_error(fs, ino, err);
511 static int update_atime(ext2_filsys fs, ext2_ino_t ino)
514 struct ext2_inode_large inode, *pinode;
515 struct timespec atime, mtime, now;
517 if (!(fs->flags & EXT2_FLAG_RW))
519 memset(&inode, 0, sizeof(inode));
520 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
523 return translate_error(fs, ino, err);
526 EXT4_INODE_GET_XTIME(i_atime, &atime, pinode);
527 EXT4_INODE_GET_XTIME(i_mtime, &mtime, pinode);
530 * If atime is newer than mtime and atime hasn't been updated in thirty
531 * seconds, skip the atime update. Same idea as Linux "relatime".
533 if (atime.tv_sec >= mtime.tv_sec && atime.tv_sec >= now.tv_sec - 30)
535 EXT4_INODE_SET_XTIME(i_atime, &now, &inode);
537 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
540 return translate_error(fs, ino, err);
545 static int update_mtime(ext2_filsys fs, ext2_ino_t ino,
546 struct ext2_inode_large *pinode)
549 struct ext2_inode_large inode;
554 EXT4_INODE_SET_XTIME(i_mtime, &now, pinode);
555 EXT4_INODE_SET_XTIME(i_ctime, &now, pinode);
556 increment_version(pinode);
560 memset(&inode, 0, sizeof(inode));
561 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
564 return translate_error(fs, ino, err);
567 EXT4_INODE_SET_XTIME(i_mtime, &now, &inode);
568 EXT4_INODE_SET_XTIME(i_ctime, &now, &inode);
569 increment_version(&inode);
571 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
574 return translate_error(fs, ino, err);
579 static int ext2_file_type(unsigned int mode)
581 if (LINUX_S_ISREG(mode))
582 return EXT2_FT_REG_FILE;
584 if (LINUX_S_ISDIR(mode))
587 if (LINUX_S_ISCHR(mode))
588 return EXT2_FT_CHRDEV;
590 if (LINUX_S_ISBLK(mode))
591 return EXT2_FT_BLKDEV;
593 if (LINUX_S_ISLNK(mode))
594 return EXT2_FT_SYMLINK;
596 if (LINUX_S_ISFIFO(mode))
599 if (LINUX_S_ISSOCK(mode))
605 static int fs_can_allocate(struct fuse2fs *ff, blk64_t num)
607 ext2_filsys fs = ff->fs;
610 dbg_printf("%s: Asking for %llu; alloc_all=%d total=%llu free=%llu "
611 "rsvd=%llu\n", __func__, num, ff->alloc_all_blocks,
612 ext2fs_blocks_count(fs->super),
613 ext2fs_free_blocks_count(fs->super),
614 ext2fs_r_blocks_count(fs->super));
615 if (num > ext2fs_blocks_count(fs->super))
618 if (ff->alloc_all_blocks)
622 * Different meaning for r_blocks -- libext2fs has bugs where the FS
623 * can get corrupted if it totally runs out of blocks. Avoid this
624 * by refusing to allocate any of the reserve blocks to anybody.
626 reserved = ext2fs_r_blocks_count(fs->super);
628 reserved = ext2fs_blocks_count(fs->super) / 10;
629 return ext2fs_free_blocks_count(fs->super) > reserved + num;
632 static int fs_writeable(ext2_filsys fs)
634 return (fs->flags & EXT2_FLAG_RW) && (fs->super->s_error_count == 0);
637 static int check_inum_access(ext2_filsys fs, ext2_ino_t ino, mode_t mask)
639 struct fuse_context *ctxt = fuse_get_context();
640 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
641 struct ext2_inode inode;
645 /* no writing to read-only or broken fs */
646 if ((mask & W_OK) && !fs_writeable(fs))
649 err = ext2fs_read_inode(fs, ino, &inode);
651 return translate_error(fs, ino, err);
652 perms = inode.i_mode & 0777;
654 dbg_printf("access ino=%d mask=e%s%s%s perms=0%o fuid=%d fgid=%d "
655 "uid=%d gid=%d\n", ino,
656 (mask & R_OK ? "r" : ""), (mask & W_OK ? "w" : ""),
657 (mask & X_OK ? "x" : ""), perms, inode_uid(inode),
658 inode_gid(inode), ctxt->uid, ctxt->gid);
660 /* existence check */
666 (inode.i_flags & EXT2_IMMUTABLE_FL))
669 /* Figure out what root's allowed to do */
670 if (ff->fakeroot || ctxt->uid == 0) {
671 /* Non-file access always ok */
672 if (!LINUX_S_ISREG(inode.i_mode))
675 /* R/W access to a file always ok */
679 /* X access to a file ok if a user/group/other can X */
683 /* Trying to execute a file that's not executable. BZZT! */
687 /* allow owner, if perms match */
688 if (inode_uid(inode) == ctxt->uid) {
689 if ((mask & (perms >> 6)) == mask)
694 /* allow group, if perms match */
695 if (inode_gid(inode) == ctxt->gid) {
696 if ((mask & (perms >> 3)) == mask)
701 /* otherwise check other */
702 if ((mask & perms) == mask)
707 static void op_destroy(void *p EXT2FS_ATTR((unused)))
709 struct fuse_context *ctxt = fuse_get_context();
710 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
714 if (ff->magic != FUSE2FS_MAGIC) {
715 translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC);
719 dbg_printf("%s: dev=%s\n", __func__, fs->device_name);
720 if (fs->flags & EXT2_FLAG_RW) {
721 fs->super->s_state |= EXT2_VALID_FS;
722 if (fs->super->s_error_count)
723 fs->super->s_state |= EXT2_ERROR_FS;
724 ext2fs_mark_super_dirty(fs);
725 err = ext2fs_set_gdt_csum(fs);
727 translate_error(fs, 0, err);
729 err = ext2fs_flush2(fs, 0);
731 translate_error(fs, 0, err);
735 static void *op_init(struct fuse_conn_info *conn
736 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
737 , struct fuse_config *cfg EXT2FS_ATTR((unused))
741 struct fuse_context *ctxt = fuse_get_context();
742 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
746 if (ff->magic != FUSE2FS_MAGIC) {
747 translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC);
751 dbg_printf("%s: dev=%s\n", __func__, fs->device_name);
752 #ifdef FUSE_CAP_IOCTL_DIR
753 conn->want |= FUSE_CAP_IOCTL_DIR;
755 if (fs->flags & EXT2_FLAG_RW) {
756 fs->super->s_mnt_count++;
757 ext2fs_set_tstamp(fs->super, s_mtime, time(NULL));
758 fs->super->s_state &= ~EXT2_VALID_FS;
759 ext2fs_mark_super_dirty(fs);
760 err = ext2fs_flush2(fs, 0);
762 translate_error(fs, 0, err);
767 static int stat_inode(ext2_filsys fs, ext2_ino_t ino, struct stat *statbuf)
769 struct ext2_inode_large inode;
775 memset(&inode, 0, sizeof(inode));
776 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
779 return translate_error(fs, ino, err);
781 memcpy(&fakedev, fs->super->s_uuid, sizeof(fakedev));
782 statbuf->st_dev = fakedev;
783 statbuf->st_ino = ino;
784 statbuf->st_mode = inode.i_mode;
785 statbuf->st_nlink = inode.i_links_count;
786 statbuf->st_uid = inode_uid(inode);
787 statbuf->st_gid = inode_gid(inode);
788 statbuf->st_size = EXT2_I_SIZE(&inode);
789 statbuf->st_blksize = fs->blocksize;
790 statbuf->st_blocks = ext2fs_get_stat_i_blocks(fs,
791 (struct ext2_inode *)&inode);
792 EXT4_INODE_GET_XTIME(i_atime, &tv, &inode);
793 statbuf->st_atime = tv.tv_sec;
794 EXT4_INODE_GET_XTIME(i_mtime, &tv, &inode);
795 statbuf->st_mtime = tv.tv_sec;
796 EXT4_INODE_GET_XTIME(i_ctime, &tv, &inode);
797 statbuf->st_ctime = tv.tv_sec;
798 if (LINUX_S_ISCHR(inode.i_mode) ||
799 LINUX_S_ISBLK(inode.i_mode)) {
800 if (inode.i_block[0])
801 statbuf->st_rdev = inode.i_block[0];
803 statbuf->st_rdev = inode.i_block[1];
809 static int op_getattr(const char *path, struct stat *statbuf
810 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
811 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
815 struct fuse_context *ctxt = fuse_get_context();
816 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
822 FUSE2FS_CHECK_CONTEXT(ff);
824 dbg_printf("%s: path=%s\n", __func__, path);
825 pthread_mutex_lock(&ff->bfl);
826 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
828 ret = translate_error(fs, 0, err);
831 ret = stat_inode(fs, ino, statbuf);
833 pthread_mutex_unlock(&ff->bfl);
837 static int op_readlink(const char *path, char *buf, size_t len)
839 struct fuse_context *ctxt = fuse_get_context();
840 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
844 struct ext2_inode inode;
849 FUSE2FS_CHECK_CONTEXT(ff);
851 dbg_printf("%s: path=%s\n", __func__, path);
852 pthread_mutex_lock(&ff->bfl);
853 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
854 if (err || ino == 0) {
855 ret = translate_error(fs, 0, err);
859 err = ext2fs_read_inode(fs, ino, &inode);
861 ret = translate_error(fs, ino, err);
865 if (!LINUX_S_ISLNK(inode.i_mode)) {
871 if (inode.i_size < len)
873 if (ext2fs_is_fast_symlink(&inode))
874 memcpy(buf, (char *)inode.i_block, len);
876 /* big/inline symlink */
878 err = ext2fs_file_open(fs, ino, 0, &file);
880 ret = translate_error(fs, ino, err);
884 err = ext2fs_file_read(file, buf, len, &got);
885 if (err || got != len) {
886 ext2fs_file_close(file);
887 ret = translate_error(fs, ino, err);
892 err = ext2fs_file_close(file);
896 ret = translate_error(fs, ino, err);
902 if (fs_writeable(fs)) {
903 ret = update_atime(fs, ino);
909 pthread_mutex_unlock(&ff->bfl);
913 static int op_mknod(const char *path, mode_t mode, dev_t dev)
915 struct fuse_context *ctxt = fuse_get_context();
916 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
918 ext2_ino_t parent, child;
923 struct ext2_inode_large inode;
926 FUSE2FS_CHECK_CONTEXT(ff);
928 dbg_printf("%s: path=%s mode=0%o dev=0x%x\n", __func__, path, mode,
930 temp_path = strdup(path);
935 node_name = strrchr(temp_path, '/');
944 pthread_mutex_lock(&ff->bfl);
945 if (!fs_can_allocate(ff, 2)) {
950 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
953 ret = translate_error(fs, 0, err);
957 ret = check_inum_access(fs, parent, W_OK);
963 if (LINUX_S_ISCHR(mode))
964 filetype = EXT2_FT_CHRDEV;
965 else if (LINUX_S_ISBLK(mode))
966 filetype = EXT2_FT_BLKDEV;
967 else if (LINUX_S_ISFIFO(mode))
968 filetype = EXT2_FT_FIFO;
969 else if (LINUX_S_ISSOCK(mode))
970 filetype = EXT2_FT_SOCK;
976 err = ext2fs_new_inode(fs, parent, mode, 0, &child);
978 ret = translate_error(fs, 0, err);
982 dbg_printf("%s: create ino=%d/name=%s in dir=%d\n", __func__, child,
984 err = ext2fs_link(fs, parent, node_name, child, filetype);
985 if (err == EXT2_ET_DIR_NO_SPACE) {
986 err = ext2fs_expand_dir(fs, parent);
988 ret = translate_error(fs, parent, err);
992 err = ext2fs_link(fs, parent, node_name, child,
996 ret = translate_error(fs, parent, err);
1000 ret = update_mtime(fs, parent, NULL);
1004 memset(&inode, 0, sizeof(inode));
1005 inode.i_mode = mode;
1008 inode.i_block[1] = dev;
1010 inode.i_block[0] = dev;
1011 inode.i_links_count = 1;
1012 inode.i_extra_isize = sizeof(struct ext2_inode_large) -
1013 EXT2_GOOD_OLD_INODE_SIZE;
1014 inode.i_uid = ctxt->uid;
1015 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
1016 inode.i_gid = ctxt->gid;
1017 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
1019 err = ext2fs_write_new_inode(fs, child, (struct ext2_inode *)&inode);
1021 ret = translate_error(fs, child, err);
1025 inode.i_generation = ff->next_generation++;
1027 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
1030 ret = translate_error(fs, child, err);
1034 ext2fs_inode_alloc_stats2(fs, child, 1, 0);
1037 pthread_mutex_unlock(&ff->bfl);
1043 static int op_mkdir(const char *path, mode_t mode)
1045 struct fuse_context *ctxt = fuse_get_context();
1046 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1048 ext2_ino_t parent, child;
1052 struct ext2_inode_large inode;
1058 FUSE2FS_CHECK_CONTEXT(ff);
1060 dbg_printf("%s: path=%s mode=0%o\n", __func__, path, mode);
1061 temp_path = strdup(path);
1066 node_name = strrchr(temp_path, '/');
1075 pthread_mutex_lock(&ff->bfl);
1076 if (!fs_can_allocate(ff, 1)) {
1081 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1084 ret = translate_error(fs, 0, err);
1088 ret = check_inum_access(fs, parent, W_OK);
1092 /* Is the parent dir sgid? */
1093 err = ext2fs_read_inode_full(fs, parent, (struct ext2_inode *)&inode,
1096 ret = translate_error(fs, parent, err);
1099 parent_sgid = inode.i_mode & S_ISGID;
1103 err = ext2fs_mkdir(fs, parent, 0, node_name);
1104 if (err == EXT2_ET_DIR_NO_SPACE) {
1105 err = ext2fs_expand_dir(fs, parent);
1107 ret = translate_error(fs, parent, err);
1111 err = ext2fs_mkdir(fs, parent, 0, node_name);
1114 ret = translate_error(fs, parent, err);
1118 ret = update_mtime(fs, parent, NULL);
1122 /* Still have to update the uid/gid of the dir */
1123 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1126 ret = translate_error(fs, 0, err);
1129 dbg_printf("%s: created ino=%d/path=%s in dir=%d\n", __func__, child,
1132 memset(&inode, 0, sizeof(inode));
1133 err = ext2fs_read_inode_full(fs, child, (struct ext2_inode *)&inode,
1136 ret = translate_error(fs, child, err);
1140 inode.i_uid = ctxt->uid;
1141 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
1142 inode.i_gid = ctxt->gid;
1143 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
1144 inode.i_mode = LINUX_S_IFDIR | (mode & ~S_ISUID) |
1146 inode.i_generation = ff->next_generation++;
1148 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
1151 ret = translate_error(fs, child, err);
1155 /* Rewrite the directory block checksum, having set i_generation */
1156 if ((inode.i_flags & EXT4_INLINE_DATA_FL) ||
1157 !ext2fs_has_feature_metadata_csum(fs->super))
1159 err = ext2fs_new_dir_block(fs, child, parent, &block);
1161 ret = translate_error(fs, child, err);
1164 err = ext2fs_bmap2(fs, child, (struct ext2_inode *)&inode, NULL, 0, 0,
1167 ret = translate_error(fs, child, err);
1170 err = ext2fs_write_dir_block4(fs, blk, block, 0, child);
1172 ret = translate_error(fs, child, err);
1177 ext2fs_free_mem(&block);
1179 pthread_mutex_unlock(&ff->bfl);
1185 static int unlink_file_by_name(ext2_filsys fs, const char *path)
1189 char *filename = strdup(path);
1193 base_name = strrchr(filename, '/');
1195 *base_name++ = '\0';
1196 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, filename,
1200 return translate_error(fs, 0, err);
1203 dir = EXT2_ROOT_INO;
1204 base_name = filename;
1207 ret = check_inum_access(fs, dir, W_OK);
1213 dbg_printf("%s: unlinking name=%s from dir=%d\n", __func__,
1215 err = ext2fs_unlink(fs, dir, base_name, 0, 0);
1218 return translate_error(fs, dir, err);
1220 return update_mtime(fs, dir, NULL);
1223 static int remove_inode(struct fuse2fs *ff, ext2_ino_t ino)
1225 ext2_filsys fs = ff->fs;
1227 struct ext2_inode_large inode;
1230 memset(&inode, 0, sizeof(inode));
1231 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1234 ret = translate_error(fs, ino, err);
1237 dbg_printf("%s: put ino=%d links=%d\n", __func__, ino,
1238 inode.i_links_count);
1240 switch (inode.i_links_count) {
1242 return 0; /* XXX: already done? */
1244 inode.i_links_count--;
1245 ext2fs_set_dtime(fs, EXT2_INODE(&inode));
1248 inode.i_links_count--;
1251 ret = update_ctime(fs, ino, &inode);
1255 if (inode.i_links_count)
1258 /* Nobody holds this file; free its blocks! */
1259 err = ext2fs_free_ext_attr(fs, ino, &inode);
1263 if (ext2fs_inode_has_valid_blocks2(fs, (struct ext2_inode *)&inode)) {
1264 err = ext2fs_punch(fs, ino, (struct ext2_inode *)&inode, NULL,
1267 ret = translate_error(fs, ino, err);
1272 ext2fs_inode_alloc_stats2(fs, ino, -1,
1273 LINUX_S_ISDIR(inode.i_mode));
1276 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
1279 ret = translate_error(fs, ino, err);
1286 static int __op_unlink(struct fuse2fs *ff, const char *path)
1288 ext2_filsys fs = ff->fs;
1293 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1295 ret = translate_error(fs, 0, err);
1299 ret = unlink_file_by_name(fs, path);
1303 ret = remove_inode(ff, ino);
1310 static int op_unlink(const char *path)
1312 struct fuse_context *ctxt = fuse_get_context();
1313 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1316 FUSE2FS_CHECK_CONTEXT(ff);
1317 pthread_mutex_lock(&ff->bfl);
1318 ret = __op_unlink(ff, path);
1319 pthread_mutex_unlock(&ff->bfl);
1328 static int rmdir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
1329 int entry EXT2FS_ATTR((unused)),
1330 struct ext2_dir_entry *dirent,
1331 int offset EXT2FS_ATTR((unused)),
1332 int blocksize EXT2FS_ATTR((unused)),
1333 char *buf EXT2FS_ATTR((unused)),
1336 struct rd_struct *rds = (struct rd_struct *) private;
1338 if (dirent->inode == 0)
1340 if (((dirent->name_len & 0xFF) == 1) && (dirent->name[0] == '.'))
1342 if (((dirent->name_len & 0xFF) == 2) && (dirent->name[0] == '.') &&
1343 (dirent->name[1] == '.')) {
1344 rds->parent = dirent->inode;
1351 static int __op_rmdir(struct fuse2fs *ff, const char *path)
1353 ext2_filsys fs = ff->fs;
1356 struct ext2_inode_large inode;
1357 struct rd_struct rds;
1360 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &child);
1362 ret = translate_error(fs, 0, err);
1365 dbg_printf("%s: rmdir path=%s ino=%d\n", __func__, path, child);
1370 err = ext2fs_dir_iterate2(fs, child, 0, 0, rmdir_proc, &rds);
1372 ret = translate_error(fs, child, err);
1376 if (rds.empty == 0) {
1381 ret = unlink_file_by_name(fs, path);
1384 /* Directories have to be "removed" twice. */
1385 ret = remove_inode(ff, child);
1388 ret = remove_inode(ff, child);
1393 dbg_printf("%s: decr dir=%d link count\n", __func__,
1395 err = ext2fs_read_inode_full(fs, rds.parent,
1396 (struct ext2_inode *)&inode,
1399 ret = translate_error(fs, rds.parent, err);
1402 if (inode.i_links_count > 1)
1403 inode.i_links_count--;
1404 ret = update_mtime(fs, rds.parent, &inode);
1407 err = ext2fs_write_inode_full(fs, rds.parent,
1408 (struct ext2_inode *)&inode,
1411 ret = translate_error(fs, rds.parent, err);
1420 static int op_rmdir(const char *path)
1422 struct fuse_context *ctxt = fuse_get_context();
1423 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1426 FUSE2FS_CHECK_CONTEXT(ff);
1427 pthread_mutex_lock(&ff->bfl);
1428 ret = __op_rmdir(ff, path);
1429 pthread_mutex_unlock(&ff->bfl);
1433 static int op_symlink(const char *src, const char *dest)
1435 struct fuse_context *ctxt = fuse_get_context();
1436 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1438 ext2_ino_t parent, child;
1442 struct ext2_inode_large inode;
1445 FUSE2FS_CHECK_CONTEXT(ff);
1447 dbg_printf("%s: symlink %s to %s\n", __func__, src, dest);
1448 temp_path = strdup(dest);
1453 node_name = strrchr(temp_path, '/');
1462 pthread_mutex_lock(&ff->bfl);
1463 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1467 ret = translate_error(fs, 0, err);
1471 ret = check_inum_access(fs, parent, W_OK);
1476 /* Create symlink */
1477 err = ext2fs_symlink(fs, parent, 0, node_name, src);
1478 if (err == EXT2_ET_DIR_NO_SPACE) {
1479 err = ext2fs_expand_dir(fs, parent);
1481 ret = translate_error(fs, parent, err);
1485 err = ext2fs_symlink(fs, parent, 0, node_name, src);
1488 ret = translate_error(fs, parent, err);
1492 /* Update parent dir's mtime */
1493 ret = update_mtime(fs, parent, NULL);
1497 /* Still have to update the uid/gid of the symlink */
1498 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1501 ret = translate_error(fs, 0, err);
1504 dbg_printf("%s: symlinking ino=%d/name=%s to dir=%d\n", __func__,
1505 child, node_name, parent);
1507 memset(&inode, 0, sizeof(inode));
1508 err = ext2fs_read_inode_full(fs, child, (struct ext2_inode *)&inode,
1511 ret = translate_error(fs, child, err);
1515 inode.i_uid = ctxt->uid;
1516 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
1517 inode.i_gid = ctxt->gid;
1518 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
1519 inode.i_generation = ff->next_generation++;
1521 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
1524 ret = translate_error(fs, child, err);
1528 pthread_mutex_unlock(&ff->bfl);
1534 struct update_dotdot {
1535 ext2_ino_t new_dotdot;
1538 static int update_dotdot_helper(ext2_ino_t dir EXT2FS_ATTR((unused)),
1539 int entry EXT2FS_ATTR((unused)),
1540 struct ext2_dir_entry *dirent,
1541 int offset EXT2FS_ATTR((unused)),
1542 int blocksize EXT2FS_ATTR((unused)),
1543 char *buf EXT2FS_ATTR((unused)),
1546 struct update_dotdot *ud = priv_data;
1548 if (ext2fs_dirent_name_len(dirent) == 2 &&
1549 dirent->name[0] == '.' && dirent->name[1] == '.') {
1550 dirent->inode = ud->new_dotdot;
1551 return DIRENT_CHANGED | DIRENT_ABORT;
1557 static int op_rename(const char *from, const char *to
1558 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1559 , unsigned int flags EXT2FS_ATTR((unused))
1563 struct fuse_context *ctxt = fuse_get_context();
1564 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1567 ext2_ino_t from_ino, to_ino, to_dir_ino, from_dir_ino;
1568 char *temp_to = NULL, *temp_from = NULL;
1570 struct ext2_inode inode;
1571 struct update_dotdot ud;
1574 FUSE2FS_CHECK_CONTEXT(ff);
1576 dbg_printf("%s: renaming %s to %s\n", __func__, from, to);
1577 pthread_mutex_lock(&ff->bfl);
1578 if (!fs_can_allocate(ff, 5)) {
1583 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, from, &from_ino);
1584 if (err || from_ino == 0) {
1585 ret = translate_error(fs, 0, err);
1589 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, to, &to_ino);
1590 if (err && err != EXT2_ET_FILE_NOT_FOUND) {
1591 ret = translate_error(fs, 0, err);
1595 if (err == EXT2_ET_FILE_NOT_FOUND)
1598 /* Already the same file? */
1599 if (to_ino != 0 && to_ino == from_ino) {
1604 temp_to = strdup(to);
1610 temp_from = strdup(from);
1616 /* Find parent dir of the source and check write access */
1617 cp = strrchr(temp_from, '/');
1625 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_from,
1629 ret = translate_error(fs, 0, err);
1632 if (from_dir_ino == 0) {
1637 ret = check_inum_access(fs, from_dir_ino, W_OK);
1641 /* Find parent dir of the destination and check write access */
1642 cp = strrchr(temp_to, '/');
1650 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_to,
1654 ret = translate_error(fs, 0, err);
1657 if (to_dir_ino == 0) {
1662 ret = check_inum_access(fs, to_dir_ino, W_OK);
1666 /* If the target exists, unlink it first */
1668 err = ext2fs_read_inode(fs, to_ino, &inode);
1670 ret = translate_error(fs, to_ino, err);
1674 dbg_printf("%s: unlinking %s ino=%d\n", __func__,
1675 LINUX_S_ISDIR(inode.i_mode) ? "dir" : "file",
1677 if (LINUX_S_ISDIR(inode.i_mode))
1678 ret = __op_rmdir(ff, to);
1680 ret = __op_unlink(ff, to);
1685 /* Get ready to do the move */
1686 err = ext2fs_read_inode(fs, from_ino, &inode);
1688 ret = translate_error(fs, from_ino, err);
1692 /* Link in the new file */
1693 dbg_printf("%s: linking ino=%d/path=%s to dir=%d\n", __func__,
1694 from_ino, cp + 1, to_dir_ino);
1695 err = ext2fs_link(fs, to_dir_ino, cp + 1, from_ino,
1696 ext2_file_type(inode.i_mode));
1697 if (err == EXT2_ET_DIR_NO_SPACE) {
1698 err = ext2fs_expand_dir(fs, to_dir_ino);
1700 ret = translate_error(fs, to_dir_ino, err);
1704 err = ext2fs_link(fs, to_dir_ino, cp + 1, from_ino,
1705 ext2_file_type(inode.i_mode));
1708 ret = translate_error(fs, to_dir_ino, err);
1712 /* Update '..' pointer if dir */
1713 err = ext2fs_read_inode(fs, from_ino, &inode);
1715 ret = translate_error(fs, from_ino, err);
1719 if (LINUX_S_ISDIR(inode.i_mode)) {
1720 ud.new_dotdot = to_dir_ino;
1721 dbg_printf("%s: updating .. entry for dir=%d\n", __func__,
1723 err = ext2fs_dir_iterate2(fs, from_ino, 0, NULL,
1724 update_dotdot_helper, &ud);
1726 ret = translate_error(fs, from_ino, err);
1730 /* Decrease from_dir_ino's links_count */
1731 dbg_printf("%s: moving linkcount from dir=%d to dir=%d\n",
1732 __func__, from_dir_ino, to_dir_ino);
1733 err = ext2fs_read_inode(fs, from_dir_ino, &inode);
1735 ret = translate_error(fs, from_dir_ino, err);
1738 inode.i_links_count--;
1739 err = ext2fs_write_inode(fs, from_dir_ino, &inode);
1741 ret = translate_error(fs, from_dir_ino, err);
1745 /* Increase to_dir_ino's links_count */
1746 err = ext2fs_read_inode(fs, to_dir_ino, &inode);
1748 ret = translate_error(fs, to_dir_ino, err);
1751 inode.i_links_count++;
1752 err = ext2fs_write_inode(fs, to_dir_ino, &inode);
1754 ret = translate_error(fs, to_dir_ino, err);
1759 /* Update timestamps */
1760 ret = update_ctime(fs, from_ino, NULL);
1764 ret = update_mtime(fs, to_dir_ino, NULL);
1768 /* Remove the old file */
1769 ret = unlink_file_by_name(fs, from);
1773 /* Flush the whole mess out */
1774 err = ext2fs_flush2(fs, 0);
1776 ret = translate_error(fs, 0, err);
1782 pthread_mutex_unlock(&ff->bfl);
1786 static int op_link(const char *src, const char *dest)
1788 struct fuse_context *ctxt = fuse_get_context();
1789 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1794 ext2_ino_t parent, ino;
1795 struct ext2_inode_large inode;
1798 FUSE2FS_CHECK_CONTEXT(ff);
1800 dbg_printf("%s: src=%s dest=%s\n", __func__, src, dest);
1801 temp_path = strdup(dest);
1806 node_name = strrchr(temp_path, '/');
1815 pthread_mutex_lock(&ff->bfl);
1816 if (!fs_can_allocate(ff, 2)) {
1821 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1829 ret = check_inum_access(fs, parent, W_OK);
1834 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, src, &ino);
1835 if (err || ino == 0) {
1836 ret = translate_error(fs, 0, err);
1840 memset(&inode, 0, sizeof(inode));
1841 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1844 ret = translate_error(fs, ino, err);
1848 inode.i_links_count++;
1849 ret = update_ctime(fs, ino, &inode);
1853 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
1856 ret = translate_error(fs, ino, err);
1860 dbg_printf("%s: linking ino=%d/name=%s to dir=%d\n", __func__, ino,
1862 err = ext2fs_link(fs, parent, node_name, ino,
1863 ext2_file_type(inode.i_mode));
1864 if (err == EXT2_ET_DIR_NO_SPACE) {
1865 err = ext2fs_expand_dir(fs, parent);
1867 ret = translate_error(fs, parent, err);
1871 err = ext2fs_link(fs, parent, node_name, ino,
1872 ext2_file_type(inode.i_mode));
1875 ret = translate_error(fs, parent, err);
1879 ret = update_mtime(fs, parent, NULL);
1884 pthread_mutex_unlock(&ff->bfl);
1890 static int op_chmod(const char *path, mode_t mode
1891 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1892 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
1896 struct fuse_context *ctxt = fuse_get_context();
1897 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1901 struct ext2_inode_large inode;
1904 FUSE2FS_CHECK_CONTEXT(ff);
1906 pthread_mutex_lock(&ff->bfl);
1907 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1909 ret = translate_error(fs, 0, err);
1912 dbg_printf("%s: path=%s mode=0%o ino=%d\n", __func__, path, mode, ino);
1914 memset(&inode, 0, sizeof(inode));
1915 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1918 ret = translate_error(fs, ino, err);
1922 if (!ff->fakeroot && ctxt->uid != 0 && ctxt->uid != inode_uid(inode)) {
1928 * XXX: We should really check that the inode gid is not in /any/
1929 * of the user's groups, but FUSE only tells us about the primary
1932 if (!ff->fakeroot && ctxt->uid != 0 && ctxt->gid != inode_gid(inode))
1935 inode.i_mode &= ~0xFFF;
1936 inode.i_mode |= mode & 0xFFF;
1937 ret = update_ctime(fs, ino, &inode);
1941 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
1944 ret = translate_error(fs, ino, err);
1949 pthread_mutex_unlock(&ff->bfl);
1953 static int op_chown(const char *path, uid_t owner, gid_t group
1954 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1955 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
1959 struct fuse_context *ctxt = fuse_get_context();
1960 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1964 struct ext2_inode_large inode;
1967 FUSE2FS_CHECK_CONTEXT(ff);
1969 pthread_mutex_lock(&ff->bfl);
1970 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1972 ret = translate_error(fs, 0, err);
1975 dbg_printf("%s: path=%s owner=%d group=%d ino=%d\n", __func__,
1976 path, owner, group, ino);
1978 memset(&inode, 0, sizeof(inode));
1979 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
1982 ret = translate_error(fs, ino, err);
1986 /* FUSE seems to feed us ~0 to mean "don't change" */
1987 if (owner != (uid_t) ~0) {
1988 /* Only root gets to change UID. */
1989 if (!ff->fakeroot && ctxt->uid != 0 &&
1990 !(inode_uid(inode) == ctxt->uid && owner == ctxt->uid)) {
1994 inode.i_uid = owner;
1995 ext2fs_set_i_uid_high(inode, owner >> 16);
1998 if (group != (gid_t) ~0) {
1999 /* Only root or the owner get to change GID. */
2000 if (!ff->fakeroot && ctxt->uid != 0 &&
2001 inode_uid(inode) != ctxt->uid) {
2006 /* XXX: We /should/ check group membership but FUSE */
2007 inode.i_gid = group;
2008 ext2fs_set_i_gid_high(inode, group >> 16);
2011 ret = update_ctime(fs, ino, &inode);
2015 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
2018 ret = translate_error(fs, ino, err);
2023 pthread_mutex_unlock(&ff->bfl);
2027 static int op_truncate(const char *path, off_t len
2028 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
2029 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
2033 struct fuse_context *ctxt = fuse_get_context();
2034 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2041 FUSE2FS_CHECK_CONTEXT(ff);
2043 pthread_mutex_lock(&ff->bfl);
2044 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2045 if (err || ino == 0) {
2046 ret = translate_error(fs, 0, err);
2049 dbg_printf("%s: ino=%d len=%jd\n", __func__, ino, len);
2051 ret = check_inum_access(fs, ino, W_OK);
2055 err = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &file);
2057 ret = translate_error(fs, ino, err);
2061 err = ext2fs_file_set_size2(file, len);
2063 ret = translate_error(fs, ino, err);
2068 err = ext2fs_file_close(file);
2072 ret = translate_error(fs, ino, err);
2076 ret = update_mtime(fs, ino, NULL);
2079 pthread_mutex_unlock(&ff->bfl);
2084 static void detect_linux_executable_open(int kernel_flags, int *access_check,
2085 int *e2fs_open_flags)
2088 * On Linux, execve will bleed __FMODE_EXEC into the file mode flags,
2089 * and FUSE is more than happy to let that slip through.
2091 if (kernel_flags & 0x20) {
2092 *access_check = X_OK;
2093 *e2fs_open_flags &= ~EXT2_FILE_WRITE;
2097 static void detect_linux_executable_open(int kernel_flags, int *access_check,
2098 int *e2fs_open_flags)
2102 #endif /* __linux__ */
2104 static int __op_open(struct fuse2fs *ff, const char *path,
2105 struct fuse_file_info *fp)
2107 ext2_filsys fs = ff->fs;
2109 struct fuse2fs_file_handle *file;
2110 int check = 0, ret = 0;
2112 dbg_printf("%s: path=%s\n", __func__, path);
2113 err = ext2fs_get_mem(sizeof(*file), &file);
2115 return translate_error(fs, 0, err);
2116 file->magic = FUSE2FS_FILE_MAGIC;
2118 file->open_flags = 0;
2119 switch (fp->flags & O_ACCMODE) {
2125 file->open_flags |= EXT2_FILE_WRITE;
2128 check = R_OK | W_OK;
2129 file->open_flags |= EXT2_FILE_WRITE;
2133 detect_linux_executable_open(fp->flags, &check, &file->open_flags);
2135 if (fp->flags & O_CREAT)
2136 file->open_flags |= EXT2_FILE_CREATE;
2138 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &file->ino);
2139 if (err || file->ino == 0) {
2140 ret = translate_error(fs, 0, err);
2143 dbg_printf("%s: ino=%d\n", __func__, file->ino);
2145 ret = check_inum_access(fs, file->ino, check);
2148 * In a regular (Linux) fs driver, the kernel will open
2149 * binaries for reading if the user has --x privileges (i.e.
2150 * execute without read). Since the kernel doesn't have any
2151 * way to tell us if it's opening a file via execve, we'll
2152 * just assume that allowing access is ok if asking for ro mode
2153 * fails but asking for x mode succeeds. Of course we can
2154 * also employ undocumented hacks (see above).
2156 if (check == R_OK) {
2157 ret = check_inum_access(fs, file->ino, X_OK);
2163 fp->fh = (uintptr_t)file;
2167 ext2fs_free_mem(&file);
2171 static int op_open(const char *path, struct fuse_file_info *fp)
2173 struct fuse_context *ctxt = fuse_get_context();
2174 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2177 FUSE2FS_CHECK_CONTEXT(ff);
2178 pthread_mutex_lock(&ff->bfl);
2179 ret = __op_open(ff, path, fp);
2180 pthread_mutex_unlock(&ff->bfl);
2184 static int op_read(const char *path EXT2FS_ATTR((unused)), char *buf,
2185 size_t len, off_t offset,
2186 struct fuse_file_info *fp)
2188 struct fuse_context *ctxt = fuse_get_context();
2189 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2190 struct fuse2fs_file_handle *fh =
2191 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2195 unsigned int got = 0;
2198 FUSE2FS_CHECK_CONTEXT(ff);
2200 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2201 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino, offset,
2203 pthread_mutex_lock(&ff->bfl);
2204 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
2206 ret = translate_error(fs, fh->ino, err);
2210 err = ext2fs_file_llseek(efp, offset, SEEK_SET, NULL);
2212 ret = translate_error(fs, fh->ino, err);
2216 err = ext2fs_file_read(efp, buf, len, &got);
2218 ret = translate_error(fs, fh->ino, err);
2223 err = ext2fs_file_close(efp);
2227 ret = translate_error(fs, fh->ino, err);
2231 if (fs_writeable(fs)) {
2232 ret = update_atime(fs, fh->ino);
2237 pthread_mutex_unlock(&ff->bfl);
2238 return got ? (int) got : ret;
2241 static int op_write(const char *path EXT2FS_ATTR((unused)),
2242 const char *buf, size_t len, off_t offset,
2243 struct fuse_file_info *fp)
2245 struct fuse_context *ctxt = fuse_get_context();
2246 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2247 struct fuse2fs_file_handle *fh =
2248 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2252 unsigned int got = 0;
2255 FUSE2FS_CHECK_CONTEXT(ff);
2257 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2258 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino, offset,
2260 pthread_mutex_lock(&ff->bfl);
2261 if (!fs_writeable(fs)) {
2266 if (!fs_can_allocate(ff, len / fs->blocksize)) {
2271 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
2273 ret = translate_error(fs, fh->ino, err);
2277 err = ext2fs_file_llseek(efp, offset, SEEK_SET, NULL);
2279 ret = translate_error(fs, fh->ino, err);
2283 err = ext2fs_file_write(efp, buf, len, &got);
2285 ret = translate_error(fs, fh->ino, err);
2289 err = ext2fs_file_flush(efp);
2292 ret = translate_error(fs, fh->ino, err);
2297 err = ext2fs_file_close(efp);
2301 ret = translate_error(fs, fh->ino, err);
2305 ret = update_mtime(fs, fh->ino, NULL);
2310 pthread_mutex_unlock(&ff->bfl);
2311 return got ? (int) got : ret;
2314 static int op_release(const char *path EXT2FS_ATTR((unused)),
2315 struct fuse_file_info *fp)
2317 struct fuse_context *ctxt = fuse_get_context();
2318 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2319 struct fuse2fs_file_handle *fh =
2320 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2325 FUSE2FS_CHECK_CONTEXT(ff);
2327 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2328 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
2329 pthread_mutex_lock(&ff->bfl);
2330 if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) {
2331 err = ext2fs_flush2(fs, EXT2_FLAG_FLUSH_NO_SYNC);
2333 ret = translate_error(fs, fh->ino, err);
2336 pthread_mutex_unlock(&ff->bfl);
2338 ext2fs_free_mem(&fh);
2343 static int op_fsync(const char *path EXT2FS_ATTR((unused)),
2344 int datasync EXT2FS_ATTR((unused)),
2345 struct fuse_file_info *fp)
2347 struct fuse_context *ctxt = fuse_get_context();
2348 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2349 struct fuse2fs_file_handle *fh =
2350 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2355 FUSE2FS_CHECK_CONTEXT(ff);
2357 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2358 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
2359 /* For now, flush everything, even if it's slow */
2360 pthread_mutex_lock(&ff->bfl);
2361 if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) {
2362 err = ext2fs_flush2(fs, 0);
2364 ret = translate_error(fs, fh->ino, err);
2366 pthread_mutex_unlock(&ff->bfl);
2371 static int op_statfs(const char *path EXT2FS_ATTR((unused)),
2372 struct statvfs *buf)
2374 struct fuse_context *ctxt = fuse_get_context();
2375 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2378 blk64_t overhead, reserved, free;
2380 FUSE2FS_CHECK_CONTEXT(ff);
2382 dbg_printf("%s: path=%s\n", __func__, path);
2383 buf->f_bsize = fs->blocksize;
2389 overhead = fs->desc_blocks +
2390 (blk64_t)fs->group_desc_count *
2391 (fs->inode_blocks_per_group + 2);
2392 reserved = ext2fs_r_blocks_count(fs->super);
2394 reserved = ext2fs_blocks_count(fs->super) / 10;
2395 free = ext2fs_free_blocks_count(fs->super);
2397 buf->f_blocks = ext2fs_blocks_count(fs->super) - overhead;
2398 buf->f_bfree = free;
2399 if (free < reserved)
2402 buf->f_bavail = free - reserved;
2403 buf->f_files = fs->super->s_inodes_count;
2404 buf->f_ffree = fs->super->s_free_inodes_count;
2405 buf->f_favail = fs->super->s_free_inodes_count;
2406 f = (uint64_t *)fs->super->s_uuid;
2412 if (fs->flags & EXT2_FLAG_RW)
2413 buf->f_flag |= ST_RDONLY;
2414 buf->f_namemax = EXT2_NAME_LEN;
2419 typedef errcode_t (*xattr_xlate_get)(void **cooked_buf, size_t *cooked_sz,
2420 const void *raw_buf, size_t raw_sz);
2421 typedef errcode_t (*xattr_xlate_set)(const void *cooked_buf, size_t cooked_sz,
2422 const void **raw_buf, size_t *raw_sz);
2423 struct xattr_translate {
2425 xattr_xlate_get get;
2426 xattr_xlate_set set;
2429 #define XATTR_TRANSLATOR(p, g, s) \
2431 .get = (xattr_xlate_get)(g), \
2432 .set = (xattr_xlate_set)(s)}
2434 static struct xattr_translate xattr_translators[] = {
2435 #ifdef TRANSLATE_LINUX_ACLS
2436 XATTR_TRANSLATOR(ACL_EA_ACCESS, ext4_to_fuse_acl, fuse_to_ext4_acl),
2437 XATTR_TRANSLATOR(ACL_EA_DEFAULT, ext4_to_fuse_acl, fuse_to_ext4_acl),
2439 XATTR_TRANSLATOR(NULL, NULL, NULL),
2441 #undef XATTR_TRANSLATOR
2443 static int op_getxattr(const char *path, const char *key, char *value,
2446 struct fuse_context *ctxt = fuse_get_context();
2447 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2449 struct ext2_xattr_handle *h;
2450 struct xattr_translate *xt;
2457 FUSE2FS_CHECK_CONTEXT(ff);
2459 pthread_mutex_lock(&ff->bfl);
2460 if (!ext2fs_has_feature_xattr(fs->super)) {
2465 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2466 if (err || ino == 0) {
2467 ret = translate_error(fs, 0, err);
2470 dbg_printf("%s: ino=%d\n", __func__, ino);
2472 ret = check_inum_access(fs, ino, R_OK);
2476 err = ext2fs_xattrs_open(fs, ino, &h);
2478 ret = translate_error(fs, ino, err);
2482 err = ext2fs_xattrs_read(h);
2484 ret = translate_error(fs, ino, err);
2488 err = ext2fs_xattr_get(h, key, &ptr, &plen);
2490 ret = translate_error(fs, ino, err);
2494 for (xt = xattr_translators; xt->prefix != NULL; xt++) {
2495 if (strncmp(key, xt->prefix, strlen(xt->prefix)) == 0) {
2496 err = xt->get(&cptr, &clen, ptr, plen);
2499 ext2fs_free_mem(&ptr);
2507 } else if (len < plen) {
2510 memcpy(value, ptr, plen);
2515 ext2fs_free_mem(&ptr);
2517 err = ext2fs_xattrs_close(&h);
2519 ret = translate_error(fs, ino, err);
2521 pthread_mutex_unlock(&ff->bfl);
2526 static int count_buffer_space(char *name, char *value EXT2FS_ATTR((unused)),
2527 size_t value_len EXT2FS_ATTR((unused)),
2528 ext2_ino_t inode_num EXT2FS_ATTR((unused)),
2531 unsigned int *x = data;
2533 *x = *x + strlen(name) + 1;
2537 static int copy_names(char *name, char *value EXT2FS_ATTR((unused)),
2538 size_t value_len EXT2FS_ATTR((unused)),
2539 ext2_ino_t inode_num EXT2FS_ATTR((unused)),
2543 size_t name_len = strlen(name);
2545 memcpy(*b, name, name_len + 1);
2546 *b = *b + name_len + 1;
2551 static int op_listxattr(const char *path, char *names, size_t len)
2553 struct fuse_context *ctxt = fuse_get_context();
2554 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2556 struct ext2_xattr_handle *h;
2562 FUSE2FS_CHECK_CONTEXT(ff);
2564 pthread_mutex_lock(&ff->bfl);
2565 if (!ext2fs_has_feature_xattr(fs->super)) {
2570 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2571 if (err || ino == 0) {
2572 ret = translate_error(fs, ino, err);
2575 dbg_printf("%s: ino=%d\n", __func__, ino);
2577 ret = check_inum_access(fs, ino, R_OK);
2581 err = ext2fs_xattrs_open(fs, ino, &h);
2583 ret = translate_error(fs, ino, err);
2587 err = ext2fs_xattrs_read(h);
2589 ret = translate_error(fs, ino, err);
2593 /* Count buffer space needed for names */
2595 err = ext2fs_xattrs_iterate(h, count_buffer_space, &bufsz);
2597 ret = translate_error(fs, ino, err);
2604 } else if (len < bufsz) {
2609 /* Copy names out */
2610 memset(names, 0, len);
2611 err = ext2fs_xattrs_iterate(h, copy_names, &names);
2613 ret = translate_error(fs, ino, err);
2618 err = ext2fs_xattrs_close(&h);
2620 ret = translate_error(fs, ino, err);
2622 pthread_mutex_unlock(&ff->bfl);
2627 static int op_setxattr(const char *path EXT2FS_ATTR((unused)),
2628 const char *key, const char *value,
2629 size_t len, int flags EXT2FS_ATTR((unused)))
2631 struct fuse_context *ctxt = fuse_get_context();
2632 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2634 struct ext2_xattr_handle *h;
2635 struct xattr_translate *xt;
2642 FUSE2FS_CHECK_CONTEXT(ff);
2644 pthread_mutex_lock(&ff->bfl);
2645 if (!ext2fs_has_feature_xattr(fs->super)) {
2650 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2651 if (err || ino == 0) {
2652 ret = translate_error(fs, 0, err);
2655 dbg_printf("%s: ino=%d\n", __func__, ino);
2657 ret = check_inum_access(fs, ino, W_OK);
2658 if (ret == -EACCES) {
2664 err = ext2fs_xattrs_open(fs, ino, &h);
2666 ret = translate_error(fs, ino, err);
2670 err = ext2fs_xattrs_read(h);
2672 ret = translate_error(fs, ino, err);
2678 for (xt = xattr_translators; xt->prefix != NULL; xt++) {
2679 if (strncmp(key, xt->prefix, strlen(xt->prefix)) == 0) {
2680 err = xt->set(value, len, &cvalue, &clen);
2686 err = ext2fs_xattr_set(h, key, cvalue, clen);
2688 ret = translate_error(fs, ino, err);
2692 ret = update_ctime(fs, ino, NULL);
2694 if (cvalue != value)
2695 ext2fs_free_mem(&cvalue);
2697 err = ext2fs_xattrs_close(&h);
2699 ret = translate_error(fs, ino, err);
2701 pthread_mutex_unlock(&ff->bfl);
2706 static int op_removexattr(const char *path, const char *key)
2708 struct fuse_context *ctxt = fuse_get_context();
2709 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2711 struct ext2_xattr_handle *h;
2716 FUSE2FS_CHECK_CONTEXT(ff);
2718 pthread_mutex_lock(&ff->bfl);
2719 if (!ext2fs_has_feature_xattr(fs->super)) {
2724 if (!fs_can_allocate(ff, 1)) {
2729 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2730 if (err || ino == 0) {
2731 ret = translate_error(fs, 0, err);
2734 dbg_printf("%s: ino=%d\n", __func__, ino);
2736 ret = check_inum_access(fs, ino, W_OK);
2740 err = ext2fs_xattrs_open(fs, ino, &h);
2742 ret = translate_error(fs, ino, err);
2746 err = ext2fs_xattrs_read(h);
2748 ret = translate_error(fs, ino, err);
2752 err = ext2fs_xattr_remove(h, key);
2754 ret = translate_error(fs, ino, err);
2758 ret = update_ctime(fs, ino, NULL);
2760 err = ext2fs_xattrs_close(&h);
2762 ret = translate_error(fs, ino, err);
2764 pthread_mutex_unlock(&ff->bfl);
2769 struct readdir_iter {
2771 fuse_fill_dir_t func;
2774 static int op_readdir_iter(ext2_ino_t dir EXT2FS_ATTR((unused)),
2775 int entry EXT2FS_ATTR((unused)),
2776 struct ext2_dir_entry *dirent,
2777 int offset EXT2FS_ATTR((unused)),
2778 int blocksize EXT2FS_ATTR((unused)),
2779 char *buf EXT2FS_ATTR((unused)), void *data)
2781 struct readdir_iter *i = data;
2782 char namebuf[EXT2_NAME_LEN + 1];
2785 memcpy(namebuf, dirent->name, dirent->name_len & 0xFF);
2786 namebuf[dirent->name_len & 0xFF] = 0;
2787 ret = i->func(i->buf, namebuf, NULL, 0
2788 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
2793 return DIRENT_ABORT;
2798 static int op_readdir(const char *path EXT2FS_ATTR((unused)),
2799 void *buf, fuse_fill_dir_t fill_func,
2800 off_t offset EXT2FS_ATTR((unused)),
2801 struct fuse_file_info *fp
2802 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
2803 , enum fuse_readdir_flags flags EXT2FS_ATTR((unused))
2807 struct fuse_context *ctxt = fuse_get_context();
2808 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2809 struct fuse2fs_file_handle *fh =
2810 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2813 struct readdir_iter i;
2816 FUSE2FS_CHECK_CONTEXT(ff);
2818 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2819 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
2820 pthread_mutex_lock(&ff->bfl);
2823 err = ext2fs_dir_iterate2(fs, fh->ino, 0, NULL, op_readdir_iter, &i);
2825 ret = translate_error(fs, fh->ino, err);
2829 if (fs_writeable(fs)) {
2830 ret = update_atime(fs, fh->ino);
2835 pthread_mutex_unlock(&ff->bfl);
2839 static int op_access(const char *path, int mask)
2841 struct fuse_context *ctxt = fuse_get_context();
2842 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2848 FUSE2FS_CHECK_CONTEXT(ff);
2850 dbg_printf("%s: path=%s mask=0x%x\n", __func__, path, mask);
2851 pthread_mutex_lock(&ff->bfl);
2852 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2853 if (err || ino == 0) {
2854 ret = translate_error(fs, 0, err);
2858 ret = check_inum_access(fs, ino, mask);
2863 pthread_mutex_unlock(&ff->bfl);
2867 static int op_create(const char *path, mode_t mode, struct fuse_file_info *fp)
2869 struct fuse_context *ctxt = fuse_get_context();
2870 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2872 ext2_ino_t parent, child;
2877 struct ext2_inode_large inode;
2880 FUSE2FS_CHECK_CONTEXT(ff);
2882 dbg_printf("%s: path=%s mode=0%o\n", __func__, path, mode);
2883 temp_path = strdup(path);
2888 node_name = strrchr(temp_path, '/');
2897 pthread_mutex_lock(&ff->bfl);
2898 if (!fs_can_allocate(ff, 1)) {
2903 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
2906 ret = translate_error(fs, 0, err);
2910 ret = check_inum_access(fs, parent, W_OK);
2916 filetype = ext2_file_type(mode);
2918 err = ext2fs_new_inode(fs, parent, mode, 0, &child);
2920 ret = translate_error(fs, parent, err);
2924 dbg_printf("%s: creating ino=%d/name=%s in dir=%d\n", __func__, child,
2926 err = ext2fs_link(fs, parent, node_name, child, filetype);
2927 if (err == EXT2_ET_DIR_NO_SPACE) {
2928 err = ext2fs_expand_dir(fs, parent);
2930 ret = translate_error(fs, parent, err);
2934 err = ext2fs_link(fs, parent, node_name, child,
2938 ret = translate_error(fs, parent, err);
2942 ret = update_mtime(fs, parent, NULL);
2946 memset(&inode, 0, sizeof(inode));
2947 inode.i_mode = mode;
2948 inode.i_links_count = 1;
2949 inode.i_extra_isize = sizeof(struct ext2_inode_large) -
2950 EXT2_GOOD_OLD_INODE_SIZE;
2951 inode.i_uid = ctxt->uid;
2952 ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
2953 inode.i_gid = ctxt->gid;
2954 ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
2955 if (ext2fs_has_feature_extents(fs->super)) {
2956 ext2_extent_handle_t handle;
2958 inode.i_flags &= ~EXT4_EXTENTS_FL;
2959 ret = ext2fs_extent_open2(fs, child,
2960 (struct ext2_inode *)&inode, &handle);
2963 ext2fs_extent_free(handle);
2966 err = ext2fs_write_new_inode(fs, child, (struct ext2_inode *)&inode);
2968 ret = translate_error(fs, child, err);
2972 inode.i_generation = ff->next_generation++;
2974 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
2977 ret = translate_error(fs, child, err);
2981 ext2fs_inode_alloc_stats2(fs, child, 1, 0);
2983 ret = __op_open(ff, path, fp);
2987 pthread_mutex_unlock(&ff->bfl);
2993 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
2994 static int op_ftruncate(const char *path EXT2FS_ATTR((unused)),
2995 off_t len, struct fuse_file_info *fp)
2997 struct fuse_context *ctxt = fuse_get_context();
2998 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2999 struct fuse2fs_file_handle *fh =
3000 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3006 FUSE2FS_CHECK_CONTEXT(ff);
3008 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3009 dbg_printf("%s: ino=%d len=%jd\n", __func__, fh->ino, len);
3010 pthread_mutex_lock(&ff->bfl);
3011 if (!fs_writeable(fs)) {
3016 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
3018 ret = translate_error(fs, fh->ino, err);
3022 err = ext2fs_file_set_size2(efp, len);
3024 ret = translate_error(fs, fh->ino, err);
3029 err = ext2fs_file_close(efp);
3033 ret = translate_error(fs, fh->ino, err);
3037 ret = update_mtime(fs, fh->ino, NULL);
3042 pthread_mutex_unlock(&ff->bfl);
3046 static int op_fgetattr(const char *path EXT2FS_ATTR((unused)),
3047 struct stat *statbuf,
3048 struct fuse_file_info *fp)
3050 struct fuse_context *ctxt = fuse_get_context();
3051 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3053 struct fuse2fs_file_handle *fh =
3054 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3057 FUSE2FS_CHECK_CONTEXT(ff);
3059 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3060 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3061 pthread_mutex_lock(&ff->bfl);
3062 ret = stat_inode(fs, fh->ino, statbuf);
3063 pthread_mutex_unlock(&ff->bfl);
3067 #endif /* FUSE_VERSION < FUSE_MAKE_VERSION(3, 0) */
3069 static int op_utimens(const char *path, const struct timespec ctv[2]
3070 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
3071 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
3075 struct fuse_context *ctxt = fuse_get_context();
3076 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3077 struct timespec tv[2];
3081 struct ext2_inode_large inode;
3084 FUSE2FS_CHECK_CONTEXT(ff);
3086 pthread_mutex_lock(&ff->bfl);
3087 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
3089 ret = translate_error(fs, 0, err);
3092 dbg_printf("%s: ino=%d\n", __func__, ino);
3094 ret = check_inum_access(fs, ino, W_OK);
3098 memset(&inode, 0, sizeof(inode));
3099 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
3102 ret = translate_error(fs, ino, err);
3109 if (tv[0].tv_nsec == UTIME_NOW)
3111 if (tv[1].tv_nsec == UTIME_NOW)
3113 #endif /* UTIME_NOW */
3115 if (tv[0].tv_nsec != UTIME_OMIT)
3116 EXT4_INODE_SET_XTIME(i_atime, tv, &inode);
3117 if (tv[1].tv_nsec != UTIME_OMIT)
3118 EXT4_INODE_SET_XTIME(i_mtime, tv + 1, &inode);
3119 #endif /* UTIME_OMIT */
3120 ret = update_ctime(fs, ino, &inode);
3124 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
3127 ret = translate_error(fs, ino, err);
3132 pthread_mutex_unlock(&ff->bfl);
3136 #ifdef SUPPORT_I_FLAGS
3137 static int ioctl_getflags(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3141 struct ext2_inode_large inode;
3143 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3144 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3145 memset(&inode, 0, sizeof(inode));
3146 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3149 return translate_error(fs, fh->ino, err);
3151 *(__u32 *)data = inode.i_flags & EXT2_FL_USER_VISIBLE;
3155 #define FUSE2FS_MODIFIABLE_IFLAGS \
3156 (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL | EXT2_NODUMP_FL | \
3157 EXT2_NOATIME_FL | EXT3_JOURNAL_DATA_FL | EXT2_DIRSYNC_FL | \
3160 static int ioctl_setflags(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3164 struct ext2_inode_large inode;
3166 __u32 flags = *(__u32 *)data;
3167 struct fuse_context *ctxt = fuse_get_context();
3168 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3170 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3171 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3172 memset(&inode, 0, sizeof(inode));
3173 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3176 return translate_error(fs, fh->ino, err);
3178 if (!ff->fakeroot && ctxt->uid != 0 && inode_uid(inode) != ctxt->uid)
3181 if ((inode.i_flags ^ flags) & ~FUSE2FS_MODIFIABLE_IFLAGS)
3184 inode.i_flags = (inode.i_flags & ~FUSE2FS_MODIFIABLE_IFLAGS) |
3185 (flags & FUSE2FS_MODIFIABLE_IFLAGS);
3187 ret = update_ctime(fs, fh->ino, &inode);
3191 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3194 return translate_error(fs, fh->ino, err);
3199 static int ioctl_getversion(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3203 struct ext2_inode_large inode;
3205 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3206 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3207 memset(&inode, 0, sizeof(inode));
3208 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3211 return translate_error(fs, fh->ino, err);
3213 *(__u32 *)data = inode.i_generation;
3217 static int ioctl_setversion(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3221 struct ext2_inode_large inode;
3223 __u32 generation = *(__u32 *)data;
3224 struct fuse_context *ctxt = fuse_get_context();
3225 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3227 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3228 dbg_printf("%s: ino=%d\n", __func__, fh->ino);
3229 memset(&inode, 0, sizeof(inode));
3230 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3233 return translate_error(fs, fh->ino, err);
3235 if (!ff->fakeroot && ctxt->uid != 0 && inode_uid(inode) != ctxt->uid)
3238 inode.i_generation = generation;
3240 ret = update_ctime(fs, fh->ino, &inode);
3244 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3247 return translate_error(fs, fh->ino, err);
3251 #endif /* SUPPORT_I_FLAGS */
3254 static int ioctl_fitrim(ext2_filsys fs, struct fuse2fs_file_handle *fh,
3257 struct fstrim_range *fr = data;
3258 blk64_t start, end, max_blocks, b, cleared;
3261 start = fr->start / fs->blocksize;
3262 end = (fr->start + fr->len - 1) / fs->blocksize;
3263 dbg_printf("%s: start=%llu end=%llu\n", __func__, start, end);
3265 if (start < fs->super->s_first_data_block)
3266 start = fs->super->s_first_data_block;
3267 if (start >= ext2fs_blocks_count(fs->super))
3268 start = ext2fs_blocks_count(fs->super) - 1;
3270 if (end < fs->super->s_first_data_block)
3271 end = fs->super->s_first_data_block;
3272 if (end >= ext2fs_blocks_count(fs->super))
3273 end = ext2fs_blocks_count(fs->super) - 1;
3276 max_blocks = 2048ULL * 1024 * 1024 / fs->blocksize;
3279 while (start <= end) {
3280 err = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
3281 start, end, &start);
3285 return translate_error(fs, fh->ino, err);
3287 b = start + max_blocks < end ? start + max_blocks : end;
3288 err = ext2fs_find_first_set_block_bitmap2(fs->block_map,
3290 if (err && err != ENOENT)
3291 return translate_error(fs, fh->ino, err);
3292 if (b - start >= fr->minlen) {
3293 err = io_channel_discard(fs->io, start, b - start);
3295 return translate_error(fs, fh->ino, err);
3296 cleared += b - start;
3297 fr->len = cleared * fs->blocksize;
3306 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
3307 static int op_ioctl(const char *path EXT2FS_ATTR((unused)),
3308 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
3313 void *arg EXT2FS_ATTR((unused)),
3314 struct fuse_file_info *fp,
3315 unsigned int flags EXT2FS_ATTR((unused)), void *data)
3317 struct fuse_context *ctxt = fuse_get_context();
3318 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3319 struct fuse2fs_file_handle *fh =
3320 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3324 FUSE2FS_CHECK_CONTEXT(ff);
3326 pthread_mutex_lock(&ff->bfl);
3327 switch ((unsigned long) cmd) {
3328 #ifdef SUPPORT_I_FLAGS
3329 case EXT2_IOC_GETFLAGS:
3330 ret = ioctl_getflags(fs, fh, data);
3332 case EXT2_IOC_SETFLAGS:
3333 ret = ioctl_setflags(fs, fh, data);
3335 case EXT2_IOC_GETVERSION:
3336 ret = ioctl_getversion(fs, fh, data);
3338 case EXT2_IOC_SETVERSION:
3339 ret = ioctl_setversion(fs, fh, data);
3344 ret = ioctl_fitrim(fs, fh, data);
3348 dbg_printf("%s: Unknown ioctl %d\n", __func__, cmd);
3351 pthread_mutex_unlock(&ff->bfl);
3355 #endif /* FUSE 28 */
3357 static int op_bmap(const char *path, size_t blocksize EXT2FS_ATTR((unused)),
3360 struct fuse_context *ctxt = fuse_get_context();
3361 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3367 FUSE2FS_CHECK_CONTEXT(ff);
3369 pthread_mutex_lock(&ff->bfl);
3370 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
3372 ret = translate_error(fs, 0, err);
3375 dbg_printf("%s: ino=%d blk=%"PRIu64"\n", __func__, ino, *idx);
3377 err = ext2fs_bmap2(fs, ino, NULL, NULL, 0, *idx, 0, (blk64_t *)idx);
3379 ret = translate_error(fs, ino, err);
3384 pthread_mutex_unlock(&ff->bfl);
3388 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3389 # ifdef SUPPORT_FALLOCATE
3390 static int fallocate_helper(struct fuse_file_info *fp, int mode, off_t offset,
3393 struct fuse_context *ctxt = fuse_get_context();
3394 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3395 struct fuse2fs_file_handle *fh =
3396 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3398 struct ext2_inode_large inode;
3404 FUSE2FS_CHECK_CONTEXT(ff);
3406 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3407 start = offset / fs->blocksize;
3408 end = (offset + len - 1) / fs->blocksize;
3409 dbg_printf("%s: ino=%d mode=0x%x start=%jd end=%llu\n", __func__,
3410 fh->ino, mode, offset / fs->blocksize, end);
3411 if (!fs_can_allocate(ff, len / fs->blocksize))
3414 memset(&inode, 0, sizeof(inode));
3415 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3419 fsize = EXT2_I_SIZE(&inode);
3421 /* Allocate a bunch of blocks */
3422 flags = (mode & FL_KEEP_SIZE_FLAG ? 0 :
3423 EXT2_FALLOCATE_INIT_BEYOND_EOF);
3424 err = ext2fs_fallocate(fs, flags, fh->ino,
3425 (struct ext2_inode *)&inode,
3426 ~0ULL, start, end - start + 1);
3427 if (err && err != EXT2_ET_BLOCK_ALLOC_FAIL)
3428 return translate_error(fs, fh->ino, err);
3431 if (!(mode & FL_KEEP_SIZE_FLAG)) {
3432 if ((__u64) offset + len > fsize) {
3433 err = ext2fs_inode_size_set(fs,
3434 (struct ext2_inode *)&inode,
3437 return translate_error(fs, fh->ino, err);
3441 err = update_mtime(fs, fh->ino, &inode);
3445 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3448 return translate_error(fs, fh->ino, err);
3453 static errcode_t clean_block_middle(ext2_filsys fs, ext2_ino_t ino,
3454 struct ext2_inode_large *inode, off_t offset,
3455 off_t len, char **buf)
3462 residue = offset % fs->blocksize;
3467 err = ext2fs_get_mem(fs->blocksize, buf);
3472 err = ext2fs_bmap2(fs, ino, (struct ext2_inode *)inode, *buf, 0,
3473 offset / fs->blocksize, &retflags, &blk);
3476 if (!blk || (retflags & BMAP_RET_UNINIT))
3479 err = io_channel_read_blk(fs->io, blk, 1, *buf);
3483 memset(*buf + residue, 0, len);
3485 return io_channel_write_blk(fs->io, blk, 1, *buf);
3488 static errcode_t clean_block_edge(ext2_filsys fs, ext2_ino_t ino,
3489 struct ext2_inode_large *inode, off_t offset,
3490 int clean_before, char **buf)
3497 residue = offset % fs->blocksize;
3502 err = ext2fs_get_mem(fs->blocksize, buf);
3507 err = ext2fs_bmap2(fs, ino, (struct ext2_inode *)inode, *buf, 0,
3508 offset / fs->blocksize, &retflags, &blk);
3512 err = io_channel_read_blk(fs->io, blk, 1, *buf);
3515 if (!blk || (retflags & BMAP_RET_UNINIT))
3519 memset(*buf, 0, residue);
3521 memset(*buf + residue, 0, fs->blocksize - residue);
3523 return io_channel_write_blk(fs->io, blk, 1, *buf);
3526 static int punch_helper(struct fuse_file_info *fp, int mode, off_t offset,
3529 struct fuse_context *ctxt = fuse_get_context();
3530 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3531 struct fuse2fs_file_handle *fh =
3532 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3534 struct ext2_inode_large inode;
3539 FUSE2FS_CHECK_CONTEXT(ff);
3541 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3542 dbg_printf("%s: offset=%jd len=%jd\n", __func__, offset, len);
3544 /* kernel ext4 punch requires this flag to be set */
3545 if (!(mode & FL_KEEP_SIZE_FLAG))
3548 /* Punch out a bunch of blocks */
3549 start = (offset + fs->blocksize - 1) / fs->blocksize;
3550 end = (offset + len - fs->blocksize) / fs->blocksize;
3551 dbg_printf("%s: ino=%d mode=0x%x start=%llu end=%llu\n", __func__,
3552 fh->ino, mode, start, end);
3554 memset(&inode, 0, sizeof(inode));
3555 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3558 return translate_error(fs, fh->ino, err);
3560 /* Zero everything before the first block and after the last block */
3561 if ((offset / fs->blocksize) == ((offset + len) / fs->blocksize))
3562 err = clean_block_middle(fs, fh->ino, &inode, offset,
3565 err = clean_block_edge(fs, fh->ino, &inode, offset, 0, &buf);
3567 err = clean_block_edge(fs, fh->ino, &inode,
3568 offset + len, 1, &buf);
3571 ext2fs_free_mem(&buf);
3573 return translate_error(fs, fh->ino, err);
3575 /* Unmap full blocks in the middle */
3577 err = ext2fs_punch(fs, fh->ino, (struct ext2_inode *)&inode,
3580 return translate_error(fs, fh->ino, err);
3583 err = update_mtime(fs, fh->ino, &inode);
3587 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
3590 return translate_error(fs, fh->ino, err);
3595 static int op_fallocate(const char *path EXT2FS_ATTR((unused)), int mode,
3596 off_t offset, off_t len,
3597 struct fuse_file_info *fp)
3599 struct fuse_context *ctxt = fuse_get_context();
3600 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3601 ext2_filsys fs = ff->fs;
3604 /* Catch unknown flags */
3605 if (mode & ~(FL_PUNCH_HOLE_FLAG | FL_KEEP_SIZE_FLAG))
3608 pthread_mutex_lock(&ff->bfl);
3609 if (!fs_writeable(fs)) {
3613 if (mode & FL_PUNCH_HOLE_FLAG)
3614 ret = punch_helper(fp, mode, offset, len);
3616 ret = fallocate_helper(fp, mode, offset, len);
3618 pthread_mutex_unlock(&ff->bfl);
3622 # endif /* SUPPORT_FALLOCATE */
3623 #endif /* FUSE 29 */
3625 static struct fuse_operations fs_ops = {
3627 .destroy = op_destroy,
3628 .getattr = op_getattr,
3629 .readlink = op_readlink,
3632 .unlink = op_unlink,
3634 .symlink = op_symlink,
3635 .rename = op_rename,
3639 .truncate = op_truncate,
3643 .statfs = op_statfs,
3644 .release = op_release,
3646 .setxattr = op_setxattr,
3647 .getxattr = op_getxattr,
3648 .listxattr = op_listxattr,
3649 .removexattr = op_removexattr,
3651 .readdir = op_readdir,
3652 .releasedir = op_release,
3653 .fsyncdir = op_fsync,
3654 .access = op_access,
3655 .create = op_create,
3656 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
3657 .ftruncate = op_ftruncate,
3658 .fgetattr = op_fgetattr,
3660 .utimens = op_utimens,
3661 #if (FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)) && (FUSE_VERSION < FUSE_MAKE_VERSION(3, 0))
3662 # if defined(UTIME_NOW) || defined(UTIME_OMIT)
3663 .flag_utime_omit_ok = 1,
3671 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
3673 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
3674 .flag_nullpath_ok = 1,
3677 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3678 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
3681 # ifdef SUPPORT_FALLOCATE
3682 .fallocate = op_fallocate,
3687 static int get_random_bytes(void *p, size_t sz)
3692 fd = open("/dev/urandom", O_RDONLY);
3694 perror("/dev/urandom");
3698 r = read(fd, p, sz);
3701 return (size_t) r == sz;
3710 #define FUSE2FS_OPT(t, p, v) { t, offsetof(struct fuse2fs, p), v }
3712 static struct fuse_opt fuse2fs_opts[] = {
3713 FUSE2FS_OPT("ro", ro, 1),
3714 FUSE2FS_OPT("errors=panic", panic_on_error, 1),
3715 FUSE2FS_OPT("minixdf", minixdf, 1),
3716 FUSE2FS_OPT("fakeroot", fakeroot, 1),
3717 FUSE2FS_OPT("fuse2fs_debug", debug, 1),
3718 FUSE2FS_OPT("no_default_opts", no_default_opts, 1),
3719 FUSE2FS_OPT("norecovery", norecovery, 1),
3720 FUSE2FS_OPT("offset=%lu", offset, 0),
3722 FUSE_OPT_KEY("-V", FUSE2FS_VERSION),
3723 FUSE_OPT_KEY("--version", FUSE2FS_VERSION),
3724 FUSE_OPT_KEY("-h", FUSE2FS_HELP),
3725 FUSE_OPT_KEY("--help", FUSE2FS_HELP),
3726 FUSE_OPT_KEY("--helpfull", FUSE2FS_HELPFULL),
3731 static int fuse2fs_opt_proc(void *data, const char *arg,
3732 int key, struct fuse_args *outargs)
3734 struct fuse2fs *ff = data;
3737 case FUSE_OPT_KEY_NONOPT:
3739 ff->device = strdup(arg);
3744 case FUSE2FS_HELPFULL:
3746 "usage: %s device/image mountpoint [options]\n"
3748 "general options:\n"
3749 " -o opt,[opt...] mount options\n"
3750 " -h --help print help\n"
3751 " -V --version print version\n"
3753 "fuse2fs options:\n"
3754 " -o ro read-only mount\n"
3755 " -o errors=panic dump core on error\n"
3756 " -o minixdf minix-style df\n"
3757 " -o fakeroot pretend to be root for permission checks\n"
3758 " -o no_default_opts do not include default fuse options\n"
3759 " -o offset=<bytes> similar to mount -o offset=<bytes>, mount the partition starting at <bytes>\n"
3760 " -o norecovery don't replay the journal (implies ro)\n"
3761 " -o fuse2fs_debug enable fuse2fs debugging\n"
3764 if (key == FUSE2FS_HELPFULL) {
3765 fuse_opt_add_arg(outargs, "-ho");
3766 fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL);
3768 fprintf(stderr, "Try --helpfull to get a list of "
3769 "all flags, including the FUSE options.\n");
3773 case FUSE2FS_VERSION:
3774 fprintf(stderr, "fuse2fs %s (%s)\n", E2FSPROGS_VERSION,
3776 fuse_opt_add_arg(outargs, "--version");
3777 fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL);
3783 int main(int argc, char *argv[])
3785 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
3786 struct fuse2fs fctx;
3789 char extra_args[BUFSIZ];
3791 int flags = EXT2_FLAG_64BITS | EXT2_FLAG_THREADS | EXT2_FLAG_EXCLUSIVE;
3793 memset(&fctx, 0, sizeof(fctx));
3794 fctx.magic = FUSE2FS_MAGIC;
3796 fuse_opt_parse(&args, &fctx, fuse2fs_opts, fuse2fs_opt_proc);
3797 if (fctx.device == NULL) {
3798 fprintf(stderr, "Missing ext4 device/image\n");
3799 fprintf(stderr, "See '%s -h' for usage\n", argv[0]);
3803 if (fctx.norecovery)
3806 printf("%s", _("Mounting read-only.\n"));
3809 setlocale(LC_MESSAGES, "");
3810 setlocale(LC_CTYPE, "");
3811 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
3812 textdomain(NLS_CAT_NAME);
3813 set_com_err_gettext(gettext);
3815 add_error_table(&et_ext2_error_table);
3817 /* Set up error logging */
3818 logfile = getenv("FUSE2FS_LOGFILE");
3820 fctx.err_fp = fopen(logfile, "a");
3826 fctx.err_fp = stderr;
3828 /* Will we allow users to allocate every last block? */
3829 if (getenv("FUSE2FS_ALLOC_ALL_BLOCKS")) {
3830 printf(_("%s: Allowing users to allocate all blocks. "
3831 "This is dangerous!\n"), fctx.device);
3832 fctx.alloc_all_blocks = 1;
3835 /* Start up the fs (while we still can use stdout) */
3838 flags |= EXT2_FLAG_RW;
3840 sprintf(options, "offset=%lu", fctx.offset);
3841 err = ext2fs_open2(fctx.device, options, flags, 0, 0, unix_io_manager,
3844 printf(_("%s: %s.\n"), fctx.device, error_message(err));
3845 printf(_("Please run e2fsck -fy %s.\n"), fctx.device);
3848 fctx.fs = global_fs;
3849 global_fs->priv_data = &fctx;
3853 if (ext2fs_has_feature_journal_needs_recovery(global_fs->super)) {
3854 if (fctx.norecovery) {
3855 printf(_("%s: mounting read-only without "
3856 "recovering journal\n"),
3858 } else if (!fctx.ro) {
3859 printf(_("%s: recovering journal\n"), fctx.device);
3860 err = ext2fs_run_ext3_journal(&global_fs);
3862 printf(_("%s: %s.\n"), fctx.device,
3863 error_message(err));
3864 printf(_("Please run e2fsck -fy %s.\n"),
3868 ext2fs_clear_feature_journal_needs_recovery(global_fs->super);
3869 ext2fs_mark_super_dirty(global_fs);
3871 printf("%s", _("Journal needs recovery; running "
3872 "`e2fsck -E journal_only' is required.\n"));
3878 if (ext2fs_has_feature_journal(global_fs->super))
3879 printf(_("%s: Writing to the journal is not supported.\n"),
3881 err = ext2fs_read_inode_bitmap(global_fs);
3883 translate_error(global_fs, 0, err);
3886 err = ext2fs_read_block_bitmap(global_fs);
3888 translate_error(global_fs, 0, err);
3893 if (!(global_fs->super->s_state & EXT2_VALID_FS))
3894 printf("%s", _("Warning: Mounting unchecked fs, running e2fsck "
3895 "is recommended.\n"));
3896 if (global_fs->super->s_max_mnt_count > 0 &&
3897 global_fs->super->s_mnt_count >= global_fs->super->s_max_mnt_count)
3898 printf("%s", _("Warning: Maximal mount count reached, running "
3899 "e2fsck is recommended.\n"));
3900 if (global_fs->super->s_checkinterval > 0 &&
3901 (time_t) (global_fs->super->s_lastcheck +
3902 global_fs->super->s_checkinterval) <= time(0))
3903 printf("%s", _("Warning: Check time reached; running e2fsck "
3904 "is recommended.\n"));
3905 if (global_fs->super->s_last_orphan)
3907 _("Orphans detected; running e2fsck is recommended.\n"));
3909 if (global_fs->super->s_state & EXT2_ERROR_FS) {
3911 _("Errors detected; running e2fsck is required.\n"));
3915 /* Initialize generation counter */
3916 get_random_bytes(&fctx.next_generation, sizeof(unsigned int));
3918 /* Set up default fuse parameters */
3919 snprintf(extra_args, BUFSIZ, "-okernel_cache,subtype=ext4,"
3920 "fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS,
3922 if (fctx.no_default_opts == 0)
3923 fuse_opt_add_arg(&args, extra_args);
3925 if (fctx.fakeroot) {
3926 #ifdef HAVE_MOUNT_NODEV
3927 fuse_opt_add_arg(&args,"-onodev");
3929 #ifdef HAVE_MOUNT_NOSUID
3930 fuse_opt_add_arg(&args,"-onosuid");
3937 printf("fuse arguments:");
3938 for (i = 0; i < args.argc; i++)
3939 printf(" '%s'", args.argv[i]);
3943 pthread_mutex_init(&fctx.bfl, NULL);
3944 fuse_main(args.argc, args.argv, &fs_ops, &fctx);
3945 pthread_mutex_destroy(&fctx.bfl);
3950 err = ext2fs_close(global_fs);
3952 com_err(argv[0], err, "while closing fs");
3958 static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino,
3959 const char *file, int line)
3961 struct timespec now;
3963 struct fuse2fs *ff = fs->priv_data;
3966 /* Translate ext2 error to unix error code */
3967 if (err < EXT2_ET_BASE)
3968 goto no_translation;
3970 case EXT2_ET_NO_MEMORY:
3971 case EXT2_ET_TDB_ERR_OOM:
3974 case EXT2_ET_INVALID_ARGUMENT:
3975 case EXT2_ET_LLSEEK_FAILED:
3978 case EXT2_ET_NO_DIRECTORY:
3981 case EXT2_ET_FILE_NOT_FOUND:
3984 case EXT2_ET_DIR_NO_SPACE:
3987 case EXT2_ET_TOOSMALL:
3988 case EXT2_ET_BLOCK_ALLOC_FAIL:
3989 case EXT2_ET_INODE_ALLOC_FAIL:
3990 case EXT2_ET_EA_NO_SPACE:
3993 case EXT2_ET_SYMLINK_LOOP:
3996 case EXT2_ET_FILE_TOO_BIG:
3999 case EXT2_ET_TDB_ERR_EXISTS:
4000 case EXT2_ET_FILE_EXISTS:
4003 case EXT2_ET_MMP_FAILED:
4004 case EXT2_ET_MMP_FSCK_ON:
4007 case EXT2_ET_EA_KEY_NOT_FOUND:
4014 /* Sometimes fuse returns a garbage file handle pointer to us... */
4015 case EXT2_ET_MAGIC_EXT2_FILE:
4018 case EXT2_ET_UNIMPLEMENTED:
4032 fprintf(ff->err_fp, "FUSE2FS (%s): %s (inode #%d) at %s:%d.\n",
4033 fs->device_name ? fs->device_name : "???",
4034 error_message(err), ino, file, line);
4036 fprintf(ff->err_fp, "FUSE2FS (%s): %s at %s:%d.\n",
4037 fs->device_name ? fs->device_name : "???",
4038 error_message(err), file, line);
4041 /* Make a note in the error log */
4043 ext2fs_set_tstamp(fs->super, s_last_error_time, now.tv_sec);
4044 fs->super->s_last_error_ino = ino;
4045 fs->super->s_last_error_line = line;
4046 fs->super->s_last_error_block = err; /* Yeah... */
4047 strncpy((char *)fs->super->s_last_error_func, file,
4048 sizeof(fs->super->s_last_error_func));
4049 if (ext2fs_get_tstamp(fs->super, s_first_error_time) == 0) {
4050 ext2fs_set_tstamp(fs->super, s_first_error_time, now.tv_sec);
4051 fs->super->s_first_error_ino = ino;
4052 fs->super->s_first_error_line = line;
4053 fs->super->s_first_error_block = err;
4054 strncpy((char *)fs->super->s_first_error_func, file,
4055 sizeof(fs->super->s_first_error_func));
4058 fs->super->s_error_count++;
4059 ext2fs_mark_super_dirty(fs);
4061 if (ff->panic_on_error)