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 ",nonempty,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
.i_uid
, inode
.i_gid
,
652 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
.i_uid
== ctxt
->uid
) {
683 if ((mask
& (perms
>> 6)) == mask
)
688 /* allow group, if perms match */
689 if (inode
.i_gid
== 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
.i_uid
;
794 statbuf
->st_gid
= inode
.i_gid
;
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 inode
.i_gid
= ctxt
->gid
;
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 inode
.i_gid
= ctxt
->gid
;
1142 inode
.i_mode
= LINUX_S_IFDIR
| (mode
& ~(S_ISUID
| fs
->umask
)) |
1144 inode
.i_generation
= ff
->next_generation
++;
1146 err
= ext2fs_write_inode_full(fs
, child
, (struct ext2_inode
*)&inode
,
1149 ret
= translate_error(fs
, child
, err
);
1153 /* Rewrite the directory block checksum, having set i_generation */
1154 if ((inode
.i_flags
& EXT4_INLINE_DATA_FL
) ||
1155 !ext2fs_has_feature_metadata_csum(fs
->super
))
1157 err
= ext2fs_new_dir_block(fs
, child
, parent
, &block
);
1159 ret
= translate_error(fs
, child
, err
);
1162 err
= ext2fs_bmap2(fs
, child
, (struct ext2_inode
*)&inode
, NULL
, 0, 0,
1165 ret
= translate_error(fs
, child
, err
);
1168 err
= ext2fs_write_dir_block4(fs
, blk
, block
, 0, child
);
1170 ret
= translate_error(fs
, child
, err
);
1175 ext2fs_free_mem(&block
);
1177 pthread_mutex_unlock(&ff
->bfl
);
1183 static int unlink_file_by_name(ext2_filsys fs
, const char *path
)
1187 char *filename
= strdup(path
);
1191 base_name
= strrchr(filename
, '/');
1193 *base_name
++ = '\0';
1194 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, filename
,
1198 return translate_error(fs
, 0, err
);
1201 dir
= EXT2_ROOT_INO
;
1202 base_name
= filename
;
1205 ret
= check_inum_access(fs
, dir
, W_OK
);
1211 dbg_printf("%s: unlinking name=%s from dir=%d\n", __func__
,
1213 err
= ext2fs_unlink(fs
, dir
, base_name
, 0, 0);
1216 return translate_error(fs
, dir
, err
);
1218 return update_mtime(fs
, dir
, NULL
);
1221 static int remove_inode(struct fuse2fs
*ff
, ext2_ino_t ino
)
1223 ext2_filsys fs
= ff
->fs
;
1225 struct ext2_inode_large inode
;
1228 memset(&inode
, 0, sizeof(inode
));
1229 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1232 ret
= translate_error(fs
, ino
, err
);
1235 dbg_printf("%s: put ino=%d links=%d\n", __func__
, ino
,
1236 inode
.i_links_count
);
1238 switch (inode
.i_links_count
) {
1240 return 0; /* XXX: already done? */
1242 inode
.i_links_count
--;
1243 inode
.i_dtime
= fs
->now
? fs
->now
: time(0);
1246 inode
.i_links_count
--;
1249 ret
= update_ctime(fs
, ino
, &inode
);
1253 if (inode
.i_links_count
)
1256 /* Nobody holds this file; free its blocks! */
1257 err
= ext2fs_free_ext_attr(fs
, ino
, &inode
);
1261 if (ext2fs_inode_has_valid_blocks2(fs
, (struct ext2_inode
*)&inode
)) {
1262 err
= ext2fs_punch(fs
, ino
, (struct ext2_inode
*)&inode
, NULL
,
1265 ret
= translate_error(fs
, ino
, err
);
1270 ext2fs_inode_alloc_stats2(fs
, ino
, -1,
1271 LINUX_S_ISDIR(inode
.i_mode
));
1274 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1277 ret
= translate_error(fs
, ino
, err
);
1284 static int __op_unlink(struct fuse2fs
*ff
, const char *path
)
1286 ext2_filsys fs
= ff
->fs
;
1291 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
1293 ret
= translate_error(fs
, 0, err
);
1297 ret
= unlink_file_by_name(fs
, path
);
1301 ret
= remove_inode(ff
, ino
);
1308 static int op_unlink(const char *path
)
1310 struct fuse_context
*ctxt
= fuse_get_context();
1311 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1314 FUSE2FS_CHECK_CONTEXT(ff
);
1315 pthread_mutex_lock(&ff
->bfl
);
1316 ret
= __op_unlink(ff
, path
);
1317 pthread_mutex_unlock(&ff
->bfl
);
1326 static int rmdir_proc(ext2_ino_t dir
EXT2FS_ATTR((unused
)),
1327 int entry
EXT2FS_ATTR((unused
)),
1328 struct ext2_dir_entry
*dirent
,
1329 int offset
EXT2FS_ATTR((unused
)),
1330 int blocksize
EXT2FS_ATTR((unused
)),
1331 char *buf
EXT2FS_ATTR((unused
)),
1334 struct rd_struct
*rds
= (struct rd_struct
*) private;
1336 if (dirent
->inode
== 0)
1338 if (((dirent
->name_len
& 0xFF) == 1) && (dirent
->name
[0] == '.'))
1340 if (((dirent
->name_len
& 0xFF) == 2) && (dirent
->name
[0] == '.') &&
1341 (dirent
->name
[1] == '.')) {
1342 rds
->parent
= dirent
->inode
;
1349 static int __op_rmdir(struct fuse2fs
*ff
, const char *path
)
1351 ext2_filsys fs
= ff
->fs
;
1354 struct ext2_inode_large inode
;
1355 struct rd_struct rds
;
1358 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &child
);
1360 ret
= translate_error(fs
, 0, err
);
1363 dbg_printf("%s: rmdir path=%s ino=%d\n", __func__
, path
, child
);
1368 err
= ext2fs_dir_iterate2(fs
, child
, 0, 0, rmdir_proc
, &rds
);
1370 ret
= translate_error(fs
, child
, err
);
1374 if (rds
.empty
== 0) {
1379 ret
= unlink_file_by_name(fs
, path
);
1382 /* Directories have to be "removed" twice. */
1383 ret
= remove_inode(ff
, child
);
1386 ret
= remove_inode(ff
, child
);
1391 dbg_printf("%s: decr dir=%d link count\n", __func__
,
1393 err
= ext2fs_read_inode_full(fs
, rds
.parent
,
1394 (struct ext2_inode
*)&inode
,
1397 ret
= translate_error(fs
, rds
.parent
, err
);
1400 if (inode
.i_links_count
> 1)
1401 inode
.i_links_count
--;
1402 ret
= update_mtime(fs
, rds
.parent
, &inode
);
1405 err
= ext2fs_write_inode_full(fs
, rds
.parent
,
1406 (struct ext2_inode
*)&inode
,
1409 ret
= translate_error(fs
, rds
.parent
, err
);
1418 static int op_rmdir(const char *path
)
1420 struct fuse_context
*ctxt
= fuse_get_context();
1421 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1424 FUSE2FS_CHECK_CONTEXT(ff
);
1425 pthread_mutex_lock(&ff
->bfl
);
1426 ret
= __op_rmdir(ff
, path
);
1427 pthread_mutex_unlock(&ff
->bfl
);
1431 static int op_symlink(const char *src
, const char *dest
)
1433 struct fuse_context
*ctxt
= fuse_get_context();
1434 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1436 ext2_ino_t parent
, child
;
1440 struct ext2_inode_large inode
;
1443 FUSE2FS_CHECK_CONTEXT(ff
);
1445 dbg_printf("%s: symlink %s to %s\n", __func__
, src
, dest
);
1446 temp_path
= strdup(dest
);
1451 node_name
= strrchr(temp_path
, '/');
1460 pthread_mutex_lock(&ff
->bfl
);
1461 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_path
,
1465 ret
= translate_error(fs
, 0, err
);
1469 ret
= check_inum_access(fs
, parent
, W_OK
);
1474 /* Create symlink */
1475 err
= ext2fs_symlink(fs
, parent
, 0, node_name
, src
);
1476 if (err
== EXT2_ET_DIR_NO_SPACE
) {
1477 err
= ext2fs_expand_dir(fs
, parent
);
1479 ret
= translate_error(fs
, parent
, err
);
1483 err
= ext2fs_symlink(fs
, parent
, 0, node_name
, src
);
1486 ret
= translate_error(fs
, parent
, err
);
1490 /* Update parent dir's mtime */
1491 ret
= update_mtime(fs
, parent
, NULL
);
1495 /* Still have to update the uid/gid of the symlink */
1496 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_path
,
1499 ret
= translate_error(fs
, 0, err
);
1502 dbg_printf("%s: symlinking ino=%d/name=%s to dir=%d\n", __func__
,
1503 child
, node_name
, parent
);
1505 memset(&inode
, 0, sizeof(inode
));
1506 err
= ext2fs_read_inode_full(fs
, child
, (struct ext2_inode
*)&inode
,
1509 ret
= translate_error(fs
, child
, err
);
1513 inode
.i_uid
= ctxt
->uid
;
1514 inode
.i_gid
= ctxt
->gid
;
1515 inode
.i_generation
= ff
->next_generation
++;
1517 err
= ext2fs_write_inode_full(fs
, child
, (struct ext2_inode
*)&inode
,
1520 ret
= translate_error(fs
, child
, err
);
1524 pthread_mutex_unlock(&ff
->bfl
);
1530 struct update_dotdot
{
1531 ext2_ino_t new_dotdot
;
1534 static int update_dotdot_helper(ext2_ino_t dir
EXT2FS_ATTR((unused
)),
1535 int entry
EXT2FS_ATTR((unused
)),
1536 struct ext2_dir_entry
*dirent
,
1537 int offset
EXT2FS_ATTR((unused
)),
1538 int blocksize
EXT2FS_ATTR((unused
)),
1539 char *buf
EXT2FS_ATTR((unused
)),
1542 struct update_dotdot
*ud
= priv_data
;
1544 if (ext2fs_dirent_name_len(dirent
) == 2 &&
1545 dirent
->name
[0] == '.' && dirent
->name
[1] == '.') {
1546 dirent
->inode
= ud
->new_dotdot
;
1547 return DIRENT_CHANGED
| DIRENT_ABORT
;
1553 static int op_rename(const char *from
, const char *to
)
1555 struct fuse_context
*ctxt
= fuse_get_context();
1556 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1559 ext2_ino_t from_ino
, to_ino
, to_dir_ino
, from_dir_ino
;
1560 char *temp_to
= NULL
, *temp_from
= NULL
;
1562 struct ext2_inode inode
;
1563 struct update_dotdot ud
;
1566 FUSE2FS_CHECK_CONTEXT(ff
);
1568 dbg_printf("%s: renaming %s to %s\n", __func__
, from
, to
);
1569 pthread_mutex_lock(&ff
->bfl
);
1570 if (!fs_can_allocate(ff
, 5)) {
1575 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, from
, &from_ino
);
1576 if (err
|| from_ino
== 0) {
1577 ret
= translate_error(fs
, 0, err
);
1581 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, to
, &to_ino
);
1582 if (err
&& err
!= EXT2_ET_FILE_NOT_FOUND
) {
1583 ret
= translate_error(fs
, 0, err
);
1587 if (err
== EXT2_ET_FILE_NOT_FOUND
)
1590 /* Already the same file? */
1591 if (to_ino
!= 0 && to_ino
== from_ino
) {
1596 temp_to
= strdup(to
);
1602 temp_from
= strdup(from
);
1608 /* Find parent dir of the source and check write access */
1609 cp
= strrchr(temp_from
, '/');
1617 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_from
,
1621 ret
= translate_error(fs
, 0, err
);
1624 if (from_dir_ino
== 0) {
1629 ret
= check_inum_access(fs
, from_dir_ino
, W_OK
);
1633 /* Find parent dir of the destination and check write access */
1634 cp
= strrchr(temp_to
, '/');
1642 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_to
,
1646 ret
= translate_error(fs
, 0, err
);
1649 if (to_dir_ino
== 0) {
1654 ret
= check_inum_access(fs
, to_dir_ino
, W_OK
);
1658 /* If the target exists, unlink it first */
1660 err
= ext2fs_read_inode(fs
, to_ino
, &inode
);
1662 ret
= translate_error(fs
, to_ino
, err
);
1666 dbg_printf("%s: unlinking %s ino=%d\n", __func__
,
1667 LINUX_S_ISDIR(inode
.i_mode
) ? "dir" : "file",
1669 if (LINUX_S_ISDIR(inode
.i_mode
))
1670 ret
= __op_rmdir(ff
, to
);
1672 ret
= __op_unlink(ff
, to
);
1677 /* Get ready to do the move */
1678 err
= ext2fs_read_inode(fs
, from_ino
, &inode
);
1680 ret
= translate_error(fs
, from_ino
, err
);
1684 /* Link in the new file */
1685 dbg_printf("%s: linking ino=%d/path=%s to dir=%d\n", __func__
,
1686 from_ino
, cp
+ 1, to_dir_ino
);
1687 err
= ext2fs_link(fs
, to_dir_ino
, cp
+ 1, from_ino
,
1688 ext2_file_type(inode
.i_mode
));
1689 if (err
== EXT2_ET_DIR_NO_SPACE
) {
1690 err
= ext2fs_expand_dir(fs
, to_dir_ino
);
1692 ret
= translate_error(fs
, to_dir_ino
, err
);
1696 err
= ext2fs_link(fs
, to_dir_ino
, cp
+ 1, from_ino
,
1697 ext2_file_type(inode
.i_mode
));
1700 ret
= translate_error(fs
, to_dir_ino
, err
);
1704 /* Update '..' pointer if dir */
1705 err
= ext2fs_read_inode(fs
, from_ino
, &inode
);
1707 ret
= translate_error(fs
, from_ino
, err
);
1711 if (LINUX_S_ISDIR(inode
.i_mode
)) {
1712 ud
.new_dotdot
= to_dir_ino
;
1713 dbg_printf("%s: updating .. entry for dir=%d\n", __func__
,
1715 err
= ext2fs_dir_iterate2(fs
, from_ino
, 0, NULL
,
1716 update_dotdot_helper
, &ud
);
1718 ret
= translate_error(fs
, from_ino
, err
);
1722 /* Decrease from_dir_ino's links_count */
1723 dbg_printf("%s: moving linkcount from dir=%d to dir=%d\n",
1724 __func__
, from_dir_ino
, to_dir_ino
);
1725 err
= ext2fs_read_inode(fs
, from_dir_ino
, &inode
);
1727 ret
= translate_error(fs
, from_dir_ino
, err
);
1730 inode
.i_links_count
--;
1731 err
= ext2fs_write_inode(fs
, from_dir_ino
, &inode
);
1733 ret
= translate_error(fs
, from_dir_ino
, err
);
1737 /* Increase to_dir_ino's links_count */
1738 err
= ext2fs_read_inode(fs
, to_dir_ino
, &inode
);
1740 ret
= translate_error(fs
, to_dir_ino
, err
);
1743 inode
.i_links_count
++;
1744 err
= ext2fs_write_inode(fs
, to_dir_ino
, &inode
);
1746 ret
= translate_error(fs
, to_dir_ino
, err
);
1751 /* Update timestamps */
1752 ret
= update_ctime(fs
, from_ino
, NULL
);
1756 ret
= update_mtime(fs
, to_dir_ino
, NULL
);
1760 /* Remove the old file */
1761 ret
= unlink_file_by_name(fs
, from
);
1765 /* Flush the whole mess out */
1766 err
= ext2fs_flush2(fs
, 0);
1768 ret
= translate_error(fs
, 0, err
);
1774 pthread_mutex_unlock(&ff
->bfl
);
1778 static int op_link(const char *src
, const char *dest
)
1780 struct fuse_context
*ctxt
= fuse_get_context();
1781 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1786 ext2_ino_t parent
, ino
;
1787 struct ext2_inode_large inode
;
1790 FUSE2FS_CHECK_CONTEXT(ff
);
1792 dbg_printf("%s: src=%s dest=%s\n", __func__
, src
, dest
);
1793 temp_path
= strdup(dest
);
1798 node_name
= strrchr(temp_path
, '/');
1807 pthread_mutex_lock(&ff
->bfl
);
1808 if (!fs_can_allocate(ff
, 2)) {
1813 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_path
,
1821 ret
= check_inum_access(fs
, parent
, W_OK
);
1826 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, src
, &ino
);
1827 if (err
|| ino
== 0) {
1828 ret
= translate_error(fs
, 0, err
);
1832 memset(&inode
, 0, sizeof(inode
));
1833 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1836 ret
= translate_error(fs
, ino
, err
);
1840 inode
.i_links_count
++;
1841 ret
= update_ctime(fs
, ino
, &inode
);
1845 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1848 ret
= translate_error(fs
, ino
, err
);
1852 dbg_printf("%s: linking ino=%d/name=%s to dir=%d\n", __func__
, ino
,
1854 err
= ext2fs_link(fs
, parent
, node_name
, ino
,
1855 ext2_file_type(inode
.i_mode
));
1856 if (err
== EXT2_ET_DIR_NO_SPACE
) {
1857 err
= ext2fs_expand_dir(fs
, parent
);
1859 ret
= translate_error(fs
, parent
, err
);
1863 err
= ext2fs_link(fs
, parent
, node_name
, ino
,
1864 ext2_file_type(inode
.i_mode
));
1867 ret
= translate_error(fs
, parent
, err
);
1871 ret
= update_mtime(fs
, parent
, NULL
);
1876 pthread_mutex_unlock(&ff
->bfl
);
1882 static int op_chmod(const char *path
, mode_t mode
)
1884 struct fuse_context
*ctxt
= fuse_get_context();
1885 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1889 struct ext2_inode_large inode
;
1892 FUSE2FS_CHECK_CONTEXT(ff
);
1894 pthread_mutex_lock(&ff
->bfl
);
1895 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
1897 ret
= translate_error(fs
, 0, err
);
1900 dbg_printf("%s: path=%s mode=0%o ino=%d\n", __func__
, path
, mode
, ino
);
1902 memset(&inode
, 0, sizeof(inode
));
1903 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1906 ret
= translate_error(fs
, ino
, err
);
1910 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 && ctxt
->uid
!= inode
.i_uid
) {
1916 * XXX: We should really check that the inode gid is not in /any/
1917 * of the user's groups, but FUSE only tells us about the primary
1920 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 && ctxt
->gid
!= inode
.i_gid
)
1923 inode
.i_mode
&= ~0xFFF;
1924 inode
.i_mode
|= mode
& 0xFFF;
1925 ret
= update_ctime(fs
, ino
, &inode
);
1929 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1932 ret
= translate_error(fs
, ino
, err
);
1937 pthread_mutex_unlock(&ff
->bfl
);
1941 static int op_chown(const char *path
, uid_t owner
, gid_t group
)
1943 struct fuse_context
*ctxt
= fuse_get_context();
1944 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1948 struct ext2_inode_large inode
;
1951 FUSE2FS_CHECK_CONTEXT(ff
);
1953 pthread_mutex_lock(&ff
->bfl
);
1954 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
1956 ret
= translate_error(fs
, 0, err
);
1959 dbg_printf("%s: path=%s owner=%d group=%d ino=%d\n", __func__
,
1960 path
, owner
, group
, ino
);
1962 memset(&inode
, 0, sizeof(inode
));
1963 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1966 ret
= translate_error(fs
, ino
, err
);
1970 /* FUSE seems to feed us ~0 to mean "don't change" */
1971 if (owner
!= (uid_t
) ~0) {
1972 /* Only root gets to change UID. */
1973 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 &&
1974 !(inode
.i_uid
== ctxt
->uid
&& owner
== ctxt
->uid
)) {
1978 inode
.i_uid
= owner
;
1981 if (group
!= (gid_t
) ~0) {
1982 /* Only root or the owner get to change GID. */
1983 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 && inode
.i_uid
!= ctxt
->uid
) {
1988 /* XXX: We /should/ check group membership but FUSE */
1989 inode
.i_gid
= group
;
1992 ret
= update_ctime(fs
, ino
, &inode
);
1996 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1999 ret
= translate_error(fs
, ino
, err
);
2004 pthread_mutex_unlock(&ff
->bfl
);
2008 static int op_truncate(const char *path
, off_t len
)
2010 struct fuse_context
*ctxt
= fuse_get_context();
2011 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2018 FUSE2FS_CHECK_CONTEXT(ff
);
2020 pthread_mutex_lock(&ff
->bfl
);
2021 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2022 if (err
|| ino
== 0) {
2023 ret
= translate_error(fs
, 0, err
);
2026 dbg_printf("%s: ino=%d len=%jd\n", __func__
, ino
, len
);
2028 ret
= check_inum_access(fs
, ino
, W_OK
);
2032 err
= ext2fs_file_open(fs
, ino
, EXT2_FILE_WRITE
, &file
);
2034 ret
= translate_error(fs
, ino
, err
);
2038 err
= ext2fs_file_set_size2(file
, len
);
2040 ret
= translate_error(fs
, ino
, err
);
2045 err
= ext2fs_file_close(file
);
2049 ret
= translate_error(fs
, ino
, err
);
2053 ret
= update_mtime(fs
, ino
, NULL
);
2056 pthread_mutex_unlock(&ff
->bfl
);
2061 static void detect_linux_executable_open(int kernel_flags
, int *access_check
,
2062 int *e2fs_open_flags
)
2065 * On Linux, execve will bleed __FMODE_EXEC into the file mode flags,
2066 * and FUSE is more than happy to let that slip through.
2068 if (kernel_flags
& 0x20) {
2069 *access_check
= X_OK
;
2070 *e2fs_open_flags
&= ~EXT2_FILE_WRITE
;
2074 static void detect_linux_executable_open(int kernel_flags
, int *access_check
,
2075 int *e2fs_open_flags
)
2079 #endif /* __linux__ */
2081 static int __op_open(struct fuse2fs
*ff
, const char *path
,
2082 struct fuse_file_info
*fp
)
2084 ext2_filsys fs
= ff
->fs
;
2086 struct fuse2fs_file_handle
*file
;
2087 int check
= 0, ret
= 0;
2089 dbg_printf("%s: path=%s\n", __func__
, path
);
2090 err
= ext2fs_get_mem(sizeof(*file
), &file
);
2092 return translate_error(fs
, 0, err
);
2093 file
->magic
= FUSE2FS_FILE_MAGIC
;
2095 file
->open_flags
= 0;
2096 switch (fp
->flags
& O_ACCMODE
) {
2102 file
->open_flags
|= EXT2_FILE_WRITE
;
2105 check
= R_OK
| W_OK
;
2106 file
->open_flags
|= EXT2_FILE_WRITE
;
2110 detect_linux_executable_open(fp
->flags
, &check
, &file
->open_flags
);
2112 if (fp
->flags
& O_CREAT
)
2113 file
->open_flags
|= EXT2_FILE_CREATE
;
2115 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &file
->ino
);
2116 if (err
|| file
->ino
== 0) {
2117 ret
= translate_error(fs
, 0, err
);
2120 dbg_printf("%s: ino=%d\n", __func__
, file
->ino
);
2122 ret
= check_inum_access(fs
, file
->ino
, check
);
2125 * In a regular (Linux) fs driver, the kernel will open
2126 * binaries for reading if the user has --x privileges (i.e.
2127 * execute without read). Since the kernel doesn't have any
2128 * way to tell us if it's opening a file via execve, we'll
2129 * just assume that allowing access is ok if asking for ro mode
2130 * fails but asking for x mode succeeds. Of course we can
2131 * also employ undocumented hacks (see above).
2133 if (check
== R_OK
) {
2134 ret
= check_inum_access(fs
, file
->ino
, X_OK
);
2140 fp
->fh
= (uintptr_t)file
;
2144 ext2fs_free_mem(&file
);
2148 static int op_open(const char *path
, struct fuse_file_info
*fp
)
2150 struct fuse_context
*ctxt
= fuse_get_context();
2151 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2154 FUSE2FS_CHECK_CONTEXT(ff
);
2155 pthread_mutex_lock(&ff
->bfl
);
2156 ret
= __op_open(ff
, path
, fp
);
2157 pthread_mutex_unlock(&ff
->bfl
);
2161 static int op_read(const char *path
EXT2FS_ATTR((unused
)), char *buf
,
2162 size_t len
, off_t offset
,
2163 struct fuse_file_info
*fp
)
2165 struct fuse_context
*ctxt
= fuse_get_context();
2166 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2167 struct fuse2fs_file_handle
*fh
=
2168 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2172 unsigned int got
= 0;
2175 FUSE2FS_CHECK_CONTEXT(ff
);
2177 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2178 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__
, fh
->ino
, offset
,
2180 pthread_mutex_lock(&ff
->bfl
);
2181 err
= ext2fs_file_open(fs
, fh
->ino
, fh
->open_flags
, &efp
);
2183 ret
= translate_error(fs
, fh
->ino
, err
);
2187 err
= ext2fs_file_llseek(efp
, offset
, SEEK_SET
, NULL
);
2189 ret
= translate_error(fs
, fh
->ino
, err
);
2193 err
= ext2fs_file_read(efp
, buf
, len
, &got
);
2195 ret
= translate_error(fs
, fh
->ino
, err
);
2200 err
= ext2fs_file_close(efp
);
2204 ret
= translate_error(fs
, fh
->ino
, err
);
2208 if (fs_writeable(fs
)) {
2209 ret
= update_atime(fs
, fh
->ino
);
2214 pthread_mutex_unlock(&ff
->bfl
);
2215 return got
? (int) got
: ret
;
2218 static int op_write(const char *path
EXT2FS_ATTR((unused
)),
2219 const char *buf
, size_t len
, off_t offset
,
2220 struct fuse_file_info
*fp
)
2222 struct fuse_context
*ctxt
= fuse_get_context();
2223 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2224 struct fuse2fs_file_handle
*fh
=
2225 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2229 unsigned int got
= 0;
2232 FUSE2FS_CHECK_CONTEXT(ff
);
2234 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2235 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__
, fh
->ino
, offset
,
2237 pthread_mutex_lock(&ff
->bfl
);
2238 if (!fs_writeable(fs
)) {
2243 if (!fs_can_allocate(ff
, len
/ fs
->blocksize
)) {
2248 err
= ext2fs_file_open(fs
, fh
->ino
, fh
->open_flags
, &efp
);
2250 ret
= translate_error(fs
, fh
->ino
, err
);
2254 err
= ext2fs_file_llseek(efp
, offset
, SEEK_SET
, NULL
);
2256 ret
= translate_error(fs
, fh
->ino
, err
);
2260 err
= ext2fs_file_write(efp
, buf
, len
, &got
);
2262 ret
= translate_error(fs
, fh
->ino
, err
);
2266 err
= ext2fs_file_flush(efp
);
2269 ret
= translate_error(fs
, fh
->ino
, err
);
2274 err
= ext2fs_file_close(efp
);
2278 ret
= translate_error(fs
, fh
->ino
, err
);
2282 ret
= update_mtime(fs
, fh
->ino
, NULL
);
2287 pthread_mutex_unlock(&ff
->bfl
);
2288 return got
? (int) got
: ret
;
2291 static int op_release(const char *path
EXT2FS_ATTR((unused
)),
2292 struct fuse_file_info
*fp
)
2294 struct fuse_context
*ctxt
= fuse_get_context();
2295 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2296 struct fuse2fs_file_handle
*fh
=
2297 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2302 FUSE2FS_CHECK_CONTEXT(ff
);
2304 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2305 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
2306 pthread_mutex_lock(&ff
->bfl
);
2307 if (fs_writeable(fs
) && fh
->open_flags
& EXT2_FILE_WRITE
) {
2308 err
= ext2fs_flush2(fs
, EXT2_FLAG_FLUSH_NO_SYNC
);
2310 ret
= translate_error(fs
, fh
->ino
, err
);
2313 pthread_mutex_unlock(&ff
->bfl
);
2315 ext2fs_free_mem(&fh
);
2320 static int op_fsync(const char *path
EXT2FS_ATTR((unused
)),
2321 int datasync
EXT2FS_ATTR((unused
)),
2322 struct fuse_file_info
*fp
)
2324 struct fuse_context
*ctxt
= fuse_get_context();
2325 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2326 struct fuse2fs_file_handle
*fh
=
2327 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2332 FUSE2FS_CHECK_CONTEXT(ff
);
2334 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2335 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
2336 /* For now, flush everything, even if it's slow */
2337 pthread_mutex_lock(&ff
->bfl
);
2338 if (fs_writeable(fs
) && fh
->open_flags
& EXT2_FILE_WRITE
) {
2339 err
= ext2fs_flush2(fs
, 0);
2341 ret
= translate_error(fs
, fh
->ino
, err
);
2343 pthread_mutex_unlock(&ff
->bfl
);
2348 static int op_statfs(const char *path
EXT2FS_ATTR((unused
)),
2349 struct statvfs
*buf
)
2351 struct fuse_context
*ctxt
= fuse_get_context();
2352 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2355 blk64_t overhead
, reserved
, free
;
2357 FUSE2FS_CHECK_CONTEXT(ff
);
2359 dbg_printf("%s: path=%s\n", __func__
, path
);
2360 buf
->f_bsize
= fs
->blocksize
;
2366 overhead
= fs
->desc_blocks
+
2367 fs
->group_desc_count
*
2368 (fs
->inode_blocks_per_group
+ 2);
2369 reserved
= ext2fs_r_blocks_count(fs
->super
);
2371 reserved
= ext2fs_blocks_count(fs
->super
) / 10;
2372 free
= ext2fs_free_blocks_count(fs
->super
);
2374 buf
->f_blocks
= ext2fs_blocks_count(fs
->super
) - overhead
;
2375 buf
->f_bfree
= free
;
2376 if (free
< reserved
)
2379 buf
->f_bavail
= free
- reserved
;
2380 buf
->f_files
= fs
->super
->s_inodes_count
;
2381 buf
->f_ffree
= fs
->super
->s_free_inodes_count
;
2382 buf
->f_favail
= fs
->super
->s_free_inodes_count
;
2383 f
= (uint64_t *)fs
->super
->s_uuid
;
2389 if (fs
->flags
& EXT2_FLAG_RW
)
2390 buf
->f_flag
|= ST_RDONLY
;
2391 buf
->f_namemax
= EXT2_NAME_LEN
;
2396 typedef errcode_t (*xattr_xlate_get
)(void **cooked_buf
, size_t *cooked_sz
,
2397 const void *raw_buf
, size_t raw_sz
);
2398 typedef errcode_t (*xattr_xlate_set
)(const void *cooked_buf
, size_t cooked_sz
,
2399 const void **raw_buf
, size_t *raw_sz
);
2400 struct xattr_translate
{
2402 xattr_xlate_get get
;
2403 xattr_xlate_set set
;
2406 #define XATTR_TRANSLATOR(p, g, s) \
2408 .get = (xattr_xlate_get)(g), \
2409 .set = (xattr_xlate_set)(s)}
2411 static struct xattr_translate xattr_translators
[] = {
2412 #ifdef TRANSLATE_LINUX_ACLS
2413 XATTR_TRANSLATOR(ACL_EA_ACCESS
, ext4_to_fuse_acl
, fuse_to_ext4_acl
),
2414 XATTR_TRANSLATOR(ACL_EA_DEFAULT
, ext4_to_fuse_acl
, fuse_to_ext4_acl
),
2416 XATTR_TRANSLATOR(NULL
, NULL
, NULL
),
2418 #undef XATTR_TRANSLATOR
2420 static int op_getxattr(const char *path
, const char *key
, char *value
,
2423 struct fuse_context
*ctxt
= fuse_get_context();
2424 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2426 struct ext2_xattr_handle
*h
;
2427 struct xattr_translate
*xt
;
2434 FUSE2FS_CHECK_CONTEXT(ff
);
2436 pthread_mutex_lock(&ff
->bfl
);
2437 if (!ext2fs_has_feature_xattr(fs
->super
)) {
2442 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2443 if (err
|| ino
== 0) {
2444 ret
= translate_error(fs
, 0, err
);
2447 dbg_printf("%s: ino=%d\n", __func__
, ino
);
2449 ret
= check_inum_access(fs
, ino
, R_OK
);
2453 err
= ext2fs_xattrs_open(fs
, ino
, &h
);
2455 ret
= translate_error(fs
, ino
, err
);
2459 err
= ext2fs_xattrs_read(h
);
2461 ret
= translate_error(fs
, ino
, err
);
2465 err
= ext2fs_xattr_get(h
, key
, &ptr
, &plen
);
2467 ret
= translate_error(fs
, ino
, err
);
2471 for (xt
= xattr_translators
; xt
->prefix
!= NULL
; xt
++) {
2472 if (strncmp(key
, xt
->prefix
, strlen(xt
->prefix
)) == 0) {
2473 err
= xt
->get(&cptr
, &clen
, ptr
, plen
);
2476 ext2fs_free_mem(&ptr
);
2484 } else if (len
< plen
) {
2487 memcpy(value
, ptr
, plen
);
2492 ext2fs_free_mem(&ptr
);
2494 err
= ext2fs_xattrs_close(&h
);
2496 ret
= translate_error(fs
, ino
, err
);
2498 pthread_mutex_unlock(&ff
->bfl
);
2503 static int count_buffer_space(char *name
, char *value
EXT2FS_ATTR((unused
)),
2504 size_t value_len
EXT2FS_ATTR((unused
)),
2507 unsigned int *x
= data
;
2509 *x
= *x
+ strlen(name
) + 1;
2513 static int copy_names(char *name
, char *value
EXT2FS_ATTR((unused
)),
2514 size_t value_len
EXT2FS_ATTR((unused
)), void *data
)
2518 strncpy(*b
, name
, strlen(name
));
2519 *b
= *b
+ strlen(name
) + 1;
2524 static int op_listxattr(const char *path
, char *names
, size_t len
)
2526 struct fuse_context
*ctxt
= fuse_get_context();
2527 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2529 struct ext2_xattr_handle
*h
;
2535 FUSE2FS_CHECK_CONTEXT(ff
);
2537 pthread_mutex_lock(&ff
->bfl
);
2538 if (!ext2fs_has_feature_xattr(fs
->super
)) {
2543 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2544 if (err
|| ino
== 0) {
2545 ret
= translate_error(fs
, ino
, err
);
2548 dbg_printf("%s: ino=%d\n", __func__
, ino
);
2550 ret
= check_inum_access(fs
, ino
, R_OK
);
2554 err
= ext2fs_xattrs_open(fs
, ino
, &h
);
2556 ret
= translate_error(fs
, ino
, err
);
2560 err
= ext2fs_xattrs_read(h
);
2562 ret
= translate_error(fs
, ino
, err
);
2566 /* Count buffer space needed for names */
2568 err
= ext2fs_xattrs_iterate(h
, count_buffer_space
, &bufsz
);
2570 ret
= translate_error(fs
, ino
, err
);
2577 } else if (len
< bufsz
) {
2582 /* Copy names out */
2583 memset(names
, 0, len
);
2584 err
= ext2fs_xattrs_iterate(h
, copy_names
, &names
);
2586 ret
= translate_error(fs
, ino
, err
);
2591 err
= ext2fs_xattrs_close(&h
);
2593 ret
= translate_error(fs
, ino
, err
);
2595 pthread_mutex_unlock(&ff
->bfl
);
2600 static int op_setxattr(const char *path
EXT2FS_ATTR((unused
)),
2601 const char *key
, const char *value
,
2602 size_t len
, int flags
EXT2FS_ATTR((unused
)))
2604 struct fuse_context
*ctxt
= fuse_get_context();
2605 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2607 struct ext2_xattr_handle
*h
;
2608 struct xattr_translate
*xt
;
2615 FUSE2FS_CHECK_CONTEXT(ff
);
2617 pthread_mutex_lock(&ff
->bfl
);
2618 if (!ext2fs_has_feature_xattr(fs
->super
)) {
2623 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2624 if (err
|| ino
== 0) {
2625 ret
= translate_error(fs
, 0, err
);
2628 dbg_printf("%s: ino=%d\n", __func__
, ino
);
2630 ret
= check_inum_access(fs
, ino
, W_OK
);
2631 if (ret
== -EACCES
) {
2637 err
= ext2fs_xattrs_open(fs
, ino
, &h
);
2639 ret
= translate_error(fs
, ino
, err
);
2643 err
= ext2fs_xattrs_read(h
);
2645 ret
= translate_error(fs
, ino
, err
);
2651 for (xt
= xattr_translators
; xt
->prefix
!= NULL
; xt
++) {
2652 if (strncmp(key
, xt
->prefix
, strlen(xt
->prefix
)) == 0) {
2653 err
= xt
->set(value
, len
, &cvalue
, &clen
);
2659 err
= ext2fs_xattr_set(h
, key
, cvalue
, clen
);
2661 ret
= translate_error(fs
, ino
, err
);
2665 ret
= update_ctime(fs
, ino
, NULL
);
2667 if (cvalue
!= value
)
2668 ext2fs_free_mem(&cvalue
);
2670 err
= ext2fs_xattrs_close(&h
);
2672 ret
= translate_error(fs
, ino
, err
);
2674 pthread_mutex_unlock(&ff
->bfl
);
2679 static int op_removexattr(const char *path
, const char *key
)
2681 struct fuse_context
*ctxt
= fuse_get_context();
2682 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2684 struct ext2_xattr_handle
*h
;
2689 FUSE2FS_CHECK_CONTEXT(ff
);
2691 pthread_mutex_lock(&ff
->bfl
);
2692 if (!ext2fs_has_feature_xattr(fs
->super
)) {
2697 if (!fs_can_allocate(ff
, 1)) {
2702 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2703 if (err
|| ino
== 0) {
2704 ret
= translate_error(fs
, 0, err
);
2707 dbg_printf("%s: ino=%d\n", __func__
, ino
);
2709 ret
= check_inum_access(fs
, ino
, W_OK
);
2713 err
= ext2fs_xattrs_open(fs
, ino
, &h
);
2715 ret
= translate_error(fs
, ino
, err
);
2719 err
= ext2fs_xattrs_read(h
);
2721 ret
= translate_error(fs
, ino
, err
);
2725 err
= ext2fs_xattr_remove(h
, key
);
2727 ret
= translate_error(fs
, ino
, err
);
2731 ret
= update_ctime(fs
, ino
, NULL
);
2733 err
= ext2fs_xattrs_close(&h
);
2735 ret
= translate_error(fs
, ino
, err
);
2737 pthread_mutex_unlock(&ff
->bfl
);
2742 struct readdir_iter
{
2744 fuse_fill_dir_t func
;
2747 static int op_readdir_iter(ext2_ino_t dir
EXT2FS_ATTR((unused
)),
2748 int entry
EXT2FS_ATTR((unused
)),
2749 struct ext2_dir_entry
*dirent
,
2750 int offset
EXT2FS_ATTR((unused
)),
2751 int blocksize
EXT2FS_ATTR((unused
)),
2752 char *buf
EXT2FS_ATTR((unused
)), void *data
)
2754 struct readdir_iter
*i
= data
;
2755 char namebuf
[EXT2_NAME_LEN
+ 1];
2758 memcpy(namebuf
, dirent
->name
, dirent
->name_len
& 0xFF);
2759 namebuf
[dirent
->name_len
& 0xFF] = 0;
2760 ret
= i
->func(i
->buf
, namebuf
, NULL
, 0);
2762 return DIRENT_ABORT
;
2767 static int op_readdir(const char *path
EXT2FS_ATTR((unused
)),
2768 void *buf
, fuse_fill_dir_t fill_func
,
2769 off_t offset
EXT2FS_ATTR((unused
)),
2770 struct fuse_file_info
*fp
)
2772 struct fuse_context
*ctxt
= fuse_get_context();
2773 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2774 struct fuse2fs_file_handle
*fh
=
2775 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2778 struct readdir_iter i
;
2781 FUSE2FS_CHECK_CONTEXT(ff
);
2783 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2784 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
2785 pthread_mutex_lock(&ff
->bfl
);
2788 err
= ext2fs_dir_iterate2(fs
, fh
->ino
, 0, NULL
, op_readdir_iter
, &i
);
2790 ret
= translate_error(fs
, fh
->ino
, err
);
2794 if (fs_writeable(fs
)) {
2795 ret
= update_atime(fs
, fh
->ino
);
2800 pthread_mutex_unlock(&ff
->bfl
);
2804 static int op_access(const char *path
, int mask
)
2806 struct fuse_context
*ctxt
= fuse_get_context();
2807 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2813 FUSE2FS_CHECK_CONTEXT(ff
);
2815 dbg_printf("%s: path=%s mask=0x%x\n", __func__
, path
, mask
);
2816 pthread_mutex_lock(&ff
->bfl
);
2817 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2818 if (err
|| ino
== 0) {
2819 ret
= translate_error(fs
, 0, err
);
2823 ret
= check_inum_access(fs
, ino
, mask
);
2828 pthread_mutex_unlock(&ff
->bfl
);
2832 static int op_create(const char *path
, mode_t mode
, struct fuse_file_info
*fp
)
2834 struct fuse_context
*ctxt
= fuse_get_context();
2835 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2837 ext2_ino_t parent
, child
;
2842 struct ext2_inode_large inode
;
2845 FUSE2FS_CHECK_CONTEXT(ff
);
2847 dbg_printf("%s: path=%s mode=0%o\n", __func__
, path
, mode
);
2848 temp_path
= strdup(path
);
2853 node_name
= strrchr(temp_path
, '/');
2862 pthread_mutex_lock(&ff
->bfl
);
2863 if (!fs_can_allocate(ff
, 1)) {
2868 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_path
,
2871 ret
= translate_error(fs
, 0, err
);
2875 ret
= check_inum_access(fs
, parent
, W_OK
);
2881 filetype
= ext2_file_type(mode
);
2883 err
= ext2fs_new_inode(fs
, parent
, mode
, 0, &child
);
2885 ret
= translate_error(fs
, parent
, err
);
2889 dbg_printf("%s: creating ino=%d/name=%s in dir=%d\n", __func__
, child
,
2891 err
= ext2fs_link(fs
, parent
, node_name
, child
, filetype
);
2892 if (err
== EXT2_ET_DIR_NO_SPACE
) {
2893 err
= ext2fs_expand_dir(fs
, parent
);
2895 ret
= translate_error(fs
, parent
, err
);
2899 err
= ext2fs_link(fs
, parent
, node_name
, child
,
2903 ret
= translate_error(fs
, parent
, err
);
2907 ret
= update_mtime(fs
, parent
, NULL
);
2911 memset(&inode
, 0, sizeof(inode
));
2912 inode
.i_mode
= mode
;
2913 inode
.i_links_count
= 1;
2914 inode
.i_extra_isize
= sizeof(struct ext2_inode_large
) -
2915 EXT2_GOOD_OLD_INODE_SIZE
;
2916 inode
.i_uid
= ctxt
->uid
;
2917 inode
.i_gid
= ctxt
->gid
;
2918 if (ext2fs_has_feature_extents(fs
->super
)) {
2919 ext2_extent_handle_t handle
;
2921 inode
.i_flags
&= ~EXT4_EXTENTS_FL
;
2922 ret
= ext2fs_extent_open2(fs
, child
,
2923 (struct ext2_inode
*)&inode
, &handle
);
2926 ext2fs_extent_free(handle
);
2929 err
= ext2fs_write_new_inode(fs
, child
, (struct ext2_inode
*)&inode
);
2931 ret
= translate_error(fs
, child
, err
);
2935 inode
.i_generation
= ff
->next_generation
++;
2937 err
= ext2fs_write_inode_full(fs
, child
, (struct ext2_inode
*)&inode
,
2940 ret
= translate_error(fs
, child
, err
);
2944 ext2fs_inode_alloc_stats2(fs
, child
, 1, 0);
2946 ret
= __op_open(ff
, path
, fp
);
2950 pthread_mutex_unlock(&ff
->bfl
);
2956 static int op_ftruncate(const char *path
EXT2FS_ATTR((unused
)),
2957 off_t len
, struct fuse_file_info
*fp
)
2959 struct fuse_context
*ctxt
= fuse_get_context();
2960 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2961 struct fuse2fs_file_handle
*fh
=
2962 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2968 FUSE2FS_CHECK_CONTEXT(ff
);
2970 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2971 dbg_printf("%s: ino=%d len=%jd\n", __func__
, fh
->ino
, len
);
2972 pthread_mutex_lock(&ff
->bfl
);
2973 if (!fs_writeable(fs
)) {
2978 err
= ext2fs_file_open(fs
, fh
->ino
, fh
->open_flags
, &efp
);
2980 ret
= translate_error(fs
, fh
->ino
, err
);
2984 err
= ext2fs_file_set_size2(efp
, len
);
2986 ret
= translate_error(fs
, fh
->ino
, err
);
2991 err
= ext2fs_file_close(efp
);
2995 ret
= translate_error(fs
, fh
->ino
, err
);
2999 ret
= update_mtime(fs
, fh
->ino
, NULL
);
3004 pthread_mutex_unlock(&ff
->bfl
);
3008 static int op_fgetattr(const char *path
EXT2FS_ATTR((unused
)),
3009 struct stat
*statbuf
,
3010 struct fuse_file_info
*fp
)
3012 struct fuse_context
*ctxt
= fuse_get_context();
3013 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3015 struct fuse2fs_file_handle
*fh
=
3016 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
3019 FUSE2FS_CHECK_CONTEXT(ff
);
3021 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3022 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
3023 pthread_mutex_lock(&ff
->bfl
);
3024 ret
= stat_inode(fs
, fh
->ino
, statbuf
);
3025 pthread_mutex_unlock(&ff
->bfl
);
3030 static int op_utimens(const char *path
, const struct timespec ctv
[2])
3032 struct fuse_context
*ctxt
= fuse_get_context();
3033 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3034 struct timespec tv
[2];
3038 struct ext2_inode_large inode
;
3041 FUSE2FS_CHECK_CONTEXT(ff
);
3043 pthread_mutex_lock(&ff
->bfl
);
3044 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
3046 ret
= translate_error(fs
, 0, err
);
3049 dbg_printf("%s: ino=%d\n", __func__
, ino
);
3051 ret
= check_inum_access(fs
, ino
, W_OK
);
3055 memset(&inode
, 0, sizeof(inode
));
3056 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
3059 ret
= translate_error(fs
, ino
, err
);
3066 if (tv
[0].tv_nsec
== UTIME_NOW
)
3068 if (tv
[1].tv_nsec
== UTIME_NOW
)
3070 #endif /* UTIME_NOW */
3072 if (tv
[0].tv_nsec
!= UTIME_OMIT
)
3073 EXT4_INODE_SET_XTIME(i_atime
, tv
, &inode
);
3074 if (tv
[1].tv_nsec
!= UTIME_OMIT
)
3075 EXT4_INODE_SET_XTIME(i_mtime
, tv
+ 1, &inode
);
3076 #endif /* UTIME_OMIT */
3077 ret
= update_ctime(fs
, ino
, &inode
);
3081 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
3084 ret
= translate_error(fs
, ino
, err
);
3089 pthread_mutex_unlock(&ff
->bfl
);
3093 #ifdef SUPPORT_I_FLAGS
3094 static int ioctl_getflags(ext2_filsys fs
, struct fuse2fs_file_handle
*fh
,
3098 struct ext2_inode_large inode
;
3100 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3101 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
3102 memset(&inode
, 0, sizeof(inode
));
3103 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3106 return translate_error(fs
, fh
->ino
, err
);
3108 *(__u32
*)data
= inode
.i_flags
& EXT2_FL_USER_VISIBLE
;
3112 #define FUSE2FS_MODIFIABLE_IFLAGS \
3113 (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL | EXT2_NODUMP_FL | \
3114 EXT2_NOATIME_FL | EXT3_JOURNAL_DATA_FL | EXT2_DIRSYNC_FL | \
3117 static int ioctl_setflags(ext2_filsys fs
, struct fuse2fs_file_handle
*fh
,
3121 struct ext2_inode_large inode
;
3123 __u32 flags
= *(__u32
*)data
;
3124 struct fuse_context
*ctxt
= fuse_get_context();
3125 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3127 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3128 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
3129 memset(&inode
, 0, sizeof(inode
));
3130 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3133 return translate_error(fs
, fh
->ino
, err
);
3135 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 && inode
.i_uid
!= ctxt
->uid
)
3138 if ((inode
.i_flags
^ flags
) & ~FUSE2FS_MODIFIABLE_IFLAGS
)
3141 inode
.i_flags
= (inode
.i_flags
& ~FUSE2FS_MODIFIABLE_IFLAGS
) |
3142 (flags
& FUSE2FS_MODIFIABLE_IFLAGS
);
3144 ret
= update_ctime(fs
, fh
->ino
, &inode
);
3148 err
= ext2fs_write_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3151 return translate_error(fs
, fh
->ino
, err
);
3156 static int ioctl_getversion(ext2_filsys fs
, struct fuse2fs_file_handle
*fh
,
3160 struct ext2_inode_large inode
;
3162 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3163 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
3164 memset(&inode
, 0, sizeof(inode
));
3165 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3168 return translate_error(fs
, fh
->ino
, err
);
3170 *(__u32
*)data
= inode
.i_generation
;
3174 static int ioctl_setversion(ext2_filsys fs
, struct fuse2fs_file_handle
*fh
,
3178 struct ext2_inode_large inode
;
3180 __u32 generation
= *(__u32
*)data
;
3181 struct fuse_context
*ctxt
= fuse_get_context();
3182 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3184 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3185 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
3186 memset(&inode
, 0, sizeof(inode
));
3187 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3190 return translate_error(fs
, fh
->ino
, err
);
3192 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 && inode
.i_uid
!= ctxt
->uid
)
3195 inode
.i_generation
= generation
;
3197 ret
= update_ctime(fs
, fh
->ino
, &inode
);
3201 err
= ext2fs_write_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3204 return translate_error(fs
, fh
->ino
, err
);
3208 #endif /* SUPPORT_I_FLAGS */
3211 static int ioctl_fitrim(ext2_filsys fs
, struct fuse2fs_file_handle
*fh
,
3214 struct fstrim_range
*fr
= data
;
3215 blk64_t start
, end
, max_blocks
, b
, cleared
;
3218 start
= fr
->start
/ fs
->blocksize
;
3219 end
= (fr
->start
+ fr
->len
- 1) / fs
->blocksize
;
3220 dbg_printf("%s: start=%llu end=%llu\n", __func__
, start
, end
);
3222 if (start
< fs
->super
->s_first_data_block
)
3223 start
= fs
->super
->s_first_data_block
;
3224 if (start
>= ext2fs_blocks_count(fs
->super
))
3225 start
= ext2fs_blocks_count(fs
->super
) - 1;
3227 if (end
< fs
->super
->s_first_data_block
)
3228 end
= fs
->super
->s_first_data_block
;
3229 if (end
>= ext2fs_blocks_count(fs
->super
))
3230 end
= ext2fs_blocks_count(fs
->super
) - 1;
3233 max_blocks
= 2048ULL * 1024 * 1024 / fs
->blocksize
;
3236 while (start
<= end
) {
3237 err
= ext2fs_find_first_zero_block_bitmap2(fs
->block_map
,
3238 start
, end
, &start
);
3242 return translate_error(fs
, fh
->ino
, err
);
3244 b
= start
+ max_blocks
< end
? start
+ max_blocks
: end
;
3245 err
= ext2fs_find_first_set_block_bitmap2(fs
->block_map
,
3247 if (err
&& err
!= ENOENT
)
3248 return translate_error(fs
, fh
->ino
, err
);
3249 if (b
- start
>= fr
->minlen
) {
3250 err
= io_channel_discard(fs
->io
, start
, b
- start
);
3252 return translate_error(fs
, fh
->ino
, err
);
3253 cleared
+= b
- start
;
3254 fr
->len
= cleared
* fs
->blocksize
;
3263 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
3264 static int op_ioctl(const char *path
EXT2FS_ATTR((unused
)), int cmd
,
3265 void *arg
EXT2FS_ATTR((unused
)),
3266 struct fuse_file_info
*fp
,
3267 unsigned int flags
EXT2FS_ATTR((unused
)), void *data
)
3269 struct fuse_context
*ctxt
= fuse_get_context();
3270 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3271 struct fuse2fs_file_handle
*fh
=
3272 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
3276 FUSE2FS_CHECK_CONTEXT(ff
);
3278 pthread_mutex_lock(&ff
->bfl
);
3279 switch ((unsigned long) cmd
) {
3280 #ifdef SUPPORT_I_FLAGS
3281 case EXT2_IOC_GETFLAGS
:
3282 ret
= ioctl_getflags(fs
, fh
, data
);
3284 case EXT2_IOC_SETFLAGS
:
3285 ret
= ioctl_setflags(fs
, fh
, data
);
3287 case EXT2_IOC_GETVERSION
:
3288 ret
= ioctl_getversion(fs
, fh
, data
);
3290 case EXT2_IOC_SETVERSION
:
3291 ret
= ioctl_setversion(fs
, fh
, data
);
3296 ret
= ioctl_fitrim(fs
, fh
, data
);
3300 dbg_printf("%s: Unknown ioctl %d\n", __func__
, cmd
);
3303 pthread_mutex_unlock(&ff
->bfl
);
3307 #endif /* FUSE 28 */
3309 static int op_bmap(const char *path
, size_t blocksize
EXT2FS_ATTR((unused
)),
3312 struct fuse_context
*ctxt
= fuse_get_context();
3313 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3319 FUSE2FS_CHECK_CONTEXT(ff
);
3321 pthread_mutex_lock(&ff
->bfl
);
3322 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
3324 ret
= translate_error(fs
, 0, err
);
3327 dbg_printf("%s: ino=%d blk=%"PRIu64
"\n", __func__
, ino
, *idx
);
3329 err
= ext2fs_bmap2(fs
, ino
, NULL
, NULL
, 0, *idx
, 0, (blk64_t
*)idx
);
3331 ret
= translate_error(fs
, ino
, err
);
3336 pthread_mutex_unlock(&ff
->bfl
);
3340 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3341 # ifdef SUPPORT_FALLOCATE
3342 static int fallocate_helper(struct fuse_file_info
*fp
, int mode
, off_t offset
,
3345 struct fuse_context
*ctxt
= fuse_get_context();
3346 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3347 struct fuse2fs_file_handle
*fh
=
3348 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
3350 struct ext2_inode_large inode
;
3356 FUSE2FS_CHECK_CONTEXT(ff
);
3358 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3359 start
= offset
/ fs
->blocksize
;
3360 end
= (offset
+ len
- 1) / fs
->blocksize
;
3361 dbg_printf("%s: ino=%d mode=0x%x start=%jd end=%llu\n", __func__
,
3362 fh
->ino
, mode
, offset
/ fs
->blocksize
, end
);
3363 if (!fs_can_allocate(ff
, len
/ fs
->blocksize
))
3366 memset(&inode
, 0, sizeof(inode
));
3367 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3371 fsize
= EXT2_I_SIZE(&inode
);
3373 /* Allocate a bunch of blocks */
3374 flags
= (mode
& FL_KEEP_SIZE_FLAG
? 0 :
3375 EXT2_FALLOCATE_INIT_BEYOND_EOF
);
3376 err
= ext2fs_fallocate(fs
, flags
, fh
->ino
,
3377 (struct ext2_inode
*)&inode
,
3378 ~0ULL, start
, end
- start
+ 1);
3379 if (err
&& err
!= EXT2_ET_BLOCK_ALLOC_FAIL
)
3380 return translate_error(fs
, fh
->ino
, err
);
3383 if (!(mode
& FL_KEEP_SIZE_FLAG
)) {
3384 if ((__u64
) offset
+ len
> fsize
) {
3385 err
= ext2fs_inode_size_set(fs
,
3386 (struct ext2_inode
*)&inode
,
3389 return translate_error(fs
, fh
->ino
, err
);
3393 err
= update_mtime(fs
, fh
->ino
, &inode
);
3397 err
= ext2fs_write_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3400 return translate_error(fs
, fh
->ino
, err
);
3405 static errcode_t
clean_block_middle(ext2_filsys fs
, ext2_ino_t ino
,
3406 struct ext2_inode_large
*inode
, off_t offset
,
3407 off_t len
, char **buf
)
3414 residue
= offset
% fs
->blocksize
;
3419 err
= ext2fs_get_mem(fs
->blocksize
, buf
);
3424 err
= ext2fs_bmap2(fs
, ino
, (struct ext2_inode
*)inode
, *buf
, 0,
3425 offset
/ fs
->blocksize
, &retflags
, &blk
);
3428 if (!blk
|| (retflags
& BMAP_RET_UNINIT
))
3431 err
= io_channel_read_blk(fs
->io
, blk
, 1, *buf
);
3435 memset(*buf
+ residue
, 0, len
);
3437 return io_channel_write_blk(fs
->io
, blk
, 1, *buf
);
3440 static errcode_t
clean_block_edge(ext2_filsys fs
, ext2_ino_t ino
,
3441 struct ext2_inode_large
*inode
, off_t offset
,
3442 int clean_before
, char **buf
)
3449 residue
= offset
% fs
->blocksize
;
3454 err
= ext2fs_get_mem(fs
->blocksize
, buf
);
3459 err
= ext2fs_bmap2(fs
, ino
, (struct ext2_inode
*)inode
, *buf
, 0,
3460 offset
/ fs
->blocksize
, &retflags
, &blk
);
3464 err
= io_channel_read_blk(fs
->io
, blk
, 1, *buf
);
3467 if (!blk
|| (retflags
& BMAP_RET_UNINIT
))
3471 memset(*buf
, 0, residue
);
3473 memset(*buf
+ residue
, 0, fs
->blocksize
- residue
);
3475 return io_channel_write_blk(fs
->io
, blk
, 1, *buf
);
3478 static int punch_helper(struct fuse_file_info
*fp
, int mode
, off_t offset
,
3481 struct fuse_context
*ctxt
= fuse_get_context();
3482 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3483 struct fuse2fs_file_handle
*fh
=
3484 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
3486 struct ext2_inode_large inode
;
3491 FUSE2FS_CHECK_CONTEXT(ff
);
3493 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3494 dbg_printf("%s: offset=%jd len=%jd\n", __func__
, offset
, len
);
3496 /* kernel ext4 punch requires this flag to be set */
3497 if (!(mode
& FL_KEEP_SIZE_FLAG
))
3500 /* Punch out a bunch of blocks */
3501 start
= (offset
+ fs
->blocksize
- 1) / fs
->blocksize
;
3502 end
= (offset
+ len
- fs
->blocksize
) / fs
->blocksize
;
3503 dbg_printf("%s: ino=%d mode=0x%x start=%llu end=%llu\n", __func__
,
3504 fh
->ino
, mode
, start
, end
);
3506 memset(&inode
, 0, sizeof(inode
));
3507 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3510 return translate_error(fs
, fh
->ino
, err
);
3512 /* Zero everything before the first block and after the last block */
3513 if ((offset
/ fs
->blocksize
) == ((offset
+ len
) / fs
->blocksize
))
3514 err
= clean_block_middle(fs
, fh
->ino
, &inode
, offset
,
3517 err
= clean_block_edge(fs
, fh
->ino
, &inode
, offset
, 0, &buf
);
3519 err
= clean_block_edge(fs
, fh
->ino
, &inode
,
3520 offset
+ len
, 1, &buf
);
3523 ext2fs_free_mem(&buf
);
3525 return translate_error(fs
, fh
->ino
, err
);
3527 /* Unmap full blocks in the middle */
3529 err
= ext2fs_punch(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3532 return translate_error(fs
, fh
->ino
, err
);
3535 err
= update_mtime(fs
, fh
->ino
, &inode
);
3539 err
= ext2fs_write_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3542 return translate_error(fs
, fh
->ino
, err
);
3547 static int op_fallocate(const char *path
EXT2FS_ATTR((unused
)), int mode
,
3548 off_t offset
, off_t len
,
3549 struct fuse_file_info
*fp
)
3551 struct fuse_context
*ctxt
= fuse_get_context();
3552 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3553 ext2_filsys fs
= ff
->fs
;
3556 /* Catch unknown flags */
3557 if (mode
& ~(FL_PUNCH_HOLE_FLAG
| FL_KEEP_SIZE_FLAG
))
3560 pthread_mutex_lock(&ff
->bfl
);
3561 if (!fs_writeable(fs
)) {
3565 if (mode
& FL_PUNCH_HOLE_FLAG
)
3566 ret
= punch_helper(fp
, mode
, offset
, len
);
3568 ret
= fallocate_helper(fp
, mode
, offset
, len
);
3570 pthread_mutex_unlock(&ff
->bfl
);
3574 # endif /* SUPPORT_FALLOCATE */
3575 #endif /* FUSE 29 */
3577 static struct fuse_operations fs_ops
= {
3579 .destroy
= op_destroy
,
3580 .getattr
= op_getattr
,
3581 .readlink
= op_readlink
,
3584 .unlink
= op_unlink
,
3586 .symlink
= op_symlink
,
3587 .rename
= op_rename
,
3591 .truncate
= op_truncate
,
3595 .statfs
= op_statfs
,
3596 .release
= op_release
,
3598 .setxattr
= op_setxattr
,
3599 .getxattr
= op_getxattr
,
3600 .listxattr
= op_listxattr
,
3601 .removexattr
= op_removexattr
,
3603 .readdir
= op_readdir
,
3604 .releasedir
= op_release
,
3605 .fsyncdir
= op_fsync
,
3606 .access
= op_access
,
3607 .create
= op_create
,
3608 .ftruncate
= op_ftruncate
,
3609 .fgetattr
= op_fgetattr
,
3610 .utimens
= op_utimens
,
3611 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3612 # if defined(UTIME_NOW) || defined(UTIME_OMIT)
3613 .flag_utime_omit_ok
= 1,
3621 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
3623 .flag_nullpath_ok
= 1,
3625 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3627 # ifdef SUPPORT_FALLOCATE
3628 .fallocate
= op_fallocate
,
3633 static int get_random_bytes(void *p
, size_t sz
)
3638 fd
= open("/dev/urandom", O_RDONLY
);
3640 perror("/dev/urandom");
3644 r
= read(fd
, p
, sz
);
3647 return (size_t) r
== sz
;
3656 #define FUSE2FS_OPT(t, p, v) { t, offsetof(struct fuse2fs, p), v }
3658 static struct fuse_opt fuse2fs_opts
[] = {
3659 FUSE2FS_OPT("ro", ro
, 1),
3660 FUSE2FS_OPT("errors=panic", panic_on_error
, 1),
3661 FUSE2FS_OPT("minixdf", minixdf
, 1),
3662 FUSE2FS_OPT("fakeroot", fakeroot
, 1),
3663 FUSE2FS_OPT("fuse2fs_debug", debug
, 1),
3664 FUSE2FS_OPT("no_default_opts", no_default_opts
, 1),
3666 FUSE_OPT_KEY("-V", FUSE2FS_VERSION
),
3667 FUSE_OPT_KEY("--version", FUSE2FS_VERSION
),
3668 FUSE_OPT_KEY("-h", FUSE2FS_HELP
),
3669 FUSE_OPT_KEY("--help", FUSE2FS_HELP
),
3670 FUSE_OPT_KEY("--helpfull", FUSE2FS_HELPFULL
),
3675 static int fuse2fs_opt_proc(void *data
, const char *arg
,
3676 int key
, struct fuse_args
*outargs
)
3678 struct fuse2fs
*ff
= data
;
3681 case FUSE_OPT_KEY_NONOPT
:
3683 ff
->device
= strdup(arg
);
3688 case FUSE2FS_HELPFULL
:
3690 "usage: %s device/image mountpoint [options]\n"
3692 "general options:\n"
3693 " -o opt,[opt...] mount options\n"
3694 " -h --help print help\n"
3695 " -V --version print version\n"
3697 "fuse2fs options:\n"
3698 " -o ro read-only mount\n"
3699 " -o errors=panic dump core on error\n"
3700 " -o minixdf minix-style df\n"
3701 " -o fakeroot pretend to be root for permission checks\n"
3702 " -o no_default_opts do not include default fuse options\n"
3703 " -o fuse2fs_debug enable fuse2fs debugging\n"
3706 if (key
== FUSE2FS_HELPFULL
) {
3707 fuse_opt_add_arg(outargs
, "-ho");
3708 fuse_main(outargs
->argc
, outargs
->argv
, &fs_ops
, NULL
);
3710 fprintf(stderr
, "Try --helpfull to get a list of "
3711 "all flags, including the FUSE options.\n");
3715 case FUSE2FS_VERSION
:
3716 fprintf(stderr
, "fuse2fs %s (%s)\n", E2FSPROGS_VERSION
,
3718 fuse_opt_add_arg(outargs
, "--version");
3719 fuse_main(outargs
->argc
, outargs
->argv
, &fs_ops
, NULL
);
3725 int main(int argc
, char *argv
[])
3727 struct fuse_args args
= FUSE_ARGS_INIT(argc
, argv
);
3728 struct fuse2fs fctx
;
3731 char extra_args
[BUFSIZ
];
3732 int ret
= 0, flags
= EXT2_FLAG_64BITS
| EXT2_FLAG_EXCLUSIVE
;
3734 memset(&fctx
, 0, sizeof(fctx
));
3735 fctx
.magic
= FUSE2FS_MAGIC
;
3737 fuse_opt_parse(&args
, &fctx
, fuse2fs_opts
, fuse2fs_opt_proc
);
3738 if (fctx
.device
== NULL
) {
3739 fprintf(stderr
, "Missing ext4 device/image\n");
3740 fprintf(stderr
, "See '%s -h' for usage\n", argv
[0]);
3745 printf("%s", _("Mounting read-only.\n"));
3748 setlocale(LC_MESSAGES
, "");
3749 setlocale(LC_CTYPE
, "");
3750 bindtextdomain(NLS_CAT_NAME
, LOCALEDIR
);
3751 textdomain(NLS_CAT_NAME
);
3752 set_com_err_gettext(gettext
);
3754 add_error_table(&et_ext2_error_table
);
3756 /* Set up error logging */
3757 logfile
= getenv("FUSE2FS_LOGFILE");
3759 fctx
.err_fp
= fopen(logfile
, "a");
3765 fctx
.err_fp
= stderr
;
3767 /* Will we allow users to allocate every last block? */
3768 if (getenv("FUSE2FS_ALLOC_ALL_BLOCKS")) {
3769 printf(_("%s: Allowing users to allocate all blocks. "
3770 "This is dangerous!\n"), fctx
.device
);
3771 fctx
.alloc_all_blocks
= 1;
3774 /* Start up the fs (while we still can use stdout) */
3777 flags
|= EXT2_FLAG_RW
;
3778 err
= ext2fs_open2(fctx
.device
, NULL
, flags
, 0, 0, unix_io_manager
,
3781 printf(_("%s: %s.\n"), fctx
.device
, error_message(err
));
3782 printf(_("Please run e2fsck -fy %s.\n"), fctx
.device
);
3785 fctx
.fs
= global_fs
;
3786 global_fs
->priv_data
= &fctx
;
3790 if (ext2fs_has_feature_journal_needs_recovery(global_fs
->super
)) {
3792 printf(_("%s: recovering journal\n"), fctx
.device
);
3793 err
= ext2fs_run_ext3_journal(&global_fs
);
3795 printf(_("%s: %s.\n"), fctx
.device
,
3796 error_message(err
));
3797 printf(_("Please run e2fsck -fy %s.\n"),
3801 ext2fs_clear_feature_journal_needs_recovery(global_fs
->super
);
3802 ext2fs_mark_super_dirty(global_fs
);
3804 printf("%s", _("Journal needs recovery; running "
3805 "`e2fsck -E journal_only' is required.\n"));
3811 if (ext2fs_has_feature_journal(global_fs
->super
))
3812 printf(_("%s: Writing to the journal is not supported.\n"),
3814 err
= ext2fs_read_inode_bitmap(global_fs
);
3816 translate_error(global_fs
, 0, err
);
3819 err
= ext2fs_read_block_bitmap(global_fs
);
3821 translate_error(global_fs
, 0, err
);
3826 if (!(global_fs
->super
->s_state
& EXT2_VALID_FS
))
3827 printf("%s", _("Warning: Mounting unchecked fs, running e2fsck "
3828 "is recommended.\n"));
3829 if (global_fs
->super
->s_max_mnt_count
> 0 &&
3830 global_fs
->super
->s_mnt_count
>= global_fs
->super
->s_max_mnt_count
)
3831 printf("%s", _("Warning: Maximal mount count reached, running "
3832 "e2fsck is recommended.\n"));
3833 if (global_fs
->super
->s_checkinterval
> 0 &&
3834 (time_t) (global_fs
->super
->s_lastcheck
+
3835 global_fs
->super
->s_checkinterval
) <= time(0))
3836 printf("%s", _("Warning: Check time reached; running e2fsck "
3837 "is recommended.\n"));
3838 if (global_fs
->super
->s_last_orphan
)
3840 _("Orphans detected; running e2fsck is recommended.\n"));
3842 if (global_fs
->super
->s_state
& EXT2_ERROR_FS
) {
3844 _("Errors detected; running e2fsck is required.\n"));
3848 /* Initialize generation counter */
3849 get_random_bytes(&fctx
.next_generation
, sizeof(unsigned int));
3851 /* Set up default fuse parameters */
3852 snprintf(extra_args
, BUFSIZ
, "-okernel_cache,subtype=ext4,use_ino,"
3853 "fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS
,
3855 if (fctx
.no_default_opts
== 0)
3856 fuse_opt_add_arg(&args
, extra_args
);
3858 if (fctx
.fakeroot
) {
3859 #ifdef HAVE_MOUNT_NODEV
3860 fuse_opt_add_arg(&args
,"-onodev");
3862 #ifdef HAVE_MOUNT_NOSUID
3863 fuse_opt_add_arg(&args
,"-onosuid");
3870 printf("fuse arguments:");
3871 for (i
= 0; i
< args
.argc
; i
++)
3872 printf(" '%s'", args
.argv
[i
]);
3876 pthread_mutex_init(&fctx
.bfl
, NULL
);
3877 fuse_main(args
.argc
, args
.argv
, &fs_ops
, &fctx
);
3878 pthread_mutex_destroy(&fctx
.bfl
);
3883 err
= ext2fs_close(global_fs
);
3885 com_err(argv
[0], err
, "while closing fs");
3891 static int __translate_error(ext2_filsys fs
, errcode_t err
, ext2_ino_t ino
,
3892 const char *file
, int line
)
3894 struct timespec now
;
3896 struct fuse2fs
*ff
= fs
->priv_data
;
3899 /* Translate ext2 error to unix error code */
3900 if (err
< EXT2_ET_BASE
)
3901 goto no_translation
;
3903 case EXT2_ET_NO_MEMORY
:
3904 case EXT2_ET_TDB_ERR_OOM
:
3907 case EXT2_ET_INVALID_ARGUMENT
:
3908 case EXT2_ET_LLSEEK_FAILED
:
3911 case EXT2_ET_NO_DIRECTORY
:
3914 case EXT2_ET_FILE_NOT_FOUND
:
3917 case EXT2_ET_DIR_NO_SPACE
:
3920 case EXT2_ET_TOOSMALL
:
3921 case EXT2_ET_BLOCK_ALLOC_FAIL
:
3922 case EXT2_ET_INODE_ALLOC_FAIL
:
3923 case EXT2_ET_EA_NO_SPACE
:
3926 case EXT2_ET_SYMLINK_LOOP
:
3929 case EXT2_ET_FILE_TOO_BIG
:
3932 case EXT2_ET_TDB_ERR_EXISTS
:
3933 case EXT2_ET_FILE_EXISTS
:
3936 case EXT2_ET_MMP_FAILED
:
3937 case EXT2_ET_MMP_FSCK_ON
:
3940 case EXT2_ET_EA_KEY_NOT_FOUND
:
3947 /* Sometimes fuse returns a garbage file handle pointer to us... */
3948 case EXT2_ET_MAGIC_EXT2_FILE
:
3951 case EXT2_ET_UNIMPLEMENTED
:
3965 fprintf(ff
->err_fp
, "FUSE2FS (%s): %s (inode #%d) at %s:%d.\n",
3966 fs
->device_name
? fs
->device_name
: "???",
3967 error_message(err
), ino
, file
, line
);
3969 fprintf(ff
->err_fp
, "FUSE2FS (%s): %s at %s:%d.\n",
3970 fs
->device_name
? fs
->device_name
: "???",
3971 error_message(err
), file
, line
);
3974 /* Make a note in the error log */
3976 fs
->super
->s_last_error_time
= now
.tv_sec
;
3977 fs
->super
->s_last_error_ino
= ino
;
3978 fs
->super
->s_last_error_line
= line
;
3979 fs
->super
->s_last_error_block
= err
; /* Yeah... */
3980 strncpy((char *)fs
->super
->s_last_error_func
, file
,
3981 sizeof(fs
->super
->s_last_error_func
));
3982 if (fs
->super
->s_first_error_time
== 0) {
3983 fs
->super
->s_first_error_time
= now
.tv_sec
;
3984 fs
->super
->s_first_error_ino
= ino
;
3985 fs
->super
->s_first_error_line
= line
;
3986 fs
->super
->s_first_error_block
= err
;
3987 strncpy((char *)fs
->super
->s_first_error_func
, file
,
3988 sizeof(fs
->super
->s_first_error_func
));
3991 fs
->super
->s_error_count
++;
3992 ext2fs_mark_super_dirty(fs
);
3994 if (ff
->panic_on_error
)