2 * fuse2fs.c - FUSE server for e2fsprogs.
4 * Copyright (C) 2014 Oracle.
7 * This file may be redistributed under the terms of the GNU Public
11 #define _FILE_OFFSET_BITS 64
12 #define FUSE_USE_VERSION 29
19 # include <linux/fs.h>
20 # include <linux/falloc.h>
21 # include <linux/xattr.h>
22 # define FUSE_PLATFORM_OPTS ",big_writes"
23 # ifdef HAVE_SYS_ACL_H
24 # define TRANSLATE_LINUX_ACLS
27 # define FUSE_PLATFORM_OPTS ""
29 #ifdef TRANSLATE_LINUX_ACLS
32 #include <sys/ioctl.h>
36 #include "ext2fs/ext2fs.h"
37 #include "ext2fs/ext2_fs.h"
39 #include "../version.h"
44 #define _(a) (gettext(a))
46 #define N_(a) gettext_noop(a)
50 #define P_(singular, plural, n) (ngettext(singular, plural, n))
52 #define NLS_CAT_NAME "e2fsprogs"
55 #define LOCALEDIR "/usr/share/locale"
60 #define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural))
63 static ext2_filsys global_fs
; /* Try not to use this directly */
68 # define dbg_printf(f, a...) do {printf("FUSE2FS-" f, ## a); \
72 # define dbg_printf(f, a...)
75 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
78 # define SUPPORT_I_FLAGS
83 #ifdef FALLOC_FL_KEEP_SIZE
84 # define FL_KEEP_SIZE_FLAG FALLOC_FL_KEEP_SIZE
85 # define SUPPORT_FALLOCATE
87 # define FL_KEEP_SIZE_FLAG (0)
90 #ifdef FALLOC_FL_PUNCH_HOLE
91 # define FL_PUNCH_HOLE_FLAG FALLOC_FL_PUNCH_HOLE
93 # define FL_PUNCH_HOLE_FLAG (0)
96 errcode_t
ext2fs_run_ext3_journal(ext2_filsys
*fs
);
98 #ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jbd-debug */
99 int journal_enable_debug
= -1;
102 /* ACL translation stuff */
103 #ifdef TRANSLATE_LINUX_ACLS
105 * Copied from acl_ea.h in libacl source; ACLs have to be sent to and from fuse
106 * in this format... at least on Linux.
108 #define ACL_EA_ACCESS "system.posix_acl_access"
109 #define ACL_EA_DEFAULT "system.posix_acl_default"
111 #define ACL_EA_VERSION 0x0002
121 #if __GNUC_PREREQ (4, 8)
122 #pragma GCC diagnostic push
123 #pragma GCC diagnostic ignored "-Wpedantic"
125 acl_ea_entry a_entries
[0];
126 #if __GNUC_PREREQ (4, 8)
127 #pragma GCC diagnostic pop
131 static inline size_t acl_ea_size(int count
)
133 return sizeof(acl_ea_header
) + count
* sizeof(acl_ea_entry
);
136 static inline int acl_ea_count(size_t size
)
138 if (size
< sizeof(acl_ea_header
))
140 size
-= sizeof(acl_ea_header
);
141 if (size
% sizeof(acl_ea_entry
))
143 return size
/ sizeof(acl_ea_entry
);
147 * ext4 ACL structures, copied from fs/ext4/acl.h.
149 #define EXT4_ACL_VERSION 0x0001
160 } ext4_acl_entry_short
;
166 static inline size_t ext4_acl_size(int count
)
169 return sizeof(ext4_acl_header
) +
170 count
* sizeof(ext4_acl_entry_short
);
172 return sizeof(ext4_acl_header
) +
173 4 * sizeof(ext4_acl_entry_short
) +
174 (count
- 4) * sizeof(ext4_acl_entry
);
178 static inline int ext4_acl_count(size_t size
)
182 size
-= sizeof(ext4_acl_header
);
183 s
= size
- 4 * sizeof(ext4_acl_entry_short
);
185 if (size
% sizeof(ext4_acl_entry_short
))
187 return size
/ sizeof(ext4_acl_entry_short
);
189 if (s
% sizeof(ext4_acl_entry
))
191 return s
/ sizeof(ext4_acl_entry
) + 4;
194 static errcode_t
fuse_to_ext4_acl(acl_ea_header
*facl
, size_t facl_sz
,
195 ext4_acl_header
**eacl
, size_t *eacl_sz
)
205 facl_count
= acl_ea_count(facl_sz
);
206 h_sz
= ext4_acl_size(facl_count
);
207 if (facl_count
< 0 || facl
->a_version
!= ACL_EA_VERSION
)
208 return EXT2_ET_INVALID_ARGUMENT
;
210 err
= ext2fs_get_mem(h_sz
, &h
);
214 h
->a_version
= ext2fs_cpu_to_le32(EXT4_ACL_VERSION
);
215 hptr
= (unsigned char *) (h
+ 1);
216 for (i
= 0, a
= facl
->a_entries
; i
< facl_count
; i
++, a
++) {
217 e
= (ext4_acl_entry
*) hptr
;
218 e
->e_tag
= ext2fs_cpu_to_le16(a
->e_tag
);
219 e
->e_perm
= ext2fs_cpu_to_le16(a
->e_perm
);
224 e
->e_id
= ext2fs_cpu_to_le32(a
->e_id
);
225 hptr
+= sizeof(ext4_acl_entry
);
231 hptr
+= sizeof(ext4_acl_entry_short
);
234 err
= EXT2_ET_INVALID_ARGUMENT
;
247 static errcode_t
ext4_to_fuse_acl(acl_ea_header
**facl
, size_t *facl_sz
,
248 ext4_acl_header
*eacl
, size_t eacl_sz
)
258 eacl_count
= ext4_acl_count(eacl_sz
);
259 f_sz
= acl_ea_size(eacl_count
);
260 if (eacl_count
< 0 ||
261 eacl
->a_version
!= ext2fs_cpu_to_le32(EXT4_ACL_VERSION
))
262 return EXT2_ET_INVALID_ARGUMENT
;
264 err
= ext2fs_get_mem(f_sz
, &f
);
268 f
->a_version
= ACL_EA_VERSION
;
269 hptr
= (unsigned char *) (eacl
+ 1);
270 for (i
= 0, a
= f
->a_entries
; i
< eacl_count
; i
++, a
++) {
271 e
= (ext4_acl_entry
*) hptr
;
272 a
->e_tag
= ext2fs_le16_to_cpu(e
->e_tag
);
273 a
->e_perm
= ext2fs_le16_to_cpu(e
->e_perm
);
278 a
->e_id
= ext2fs_le32_to_cpu(e
->e_id
);
279 hptr
+= sizeof(ext4_acl_entry
);
285 hptr
+= sizeof(ext4_acl_entry_short
);
288 err
= EXT2_ET_INVALID_ARGUMENT
;
300 #endif /* TRANSLATE_LINUX_ACLS */
303 * ext2_file_t contains a struct inode, so we can't leave files open.
304 * Use this as a proxy instead.
306 #define FUSE2FS_FILE_MAGIC (0xEF53DEAFUL)
307 struct fuse2fs_file_handle
{
313 /* Main program context */
314 #define FUSE2FS_MAGIC (0xEF53DEADUL)
326 int alloc_all_blocks
;
329 unsigned int next_generation
;
332 #define FUSE2FS_CHECK_MAGIC(fs, ptr, num) do {if ((ptr)->magic != (num)) \
333 return translate_error((fs), 0, EXT2_ET_MAGIC_EXT2_FILE); \
336 #define FUSE2FS_CHECK_CONTEXT(ptr) do {if ((ptr)->magic != FUSE2FS_MAGIC) \
337 return translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC); \
340 static int __translate_error(ext2_filsys fs
, errcode_t err
, ext2_ino_t ino
,
341 const char *file
, int line
);
342 #define translate_error(fs, ino, err) __translate_error((fs), (err), (ino), \
354 #define EXT4_EPOCH_BITS 2
355 #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
356 #define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS)
359 * Extended fields will fit into an inode if the filesystem was formatted
360 * with large inodes (-I 256 or larger) and there are not currently any EAs
361 * consuming all of the available space. For new inodes we always reserve
362 * enough space for the kernel's known extended fields, but for inodes
363 * created with an old kernel this might not have been the case. None of
364 * the extended inode fields is critical for correct filesystem operation.
365 * This macro checks if a certain field fits in the inode. Note that
366 * inode-size = GOOD_OLD_INODE_SIZE + i_extra_isize
368 #define EXT4_FITS_IN_INODE(ext4_inode, field) \
369 ((offsetof(typeof(*ext4_inode), field) + \
370 sizeof((ext4_inode)->field)) \
371 <= ((size_t) EXT2_GOOD_OLD_INODE_SIZE + \
372 (ext4_inode)->i_extra_isize)) \
374 static inline __u32 ext4_encode_extra_time(const struct timespec *time)
376 __u32 extra
= sizeof(time
->tv_sec
) > 4 ?
377 ((time
->tv_sec
- (__s32
)time
->tv_sec
) >> 32) &
379 return extra
| (time
->tv_nsec
<< EXT4_EPOCH_BITS
);
382 static inline void ext4_decode_extra_time(struct timespec
*time
, __u32 extra
)
384 if (sizeof(time
->tv_sec
) > 4 && (extra
& EXT4_EPOCH_MASK
)) {
385 __u64 extra_bits
= extra
& EXT4_EPOCH_MASK
;
387 * Prior to kernel 3.14?, we had a broken decode function,
388 * wherein we effectively did this:
389 * if (extra_bits == 3)
392 time
->tv_sec
+= extra_bits
<< 32;
394 time
->tv_nsec
= ((extra
) & EXT4_NSEC_MASK
) >> EXT4_EPOCH_BITS
;
397 #define EXT4_INODE_SET_XTIME(xtime, timespec, raw_inode) \
399 (raw_inode)->xtime = (timespec)->tv_sec; \
400 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
401 (raw_inode)->xtime ## _extra = \
402 ext4_encode_extra_time(timespec); \
405 #define EXT4_EINODE_SET_XTIME(xtime, timespec, raw_inode) \
407 if (EXT4_FITS_IN_INODE(raw_inode, xtime)) \
408 (raw_inode)->xtime = (timespec)->tv_sec; \
409 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
410 (raw_inode)->xtime ## _extra = \
411 ext4_encode_extra_time(timespec); \
414 #define EXT4_INODE_GET_XTIME(xtime, timespec, raw_inode) \
416 (timespec)->tv_sec = (signed)((raw_inode)->xtime); \
417 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
418 ext4_decode_extra_time((timespec), \
419 (raw_inode)->xtime ## _extra); \
421 (timespec)->tv_nsec = 0; \
424 #define EXT4_EINODE_GET_XTIME(xtime, timespec, raw_inode) \
426 if (EXT4_FITS_IN_INODE(raw_inode, xtime)) \
427 (timespec)->tv_sec = \
428 (signed)((raw_inode)->xtime); \
429 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
430 ext4_decode_extra_time((timespec), \
431 raw_inode->xtime ## _extra); \
433 (timespec)->tv_nsec = 0; \
436 static void get_now(struct timespec
*now
)
438 #ifdef CLOCK_REALTIME
439 if (!clock_gettime(CLOCK_REALTIME
, now
))
443 now
->tv_sec
= time(NULL
);
447 static void increment_version(struct ext2_inode_large
*inode
)
451 ver
= inode
->osd1
.linux1
.l_i_version
;
452 if (EXT4_FITS_IN_INODE(inode
, i_version_hi
))
453 ver
|= (__u64
)inode
->i_version_hi
<< 32;
455 inode
->osd1
.linux1
.l_i_version
= ver
;
456 if (EXT4_FITS_IN_INODE(inode
, i_version_hi
))
457 inode
->i_version_hi
= ver
>> 32;
460 static void init_times(struct ext2_inode_large
*inode
)
465 EXT4_INODE_SET_XTIME(i_atime
, &now
, inode
);
466 EXT4_INODE_SET_XTIME(i_ctime
, &now
, inode
);
467 EXT4_INODE_SET_XTIME(i_mtime
, &now
, inode
);
468 EXT4_EINODE_SET_XTIME(i_crtime
, &now
, inode
);
469 increment_version(inode
);
472 static int update_ctime(ext2_filsys fs
, ext2_ino_t ino
,
473 struct ext2_inode_large
*pinode
)
477 struct ext2_inode_large inode
;
481 /* If user already has a inode buffer, just update that */
483 increment_version(pinode
);
484 EXT4_INODE_SET_XTIME(i_ctime
, &now
, pinode
);
488 /* Otherwise we have to read-modify-write the inode */
489 memset(&inode
, 0, sizeof(inode
));
490 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
493 return translate_error(fs
, ino
, err
);
495 increment_version(&inode
);
496 EXT4_INODE_SET_XTIME(i_ctime
, &now
, &inode
);
498 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
501 return translate_error(fs
, ino
, err
);
506 static int update_atime(ext2_filsys fs
, ext2_ino_t ino
)
509 struct ext2_inode_large inode
, *pinode
;
510 struct timespec atime
, mtime
, now
;
512 if (!(fs
->flags
& EXT2_FLAG_RW
))
514 memset(&inode
, 0, sizeof(inode
));
515 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
518 return translate_error(fs
, ino
, err
);
521 EXT4_INODE_GET_XTIME(i_atime
, &atime
, pinode
);
522 EXT4_INODE_GET_XTIME(i_mtime
, &mtime
, pinode
);
525 * If atime is newer than mtime and atime hasn't been updated in thirty
526 * seconds, skip the atime update. Same idea as Linux "relatime".
528 if (atime
.tv_sec
>= mtime
.tv_sec
&& atime
.tv_sec
>= now
.tv_sec
- 30)
530 EXT4_INODE_SET_XTIME(i_atime
, &now
, &inode
);
532 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
535 return translate_error(fs
, ino
, err
);
540 static int update_mtime(ext2_filsys fs
, ext2_ino_t ino
,
541 struct ext2_inode_large
*pinode
)
544 struct ext2_inode_large inode
;
549 EXT4_INODE_SET_XTIME(i_mtime
, &now
, pinode
);
550 EXT4_INODE_SET_XTIME(i_ctime
, &now
, pinode
);
551 increment_version(pinode
);
555 memset(&inode
, 0, sizeof(inode
));
556 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
559 return translate_error(fs
, ino
, err
);
562 EXT4_INODE_SET_XTIME(i_mtime
, &now
, &inode
);
563 EXT4_INODE_SET_XTIME(i_ctime
, &now
, &inode
);
564 increment_version(&inode
);
566 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
569 return translate_error(fs
, ino
, err
);
574 static int ext2_file_type(unsigned int mode
)
576 if (LINUX_S_ISREG(mode
))
577 return EXT2_FT_REG_FILE
;
579 if (LINUX_S_ISDIR(mode
))
582 if (LINUX_S_ISCHR(mode
))
583 return EXT2_FT_CHRDEV
;
585 if (LINUX_S_ISBLK(mode
))
586 return EXT2_FT_BLKDEV
;
588 if (LINUX_S_ISLNK(mode
))
589 return EXT2_FT_SYMLINK
;
591 if (LINUX_S_ISFIFO(mode
))
594 if (LINUX_S_ISSOCK(mode
))
600 static int fs_can_allocate(struct fuse2fs
*ff
, blk64_t num
)
602 ext2_filsys fs
= ff
->fs
;
605 dbg_printf("%s: Asking for %llu; alloc_all=%d total=%llu free=%llu "
606 "rsvd=%llu\n", __func__
, num
, ff
->alloc_all_blocks
,
607 ext2fs_blocks_count(fs
->super
),
608 ext2fs_free_blocks_count(fs
->super
),
609 ext2fs_r_blocks_count(fs
->super
));
610 if (num
> ext2fs_blocks_count(fs
->super
))
613 if (ff
->alloc_all_blocks
)
617 * Different meaning for r_blocks -- libext2fs has bugs where the FS
618 * can get corrupted if it totally runs out of blocks. Avoid this
619 * by refusing to allocate any of the reserve blocks to anybody.
621 reserved
= ext2fs_r_blocks_count(fs
->super
);
623 reserved
= ext2fs_blocks_count(fs
->super
) / 10;
624 return ext2fs_free_blocks_count(fs
->super
) > reserved
+ num
;
627 static int fs_writeable(ext2_filsys fs
)
629 return (fs
->flags
& EXT2_FLAG_RW
) && (fs
->super
->s_error_count
== 0);
632 static int check_inum_access(ext2_filsys fs
, ext2_ino_t ino
, mode_t mask
)
634 struct fuse_context
*ctxt
= fuse_get_context();
635 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
636 struct ext2_inode inode
;
640 /* no writing to read-only or broken fs */
641 if ((mask
& W_OK
) && !fs_writeable(fs
))
644 err
= ext2fs_read_inode(fs
, ino
, &inode
);
646 return translate_error(fs
, ino
, err
);
647 perms
= inode
.i_mode
& 0777;
649 dbg_printf("access ino=%d mask=e%s%s%s perms=0%o fuid=%d fgid=%d "
650 "uid=%d gid=%d\n", ino
,
651 (mask
& R_OK
? "r" : ""), (mask
& W_OK
? "w" : ""),
652 (mask
& X_OK
? "x" : ""), perms
, inode_uid(inode
),
653 inode_gid(inode
), ctxt
->uid
, ctxt
->gid
);
655 /* existence check */
661 (inode
.i_flags
& EXT2_IMMUTABLE_FL
))
664 /* Figure out what root's allowed to do */
665 if (ff
->fakeroot
|| ctxt
->uid
== 0) {
666 /* Non-file access always ok */
667 if (!LINUX_S_ISREG(inode
.i_mode
))
670 /* R/W access to a file always ok */
674 /* X access to a file ok if a user/group/other can X */
678 /* Trying to execute a file that's not executable. BZZT! */
682 /* allow owner, if perms match */
683 if (inode_uid(inode
) == ctxt
->uid
) {
684 if ((mask
& (perms
>> 6)) == mask
)
689 /* allow group, if perms match */
690 if (inode_gid(inode
) == ctxt
->gid
) {
691 if ((mask
& (perms
>> 3)) == mask
)
696 /* otherwise check other */
697 if ((mask
& perms
) == mask
)
702 static void op_destroy(void *p
EXT2FS_ATTR((unused
)))
704 struct fuse_context
*ctxt
= fuse_get_context();
705 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
709 if (ff
->magic
!= FUSE2FS_MAGIC
) {
710 translate_error(global_fs
, 0, EXT2_ET_BAD_MAGIC
);
714 dbg_printf("%s: dev=%s\n", __func__
, fs
->device_name
);
715 if (fs
->flags
& EXT2_FLAG_RW
) {
716 fs
->super
->s_state
|= EXT2_VALID_FS
;
717 if (fs
->super
->s_error_count
)
718 fs
->super
->s_state
|= EXT2_ERROR_FS
;
719 ext2fs_mark_super_dirty(fs
);
720 err
= ext2fs_set_gdt_csum(fs
);
722 translate_error(fs
, 0, err
);
724 err
= ext2fs_flush2(fs
, 0);
726 translate_error(fs
, 0, err
);
730 static void *op_init(struct fuse_conn_info
*conn
)
732 struct fuse_context
*ctxt
= fuse_get_context();
733 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
737 if (ff
->magic
!= FUSE2FS_MAGIC
) {
738 translate_error(global_fs
, 0, EXT2_ET_BAD_MAGIC
);
742 dbg_printf("%s: dev=%s\n", __func__
, fs
->device_name
);
743 #ifdef FUSE_CAP_IOCTL_DIR
744 conn
->want
|= FUSE_CAP_IOCTL_DIR
;
746 if (fs
->flags
& EXT2_FLAG_RW
) {
747 fs
->super
->s_mnt_count
++;
748 fs
->super
->s_mtime
= time(NULL
);
749 fs
->super
->s_state
&= ~EXT2_VALID_FS
;
750 ext2fs_mark_super_dirty(fs
);
751 err
= ext2fs_flush2(fs
, 0);
753 translate_error(fs
, 0, err
);
758 static int stat_inode(ext2_filsys fs
, ext2_ino_t ino
, struct stat
*statbuf
)
760 struct ext2_inode_large inode
;
766 memset(&inode
, 0, sizeof(inode
));
767 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
770 return translate_error(fs
, ino
, err
);
772 memcpy(&fakedev
, fs
->super
->s_uuid
, sizeof(fakedev
));
773 statbuf
->st_dev
= fakedev
;
774 statbuf
->st_ino
= ino
;
775 statbuf
->st_mode
= inode
.i_mode
;
776 statbuf
->st_nlink
= inode
.i_links_count
;
777 statbuf
->st_uid
= inode_uid(inode
);
778 statbuf
->st_gid
= inode_gid(inode
);
779 statbuf
->st_size
= EXT2_I_SIZE(&inode
);
780 statbuf
->st_blksize
= fs
->blocksize
;
781 statbuf
->st_blocks
= ext2fs_get_stat_i_blocks(fs
,
782 (struct ext2_inode
*)&inode
);
783 EXT4_INODE_GET_XTIME(i_atime
, &tv
, &inode
);
784 statbuf
->st_atime
= tv
.tv_sec
;
785 EXT4_INODE_GET_XTIME(i_mtime
, &tv
, &inode
);
786 statbuf
->st_mtime
= tv
.tv_sec
;
787 EXT4_INODE_GET_XTIME(i_ctime
, &tv
, &inode
);
788 statbuf
->st_ctime
= tv
.tv_sec
;
789 if (LINUX_S_ISCHR(inode
.i_mode
) ||
790 LINUX_S_ISBLK(inode
.i_mode
)) {
791 if (inode
.i_block
[0])
792 statbuf
->st_rdev
= inode
.i_block
[0];
794 statbuf
->st_rdev
= inode
.i_block
[1];
800 static int op_getattr(const char *path
, struct stat
*statbuf
)
802 struct fuse_context
*ctxt
= fuse_get_context();
803 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
809 FUSE2FS_CHECK_CONTEXT(ff
);
811 dbg_printf("%s: path=%s\n", __func__
, path
);
812 pthread_mutex_lock(&ff
->bfl
);
813 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
815 ret
= translate_error(fs
, 0, err
);
818 ret
= stat_inode(fs
, ino
, statbuf
);
820 pthread_mutex_unlock(&ff
->bfl
);
824 static int op_readlink(const char *path
, char *buf
, size_t len
)
826 struct fuse_context
*ctxt
= fuse_get_context();
827 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
831 struct ext2_inode inode
;
836 FUSE2FS_CHECK_CONTEXT(ff
);
838 dbg_printf("%s: path=%s\n", __func__
, path
);
839 pthread_mutex_lock(&ff
->bfl
);
840 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
841 if (err
|| ino
== 0) {
842 ret
= translate_error(fs
, 0, err
);
846 err
= ext2fs_read_inode(fs
, ino
, &inode
);
848 ret
= translate_error(fs
, ino
, err
);
852 if (!LINUX_S_ISLNK(inode
.i_mode
)) {
858 if (inode
.i_size
< len
)
860 if (ext2fs_is_fast_symlink(&inode
))
861 memcpy(buf
, (char *)inode
.i_block
, len
);
863 /* big/inline symlink */
865 err
= ext2fs_file_open(fs
, ino
, 0, &file
);
867 ret
= translate_error(fs
, ino
, err
);
871 err
= ext2fs_file_read(file
, buf
, len
, &got
);
872 if (err
|| got
!= len
) {
873 ext2fs_file_close(file
);
874 ret
= translate_error(fs
, ino
, err
);
879 err
= ext2fs_file_close(file
);
883 ret
= translate_error(fs
, ino
, err
);
889 if (fs_writeable(fs
)) {
890 ret
= update_atime(fs
, ino
);
896 pthread_mutex_unlock(&ff
->bfl
);
900 static int op_mknod(const char *path
, mode_t mode
, dev_t dev
)
902 struct fuse_context
*ctxt
= fuse_get_context();
903 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
905 ext2_ino_t parent
, child
;
910 struct ext2_inode_large inode
;
913 FUSE2FS_CHECK_CONTEXT(ff
);
915 dbg_printf("%s: path=%s mode=0%o dev=0x%x\n", __func__
, path
, mode
,
917 temp_path
= strdup(path
);
922 node_name
= strrchr(temp_path
, '/');
931 pthread_mutex_lock(&ff
->bfl
);
932 if (!fs_can_allocate(ff
, 2)) {
937 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_path
,
940 ret
= translate_error(fs
, 0, err
);
944 ret
= check_inum_access(fs
, parent
, W_OK
);
950 if (LINUX_S_ISCHR(mode
))
951 filetype
= EXT2_FT_CHRDEV
;
952 else if (LINUX_S_ISBLK(mode
))
953 filetype
= EXT2_FT_BLKDEV
;
954 else if (LINUX_S_ISFIFO(mode
))
955 filetype
= EXT2_FT_FIFO
;
956 else if (LINUX_S_ISSOCK(mode
))
957 filetype
= EXT2_FT_SOCK
;
963 err
= ext2fs_new_inode(fs
, parent
, mode
, 0, &child
);
965 ret
= translate_error(fs
, 0, err
);
969 dbg_printf("%s: create ino=%d/name=%s in dir=%d\n", __func__
, child
,
971 err
= ext2fs_link(fs
, parent
, node_name
, child
, filetype
);
972 if (err
== EXT2_ET_DIR_NO_SPACE
) {
973 err
= ext2fs_expand_dir(fs
, parent
);
975 ret
= translate_error(fs
, parent
, err
);
979 err
= ext2fs_link(fs
, parent
, node_name
, child
,
983 ret
= translate_error(fs
, parent
, err
);
987 ret
= update_mtime(fs
, parent
, NULL
);
991 memset(&inode
, 0, sizeof(inode
));
995 inode
.i_block
[1] = dev
;
997 inode
.i_block
[0] = dev
;
998 inode
.i_links_count
= 1;
999 inode
.i_extra_isize
= sizeof(struct ext2_inode_large
) -
1000 EXT2_GOOD_OLD_INODE_SIZE
;
1001 inode
.i_uid
= ctxt
->uid
;
1002 ext2fs_set_i_uid_high(inode
, ctxt
->uid
>> 16);
1003 inode
.i_gid
= ctxt
->gid
;
1004 ext2fs_set_i_gid_high(inode
, ctxt
->gid
>> 16);
1006 err
= ext2fs_write_new_inode(fs
, child
, (struct ext2_inode
*)&inode
);
1008 ret
= translate_error(fs
, child
, err
);
1012 inode
.i_generation
= ff
->next_generation
++;
1014 err
= ext2fs_write_inode_full(fs
, child
, (struct ext2_inode
*)&inode
,
1017 ret
= translate_error(fs
, child
, err
);
1021 ext2fs_inode_alloc_stats2(fs
, child
, 1, 0);
1024 pthread_mutex_unlock(&ff
->bfl
);
1030 static int op_mkdir(const char *path
, mode_t mode
)
1032 struct fuse_context
*ctxt
= fuse_get_context();
1033 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1035 ext2_ino_t parent
, child
;
1039 struct ext2_inode_large inode
;
1045 FUSE2FS_CHECK_CONTEXT(ff
);
1047 dbg_printf("%s: path=%s mode=0%o\n", __func__
, path
, mode
);
1048 temp_path
= strdup(path
);
1053 node_name
= strrchr(temp_path
, '/');
1062 pthread_mutex_lock(&ff
->bfl
);
1063 if (!fs_can_allocate(ff
, 1)) {
1068 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_path
,
1071 ret
= translate_error(fs
, 0, err
);
1075 ret
= check_inum_access(fs
, parent
, W_OK
);
1079 /* Is the parent dir sgid? */
1080 err
= ext2fs_read_inode_full(fs
, parent
, (struct ext2_inode
*)&inode
,
1083 ret
= translate_error(fs
, parent
, err
);
1086 parent_sgid
= inode
.i_mode
& S_ISGID
;
1090 err
= ext2fs_mkdir(fs
, parent
, 0, node_name
);
1091 if (err
== EXT2_ET_DIR_NO_SPACE
) {
1092 err
= ext2fs_expand_dir(fs
, parent
);
1094 ret
= translate_error(fs
, parent
, err
);
1098 err
= ext2fs_mkdir(fs
, parent
, 0, node_name
);
1101 ret
= translate_error(fs
, parent
, err
);
1105 ret
= update_mtime(fs
, parent
, NULL
);
1109 /* Still have to update the uid/gid of the dir */
1110 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_path
,
1113 ret
= translate_error(fs
, 0, err
);
1116 dbg_printf("%s: created ino=%d/path=%s in dir=%d\n", __func__
, child
,
1119 memset(&inode
, 0, sizeof(inode
));
1120 err
= ext2fs_read_inode_full(fs
, child
, (struct ext2_inode
*)&inode
,
1123 ret
= translate_error(fs
, child
, err
);
1127 inode
.i_uid
= ctxt
->uid
;
1128 ext2fs_set_i_uid_high(inode
, ctxt
->uid
>> 16);
1129 inode
.i_gid
= ctxt
->gid
;
1130 ext2fs_set_i_gid_high(inode
, ctxt
->gid
>> 16);
1131 inode
.i_mode
= LINUX_S_IFDIR
| (mode
& ~(S_ISUID
| fs
->umask
)) |
1133 inode
.i_generation
= ff
->next_generation
++;
1135 err
= ext2fs_write_inode_full(fs
, child
, (struct ext2_inode
*)&inode
,
1138 ret
= translate_error(fs
, child
, err
);
1142 /* Rewrite the directory block checksum, having set i_generation */
1143 if ((inode
.i_flags
& EXT4_INLINE_DATA_FL
) ||
1144 !ext2fs_has_feature_metadata_csum(fs
->super
))
1146 err
= ext2fs_new_dir_block(fs
, child
, parent
, &block
);
1148 ret
= translate_error(fs
, child
, err
);
1151 err
= ext2fs_bmap2(fs
, child
, (struct ext2_inode
*)&inode
, NULL
, 0, 0,
1154 ret
= translate_error(fs
, child
, err
);
1157 err
= ext2fs_write_dir_block4(fs
, blk
, block
, 0, child
);
1159 ret
= translate_error(fs
, child
, err
);
1164 ext2fs_free_mem(&block
);
1166 pthread_mutex_unlock(&ff
->bfl
);
1172 static int unlink_file_by_name(ext2_filsys fs
, const char *path
)
1176 char *filename
= strdup(path
);
1180 base_name
= strrchr(filename
, '/');
1182 *base_name
++ = '\0';
1183 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, filename
,
1187 return translate_error(fs
, 0, err
);
1190 dir
= EXT2_ROOT_INO
;
1191 base_name
= filename
;
1194 ret
= check_inum_access(fs
, dir
, W_OK
);
1200 dbg_printf("%s: unlinking name=%s from dir=%d\n", __func__
,
1202 err
= ext2fs_unlink(fs
, dir
, base_name
, 0, 0);
1205 return translate_error(fs
, dir
, err
);
1207 return update_mtime(fs
, dir
, NULL
);
1210 static int remove_inode(struct fuse2fs
*ff
, ext2_ino_t ino
)
1212 ext2_filsys fs
= ff
->fs
;
1214 struct ext2_inode_large inode
;
1217 memset(&inode
, 0, sizeof(inode
));
1218 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1221 ret
= translate_error(fs
, ino
, err
);
1224 dbg_printf("%s: put ino=%d links=%d\n", __func__
, ino
,
1225 inode
.i_links_count
);
1227 switch (inode
.i_links_count
) {
1229 return 0; /* XXX: already done? */
1231 inode
.i_links_count
--;
1232 inode
.i_dtime
= fs
->now
? fs
->now
: time(0);
1235 inode
.i_links_count
--;
1238 ret
= update_ctime(fs
, ino
, &inode
);
1242 if (inode
.i_links_count
)
1245 /* Nobody holds this file; free its blocks! */
1246 err
= ext2fs_free_ext_attr(fs
, ino
, &inode
);
1250 if (ext2fs_inode_has_valid_blocks2(fs
, (struct ext2_inode
*)&inode
)) {
1251 err
= ext2fs_punch(fs
, ino
, (struct ext2_inode
*)&inode
, NULL
,
1254 ret
= translate_error(fs
, ino
, err
);
1259 ext2fs_inode_alloc_stats2(fs
, ino
, -1,
1260 LINUX_S_ISDIR(inode
.i_mode
));
1263 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1266 ret
= translate_error(fs
, ino
, err
);
1273 static int __op_unlink(struct fuse2fs
*ff
, const char *path
)
1275 ext2_filsys fs
= ff
->fs
;
1280 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
1282 ret
= translate_error(fs
, 0, err
);
1286 ret
= unlink_file_by_name(fs
, path
);
1290 ret
= remove_inode(ff
, ino
);
1297 static int op_unlink(const char *path
)
1299 struct fuse_context
*ctxt
= fuse_get_context();
1300 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1303 FUSE2FS_CHECK_CONTEXT(ff
);
1304 pthread_mutex_lock(&ff
->bfl
);
1305 ret
= __op_unlink(ff
, path
);
1306 pthread_mutex_unlock(&ff
->bfl
);
1315 static int rmdir_proc(ext2_ino_t dir
EXT2FS_ATTR((unused
)),
1316 int entry
EXT2FS_ATTR((unused
)),
1317 struct ext2_dir_entry
*dirent
,
1318 int offset
EXT2FS_ATTR((unused
)),
1319 int blocksize
EXT2FS_ATTR((unused
)),
1320 char *buf
EXT2FS_ATTR((unused
)),
1323 struct rd_struct
*rds
= (struct rd_struct
*) private;
1325 if (dirent
->inode
== 0)
1327 if (((dirent
->name_len
& 0xFF) == 1) && (dirent
->name
[0] == '.'))
1329 if (((dirent
->name_len
& 0xFF) == 2) && (dirent
->name
[0] == '.') &&
1330 (dirent
->name
[1] == '.')) {
1331 rds
->parent
= dirent
->inode
;
1338 static int __op_rmdir(struct fuse2fs
*ff
, const char *path
)
1340 ext2_filsys fs
= ff
->fs
;
1343 struct ext2_inode_large inode
;
1344 struct rd_struct rds
;
1347 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &child
);
1349 ret
= translate_error(fs
, 0, err
);
1352 dbg_printf("%s: rmdir path=%s ino=%d\n", __func__
, path
, child
);
1357 err
= ext2fs_dir_iterate2(fs
, child
, 0, 0, rmdir_proc
, &rds
);
1359 ret
= translate_error(fs
, child
, err
);
1363 if (rds
.empty
== 0) {
1368 ret
= unlink_file_by_name(fs
, path
);
1371 /* Directories have to be "removed" twice. */
1372 ret
= remove_inode(ff
, child
);
1375 ret
= remove_inode(ff
, child
);
1380 dbg_printf("%s: decr dir=%d link count\n", __func__
,
1382 err
= ext2fs_read_inode_full(fs
, rds
.parent
,
1383 (struct ext2_inode
*)&inode
,
1386 ret
= translate_error(fs
, rds
.parent
, err
);
1389 if (inode
.i_links_count
> 1)
1390 inode
.i_links_count
--;
1391 ret
= update_mtime(fs
, rds
.parent
, &inode
);
1394 err
= ext2fs_write_inode_full(fs
, rds
.parent
,
1395 (struct ext2_inode
*)&inode
,
1398 ret
= translate_error(fs
, rds
.parent
, err
);
1407 static int op_rmdir(const char *path
)
1409 struct fuse_context
*ctxt
= fuse_get_context();
1410 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1413 FUSE2FS_CHECK_CONTEXT(ff
);
1414 pthread_mutex_lock(&ff
->bfl
);
1415 ret
= __op_rmdir(ff
, path
);
1416 pthread_mutex_unlock(&ff
->bfl
);
1420 static int op_symlink(const char *src
, const char *dest
)
1422 struct fuse_context
*ctxt
= fuse_get_context();
1423 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1425 ext2_ino_t parent
, child
;
1429 struct ext2_inode_large inode
;
1432 FUSE2FS_CHECK_CONTEXT(ff
);
1434 dbg_printf("%s: symlink %s to %s\n", __func__
, src
, dest
);
1435 temp_path
= strdup(dest
);
1440 node_name
= strrchr(temp_path
, '/');
1449 pthread_mutex_lock(&ff
->bfl
);
1450 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_path
,
1454 ret
= translate_error(fs
, 0, err
);
1458 ret
= check_inum_access(fs
, parent
, W_OK
);
1463 /* Create symlink */
1464 err
= ext2fs_symlink(fs
, parent
, 0, node_name
, src
);
1465 if (err
== EXT2_ET_DIR_NO_SPACE
) {
1466 err
= ext2fs_expand_dir(fs
, parent
);
1468 ret
= translate_error(fs
, parent
, err
);
1472 err
= ext2fs_symlink(fs
, parent
, 0, node_name
, src
);
1475 ret
= translate_error(fs
, parent
, err
);
1479 /* Update parent dir's mtime */
1480 ret
= update_mtime(fs
, parent
, NULL
);
1484 /* Still have to update the uid/gid of the symlink */
1485 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_path
,
1488 ret
= translate_error(fs
, 0, err
);
1491 dbg_printf("%s: symlinking ino=%d/name=%s to dir=%d\n", __func__
,
1492 child
, node_name
, parent
);
1494 memset(&inode
, 0, sizeof(inode
));
1495 err
= ext2fs_read_inode_full(fs
, child
, (struct ext2_inode
*)&inode
,
1498 ret
= translate_error(fs
, child
, err
);
1502 inode
.i_uid
= ctxt
->uid
;
1503 ext2fs_set_i_uid_high(inode
, ctxt
->uid
>> 16);
1504 inode
.i_gid
= ctxt
->gid
;
1505 ext2fs_set_i_gid_high(inode
, ctxt
->gid
>> 16);
1506 inode
.i_generation
= ff
->next_generation
++;
1508 err
= ext2fs_write_inode_full(fs
, child
, (struct ext2_inode
*)&inode
,
1511 ret
= translate_error(fs
, child
, err
);
1515 pthread_mutex_unlock(&ff
->bfl
);
1521 struct update_dotdot
{
1522 ext2_ino_t new_dotdot
;
1525 static int update_dotdot_helper(ext2_ino_t dir
EXT2FS_ATTR((unused
)),
1526 int entry
EXT2FS_ATTR((unused
)),
1527 struct ext2_dir_entry
*dirent
,
1528 int offset
EXT2FS_ATTR((unused
)),
1529 int blocksize
EXT2FS_ATTR((unused
)),
1530 char *buf
EXT2FS_ATTR((unused
)),
1533 struct update_dotdot
*ud
= priv_data
;
1535 if (ext2fs_dirent_name_len(dirent
) == 2 &&
1536 dirent
->name
[0] == '.' && dirent
->name
[1] == '.') {
1537 dirent
->inode
= ud
->new_dotdot
;
1538 return DIRENT_CHANGED
| DIRENT_ABORT
;
1544 static int op_rename(const char *from
, const char *to
)
1546 struct fuse_context
*ctxt
= fuse_get_context();
1547 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1550 ext2_ino_t from_ino
, to_ino
, to_dir_ino
, from_dir_ino
;
1551 char *temp_to
= NULL
, *temp_from
= NULL
;
1553 struct ext2_inode inode
;
1554 struct update_dotdot ud
;
1557 FUSE2FS_CHECK_CONTEXT(ff
);
1559 dbg_printf("%s: renaming %s to %s\n", __func__
, from
, to
);
1560 pthread_mutex_lock(&ff
->bfl
);
1561 if (!fs_can_allocate(ff
, 5)) {
1566 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, from
, &from_ino
);
1567 if (err
|| from_ino
== 0) {
1568 ret
= translate_error(fs
, 0, err
);
1572 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, to
, &to_ino
);
1573 if (err
&& err
!= EXT2_ET_FILE_NOT_FOUND
) {
1574 ret
= translate_error(fs
, 0, err
);
1578 if (err
== EXT2_ET_FILE_NOT_FOUND
)
1581 /* Already the same file? */
1582 if (to_ino
!= 0 && to_ino
== from_ino
) {
1587 temp_to
= strdup(to
);
1593 temp_from
= strdup(from
);
1599 /* Find parent dir of the source and check write access */
1600 cp
= strrchr(temp_from
, '/');
1608 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_from
,
1612 ret
= translate_error(fs
, 0, err
);
1615 if (from_dir_ino
== 0) {
1620 ret
= check_inum_access(fs
, from_dir_ino
, W_OK
);
1624 /* Find parent dir of the destination and check write access */
1625 cp
= strrchr(temp_to
, '/');
1633 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_to
,
1637 ret
= translate_error(fs
, 0, err
);
1640 if (to_dir_ino
== 0) {
1645 ret
= check_inum_access(fs
, to_dir_ino
, W_OK
);
1649 /* If the target exists, unlink it first */
1651 err
= ext2fs_read_inode(fs
, to_ino
, &inode
);
1653 ret
= translate_error(fs
, to_ino
, err
);
1657 dbg_printf("%s: unlinking %s ino=%d\n", __func__
,
1658 LINUX_S_ISDIR(inode
.i_mode
) ? "dir" : "file",
1660 if (LINUX_S_ISDIR(inode
.i_mode
))
1661 ret
= __op_rmdir(ff
, to
);
1663 ret
= __op_unlink(ff
, to
);
1668 /* Get ready to do the move */
1669 err
= ext2fs_read_inode(fs
, from_ino
, &inode
);
1671 ret
= translate_error(fs
, from_ino
, err
);
1675 /* Link in the new file */
1676 dbg_printf("%s: linking ino=%d/path=%s to dir=%d\n", __func__
,
1677 from_ino
, cp
+ 1, to_dir_ino
);
1678 err
= ext2fs_link(fs
, to_dir_ino
, cp
+ 1, from_ino
,
1679 ext2_file_type(inode
.i_mode
));
1680 if (err
== EXT2_ET_DIR_NO_SPACE
) {
1681 err
= ext2fs_expand_dir(fs
, to_dir_ino
);
1683 ret
= translate_error(fs
, to_dir_ino
, err
);
1687 err
= ext2fs_link(fs
, to_dir_ino
, cp
+ 1, from_ino
,
1688 ext2_file_type(inode
.i_mode
));
1691 ret
= translate_error(fs
, to_dir_ino
, err
);
1695 /* Update '..' pointer if dir */
1696 err
= ext2fs_read_inode(fs
, from_ino
, &inode
);
1698 ret
= translate_error(fs
, from_ino
, err
);
1702 if (LINUX_S_ISDIR(inode
.i_mode
)) {
1703 ud
.new_dotdot
= to_dir_ino
;
1704 dbg_printf("%s: updating .. entry for dir=%d\n", __func__
,
1706 err
= ext2fs_dir_iterate2(fs
, from_ino
, 0, NULL
,
1707 update_dotdot_helper
, &ud
);
1709 ret
= translate_error(fs
, from_ino
, err
);
1713 /* Decrease from_dir_ino's links_count */
1714 dbg_printf("%s: moving linkcount from dir=%d to dir=%d\n",
1715 __func__
, from_dir_ino
, to_dir_ino
);
1716 err
= ext2fs_read_inode(fs
, from_dir_ino
, &inode
);
1718 ret
= translate_error(fs
, from_dir_ino
, err
);
1721 inode
.i_links_count
--;
1722 err
= ext2fs_write_inode(fs
, from_dir_ino
, &inode
);
1724 ret
= translate_error(fs
, from_dir_ino
, err
);
1728 /* Increase to_dir_ino's links_count */
1729 err
= ext2fs_read_inode(fs
, to_dir_ino
, &inode
);
1731 ret
= translate_error(fs
, to_dir_ino
, err
);
1734 inode
.i_links_count
++;
1735 err
= ext2fs_write_inode(fs
, to_dir_ino
, &inode
);
1737 ret
= translate_error(fs
, to_dir_ino
, err
);
1742 /* Update timestamps */
1743 ret
= update_ctime(fs
, from_ino
, NULL
);
1747 ret
= update_mtime(fs
, to_dir_ino
, NULL
);
1751 /* Remove the old file */
1752 ret
= unlink_file_by_name(fs
, from
);
1756 /* Flush the whole mess out */
1757 err
= ext2fs_flush2(fs
, 0);
1759 ret
= translate_error(fs
, 0, err
);
1765 pthread_mutex_unlock(&ff
->bfl
);
1769 static int op_link(const char *src
, const char *dest
)
1771 struct fuse_context
*ctxt
= fuse_get_context();
1772 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1777 ext2_ino_t parent
, ino
;
1778 struct ext2_inode_large inode
;
1781 FUSE2FS_CHECK_CONTEXT(ff
);
1783 dbg_printf("%s: src=%s dest=%s\n", __func__
, src
, dest
);
1784 temp_path
= strdup(dest
);
1789 node_name
= strrchr(temp_path
, '/');
1798 pthread_mutex_lock(&ff
->bfl
);
1799 if (!fs_can_allocate(ff
, 2)) {
1804 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_path
,
1812 ret
= check_inum_access(fs
, parent
, W_OK
);
1817 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, src
, &ino
);
1818 if (err
|| ino
== 0) {
1819 ret
= translate_error(fs
, 0, err
);
1823 memset(&inode
, 0, sizeof(inode
));
1824 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1827 ret
= translate_error(fs
, ino
, err
);
1831 inode
.i_links_count
++;
1832 ret
= update_ctime(fs
, ino
, &inode
);
1836 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1839 ret
= translate_error(fs
, ino
, err
);
1843 dbg_printf("%s: linking ino=%d/name=%s to dir=%d\n", __func__
, ino
,
1845 err
= ext2fs_link(fs
, parent
, node_name
, ino
,
1846 ext2_file_type(inode
.i_mode
));
1847 if (err
== EXT2_ET_DIR_NO_SPACE
) {
1848 err
= ext2fs_expand_dir(fs
, parent
);
1850 ret
= translate_error(fs
, parent
, err
);
1854 err
= ext2fs_link(fs
, parent
, node_name
, ino
,
1855 ext2_file_type(inode
.i_mode
));
1858 ret
= translate_error(fs
, parent
, err
);
1862 ret
= update_mtime(fs
, parent
, NULL
);
1867 pthread_mutex_unlock(&ff
->bfl
);
1873 static int op_chmod(const char *path
, mode_t mode
)
1875 struct fuse_context
*ctxt
= fuse_get_context();
1876 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1880 struct ext2_inode_large inode
;
1883 FUSE2FS_CHECK_CONTEXT(ff
);
1885 pthread_mutex_lock(&ff
->bfl
);
1886 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
1888 ret
= translate_error(fs
, 0, err
);
1891 dbg_printf("%s: path=%s mode=0%o ino=%d\n", __func__
, path
, mode
, ino
);
1893 memset(&inode
, 0, sizeof(inode
));
1894 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1897 ret
= translate_error(fs
, ino
, err
);
1901 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 && ctxt
->uid
!= inode_uid(inode
)) {
1907 * XXX: We should really check that the inode gid is not in /any/
1908 * of the user's groups, but FUSE only tells us about the primary
1911 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 && ctxt
->gid
!= inode_gid(inode
))
1914 inode
.i_mode
&= ~0xFFF;
1915 inode
.i_mode
|= mode
& 0xFFF;
1916 ret
= update_ctime(fs
, ino
, &inode
);
1920 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1923 ret
= translate_error(fs
, ino
, err
);
1928 pthread_mutex_unlock(&ff
->bfl
);
1932 static int op_chown(const char *path
, uid_t owner
, gid_t group
)
1934 struct fuse_context
*ctxt
= fuse_get_context();
1935 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
1939 struct ext2_inode_large inode
;
1942 FUSE2FS_CHECK_CONTEXT(ff
);
1944 pthread_mutex_lock(&ff
->bfl
);
1945 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
1947 ret
= translate_error(fs
, 0, err
);
1950 dbg_printf("%s: path=%s owner=%d group=%d ino=%d\n", __func__
,
1951 path
, owner
, group
, ino
);
1953 memset(&inode
, 0, sizeof(inode
));
1954 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1957 ret
= translate_error(fs
, ino
, err
);
1961 /* FUSE seems to feed us ~0 to mean "don't change" */
1962 if (owner
!= (uid_t
) ~0) {
1963 /* Only root gets to change UID. */
1964 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 &&
1965 !(inode_uid(inode
) == ctxt
->uid
&& owner
== ctxt
->uid
)) {
1969 inode
.i_uid
= owner
;
1970 ext2fs_set_i_uid_high(inode
, owner
>> 16);
1973 if (group
!= (gid_t
) ~0) {
1974 /* Only root or the owner get to change GID. */
1975 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 &&
1976 inode_uid(inode
) != ctxt
->uid
) {
1981 /* XXX: We /should/ check group membership but FUSE */
1982 inode
.i_gid
= group
;
1983 ext2fs_set_i_gid_high(inode
, group
>> 16);
1986 ret
= update_ctime(fs
, ino
, &inode
);
1990 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1993 ret
= translate_error(fs
, ino
, err
);
1998 pthread_mutex_unlock(&ff
->bfl
);
2002 static int op_truncate(const char *path
, off_t len
)
2004 struct fuse_context
*ctxt
= fuse_get_context();
2005 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2012 FUSE2FS_CHECK_CONTEXT(ff
);
2014 pthread_mutex_lock(&ff
->bfl
);
2015 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2016 if (err
|| ino
== 0) {
2017 ret
= translate_error(fs
, 0, err
);
2020 dbg_printf("%s: ino=%d len=%jd\n", __func__
, ino
, len
);
2022 ret
= check_inum_access(fs
, ino
, W_OK
);
2026 err
= ext2fs_file_open(fs
, ino
, EXT2_FILE_WRITE
, &file
);
2028 ret
= translate_error(fs
, ino
, err
);
2032 err
= ext2fs_file_set_size2(file
, len
);
2034 ret
= translate_error(fs
, ino
, err
);
2039 err
= ext2fs_file_close(file
);
2043 ret
= translate_error(fs
, ino
, err
);
2047 ret
= update_mtime(fs
, ino
, NULL
);
2050 pthread_mutex_unlock(&ff
->bfl
);
2055 static void detect_linux_executable_open(int kernel_flags
, int *access_check
,
2056 int *e2fs_open_flags
)
2059 * On Linux, execve will bleed __FMODE_EXEC into the file mode flags,
2060 * and FUSE is more than happy to let that slip through.
2062 if (kernel_flags
& 0x20) {
2063 *access_check
= X_OK
;
2064 *e2fs_open_flags
&= ~EXT2_FILE_WRITE
;
2068 static void detect_linux_executable_open(int kernel_flags
, int *access_check
,
2069 int *e2fs_open_flags
)
2073 #endif /* __linux__ */
2075 static int __op_open(struct fuse2fs
*ff
, const char *path
,
2076 struct fuse_file_info
*fp
)
2078 ext2_filsys fs
= ff
->fs
;
2080 struct fuse2fs_file_handle
*file
;
2081 int check
= 0, ret
= 0;
2083 dbg_printf("%s: path=%s\n", __func__
, path
);
2084 err
= ext2fs_get_mem(sizeof(*file
), &file
);
2086 return translate_error(fs
, 0, err
);
2087 file
->magic
= FUSE2FS_FILE_MAGIC
;
2089 file
->open_flags
= 0;
2090 switch (fp
->flags
& O_ACCMODE
) {
2096 file
->open_flags
|= EXT2_FILE_WRITE
;
2099 check
= R_OK
| W_OK
;
2100 file
->open_flags
|= EXT2_FILE_WRITE
;
2104 detect_linux_executable_open(fp
->flags
, &check
, &file
->open_flags
);
2106 if (fp
->flags
& O_CREAT
)
2107 file
->open_flags
|= EXT2_FILE_CREATE
;
2109 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &file
->ino
);
2110 if (err
|| file
->ino
== 0) {
2111 ret
= translate_error(fs
, 0, err
);
2114 dbg_printf("%s: ino=%d\n", __func__
, file
->ino
);
2116 ret
= check_inum_access(fs
, file
->ino
, check
);
2119 * In a regular (Linux) fs driver, the kernel will open
2120 * binaries for reading if the user has --x privileges (i.e.
2121 * execute without read). Since the kernel doesn't have any
2122 * way to tell us if it's opening a file via execve, we'll
2123 * just assume that allowing access is ok if asking for ro mode
2124 * fails but asking for x mode succeeds. Of course we can
2125 * also employ undocumented hacks (see above).
2127 if (check
== R_OK
) {
2128 ret
= check_inum_access(fs
, file
->ino
, X_OK
);
2134 fp
->fh
= (uintptr_t)file
;
2138 ext2fs_free_mem(&file
);
2142 static int op_open(const char *path
, struct fuse_file_info
*fp
)
2144 struct fuse_context
*ctxt
= fuse_get_context();
2145 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2148 FUSE2FS_CHECK_CONTEXT(ff
);
2149 pthread_mutex_lock(&ff
->bfl
);
2150 ret
= __op_open(ff
, path
, fp
);
2151 pthread_mutex_unlock(&ff
->bfl
);
2155 static int op_read(const char *path
EXT2FS_ATTR((unused
)), char *buf
,
2156 size_t len
, off_t offset
,
2157 struct fuse_file_info
*fp
)
2159 struct fuse_context
*ctxt
= fuse_get_context();
2160 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2161 struct fuse2fs_file_handle
*fh
=
2162 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2166 unsigned int got
= 0;
2169 FUSE2FS_CHECK_CONTEXT(ff
);
2171 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2172 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__
, fh
->ino
, offset
,
2174 pthread_mutex_lock(&ff
->bfl
);
2175 err
= ext2fs_file_open(fs
, fh
->ino
, fh
->open_flags
, &efp
);
2177 ret
= translate_error(fs
, fh
->ino
, err
);
2181 err
= ext2fs_file_llseek(efp
, offset
, SEEK_SET
, NULL
);
2183 ret
= translate_error(fs
, fh
->ino
, err
);
2187 err
= ext2fs_file_read(efp
, buf
, len
, &got
);
2189 ret
= translate_error(fs
, fh
->ino
, err
);
2194 err
= ext2fs_file_close(efp
);
2198 ret
= translate_error(fs
, fh
->ino
, err
);
2202 if (fs_writeable(fs
)) {
2203 ret
= update_atime(fs
, fh
->ino
);
2208 pthread_mutex_unlock(&ff
->bfl
);
2209 return got
? (int) got
: ret
;
2212 static int op_write(const char *path
EXT2FS_ATTR((unused
)),
2213 const char *buf
, size_t len
, off_t offset
,
2214 struct fuse_file_info
*fp
)
2216 struct fuse_context
*ctxt
= fuse_get_context();
2217 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2218 struct fuse2fs_file_handle
*fh
=
2219 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2223 unsigned int got
= 0;
2226 FUSE2FS_CHECK_CONTEXT(ff
);
2228 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2229 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__
, fh
->ino
, offset
,
2231 pthread_mutex_lock(&ff
->bfl
);
2232 if (!fs_writeable(fs
)) {
2237 if (!fs_can_allocate(ff
, len
/ fs
->blocksize
)) {
2242 err
= ext2fs_file_open(fs
, fh
->ino
, fh
->open_flags
, &efp
);
2244 ret
= translate_error(fs
, fh
->ino
, err
);
2248 err
= ext2fs_file_llseek(efp
, offset
, SEEK_SET
, NULL
);
2250 ret
= translate_error(fs
, fh
->ino
, err
);
2254 err
= ext2fs_file_write(efp
, buf
, len
, &got
);
2256 ret
= translate_error(fs
, fh
->ino
, err
);
2260 err
= ext2fs_file_flush(efp
);
2263 ret
= translate_error(fs
, fh
->ino
, err
);
2268 err
= ext2fs_file_close(efp
);
2272 ret
= translate_error(fs
, fh
->ino
, err
);
2276 ret
= update_mtime(fs
, fh
->ino
, NULL
);
2281 pthread_mutex_unlock(&ff
->bfl
);
2282 return got
? (int) got
: ret
;
2285 static int op_release(const char *path
EXT2FS_ATTR((unused
)),
2286 struct fuse_file_info
*fp
)
2288 struct fuse_context
*ctxt
= fuse_get_context();
2289 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2290 struct fuse2fs_file_handle
*fh
=
2291 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2296 FUSE2FS_CHECK_CONTEXT(ff
);
2298 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2299 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
2300 pthread_mutex_lock(&ff
->bfl
);
2301 if (fs_writeable(fs
) && fh
->open_flags
& EXT2_FILE_WRITE
) {
2302 err
= ext2fs_flush2(fs
, EXT2_FLAG_FLUSH_NO_SYNC
);
2304 ret
= translate_error(fs
, fh
->ino
, err
);
2307 pthread_mutex_unlock(&ff
->bfl
);
2309 ext2fs_free_mem(&fh
);
2314 static int op_fsync(const char *path
EXT2FS_ATTR((unused
)),
2315 int datasync
EXT2FS_ATTR((unused
)),
2316 struct fuse_file_info
*fp
)
2318 struct fuse_context
*ctxt
= fuse_get_context();
2319 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2320 struct fuse2fs_file_handle
*fh
=
2321 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2326 FUSE2FS_CHECK_CONTEXT(ff
);
2328 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2329 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
2330 /* For now, flush everything, even if it's slow */
2331 pthread_mutex_lock(&ff
->bfl
);
2332 if (fs_writeable(fs
) && fh
->open_flags
& EXT2_FILE_WRITE
) {
2333 err
= ext2fs_flush2(fs
, 0);
2335 ret
= translate_error(fs
, fh
->ino
, err
);
2337 pthread_mutex_unlock(&ff
->bfl
);
2342 static int op_statfs(const char *path
EXT2FS_ATTR((unused
)),
2343 struct statvfs
*buf
)
2345 struct fuse_context
*ctxt
= fuse_get_context();
2346 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2349 blk64_t overhead
, reserved
, free
;
2351 FUSE2FS_CHECK_CONTEXT(ff
);
2353 dbg_printf("%s: path=%s\n", __func__
, path
);
2354 buf
->f_bsize
= fs
->blocksize
;
2360 overhead
= fs
->desc_blocks
+
2361 fs
->group_desc_count
*
2362 (fs
->inode_blocks_per_group
+ 2);
2363 reserved
= ext2fs_r_blocks_count(fs
->super
);
2365 reserved
= ext2fs_blocks_count(fs
->super
) / 10;
2366 free
= ext2fs_free_blocks_count(fs
->super
);
2368 buf
->f_blocks
= ext2fs_blocks_count(fs
->super
) - overhead
;
2369 buf
->f_bfree
= free
;
2370 if (free
< reserved
)
2373 buf
->f_bavail
= free
- reserved
;
2374 buf
->f_files
= fs
->super
->s_inodes_count
;
2375 buf
->f_ffree
= fs
->super
->s_free_inodes_count
;
2376 buf
->f_favail
= fs
->super
->s_free_inodes_count
;
2377 f
= (uint64_t *)fs
->super
->s_uuid
;
2383 if (fs
->flags
& EXT2_FLAG_RW
)
2384 buf
->f_flag
|= ST_RDONLY
;
2385 buf
->f_namemax
= EXT2_NAME_LEN
;
2390 typedef errcode_t (*xattr_xlate_get
)(void **cooked_buf
, size_t *cooked_sz
,
2391 const void *raw_buf
, size_t raw_sz
);
2392 typedef errcode_t (*xattr_xlate_set
)(const void *cooked_buf
, size_t cooked_sz
,
2393 const void **raw_buf
, size_t *raw_sz
);
2394 struct xattr_translate
{
2396 xattr_xlate_get get
;
2397 xattr_xlate_set set
;
2400 #define XATTR_TRANSLATOR(p, g, s) \
2402 .get = (xattr_xlate_get)(g), \
2403 .set = (xattr_xlate_set)(s)}
2405 static struct xattr_translate xattr_translators
[] = {
2406 #ifdef TRANSLATE_LINUX_ACLS
2407 XATTR_TRANSLATOR(ACL_EA_ACCESS
, ext4_to_fuse_acl
, fuse_to_ext4_acl
),
2408 XATTR_TRANSLATOR(ACL_EA_DEFAULT
, ext4_to_fuse_acl
, fuse_to_ext4_acl
),
2410 XATTR_TRANSLATOR(NULL
, NULL
, NULL
),
2412 #undef XATTR_TRANSLATOR
2414 static int op_getxattr(const char *path
, const char *key
, char *value
,
2417 struct fuse_context
*ctxt
= fuse_get_context();
2418 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2420 struct ext2_xattr_handle
*h
;
2421 struct xattr_translate
*xt
;
2428 FUSE2FS_CHECK_CONTEXT(ff
);
2430 pthread_mutex_lock(&ff
->bfl
);
2431 if (!ext2fs_has_feature_xattr(fs
->super
)) {
2436 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2437 if (err
|| ino
== 0) {
2438 ret
= translate_error(fs
, 0, err
);
2441 dbg_printf("%s: ino=%d\n", __func__
, ino
);
2443 ret
= check_inum_access(fs
, ino
, R_OK
);
2447 err
= ext2fs_xattrs_open(fs
, ino
, &h
);
2449 ret
= translate_error(fs
, ino
, err
);
2453 err
= ext2fs_xattrs_read(h
);
2455 ret
= translate_error(fs
, ino
, err
);
2459 err
= ext2fs_xattr_get(h
, key
, &ptr
, &plen
);
2461 ret
= translate_error(fs
, ino
, err
);
2465 for (xt
= xattr_translators
; xt
->prefix
!= NULL
; xt
++) {
2466 if (strncmp(key
, xt
->prefix
, strlen(xt
->prefix
)) == 0) {
2467 err
= xt
->get(&cptr
, &clen
, ptr
, plen
);
2470 ext2fs_free_mem(&ptr
);
2478 } else if (len
< plen
) {
2481 memcpy(value
, ptr
, plen
);
2486 ext2fs_free_mem(&ptr
);
2488 err
= ext2fs_xattrs_close(&h
);
2490 ret
= translate_error(fs
, ino
, err
);
2492 pthread_mutex_unlock(&ff
->bfl
);
2497 static int count_buffer_space(char *name
, char *value
EXT2FS_ATTR((unused
)),
2498 size_t value_len
EXT2FS_ATTR((unused
)),
2501 unsigned int *x
= data
;
2503 *x
= *x
+ strlen(name
) + 1;
2507 static int copy_names(char *name
, char *value
EXT2FS_ATTR((unused
)),
2508 size_t value_len
EXT2FS_ATTR((unused
)), void *data
)
2512 strncpy(*b
, name
, strlen(name
));
2513 *b
= *b
+ strlen(name
) + 1;
2518 static int op_listxattr(const char *path
, char *names
, size_t len
)
2520 struct fuse_context
*ctxt
= fuse_get_context();
2521 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2523 struct ext2_xattr_handle
*h
;
2529 FUSE2FS_CHECK_CONTEXT(ff
);
2531 pthread_mutex_lock(&ff
->bfl
);
2532 if (!ext2fs_has_feature_xattr(fs
->super
)) {
2537 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2538 if (err
|| ino
== 0) {
2539 ret
= translate_error(fs
, ino
, err
);
2542 dbg_printf("%s: ino=%d\n", __func__
, ino
);
2544 ret
= check_inum_access(fs
, ino
, R_OK
);
2548 err
= ext2fs_xattrs_open(fs
, ino
, &h
);
2550 ret
= translate_error(fs
, ino
, err
);
2554 err
= ext2fs_xattrs_read(h
);
2556 ret
= translate_error(fs
, ino
, err
);
2560 /* Count buffer space needed for names */
2562 err
= ext2fs_xattrs_iterate(h
, count_buffer_space
, &bufsz
);
2564 ret
= translate_error(fs
, ino
, err
);
2571 } else if (len
< bufsz
) {
2576 /* Copy names out */
2577 memset(names
, 0, len
);
2578 err
= ext2fs_xattrs_iterate(h
, copy_names
, &names
);
2580 ret
= translate_error(fs
, ino
, err
);
2585 err
= ext2fs_xattrs_close(&h
);
2587 ret
= translate_error(fs
, ino
, err
);
2589 pthread_mutex_unlock(&ff
->bfl
);
2594 static int op_setxattr(const char *path
EXT2FS_ATTR((unused
)),
2595 const char *key
, const char *value
,
2596 size_t len
, int flags
EXT2FS_ATTR((unused
)))
2598 struct fuse_context
*ctxt
= fuse_get_context();
2599 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2601 struct ext2_xattr_handle
*h
;
2602 struct xattr_translate
*xt
;
2609 FUSE2FS_CHECK_CONTEXT(ff
);
2611 pthread_mutex_lock(&ff
->bfl
);
2612 if (!ext2fs_has_feature_xattr(fs
->super
)) {
2617 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2618 if (err
|| ino
== 0) {
2619 ret
= translate_error(fs
, 0, err
);
2622 dbg_printf("%s: ino=%d\n", __func__
, ino
);
2624 ret
= check_inum_access(fs
, ino
, W_OK
);
2625 if (ret
== -EACCES
) {
2631 err
= ext2fs_xattrs_open(fs
, ino
, &h
);
2633 ret
= translate_error(fs
, ino
, err
);
2637 err
= ext2fs_xattrs_read(h
);
2639 ret
= translate_error(fs
, ino
, err
);
2645 for (xt
= xattr_translators
; xt
->prefix
!= NULL
; xt
++) {
2646 if (strncmp(key
, xt
->prefix
, strlen(xt
->prefix
)) == 0) {
2647 err
= xt
->set(value
, len
, &cvalue
, &clen
);
2653 err
= ext2fs_xattr_set(h
, key
, cvalue
, clen
);
2655 ret
= translate_error(fs
, ino
, err
);
2659 ret
= update_ctime(fs
, ino
, NULL
);
2661 if (cvalue
!= value
)
2662 ext2fs_free_mem(&cvalue
);
2664 err
= ext2fs_xattrs_close(&h
);
2666 ret
= translate_error(fs
, ino
, err
);
2668 pthread_mutex_unlock(&ff
->bfl
);
2673 static int op_removexattr(const char *path
, const char *key
)
2675 struct fuse_context
*ctxt
= fuse_get_context();
2676 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2678 struct ext2_xattr_handle
*h
;
2683 FUSE2FS_CHECK_CONTEXT(ff
);
2685 pthread_mutex_lock(&ff
->bfl
);
2686 if (!ext2fs_has_feature_xattr(fs
->super
)) {
2691 if (!fs_can_allocate(ff
, 1)) {
2696 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2697 if (err
|| ino
== 0) {
2698 ret
= translate_error(fs
, 0, err
);
2701 dbg_printf("%s: ino=%d\n", __func__
, ino
);
2703 ret
= check_inum_access(fs
, ino
, W_OK
);
2707 err
= ext2fs_xattrs_open(fs
, ino
, &h
);
2709 ret
= translate_error(fs
, ino
, err
);
2713 err
= ext2fs_xattrs_read(h
);
2715 ret
= translate_error(fs
, ino
, err
);
2719 err
= ext2fs_xattr_remove(h
, key
);
2721 ret
= translate_error(fs
, ino
, err
);
2725 ret
= update_ctime(fs
, ino
, NULL
);
2727 err
= ext2fs_xattrs_close(&h
);
2729 ret
= translate_error(fs
, ino
, err
);
2731 pthread_mutex_unlock(&ff
->bfl
);
2736 struct readdir_iter
{
2738 fuse_fill_dir_t func
;
2741 static int op_readdir_iter(ext2_ino_t dir
EXT2FS_ATTR((unused
)),
2742 int entry
EXT2FS_ATTR((unused
)),
2743 struct ext2_dir_entry
*dirent
,
2744 int offset
EXT2FS_ATTR((unused
)),
2745 int blocksize
EXT2FS_ATTR((unused
)),
2746 char *buf
EXT2FS_ATTR((unused
)), void *data
)
2748 struct readdir_iter
*i
= data
;
2749 char namebuf
[EXT2_NAME_LEN
+ 1];
2752 memcpy(namebuf
, dirent
->name
, dirent
->name_len
& 0xFF);
2753 namebuf
[dirent
->name_len
& 0xFF] = 0;
2754 ret
= i
->func(i
->buf
, namebuf
, NULL
, 0);
2756 return DIRENT_ABORT
;
2761 static int op_readdir(const char *path
EXT2FS_ATTR((unused
)),
2762 void *buf
, fuse_fill_dir_t fill_func
,
2763 off_t offset
EXT2FS_ATTR((unused
)),
2764 struct fuse_file_info
*fp
)
2766 struct fuse_context
*ctxt
= fuse_get_context();
2767 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2768 struct fuse2fs_file_handle
*fh
=
2769 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2772 struct readdir_iter i
;
2775 FUSE2FS_CHECK_CONTEXT(ff
);
2777 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2778 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
2779 pthread_mutex_lock(&ff
->bfl
);
2782 err
= ext2fs_dir_iterate2(fs
, fh
->ino
, 0, NULL
, op_readdir_iter
, &i
);
2784 ret
= translate_error(fs
, fh
->ino
, err
);
2788 if (fs_writeable(fs
)) {
2789 ret
= update_atime(fs
, fh
->ino
);
2794 pthread_mutex_unlock(&ff
->bfl
);
2798 static int op_access(const char *path
, int mask
)
2800 struct fuse_context
*ctxt
= fuse_get_context();
2801 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2807 FUSE2FS_CHECK_CONTEXT(ff
);
2809 dbg_printf("%s: path=%s mask=0x%x\n", __func__
, path
, mask
);
2810 pthread_mutex_lock(&ff
->bfl
);
2811 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
2812 if (err
|| ino
== 0) {
2813 ret
= translate_error(fs
, 0, err
);
2817 ret
= check_inum_access(fs
, ino
, mask
);
2822 pthread_mutex_unlock(&ff
->bfl
);
2826 static int op_create(const char *path
, mode_t mode
, struct fuse_file_info
*fp
)
2828 struct fuse_context
*ctxt
= fuse_get_context();
2829 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2831 ext2_ino_t parent
, child
;
2836 struct ext2_inode_large inode
;
2839 FUSE2FS_CHECK_CONTEXT(ff
);
2841 dbg_printf("%s: path=%s mode=0%o\n", __func__
, path
, mode
);
2842 temp_path
= strdup(path
);
2847 node_name
= strrchr(temp_path
, '/');
2856 pthread_mutex_lock(&ff
->bfl
);
2857 if (!fs_can_allocate(ff
, 1)) {
2862 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, temp_path
,
2865 ret
= translate_error(fs
, 0, err
);
2869 ret
= check_inum_access(fs
, parent
, W_OK
);
2875 filetype
= ext2_file_type(mode
);
2877 err
= ext2fs_new_inode(fs
, parent
, mode
, 0, &child
);
2879 ret
= translate_error(fs
, parent
, err
);
2883 dbg_printf("%s: creating ino=%d/name=%s in dir=%d\n", __func__
, child
,
2885 err
= ext2fs_link(fs
, parent
, node_name
, child
, filetype
);
2886 if (err
== EXT2_ET_DIR_NO_SPACE
) {
2887 err
= ext2fs_expand_dir(fs
, parent
);
2889 ret
= translate_error(fs
, parent
, err
);
2893 err
= ext2fs_link(fs
, parent
, node_name
, child
,
2897 ret
= translate_error(fs
, parent
, err
);
2901 ret
= update_mtime(fs
, parent
, NULL
);
2905 memset(&inode
, 0, sizeof(inode
));
2906 inode
.i_mode
= mode
;
2907 inode
.i_links_count
= 1;
2908 inode
.i_extra_isize
= sizeof(struct ext2_inode_large
) -
2909 EXT2_GOOD_OLD_INODE_SIZE
;
2910 inode
.i_uid
= ctxt
->uid
;
2911 ext2fs_set_i_uid_high(inode
, ctxt
->uid
>> 16);
2912 inode
.i_gid
= ctxt
->gid
;
2913 ext2fs_set_i_gid_high(inode
, ctxt
->gid
>> 16);
2914 if (ext2fs_has_feature_extents(fs
->super
)) {
2915 ext2_extent_handle_t handle
;
2917 inode
.i_flags
&= ~EXT4_EXTENTS_FL
;
2918 ret
= ext2fs_extent_open2(fs
, child
,
2919 (struct ext2_inode
*)&inode
, &handle
);
2922 ext2fs_extent_free(handle
);
2925 err
= ext2fs_write_new_inode(fs
, child
, (struct ext2_inode
*)&inode
);
2927 ret
= translate_error(fs
, child
, err
);
2931 inode
.i_generation
= ff
->next_generation
++;
2933 err
= ext2fs_write_inode_full(fs
, child
, (struct ext2_inode
*)&inode
,
2936 ret
= translate_error(fs
, child
, err
);
2940 ext2fs_inode_alloc_stats2(fs
, child
, 1, 0);
2942 ret
= __op_open(ff
, path
, fp
);
2946 pthread_mutex_unlock(&ff
->bfl
);
2952 static int op_ftruncate(const char *path
EXT2FS_ATTR((unused
)),
2953 off_t len
, struct fuse_file_info
*fp
)
2955 struct fuse_context
*ctxt
= fuse_get_context();
2956 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
2957 struct fuse2fs_file_handle
*fh
=
2958 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
2964 FUSE2FS_CHECK_CONTEXT(ff
);
2966 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
2967 dbg_printf("%s: ino=%d len=%jd\n", __func__
, fh
->ino
, len
);
2968 pthread_mutex_lock(&ff
->bfl
);
2969 if (!fs_writeable(fs
)) {
2974 err
= ext2fs_file_open(fs
, fh
->ino
, fh
->open_flags
, &efp
);
2976 ret
= translate_error(fs
, fh
->ino
, err
);
2980 err
= ext2fs_file_set_size2(efp
, len
);
2982 ret
= translate_error(fs
, fh
->ino
, err
);
2987 err
= ext2fs_file_close(efp
);
2991 ret
= translate_error(fs
, fh
->ino
, err
);
2995 ret
= update_mtime(fs
, fh
->ino
, NULL
);
3000 pthread_mutex_unlock(&ff
->bfl
);
3004 static int op_fgetattr(const char *path
EXT2FS_ATTR((unused
)),
3005 struct stat
*statbuf
,
3006 struct fuse_file_info
*fp
)
3008 struct fuse_context
*ctxt
= fuse_get_context();
3009 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3011 struct fuse2fs_file_handle
*fh
=
3012 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
3015 FUSE2FS_CHECK_CONTEXT(ff
);
3017 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3018 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
3019 pthread_mutex_lock(&ff
->bfl
);
3020 ret
= stat_inode(fs
, fh
->ino
, statbuf
);
3021 pthread_mutex_unlock(&ff
->bfl
);
3026 static int op_utimens(const char *path
, const struct timespec ctv
[2])
3028 struct fuse_context
*ctxt
= fuse_get_context();
3029 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3030 struct timespec tv
[2];
3034 struct ext2_inode_large inode
;
3037 FUSE2FS_CHECK_CONTEXT(ff
);
3039 pthread_mutex_lock(&ff
->bfl
);
3040 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
3042 ret
= translate_error(fs
, 0, err
);
3045 dbg_printf("%s: ino=%d\n", __func__
, ino
);
3047 ret
= check_inum_access(fs
, ino
, W_OK
);
3051 memset(&inode
, 0, sizeof(inode
));
3052 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
3055 ret
= translate_error(fs
, ino
, err
);
3062 if (tv
[0].tv_nsec
== UTIME_NOW
)
3064 if (tv
[1].tv_nsec
== UTIME_NOW
)
3066 #endif /* UTIME_NOW */
3068 if (tv
[0].tv_nsec
!= UTIME_OMIT
)
3069 EXT4_INODE_SET_XTIME(i_atime
, tv
, &inode
);
3070 if (tv
[1].tv_nsec
!= UTIME_OMIT
)
3071 EXT4_INODE_SET_XTIME(i_mtime
, tv
+ 1, &inode
);
3072 #endif /* UTIME_OMIT */
3073 ret
= update_ctime(fs
, ino
, &inode
);
3077 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
3080 ret
= translate_error(fs
, ino
, err
);
3085 pthread_mutex_unlock(&ff
->bfl
);
3089 #ifdef SUPPORT_I_FLAGS
3090 static int ioctl_getflags(ext2_filsys fs
, struct fuse2fs_file_handle
*fh
,
3094 struct ext2_inode_large inode
;
3096 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3097 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
3098 memset(&inode
, 0, sizeof(inode
));
3099 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3102 return translate_error(fs
, fh
->ino
, err
);
3104 *(__u32
*)data
= inode
.i_flags
& EXT2_FL_USER_VISIBLE
;
3108 #define FUSE2FS_MODIFIABLE_IFLAGS \
3109 (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL | EXT2_NODUMP_FL | \
3110 EXT2_NOATIME_FL | EXT3_JOURNAL_DATA_FL | EXT2_DIRSYNC_FL | \
3113 static int ioctl_setflags(ext2_filsys fs
, struct fuse2fs_file_handle
*fh
,
3117 struct ext2_inode_large inode
;
3119 __u32 flags
= *(__u32
*)data
;
3120 struct fuse_context
*ctxt
= fuse_get_context();
3121 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3123 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3124 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
3125 memset(&inode
, 0, sizeof(inode
));
3126 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3129 return translate_error(fs
, fh
->ino
, err
);
3131 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 && inode_uid(inode
) != ctxt
->uid
)
3134 if ((inode
.i_flags
^ flags
) & ~FUSE2FS_MODIFIABLE_IFLAGS
)
3137 inode
.i_flags
= (inode
.i_flags
& ~FUSE2FS_MODIFIABLE_IFLAGS
) |
3138 (flags
& FUSE2FS_MODIFIABLE_IFLAGS
);
3140 ret
= update_ctime(fs
, fh
->ino
, &inode
);
3144 err
= ext2fs_write_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3147 return translate_error(fs
, fh
->ino
, err
);
3152 static int ioctl_getversion(ext2_filsys fs
, struct fuse2fs_file_handle
*fh
,
3156 struct ext2_inode_large inode
;
3158 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3159 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
3160 memset(&inode
, 0, sizeof(inode
));
3161 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3164 return translate_error(fs
, fh
->ino
, err
);
3166 *(__u32
*)data
= inode
.i_generation
;
3170 static int ioctl_setversion(ext2_filsys fs
, struct fuse2fs_file_handle
*fh
,
3174 struct ext2_inode_large inode
;
3176 __u32 generation
= *(__u32
*)data
;
3177 struct fuse_context
*ctxt
= fuse_get_context();
3178 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3180 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3181 dbg_printf("%s: ino=%d\n", __func__
, fh
->ino
);
3182 memset(&inode
, 0, sizeof(inode
));
3183 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3186 return translate_error(fs
, fh
->ino
, err
);
3188 if (!ff
->fakeroot
&& ctxt
->uid
!= 0 && inode_uid(inode
) != ctxt
->uid
)
3191 inode
.i_generation
= generation
;
3193 ret
= update_ctime(fs
, fh
->ino
, &inode
);
3197 err
= ext2fs_write_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3200 return translate_error(fs
, fh
->ino
, err
);
3204 #endif /* SUPPORT_I_FLAGS */
3207 static int ioctl_fitrim(ext2_filsys fs
, struct fuse2fs_file_handle
*fh
,
3210 struct fstrim_range
*fr
= data
;
3211 blk64_t start
, end
, max_blocks
, b
, cleared
;
3214 start
= fr
->start
/ fs
->blocksize
;
3215 end
= (fr
->start
+ fr
->len
- 1) / fs
->blocksize
;
3216 dbg_printf("%s: start=%llu end=%llu\n", __func__
, start
, end
);
3218 if (start
< fs
->super
->s_first_data_block
)
3219 start
= fs
->super
->s_first_data_block
;
3220 if (start
>= ext2fs_blocks_count(fs
->super
))
3221 start
= ext2fs_blocks_count(fs
->super
) - 1;
3223 if (end
< fs
->super
->s_first_data_block
)
3224 end
= fs
->super
->s_first_data_block
;
3225 if (end
>= ext2fs_blocks_count(fs
->super
))
3226 end
= ext2fs_blocks_count(fs
->super
) - 1;
3229 max_blocks
= 2048ULL * 1024 * 1024 / fs
->blocksize
;
3232 while (start
<= end
) {
3233 err
= ext2fs_find_first_zero_block_bitmap2(fs
->block_map
,
3234 start
, end
, &start
);
3238 return translate_error(fs
, fh
->ino
, err
);
3240 b
= start
+ max_blocks
< end
? start
+ max_blocks
: end
;
3241 err
= ext2fs_find_first_set_block_bitmap2(fs
->block_map
,
3243 if (err
&& err
!= ENOENT
)
3244 return translate_error(fs
, fh
->ino
, err
);
3245 if (b
- start
>= fr
->minlen
) {
3246 err
= io_channel_discard(fs
->io
, start
, b
- start
);
3248 return translate_error(fs
, fh
->ino
, err
);
3249 cleared
+= b
- start
;
3250 fr
->len
= cleared
* fs
->blocksize
;
3259 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
3260 static int op_ioctl(const char *path
EXT2FS_ATTR((unused
)), int cmd
,
3261 void *arg
EXT2FS_ATTR((unused
)),
3262 struct fuse_file_info
*fp
,
3263 unsigned int flags
EXT2FS_ATTR((unused
)), void *data
)
3265 struct fuse_context
*ctxt
= fuse_get_context();
3266 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3267 struct fuse2fs_file_handle
*fh
=
3268 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
3272 FUSE2FS_CHECK_CONTEXT(ff
);
3274 pthread_mutex_lock(&ff
->bfl
);
3275 switch ((unsigned long) cmd
) {
3276 #ifdef SUPPORT_I_FLAGS
3277 case EXT2_IOC_GETFLAGS
:
3278 ret
= ioctl_getflags(fs
, fh
, data
);
3280 case EXT2_IOC_SETFLAGS
:
3281 ret
= ioctl_setflags(fs
, fh
, data
);
3283 case EXT2_IOC_GETVERSION
:
3284 ret
= ioctl_getversion(fs
, fh
, data
);
3286 case EXT2_IOC_SETVERSION
:
3287 ret
= ioctl_setversion(fs
, fh
, data
);
3292 ret
= ioctl_fitrim(fs
, fh
, data
);
3296 dbg_printf("%s: Unknown ioctl %d\n", __func__
, cmd
);
3299 pthread_mutex_unlock(&ff
->bfl
);
3303 #endif /* FUSE 28 */
3305 static int op_bmap(const char *path
, size_t blocksize
EXT2FS_ATTR((unused
)),
3308 struct fuse_context
*ctxt
= fuse_get_context();
3309 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3315 FUSE2FS_CHECK_CONTEXT(ff
);
3317 pthread_mutex_lock(&ff
->bfl
);
3318 err
= ext2fs_namei(fs
, EXT2_ROOT_INO
, EXT2_ROOT_INO
, path
, &ino
);
3320 ret
= translate_error(fs
, 0, err
);
3323 dbg_printf("%s: ino=%d blk=%"PRIu64
"\n", __func__
, ino
, *idx
);
3325 err
= ext2fs_bmap2(fs
, ino
, NULL
, NULL
, 0, *idx
, 0, (blk64_t
*)idx
);
3327 ret
= translate_error(fs
, ino
, err
);
3332 pthread_mutex_unlock(&ff
->bfl
);
3336 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3337 # ifdef SUPPORT_FALLOCATE
3338 static int fallocate_helper(struct fuse_file_info
*fp
, int mode
, off_t offset
,
3341 struct fuse_context
*ctxt
= fuse_get_context();
3342 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3343 struct fuse2fs_file_handle
*fh
=
3344 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
3346 struct ext2_inode_large inode
;
3352 FUSE2FS_CHECK_CONTEXT(ff
);
3354 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3355 start
= offset
/ fs
->blocksize
;
3356 end
= (offset
+ len
- 1) / fs
->blocksize
;
3357 dbg_printf("%s: ino=%d mode=0x%x start=%jd end=%llu\n", __func__
,
3358 fh
->ino
, mode
, offset
/ fs
->blocksize
, end
);
3359 if (!fs_can_allocate(ff
, len
/ fs
->blocksize
))
3362 memset(&inode
, 0, sizeof(inode
));
3363 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3367 fsize
= EXT2_I_SIZE(&inode
);
3369 /* Allocate a bunch of blocks */
3370 flags
= (mode
& FL_KEEP_SIZE_FLAG
? 0 :
3371 EXT2_FALLOCATE_INIT_BEYOND_EOF
);
3372 err
= ext2fs_fallocate(fs
, flags
, fh
->ino
,
3373 (struct ext2_inode
*)&inode
,
3374 ~0ULL, start
, end
- start
+ 1);
3375 if (err
&& err
!= EXT2_ET_BLOCK_ALLOC_FAIL
)
3376 return translate_error(fs
, fh
->ino
, err
);
3379 if (!(mode
& FL_KEEP_SIZE_FLAG
)) {
3380 if ((__u64
) offset
+ len
> fsize
) {
3381 err
= ext2fs_inode_size_set(fs
,
3382 (struct ext2_inode
*)&inode
,
3385 return translate_error(fs
, fh
->ino
, err
);
3389 err
= update_mtime(fs
, fh
->ino
, &inode
);
3393 err
= ext2fs_write_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3396 return translate_error(fs
, fh
->ino
, err
);
3401 static errcode_t
clean_block_middle(ext2_filsys fs
, ext2_ino_t ino
,
3402 struct ext2_inode_large
*inode
, off_t offset
,
3403 off_t len
, char **buf
)
3410 residue
= offset
% fs
->blocksize
;
3415 err
= ext2fs_get_mem(fs
->blocksize
, buf
);
3420 err
= ext2fs_bmap2(fs
, ino
, (struct ext2_inode
*)inode
, *buf
, 0,
3421 offset
/ fs
->blocksize
, &retflags
, &blk
);
3424 if (!blk
|| (retflags
& BMAP_RET_UNINIT
))
3427 err
= io_channel_read_blk(fs
->io
, blk
, 1, *buf
);
3431 memset(*buf
+ residue
, 0, len
);
3433 return io_channel_write_blk(fs
->io
, blk
, 1, *buf
);
3436 static errcode_t
clean_block_edge(ext2_filsys fs
, ext2_ino_t ino
,
3437 struct ext2_inode_large
*inode
, off_t offset
,
3438 int clean_before
, char **buf
)
3445 residue
= offset
% fs
->blocksize
;
3450 err
= ext2fs_get_mem(fs
->blocksize
, buf
);
3455 err
= ext2fs_bmap2(fs
, ino
, (struct ext2_inode
*)inode
, *buf
, 0,
3456 offset
/ fs
->blocksize
, &retflags
, &blk
);
3460 err
= io_channel_read_blk(fs
->io
, blk
, 1, *buf
);
3463 if (!blk
|| (retflags
& BMAP_RET_UNINIT
))
3467 memset(*buf
, 0, residue
);
3469 memset(*buf
+ residue
, 0, fs
->blocksize
- residue
);
3471 return io_channel_write_blk(fs
->io
, blk
, 1, *buf
);
3474 static int punch_helper(struct fuse_file_info
*fp
, int mode
, off_t offset
,
3477 struct fuse_context
*ctxt
= fuse_get_context();
3478 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3479 struct fuse2fs_file_handle
*fh
=
3480 (struct fuse2fs_file_handle
*)(uintptr_t)fp
->fh
;
3482 struct ext2_inode_large inode
;
3487 FUSE2FS_CHECK_CONTEXT(ff
);
3489 FUSE2FS_CHECK_MAGIC(fs
, fh
, FUSE2FS_FILE_MAGIC
);
3490 dbg_printf("%s: offset=%jd len=%jd\n", __func__
, offset
, len
);
3492 /* kernel ext4 punch requires this flag to be set */
3493 if (!(mode
& FL_KEEP_SIZE_FLAG
))
3496 /* Punch out a bunch of blocks */
3497 start
= (offset
+ fs
->blocksize
- 1) / fs
->blocksize
;
3498 end
= (offset
+ len
- fs
->blocksize
) / fs
->blocksize
;
3499 dbg_printf("%s: ino=%d mode=0x%x start=%llu end=%llu\n", __func__
,
3500 fh
->ino
, mode
, start
, end
);
3502 memset(&inode
, 0, sizeof(inode
));
3503 err
= ext2fs_read_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3506 return translate_error(fs
, fh
->ino
, err
);
3508 /* Zero everything before the first block and after the last block */
3509 if ((offset
/ fs
->blocksize
) == ((offset
+ len
) / fs
->blocksize
))
3510 err
= clean_block_middle(fs
, fh
->ino
, &inode
, offset
,
3513 err
= clean_block_edge(fs
, fh
->ino
, &inode
, offset
, 0, &buf
);
3515 err
= clean_block_edge(fs
, fh
->ino
, &inode
,
3516 offset
+ len
, 1, &buf
);
3519 ext2fs_free_mem(&buf
);
3521 return translate_error(fs
, fh
->ino
, err
);
3523 /* Unmap full blocks in the middle */
3525 err
= ext2fs_punch(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3528 return translate_error(fs
, fh
->ino
, err
);
3531 err
= update_mtime(fs
, fh
->ino
, &inode
);
3535 err
= ext2fs_write_inode_full(fs
, fh
->ino
, (struct ext2_inode
*)&inode
,
3538 return translate_error(fs
, fh
->ino
, err
);
3543 static int op_fallocate(const char *path
EXT2FS_ATTR((unused
)), int mode
,
3544 off_t offset
, off_t len
,
3545 struct fuse_file_info
*fp
)
3547 struct fuse_context
*ctxt
= fuse_get_context();
3548 struct fuse2fs
*ff
= (struct fuse2fs
*)ctxt
->private_data
;
3549 ext2_filsys fs
= ff
->fs
;
3552 /* Catch unknown flags */
3553 if (mode
& ~(FL_PUNCH_HOLE_FLAG
| FL_KEEP_SIZE_FLAG
))
3556 pthread_mutex_lock(&ff
->bfl
);
3557 if (!fs_writeable(fs
)) {
3561 if (mode
& FL_PUNCH_HOLE_FLAG
)
3562 ret
= punch_helper(fp
, mode
, offset
, len
);
3564 ret
= fallocate_helper(fp
, mode
, offset
, len
);
3566 pthread_mutex_unlock(&ff
->bfl
);
3570 # endif /* SUPPORT_FALLOCATE */
3571 #endif /* FUSE 29 */
3573 static struct fuse_operations fs_ops
= {
3575 .destroy
= op_destroy
,
3576 .getattr
= op_getattr
,
3577 .readlink
= op_readlink
,
3580 .unlink
= op_unlink
,
3582 .symlink
= op_symlink
,
3583 .rename
= op_rename
,
3587 .truncate
= op_truncate
,
3591 .statfs
= op_statfs
,
3592 .release
= op_release
,
3594 .setxattr
= op_setxattr
,
3595 .getxattr
= op_getxattr
,
3596 .listxattr
= op_listxattr
,
3597 .removexattr
= op_removexattr
,
3599 .readdir
= op_readdir
,
3600 .releasedir
= op_release
,
3601 .fsyncdir
= op_fsync
,
3602 .access
= op_access
,
3603 .create
= op_create
,
3604 .ftruncate
= op_ftruncate
,
3605 .fgetattr
= op_fgetattr
,
3606 .utimens
= op_utimens
,
3607 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3608 # if defined(UTIME_NOW) || defined(UTIME_OMIT)
3609 .flag_utime_omit_ok
= 1,
3617 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
3619 .flag_nullpath_ok
= 1,
3621 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
3623 # ifdef SUPPORT_FALLOCATE
3624 .fallocate
= op_fallocate
,
3629 static int get_random_bytes(void *p
, size_t sz
)
3634 fd
= open("/dev/urandom", O_RDONLY
);
3636 perror("/dev/urandom");
3640 r
= read(fd
, p
, sz
);
3643 return (size_t) r
== sz
;
3652 #define FUSE2FS_OPT(t, p, v) { t, offsetof(struct fuse2fs, p), v }
3654 static struct fuse_opt fuse2fs_opts
[] = {
3655 FUSE2FS_OPT("ro", ro
, 1),
3656 FUSE2FS_OPT("errors=panic", panic_on_error
, 1),
3657 FUSE2FS_OPT("minixdf", minixdf
, 1),
3658 FUSE2FS_OPT("fakeroot", fakeroot
, 1),
3659 FUSE2FS_OPT("fuse2fs_debug", debug
, 1),
3660 FUSE2FS_OPT("no_default_opts", no_default_opts
, 1),
3661 FUSE2FS_OPT("norecovery", norecovery
, 1),
3663 FUSE_OPT_KEY("-V", FUSE2FS_VERSION
),
3664 FUSE_OPT_KEY("--version", FUSE2FS_VERSION
),
3665 FUSE_OPT_KEY("-h", FUSE2FS_HELP
),
3666 FUSE_OPT_KEY("--help", FUSE2FS_HELP
),
3667 FUSE_OPT_KEY("--helpfull", FUSE2FS_HELPFULL
),
3672 static int fuse2fs_opt_proc(void *data
, const char *arg
,
3673 int key
, struct fuse_args
*outargs
)
3675 struct fuse2fs
*ff
= data
;
3678 case FUSE_OPT_KEY_NONOPT
:
3680 ff
->device
= strdup(arg
);
3685 case FUSE2FS_HELPFULL
:
3687 "usage: %s device/image mountpoint [options]\n"
3689 "general options:\n"
3690 " -o opt,[opt...] mount options\n"
3691 " -h --help print help\n"
3692 " -V --version print version\n"
3694 "fuse2fs options:\n"
3695 " -o ro read-only mount\n"
3696 " -o errors=panic dump core on error\n"
3697 " -o minixdf minix-style df\n"
3698 " -o fakeroot pretend to be root for permission checks\n"
3699 " -o no_default_opts do not include default fuse options\n"
3700 " -o norecovery don't replay the journal (implies ro)\n"
3701 " -o fuse2fs_debug enable fuse2fs debugging\n"
3704 if (key
== FUSE2FS_HELPFULL
) {
3705 fuse_opt_add_arg(outargs
, "-ho");
3706 fuse_main(outargs
->argc
, outargs
->argv
, &fs_ops
, NULL
);
3708 fprintf(stderr
, "Try --helpfull to get a list of "
3709 "all flags, including the FUSE options.\n");
3713 case FUSE2FS_VERSION
:
3714 fprintf(stderr
, "fuse2fs %s (%s)\n", E2FSPROGS_VERSION
,
3716 fuse_opt_add_arg(outargs
, "--version");
3717 fuse_main(outargs
->argc
, outargs
->argv
, &fs_ops
, NULL
);
3723 int main(int argc
, char *argv
[])
3725 struct fuse_args args
= FUSE_ARGS_INIT(argc
, argv
);
3726 struct fuse2fs fctx
;
3729 char extra_args
[BUFSIZ
];
3730 int ret
= 0, flags
= EXT2_FLAG_64BITS
| EXT2_FLAG_EXCLUSIVE
;
3732 memset(&fctx
, 0, sizeof(fctx
));
3733 fctx
.magic
= FUSE2FS_MAGIC
;
3735 fuse_opt_parse(&args
, &fctx
, fuse2fs_opts
, fuse2fs_opt_proc
);
3736 if (fctx
.device
== NULL
) {
3737 fprintf(stderr
, "Missing ext4 device/image\n");
3738 fprintf(stderr
, "See '%s -h' for usage\n", argv
[0]);
3742 if (fctx
.norecovery
)
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
)) {
3791 if (fctx
.norecovery
) {
3792 printf(_("%s: mounting read-only without "
3793 "recovering journal\n"),
3795 } else if (!fctx
.ro
) {
3796 printf(_("%s: recovering journal\n"), fctx
.device
);
3797 err
= ext2fs_run_ext3_journal(&global_fs
);
3799 printf(_("%s: %s.\n"), fctx
.device
,
3800 error_message(err
));
3801 printf(_("Please run e2fsck -fy %s.\n"),
3805 ext2fs_clear_feature_journal_needs_recovery(global_fs
->super
);
3806 ext2fs_mark_super_dirty(global_fs
);
3808 printf("%s", _("Journal needs recovery; running "
3809 "`e2fsck -E journal_only' is required.\n"));
3815 if (ext2fs_has_feature_journal(global_fs
->super
))
3816 printf(_("%s: Writing to the journal is not supported.\n"),
3818 err
= ext2fs_read_inode_bitmap(global_fs
);
3820 translate_error(global_fs
, 0, err
);
3823 err
= ext2fs_read_block_bitmap(global_fs
);
3825 translate_error(global_fs
, 0, err
);
3830 if (!(global_fs
->super
->s_state
& EXT2_VALID_FS
))
3831 printf("%s", _("Warning: Mounting unchecked fs, running e2fsck "
3832 "is recommended.\n"));
3833 if (global_fs
->super
->s_max_mnt_count
> 0 &&
3834 global_fs
->super
->s_mnt_count
>= global_fs
->super
->s_max_mnt_count
)
3835 printf("%s", _("Warning: Maximal mount count reached, running "
3836 "e2fsck is recommended.\n"));
3837 if (global_fs
->super
->s_checkinterval
> 0 &&
3838 (time_t) (global_fs
->super
->s_lastcheck
+
3839 global_fs
->super
->s_checkinterval
) <= time(0))
3840 printf("%s", _("Warning: Check time reached; running e2fsck "
3841 "is recommended.\n"));
3842 if (global_fs
->super
->s_last_orphan
)
3844 _("Orphans detected; running e2fsck is recommended.\n"));
3846 if (global_fs
->super
->s_state
& EXT2_ERROR_FS
) {
3848 _("Errors detected; running e2fsck is required.\n"));
3852 /* Initialize generation counter */
3853 get_random_bytes(&fctx
.next_generation
, sizeof(unsigned int));
3855 /* Set up default fuse parameters */
3856 snprintf(extra_args
, BUFSIZ
, "-okernel_cache,subtype=ext4,use_ino,"
3857 "fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS
,
3859 if (fctx
.no_default_opts
== 0)
3860 fuse_opt_add_arg(&args
, extra_args
);
3862 if (fctx
.fakeroot
) {
3863 #ifdef HAVE_MOUNT_NODEV
3864 fuse_opt_add_arg(&args
,"-onodev");
3866 #ifdef HAVE_MOUNT_NOSUID
3867 fuse_opt_add_arg(&args
,"-onosuid");
3874 printf("fuse arguments:");
3875 for (i
= 0; i
< args
.argc
; i
++)
3876 printf(" '%s'", args
.argv
[i
]);
3880 pthread_mutex_init(&fctx
.bfl
, NULL
);
3881 fuse_main(args
.argc
, args
.argv
, &fs_ops
, &fctx
);
3882 pthread_mutex_destroy(&fctx
.bfl
);
3887 err
= ext2fs_close(global_fs
);
3889 com_err(argv
[0], err
, "while closing fs");
3895 static int __translate_error(ext2_filsys fs
, errcode_t err
, ext2_ino_t ino
,
3896 const char *file
, int line
)
3898 struct timespec now
;
3900 struct fuse2fs
*ff
= fs
->priv_data
;
3903 /* Translate ext2 error to unix error code */
3904 if (err
< EXT2_ET_BASE
)
3905 goto no_translation
;
3907 case EXT2_ET_NO_MEMORY
:
3908 case EXT2_ET_TDB_ERR_OOM
:
3911 case EXT2_ET_INVALID_ARGUMENT
:
3912 case EXT2_ET_LLSEEK_FAILED
:
3915 case EXT2_ET_NO_DIRECTORY
:
3918 case EXT2_ET_FILE_NOT_FOUND
:
3921 case EXT2_ET_DIR_NO_SPACE
:
3924 case EXT2_ET_TOOSMALL
:
3925 case EXT2_ET_BLOCK_ALLOC_FAIL
:
3926 case EXT2_ET_INODE_ALLOC_FAIL
:
3927 case EXT2_ET_EA_NO_SPACE
:
3930 case EXT2_ET_SYMLINK_LOOP
:
3933 case EXT2_ET_FILE_TOO_BIG
:
3936 case EXT2_ET_TDB_ERR_EXISTS
:
3937 case EXT2_ET_FILE_EXISTS
:
3940 case EXT2_ET_MMP_FAILED
:
3941 case EXT2_ET_MMP_FSCK_ON
:
3944 case EXT2_ET_EA_KEY_NOT_FOUND
:
3951 /* Sometimes fuse returns a garbage file handle pointer to us... */
3952 case EXT2_ET_MAGIC_EXT2_FILE
:
3955 case EXT2_ET_UNIMPLEMENTED
:
3969 fprintf(ff
->err_fp
, "FUSE2FS (%s): %s (inode #%d) at %s:%d.\n",
3970 fs
->device_name
? fs
->device_name
: "???",
3971 error_message(err
), ino
, file
, line
);
3973 fprintf(ff
->err_fp
, "FUSE2FS (%s): %s at %s:%d.\n",
3974 fs
->device_name
? fs
->device_name
: "???",
3975 error_message(err
), file
, line
);
3978 /* Make a note in the error log */
3980 fs
->super
->s_last_error_time
= now
.tv_sec
;
3981 fs
->super
->s_last_error_ino
= ino
;
3982 fs
->super
->s_last_error_line
= line
;
3983 fs
->super
->s_last_error_block
= err
; /* Yeah... */
3984 strncpy((char *)fs
->super
->s_last_error_func
, file
,
3985 sizeof(fs
->super
->s_last_error_func
));
3986 if (fs
->super
->s_first_error_time
== 0) {
3987 fs
->super
->s_first_error_time
= now
.tv_sec
;
3988 fs
->super
->s_first_error_ino
= ino
;
3989 fs
->super
->s_first_error_line
= line
;
3990 fs
->super
->s_first_error_block
= err
;
3991 strncpy((char *)fs
->super
->s_first_error_func
, file
,
3992 sizeof(fs
->super
->s_first_error_func
));
3995 fs
->super
->s_error_count
++;
3996 ext2fs_mark_super_dirty(fs
);
3998 if (ff
->panic_on_error
)