Lines Matching +full:- +full:fs
2 * fuse2fs.c - FUSE server for e2fsprogs.
6 * %Begin-Header%
9 * %End-Header%
19 # include <linux/fs.h>
68 # define dbg_printf(f, a...) do {printf("FUSE2FS-" f, ## a); \
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;
123 #pragma GCC diagnostic ignored "-Wpedantic"
139 return -1; in acl_ea_count()
140 size -= sizeof(acl_ea_header); in acl_ea_count()
142 return -1; in acl_ea_count()
147 * ext4 ACL structures, copied from fs/ext4/acl.h.
174 (count - 4) * sizeof(ext4_acl_entry); in ext4_acl_size()
182 size -= sizeof(ext4_acl_header); in ext4_acl_count()
183 s = size - 4 * sizeof(ext4_acl_entry_short); in ext4_acl_count()
186 return -1; in ext4_acl_count()
190 return -1; in ext4_acl_count()
207 if (facl_count < 0 || facl->a_version != ACL_EA_VERSION) in fuse_to_ext4_acl()
214 h->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION); in fuse_to_ext4_acl()
216 for (i = 0, a = facl->a_entries; i < facl_count; i++, a++) { in fuse_to_ext4_acl()
218 e->e_tag = ext2fs_cpu_to_le16(a->e_tag); in fuse_to_ext4_acl()
219 e->e_perm = ext2fs_cpu_to_le16(a->e_perm); in fuse_to_ext4_acl()
221 switch (a->e_tag) { in fuse_to_ext4_acl()
224 e->e_id = ext2fs_cpu_to_le32(a->e_id); in fuse_to_ext4_acl()
261 eacl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION)) in ext4_to_fuse_acl()
268 f->a_version = ACL_EA_VERSION; in ext4_to_fuse_acl()
270 for (i = 0, a = f->a_entries; i < eacl_count; i++, a++) { in ext4_to_fuse_acl()
272 a->e_tag = ext2fs_le16_to_cpu(e->e_tag); in ext4_to_fuse_acl()
273 a->e_perm = ext2fs_le16_to_cpu(e->e_perm); in ext4_to_fuse_acl()
275 switch (a->e_tag) { in ext4_to_fuse_acl()
278 a->e_id = ext2fs_le32_to_cpu(e->e_id); in ext4_to_fuse_acl()
317 ext2_filsys fs; member
330 #define FUSE2FS_CHECK_MAGIC(fs, ptr, num) do {if ((ptr)->magic != (num)) \ argument
331 return translate_error((fs), 0, EXT2_ET_MAGIC_EXT2_FILE); \
334 #define FUSE2FS_CHECK_CONTEXT(ptr) do {if ((ptr)->magic != FUSE2FS_MAGIC) \
338 static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino,
340 #define translate_error(fs, ino, err) __translate_error((fs), (err), (ino), \ argument
353 #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
358 * with large inodes (-I 256 or larger) and there are not currently any EAs
364 * inode-size = GOOD_OLD_INODE_SIZE + i_extra_isize
368 sizeof((ext4_inode)->field)) \
370 (ext4_inode)->i_extra_isize)) \
374 __u32 extra = sizeof(time->tv_sec) > 4 ? in ext4_encode_extra_time()
375 ((time->tv_sec - (__s32)time->tv_sec) >> 32) & in ext4_encode_extra_time()
377 return extra | (time->tv_nsec << EXT4_EPOCH_BITS); in ext4_encode_extra_time()
382 if (sizeof(time->tv_sec) > 4 && (extra & EXT4_EPOCH_MASK)) { in ext4_decode_extra_time()
390 time->tv_sec += extra_bits << 32; in ext4_decode_extra_time()
392 time->tv_nsec = ((extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS; in ext4_decode_extra_time()
397 (raw_inode)->xtime = (timespec)->tv_sec; \
399 (raw_inode)->xtime ## _extra = \
406 (raw_inode)->xtime = (timespec)->tv_sec; \
408 (raw_inode)->xtime ## _extra = \
414 (timespec)->tv_sec = (signed)((raw_inode)->xtime); \
417 (raw_inode)->xtime ## _extra); \
419 (timespec)->tv_nsec = 0; \
425 (timespec)->tv_sec = \
426 (signed)((raw_inode)->xtime); \
429 raw_inode->xtime ## _extra); \
431 (timespec)->tv_nsec = 0; \
441 now->tv_sec = time(NULL); in get_now()
442 now->tv_nsec = 0; in get_now()
449 ver = inode->osd1.linux1.l_i_version; in increment_version()
451 ver |= (__u64)inode->i_version_hi << 32; in increment_version()
453 inode->osd1.linux1.l_i_version = ver; in increment_version()
455 inode->i_version_hi = ver >> 32; in increment_version()
470 static int update_ctime(ext2_filsys fs, ext2_ino_t ino, in update_ctime() argument
486 /* Otherwise we have to read-modify-write the inode */ in update_ctime()
488 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, in update_ctime()
491 return translate_error(fs, ino, err); in update_ctime()
496 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, in update_ctime()
499 return translate_error(fs, ino, err); in update_ctime()
504 static int update_atime(ext2_filsys fs, ext2_ino_t ino) in update_atime() argument
510 if (!(fs->flags & EXT2_FLAG_RW)) in update_atime()
513 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, in update_atime()
516 return translate_error(fs, ino, err); in update_atime()
526 if (atime.tv_sec >= mtime.tv_sec && atime.tv_sec >= now.tv_sec - 30) in update_atime()
530 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, in update_atime()
533 return translate_error(fs, ino, err); in update_atime()
538 static int update_mtime(ext2_filsys fs, ext2_ino_t ino, in update_mtime() argument
554 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, in update_mtime()
557 return translate_error(fs, ino, err); in update_mtime()
564 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, in update_mtime()
567 return translate_error(fs, ino, err); in update_mtime()
600 ext2_filsys fs = ff->fs; in fs_can_allocate() local
604 "rsvd=%llu\n", __func__, num, ff->alloc_all_blocks, in fs_can_allocate()
605 ext2fs_blocks_count(fs->super), in fs_can_allocate()
606 ext2fs_free_blocks_count(fs->super), in fs_can_allocate()
607 ext2fs_r_blocks_count(fs->super)); in fs_can_allocate()
608 if (num > ext2fs_blocks_count(fs->super)) in fs_can_allocate()
611 if (ff->alloc_all_blocks) in fs_can_allocate()
615 * Different meaning for r_blocks -- libext2fs has bugs where the FS in fs_can_allocate()
619 reserved = ext2fs_r_blocks_count(fs->super); in fs_can_allocate()
621 reserved = ext2fs_blocks_count(fs->super) / 10; in fs_can_allocate()
622 return ext2fs_free_blocks_count(fs->super) > reserved + num; in fs_can_allocate()
625 static int fs_writeable(ext2_filsys fs) in fs_writeable() argument
627 return (fs->flags & EXT2_FLAG_RW) && (fs->super->s_error_count == 0); in fs_writeable()
630 static int check_inum_access(ext2_filsys fs, ext2_ino_t ino, mode_t mask) in check_inum_access() argument
637 /* no writing to read-only or broken fs */ in check_inum_access()
638 if ((mask & W_OK) && !fs_writeable(fs)) in check_inum_access()
639 return -EROFS; in check_inum_access()
641 err = ext2fs_read_inode(fs, ino, &inode); in check_inum_access()
643 return translate_error(fs, ino, err); in check_inum_access()
650 ctxt->uid, ctxt->gid); in check_inum_access()
659 return -EACCES; in check_inum_access()
662 if (ctxt->uid == 0) { in check_inum_access()
663 /* Non-file access always ok */ in check_inum_access()
676 return -EACCES; in check_inum_access()
680 if (inode.i_uid == ctxt->uid) { in check_inum_access()
683 return -EACCES; in check_inum_access()
687 if (inode.i_gid == ctxt->gid) { in check_inum_access()
690 return -EACCES; in check_inum_access()
696 return -EACCES; in check_inum_access()
702 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_destroy()
703 ext2_filsys fs; in op_destroy() local
706 if (ff->magic != FUSE2FS_MAGIC) { in op_destroy()
710 fs = ff->fs; in op_destroy()
711 dbg_printf("%s: dev=%s\n", __func__, fs->device_name); in op_destroy()
712 if (fs->flags & EXT2_FLAG_RW) { in op_destroy()
713 fs->super->s_state |= EXT2_VALID_FS; in op_destroy()
714 if (fs->super->s_error_count) in op_destroy()
715 fs->super->s_state |= EXT2_ERROR_FS; in op_destroy()
716 ext2fs_mark_super_dirty(fs); in op_destroy()
717 err = ext2fs_set_gdt_csum(fs); in op_destroy()
719 translate_error(fs, 0, err); in op_destroy()
721 err = ext2fs_flush2(fs, 0); in op_destroy()
723 translate_error(fs, 0, err); in op_destroy()
730 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_init()
731 ext2_filsys fs; in op_init() local
734 if (ff->magic != FUSE2FS_MAGIC) { in op_init()
738 fs = ff->fs; in op_init()
739 dbg_printf("%s: dev=%s\n", __func__, fs->device_name); in op_init()
741 conn->want |= FUSE_CAP_IOCTL_DIR; in op_init()
743 if (fs->flags & EXT2_FLAG_RW) { in op_init()
744 fs->super->s_mnt_count++; in op_init()
745 fs->super->s_mtime = time(NULL); in op_init()
746 fs->super->s_state &= ~EXT2_VALID_FS; in op_init()
747 ext2fs_mark_super_dirty(fs); in op_init()
748 err = ext2fs_flush2(fs, 0); in op_init()
750 translate_error(fs, 0, err); in op_init()
755 static blkcnt_t blocks_from_inode(ext2_filsys fs, in blocks_from_inode() argument
760 b = inode->i_blocks; in blocks_from_inode()
761 if (ext2fs_has_feature_huge_file(fs->super)) in blocks_from_inode()
762 b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32; in blocks_from_inode()
764 if (!ext2fs_has_feature_huge_file(fs->super) || in blocks_from_inode()
765 !(inode->i_flags & EXT4_HUGE_FILE_FL)) in blocks_from_inode()
766 b *= fs->blocksize / 512; in blocks_from_inode()
767 b *= EXT2FS_CLUSTER_RATIO(fs); in blocks_from_inode()
772 static int stat_inode(ext2_filsys fs, ext2_ino_t ino, struct stat *statbuf) in stat_inode() argument
781 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, in stat_inode()
784 return translate_error(fs, ino, err); in stat_inode()
786 memcpy(&fakedev, fs->super->s_uuid, sizeof(fakedev)); in stat_inode()
787 statbuf->st_dev = fakedev; in stat_inode()
788 statbuf->st_ino = ino; in stat_inode()
789 statbuf->st_mode = inode.i_mode; in stat_inode()
790 statbuf->st_nlink = inode.i_links_count; in stat_inode()
791 statbuf->st_uid = inode.i_uid; in stat_inode()
792 statbuf->st_gid = inode.i_gid; in stat_inode()
793 statbuf->st_size = EXT2_I_SIZE(&inode); in stat_inode()
794 statbuf->st_blksize = fs->blocksize; in stat_inode()
795 statbuf->st_blocks = blocks_from_inode(fs, &inode); in stat_inode()
797 statbuf->st_atime = tv.tv_sec; in stat_inode()
799 statbuf->st_mtime = tv.tv_sec; in stat_inode()
801 statbuf->st_ctime = tv.tv_sec; in stat_inode()
805 statbuf->st_rdev = inode.i_block[0]; in stat_inode()
807 statbuf->st_rdev = inode.i_block[1]; in stat_inode()
816 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_getattr()
817 ext2_filsys fs; in op_getattr() local
823 fs = ff->fs; in op_getattr()
825 pthread_mutex_lock(&ff->bfl); in op_getattr()
826 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_getattr()
828 ret = translate_error(fs, 0, err); in op_getattr()
831 ret = stat_inode(fs, ino, statbuf); in op_getattr()
833 pthread_mutex_unlock(&ff->bfl); in op_getattr()
840 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_readlink()
841 ext2_filsys fs; in op_readlink() local
850 fs = ff->fs; in op_readlink()
852 pthread_mutex_lock(&ff->bfl); in op_readlink()
853 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_readlink()
855 ret = translate_error(fs, 0, err); in op_readlink()
859 err = ext2fs_read_inode(fs, ino, &inode); in op_readlink()
861 ret = translate_error(fs, ino, err); in op_readlink()
866 ret = -EINVAL; in op_readlink()
870 len--; in op_readlink()
878 err = ext2fs_file_open(fs, ino, 0, &file); in op_readlink()
880 ret = translate_error(fs, ino, err); in op_readlink()
887 ret = translate_error(fs, ino, err); in op_readlink()
896 ret = translate_error(fs, ino, err); in op_readlink()
902 if (fs_writeable(fs)) { in op_readlink()
903 ret = update_atime(fs, ino); in op_readlink()
909 pthread_mutex_unlock(&ff->bfl); in op_readlink()
916 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_mknod()
917 ext2_filsys fs; in op_mknod() local
927 fs = ff->fs; in op_mknod()
932 ret = -ENOMEM; in op_mknod()
937 ret = -ENOMEM; in op_mknod()
944 pthread_mutex_lock(&ff->bfl); in op_mknod()
946 ret = -ENOSPC; in op_mknod()
950 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path, in op_mknod()
953 ret = translate_error(fs, 0, err); in op_mknod()
957 ret = check_inum_access(fs, parent, W_OK); in op_mknod()
972 ret = -EINVAL; in op_mknod()
976 err = ext2fs_new_inode(fs, parent, mode, 0, &child); in op_mknod()
978 ret = translate_error(fs, 0, err); in op_mknod()
984 err = ext2fs_link(fs, parent, node_name, child, filetype); in op_mknod()
986 err = ext2fs_expand_dir(fs, parent); in op_mknod()
988 ret = translate_error(fs, parent, err); in op_mknod()
992 err = ext2fs_link(fs, parent, node_name, child, in op_mknod()
996 ret = translate_error(fs, parent, err); in op_mknod()
1000 ret = update_mtime(fs, parent, NULL); in op_mknod()
1012 inode.i_extra_isize = sizeof(struct ext2_inode_large) - in op_mknod()
1014 inode.i_uid = ctxt->uid; in op_mknod()
1015 inode.i_gid = ctxt->gid; in op_mknod()
1017 err = ext2fs_write_new_inode(fs, child, (struct ext2_inode *)&inode); in op_mknod()
1019 ret = translate_error(fs, child, err); in op_mknod()
1023 inode.i_generation = ff->next_generation++; in op_mknod()
1025 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode, in op_mknod()
1028 ret = translate_error(fs, child, err); in op_mknod()
1032 ext2fs_inode_alloc_stats2(fs, child, 1, 0); in op_mknod()
1035 pthread_mutex_unlock(&ff->bfl); in op_mknod()
1044 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_mkdir()
1045 ext2_filsys fs; in op_mkdir() local
1057 fs = ff->fs; in op_mkdir()
1061 ret = -ENOMEM; in op_mkdir()
1066 ret = -ENOMEM; in op_mkdir()
1073 pthread_mutex_lock(&ff->bfl); in op_mkdir()
1075 ret = -ENOSPC; in op_mkdir()
1079 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path, in op_mkdir()
1082 ret = translate_error(fs, 0, err); in op_mkdir()
1086 ret = check_inum_access(fs, parent, W_OK); in op_mkdir()
1091 err = ext2fs_read_inode_full(fs, parent, (struct ext2_inode *)&inode, in op_mkdir()
1094 ret = translate_error(fs, parent, err); in op_mkdir()
1101 err = ext2fs_mkdir(fs, parent, 0, node_name); in op_mkdir()
1103 err = ext2fs_expand_dir(fs, parent); in op_mkdir()
1105 ret = translate_error(fs, parent, err); in op_mkdir()
1109 err = ext2fs_mkdir(fs, parent, 0, node_name); in op_mkdir()
1112 ret = translate_error(fs, parent, err); in op_mkdir()
1116 ret = update_mtime(fs, parent, NULL); in op_mkdir()
1121 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path, in op_mkdir()
1124 ret = translate_error(fs, 0, err); in op_mkdir()
1131 err = ext2fs_read_inode_full(fs, child, (struct ext2_inode *)&inode, in op_mkdir()
1134 ret = translate_error(fs, child, err); in op_mkdir()
1138 inode.i_uid = ctxt->uid; in op_mkdir()
1139 inode.i_gid = ctxt->gid; in op_mkdir()
1140 inode.i_mode = LINUX_S_IFDIR | (mode & ~(S_ISUID | fs->umask)) | in op_mkdir()
1142 inode.i_generation = ff->next_generation++; in op_mkdir()
1144 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode, in op_mkdir()
1147 ret = translate_error(fs, child, err); in op_mkdir()
1153 !ext2fs_has_feature_metadata_csum(fs->super)) in op_mkdir()
1155 err = ext2fs_new_dir_block(fs, child, parent, &block); in op_mkdir()
1157 ret = translate_error(fs, child, err); in op_mkdir()
1160 err = ext2fs_bmap2(fs, child, (struct ext2_inode *)&inode, NULL, 0, 0, in op_mkdir()
1163 ret = translate_error(fs, child, err); in op_mkdir()
1166 err = ext2fs_write_dir_block4(fs, blk, block, 0, child); in op_mkdir()
1168 ret = translate_error(fs, child, err); in op_mkdir()
1175 pthread_mutex_unlock(&ff->bfl); in op_mkdir()
1181 static int unlink_file_by_name(ext2_filsys fs, const char *path) in unlink_file_by_name() argument
1192 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, filename, in unlink_file_by_name()
1196 return translate_error(fs, 0, err); in unlink_file_by_name()
1203 ret = check_inum_access(fs, dir, W_OK); in unlink_file_by_name()
1211 err = ext2fs_unlink(fs, dir, base_name, 0, 0); in unlink_file_by_name()
1214 return translate_error(fs, dir, err); in unlink_file_by_name()
1216 return update_mtime(fs, dir, NULL); in unlink_file_by_name()
1221 ext2_filsys fs = ff->fs; in remove_inode() local
1227 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, in remove_inode()
1230 ret = translate_error(fs, ino, err); in remove_inode()
1240 inode.i_links_count--; in remove_inode()
1241 inode.i_dtime = fs->now ? fs->now : time(0); in remove_inode()
1244 inode.i_links_count--; in remove_inode()
1247 ret = update_ctime(fs, ino, &inode); in remove_inode()
1255 err = ext2fs_free_ext_attr(fs, ino, &inode); in remove_inode()
1259 if (ext2fs_inode_has_valid_blocks2(fs, (struct ext2_inode *)&inode)) { in remove_inode()
1260 err = ext2fs_punch(fs, ino, (struct ext2_inode *)&inode, NULL, in remove_inode()
1263 ret = translate_error(fs, ino, err); in remove_inode()
1268 ext2fs_inode_alloc_stats2(fs, ino, -1, in remove_inode()
1272 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, in remove_inode()
1275 ret = translate_error(fs, ino, err); in remove_inode()
1284 ext2_filsys fs = ff->fs; in __op_unlink() local
1289 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in __op_unlink()
1291 ret = translate_error(fs, 0, err); in __op_unlink()
1295 ret = unlink_file_by_name(fs, path); in __op_unlink()
1309 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_unlink()
1313 pthread_mutex_lock(&ff->bfl); in op_unlink()
1315 pthread_mutex_unlock(&ff->bfl); in op_unlink()
1334 if (dirent->inode == 0) in rmdir_proc()
1336 if (((dirent->name_len & 0xFF) == 1) && (dirent->name[0] == '.')) in rmdir_proc()
1338 if (((dirent->name_len & 0xFF) == 2) && (dirent->name[0] == '.') && in rmdir_proc()
1339 (dirent->name[1] == '.')) { in rmdir_proc()
1340 rds->parent = dirent->inode; in rmdir_proc()
1343 rds->empty = 0; in rmdir_proc()
1349 ext2_filsys fs = ff->fs; in __op_rmdir() local
1356 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &child); in __op_rmdir()
1358 ret = translate_error(fs, 0, err); in __op_rmdir()
1366 err = ext2fs_dir_iterate2(fs, child, 0, 0, rmdir_proc, &rds); in __op_rmdir()
1368 ret = translate_error(fs, child, err); in __op_rmdir()
1373 ret = -ENOTEMPTY; in __op_rmdir()
1377 ret = unlink_file_by_name(fs, path); in __op_rmdir()
1391 err = ext2fs_read_inode_full(fs, rds.parent, in __op_rmdir()
1395 ret = translate_error(fs, rds.parent, err); in __op_rmdir()
1399 inode.i_links_count--; in __op_rmdir()
1400 ret = update_mtime(fs, rds.parent, &inode); in __op_rmdir()
1403 err = ext2fs_write_inode_full(fs, rds.parent, in __op_rmdir()
1407 ret = translate_error(fs, rds.parent, err); in __op_rmdir()
1419 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_rmdir()
1423 pthread_mutex_lock(&ff->bfl); in op_rmdir()
1425 pthread_mutex_unlock(&ff->bfl); in op_rmdir()
1432 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_symlink()
1433 ext2_filsys fs; in op_symlink() local
1442 fs = ff->fs; in op_symlink()
1446 ret = -ENOMEM; in op_symlink()
1451 ret = -ENOMEM; in op_symlink()
1458 pthread_mutex_lock(&ff->bfl); in op_symlink()
1459 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path, in op_symlink()
1463 ret = translate_error(fs, 0, err); in op_symlink()
1467 ret = check_inum_access(fs, parent, W_OK); in op_symlink()
1473 err = ext2fs_symlink(fs, parent, 0, node_name, src); in op_symlink()
1475 err = ext2fs_expand_dir(fs, parent); in op_symlink()
1477 ret = translate_error(fs, parent, err); in op_symlink()
1481 err = ext2fs_symlink(fs, parent, 0, node_name, src); in op_symlink()
1484 ret = translate_error(fs, parent, err); in op_symlink()
1489 ret = update_mtime(fs, parent, NULL); in op_symlink()
1494 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path, in op_symlink()
1497 ret = translate_error(fs, 0, err); in op_symlink()
1504 err = ext2fs_read_inode_full(fs, child, (struct ext2_inode *)&inode, in op_symlink()
1507 ret = translate_error(fs, child, err); in op_symlink()
1511 inode.i_uid = ctxt->uid; in op_symlink()
1512 inode.i_gid = ctxt->gid; in op_symlink()
1513 inode.i_generation = ff->next_generation++; in op_symlink()
1515 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode, in op_symlink()
1518 ret = translate_error(fs, child, err); in op_symlink()
1522 pthread_mutex_unlock(&ff->bfl); in op_symlink()
1543 dirent->name[0] == '.' && dirent->name[1] == '.') { in update_dotdot_helper()
1544 dirent->inode = ud->new_dotdot; in update_dotdot_helper()
1554 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_rename()
1555 ext2_filsys fs; in op_rename() local
1565 fs = ff->fs; in op_rename()
1567 pthread_mutex_lock(&ff->bfl); in op_rename()
1569 ret = -ENOSPC; in op_rename()
1573 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, from, &from_ino); in op_rename()
1575 ret = translate_error(fs, 0, err); in op_rename()
1579 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, to, &to_ino); in op_rename()
1581 ret = translate_error(fs, 0, err); in op_rename()
1596 ret = -ENOMEM; in op_rename()
1602 ret = -ENOMEM; in op_rename()
1609 ret = -EINVAL; in op_rename()
1615 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_from, in op_rename()
1619 ret = translate_error(fs, 0, err); in op_rename()
1623 ret = -ENOENT; in op_rename()
1627 ret = check_inum_access(fs, from_dir_ino, W_OK); in op_rename()
1634 ret = -EINVAL; in op_rename()
1640 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_to, in op_rename()
1644 ret = translate_error(fs, 0, err); in op_rename()
1648 ret = -ENOENT; in op_rename()
1652 ret = check_inum_access(fs, to_dir_ino, W_OK); in op_rename()
1658 err = ext2fs_read_inode(fs, to_ino, &inode); in op_rename()
1660 ret = translate_error(fs, to_ino, err); in op_rename()
1676 err = ext2fs_read_inode(fs, from_ino, &inode); in op_rename()
1678 ret = translate_error(fs, from_ino, err); in op_rename()
1685 err = ext2fs_link(fs, to_dir_ino, cp + 1, from_ino, in op_rename()
1688 err = ext2fs_expand_dir(fs, to_dir_ino); in op_rename()
1690 ret = translate_error(fs, to_dir_ino, err); in op_rename()
1694 err = ext2fs_link(fs, to_dir_ino, cp + 1, from_ino, in op_rename()
1698 ret = translate_error(fs, to_dir_ino, err); in op_rename()
1703 err = ext2fs_read_inode(fs, from_ino, &inode); in op_rename()
1705 ret = translate_error(fs, from_ino, err); in op_rename()
1713 err = ext2fs_dir_iterate2(fs, from_ino, 0, NULL, in op_rename()
1716 ret = translate_error(fs, from_ino, err); in op_rename()
1723 err = ext2fs_read_inode(fs, from_dir_ino, &inode); in op_rename()
1725 ret = translate_error(fs, from_dir_ino, err); in op_rename()
1728 inode.i_links_count--; in op_rename()
1729 err = ext2fs_write_inode(fs, from_dir_ino, &inode); in op_rename()
1731 ret = translate_error(fs, from_dir_ino, err); in op_rename()
1736 err = ext2fs_read_inode(fs, to_dir_ino, &inode); in op_rename()
1738 ret = translate_error(fs, to_dir_ino, err); in op_rename()
1742 err = ext2fs_write_inode(fs, to_dir_ino, &inode); in op_rename()
1744 ret = translate_error(fs, to_dir_ino, err); in op_rename()
1750 ret = update_ctime(fs, from_ino, NULL); in op_rename()
1754 ret = update_mtime(fs, to_dir_ino, NULL); in op_rename()
1759 ret = unlink_file_by_name(fs, from); in op_rename()
1764 err = ext2fs_flush2(fs, 0); in op_rename()
1766 ret = translate_error(fs, 0, err); in op_rename()
1772 pthread_mutex_unlock(&ff->bfl); in op_rename()
1779 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_link()
1780 ext2_filsys fs; in op_link() local
1789 fs = ff->fs; in op_link()
1793 ret = -ENOMEM; in op_link()
1798 ret = -ENOMEM; in op_link()
1805 pthread_mutex_lock(&ff->bfl); in op_link()
1807 ret = -ENOSPC; in op_link()
1811 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path, in op_link()
1815 err = -ENOENT; in op_link()
1819 ret = check_inum_access(fs, parent, W_OK); in op_link()
1824 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, src, &ino); in op_link()
1826 ret = translate_error(fs, 0, err); in op_link()
1831 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, in op_link()
1834 ret = translate_error(fs, ino, err); in op_link()
1839 ret = update_ctime(fs, ino, &inode); in op_link()
1843 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, in op_link()
1846 ret = translate_error(fs, ino, err); in op_link()
1852 err = ext2fs_link(fs, parent, node_name, ino, in op_link()
1855 err = ext2fs_expand_dir(fs, parent); in op_link()
1857 ret = translate_error(fs, parent, err); in op_link()
1861 err = ext2fs_link(fs, parent, node_name, ino, in op_link()
1865 ret = translate_error(fs, parent, err); in op_link()
1869 ret = update_mtime(fs, parent, NULL); in op_link()
1874 pthread_mutex_unlock(&ff->bfl); in op_link()
1883 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_chmod()
1884 ext2_filsys fs; in op_chmod() local
1891 fs = ff->fs; in op_chmod()
1892 pthread_mutex_lock(&ff->bfl); in op_chmod()
1893 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_chmod()
1895 ret = translate_error(fs, 0, err); in op_chmod()
1901 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, in op_chmod()
1904 ret = translate_error(fs, ino, err); in op_chmod()
1908 if (ctxt->uid != 0 && ctxt->uid != inode.i_uid) { in op_chmod()
1909 ret = -EPERM; in op_chmod()
1918 if (ctxt->uid != 0 && ctxt->gid != inode.i_gid) in op_chmod()
1923 ret = update_ctime(fs, ino, &inode); in op_chmod()
1927 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, in op_chmod()
1930 ret = translate_error(fs, ino, err); in op_chmod()
1935 pthread_mutex_unlock(&ff->bfl); in op_chmod()
1942 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_chown()
1943 ext2_filsys fs; in op_chown() local
1950 fs = ff->fs; in op_chown()
1951 pthread_mutex_lock(&ff->bfl); in op_chown()
1952 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_chown()
1954 ret = translate_error(fs, 0, err); in op_chown()
1961 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, in op_chown()
1964 ret = translate_error(fs, ino, err); in op_chown()
1971 if (ctxt->uid != 0 && in op_chown()
1972 !(inode.i_uid == ctxt->uid && owner == ctxt->uid)) { in op_chown()
1973 ret = -EPERM; in op_chown()
1981 if (ctxt->uid != 0 && inode.i_uid != ctxt->uid) { in op_chown()
1982 ret = -EPERM; in op_chown()
1990 ret = update_ctime(fs, ino, &inode); in op_chown()
1994 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, in op_chown()
1997 ret = translate_error(fs, ino, err); in op_chown()
2002 pthread_mutex_unlock(&ff->bfl); in op_chown()
2009 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_truncate()
2010 ext2_filsys fs; in op_truncate() local
2017 fs = ff->fs; in op_truncate()
2018 pthread_mutex_lock(&ff->bfl); in op_truncate()
2019 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_truncate()
2021 ret = translate_error(fs, 0, err); in op_truncate()
2026 ret = check_inum_access(fs, ino, W_OK); in op_truncate()
2030 err = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &file); in op_truncate()
2032 ret = translate_error(fs, ino, err); in op_truncate()
2038 ret = translate_error(fs, ino, err); in op_truncate()
2047 ret = translate_error(fs, ino, err); in op_truncate()
2051 ret = update_mtime(fs, ino, NULL); in op_truncate()
2054 pthread_mutex_unlock(&ff->bfl); in op_truncate()
2082 ext2_filsys fs = ff->fs; in __op_open() local
2090 return translate_error(fs, 0, err); in __op_open()
2091 file->magic = FUSE2FS_FILE_MAGIC; in __op_open()
2093 file->open_flags = 0; in __op_open()
2094 switch (fp->flags & O_ACCMODE) { in __op_open()
2100 file->open_flags |= EXT2_FILE_WRITE; in __op_open()
2104 file->open_flags |= EXT2_FILE_WRITE; in __op_open()
2108 detect_linux_executable_open(fp->flags, &check, &file->open_flags); in __op_open()
2110 if (fp->flags & O_CREAT) in __op_open()
2111 file->open_flags |= EXT2_FILE_CREATE; in __op_open()
2113 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &file->ino); in __op_open()
2114 if (err || file->ino == 0) { in __op_open()
2115 ret = translate_error(fs, 0, err); in __op_open()
2118 dbg_printf("%s: ino=%d\n", __func__, file->ino); in __op_open()
2120 ret = check_inum_access(fs, file->ino, check); in __op_open()
2123 * In a regular (Linux) fs driver, the kernel will open in __op_open()
2124 * binaries for reading if the user has --x privileges (i.e. in __op_open()
2132 ret = check_inum_access(fs, file->ino, X_OK); in __op_open()
2138 fp->fh = (uintptr_t)file; in __op_open()
2149 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_open()
2153 pthread_mutex_lock(&ff->bfl); in op_open()
2155 pthread_mutex_unlock(&ff->bfl); in op_open()
2164 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_read()
2166 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh; in op_read()
2167 ext2_filsys fs; in op_read() local
2174 fs = ff->fs; in op_read()
2175 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in op_read()
2176 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino, offset, in op_read()
2178 pthread_mutex_lock(&ff->bfl); in op_read()
2179 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp); in op_read()
2181 ret = translate_error(fs, fh->ino, err); in op_read()
2187 ret = translate_error(fs, fh->ino, err); in op_read()
2193 ret = translate_error(fs, fh->ino, err); in op_read()
2202 ret = translate_error(fs, fh->ino, err); in op_read()
2206 if (fs_writeable(fs)) { in op_read()
2207 ret = update_atime(fs, fh->ino); in op_read()
2212 pthread_mutex_unlock(&ff->bfl); in op_read()
2221 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_write()
2223 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh; in op_write()
2224 ext2_filsys fs; in op_write() local
2231 fs = ff->fs; in op_write()
2232 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in op_write()
2233 dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino, offset, in op_write()
2235 pthread_mutex_lock(&ff->bfl); in op_write()
2236 if (!fs_writeable(fs)) { in op_write()
2237 ret = -EROFS; in op_write()
2241 if (!fs_can_allocate(ff, len / fs->blocksize)) { in op_write()
2242 ret = -ENOSPC; in op_write()
2246 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp); in op_write()
2248 ret = translate_error(fs, fh->ino, err); in op_write()
2254 ret = translate_error(fs, fh->ino, err); in op_write()
2260 ret = translate_error(fs, fh->ino, err); in op_write()
2267 ret = translate_error(fs, fh->ino, err); in op_write()
2276 ret = translate_error(fs, fh->ino, err); in op_write()
2280 ret = update_mtime(fs, fh->ino, NULL); in op_write()
2285 pthread_mutex_unlock(&ff->bfl); in op_write()
2293 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_release()
2295 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh; in op_release()
2296 ext2_filsys fs; in op_release() local
2301 fs = ff->fs; in op_release()
2302 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in op_release()
2303 dbg_printf("%s: ino=%d\n", __func__, fh->ino); in op_release()
2304 pthread_mutex_lock(&ff->bfl); in op_release()
2305 if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) { in op_release()
2306 err = ext2fs_flush2(fs, EXT2_FLAG_FLUSH_NO_SYNC); in op_release()
2308 ret = translate_error(fs, fh->ino, err); in op_release()
2310 fp->fh = 0; in op_release()
2311 pthread_mutex_unlock(&ff->bfl); in op_release()
2323 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_fsync()
2325 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh; in op_fsync()
2326 ext2_filsys fs; in op_fsync() local
2331 fs = ff->fs; in op_fsync()
2332 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in op_fsync()
2333 dbg_printf("%s: ino=%d\n", __func__, fh->ino); in op_fsync()
2335 pthread_mutex_lock(&ff->bfl); in op_fsync()
2336 if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) { in op_fsync()
2337 err = ext2fs_flush2(fs, 0); in op_fsync()
2339 ret = translate_error(fs, fh->ino, err); in op_fsync()
2341 pthread_mutex_unlock(&ff->bfl); in op_fsync()
2350 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_statfs()
2351 ext2_filsys fs; in op_statfs() local
2356 fs = ff->fs; in op_statfs()
2358 buf->f_bsize = fs->blocksize; in op_statfs()
2359 buf->f_frsize = 0; in op_statfs()
2361 if (ff->minixdf) in op_statfs()
2364 overhead = fs->desc_blocks + in op_statfs()
2365 fs->group_desc_count * in op_statfs()
2366 (fs->inode_blocks_per_group + 2); in op_statfs()
2367 reserved = ext2fs_r_blocks_count(fs->super); in op_statfs()
2369 reserved = ext2fs_blocks_count(fs->super) / 10; in op_statfs()
2370 free = ext2fs_free_blocks_count(fs->super); in op_statfs()
2372 buf->f_blocks = ext2fs_blocks_count(fs->super) - overhead; in op_statfs()
2373 buf->f_bfree = free; in op_statfs()
2375 buf->f_bavail = 0; in op_statfs()
2377 buf->f_bavail = free - reserved; in op_statfs()
2378 buf->f_files = fs->super->s_inodes_count; in op_statfs()
2379 buf->f_ffree = fs->super->s_free_inodes_count; in op_statfs()
2380 buf->f_favail = fs->super->s_free_inodes_count; in op_statfs()
2381 f = (uint64_t *)fs->super->s_uuid; in op_statfs()
2385 buf->f_fsid = fsid; in op_statfs()
2386 buf->f_flag = 0; in op_statfs()
2387 if (fs->flags & EXT2_FLAG_RW) in op_statfs()
2388 buf->f_flag |= ST_RDONLY; in op_statfs()
2389 buf->f_namemax = EXT2_NAME_LEN; in op_statfs()
2422 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_getxattr()
2423 ext2_filsys fs; in op_getxattr() local
2433 fs = ff->fs; in op_getxattr()
2434 pthread_mutex_lock(&ff->bfl); in op_getxattr()
2435 if (!ext2fs_has_feature_xattr(fs->super)) { in op_getxattr()
2436 ret = -ENOTSUP; in op_getxattr()
2440 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_getxattr()
2442 ret = translate_error(fs, 0, err); in op_getxattr()
2447 ret = check_inum_access(fs, ino, R_OK); in op_getxattr()
2451 err = ext2fs_xattrs_open(fs, ino, &h); in op_getxattr()
2453 ret = translate_error(fs, ino, err); in op_getxattr()
2459 ret = translate_error(fs, ino, err); in op_getxattr()
2465 ret = translate_error(fs, ino, err); in op_getxattr()
2469 for (xt = xattr_translators; xt->prefix != NULL; xt++) { in op_getxattr()
2470 if (strncmp(key, xt->prefix, strlen(xt->prefix)) == 0) { in op_getxattr()
2471 err = xt->get(&cptr, &clen, ptr, plen); in op_getxattr()
2483 ret = -ERANGE; in op_getxattr()
2494 ret = translate_error(fs, ino, err); in op_getxattr()
2496 pthread_mutex_unlock(&ff->bfl); in op_getxattr()
2525 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_listxattr()
2526 ext2_filsys fs; in op_listxattr() local
2534 fs = ff->fs; in op_listxattr()
2535 pthread_mutex_lock(&ff->bfl); in op_listxattr()
2536 if (!ext2fs_has_feature_xattr(fs->super)) { in op_listxattr()
2537 ret = -ENOTSUP; in op_listxattr()
2541 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_listxattr()
2543 ret = translate_error(fs, ino, err); in op_listxattr()
2548 ret = check_inum_access(fs, ino, R_OK); in op_listxattr()
2552 err = ext2fs_xattrs_open(fs, ino, &h); in op_listxattr()
2554 ret = translate_error(fs, ino, err); in op_listxattr()
2560 ret = translate_error(fs, ino, err); in op_listxattr()
2568 ret = translate_error(fs, ino, err); in op_listxattr()
2576 ret = -ERANGE; in op_listxattr()
2584 ret = translate_error(fs, ino, err); in op_listxattr()
2591 ret = translate_error(fs, ino, err); in op_listxattr()
2593 pthread_mutex_unlock(&ff->bfl); in op_listxattr()
2603 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_setxattr()
2604 ext2_filsys fs; in op_setxattr() local
2614 fs = ff->fs; in op_setxattr()
2615 pthread_mutex_lock(&ff->bfl); in op_setxattr()
2616 if (!ext2fs_has_feature_xattr(fs->super)) { in op_setxattr()
2617 ret = -ENOTSUP; in op_setxattr()
2621 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_setxattr()
2623 ret = translate_error(fs, 0, err); in op_setxattr()
2628 ret = check_inum_access(fs, ino, W_OK); in op_setxattr()
2629 if (ret == -EACCES) { in op_setxattr()
2630 ret = -EPERM; in op_setxattr()
2635 err = ext2fs_xattrs_open(fs, ino, &h); in op_setxattr()
2637 ret = translate_error(fs, ino, err); in op_setxattr()
2643 ret = translate_error(fs, ino, err); in op_setxattr()
2649 for (xt = xattr_translators; xt->prefix != NULL; xt++) { in op_setxattr()
2650 if (strncmp(key, xt->prefix, strlen(xt->prefix)) == 0) { in op_setxattr()
2651 err = xt->set(value, len, &cvalue, &clen); in op_setxattr()
2659 ret = translate_error(fs, ino, err); in op_setxattr()
2663 ret = update_ctime(fs, ino, NULL); in op_setxattr()
2670 ret = translate_error(fs, ino, err); in op_setxattr()
2672 pthread_mutex_unlock(&ff->bfl); in op_setxattr()
2680 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_removexattr()
2681 ext2_filsys fs; in op_removexattr() local
2688 fs = ff->fs; in op_removexattr()
2689 pthread_mutex_lock(&ff->bfl); in op_removexattr()
2690 if (!ext2fs_has_feature_xattr(fs->super)) { in op_removexattr()
2691 ret = -ENOTSUP; in op_removexattr()
2696 ret = -ENOSPC; in op_removexattr()
2700 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_removexattr()
2702 ret = translate_error(fs, 0, err); in op_removexattr()
2707 ret = check_inum_access(fs, ino, W_OK); in op_removexattr()
2711 err = ext2fs_xattrs_open(fs, ino, &h); in op_removexattr()
2713 ret = translate_error(fs, ino, err); in op_removexattr()
2719 ret = translate_error(fs, ino, err); in op_removexattr()
2725 ret = translate_error(fs, ino, err); in op_removexattr()
2729 ret = update_ctime(fs, ino, NULL); in op_removexattr()
2733 ret = translate_error(fs, ino, err); in op_removexattr()
2735 pthread_mutex_unlock(&ff->bfl); in op_removexattr()
2756 memcpy(namebuf, dirent->name, dirent->name_len & 0xFF); in op_readdir_iter()
2757 namebuf[dirent->name_len & 0xFF] = 0; in op_readdir_iter()
2758 ret = i->func(i->buf, namebuf, NULL, 0); in op_readdir_iter()
2771 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_readdir()
2773 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh; in op_readdir()
2774 ext2_filsys fs; in op_readdir() local
2780 fs = ff->fs; in op_readdir()
2781 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in op_readdir()
2782 dbg_printf("%s: ino=%d\n", __func__, fh->ino); in op_readdir()
2783 pthread_mutex_lock(&ff->bfl); in op_readdir()
2786 err = ext2fs_dir_iterate2(fs, fh->ino, 0, NULL, op_readdir_iter, &i); in op_readdir()
2788 ret = translate_error(fs, fh->ino, err); in op_readdir()
2792 if (fs_writeable(fs)) { in op_readdir()
2793 ret = update_atime(fs, fh->ino); in op_readdir()
2798 pthread_mutex_unlock(&ff->bfl); in op_readdir()
2805 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_access()
2806 ext2_filsys fs; in op_access() local
2812 fs = ff->fs; in op_access()
2814 pthread_mutex_lock(&ff->bfl); in op_access()
2815 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_access()
2817 ret = translate_error(fs, 0, err); in op_access()
2821 ret = check_inum_access(fs, ino, mask); in op_access()
2826 pthread_mutex_unlock(&ff->bfl); in op_access()
2833 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_create()
2834 ext2_filsys fs; in op_create() local
2844 fs = ff->fs; in op_create()
2848 ret = -ENOMEM; in op_create()
2853 ret = -ENOMEM; in op_create()
2860 pthread_mutex_lock(&ff->bfl); in op_create()
2862 ret = -ENOSPC; in op_create()
2866 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path, in op_create()
2869 ret = translate_error(fs, 0, err); in op_create()
2873 ret = check_inum_access(fs, parent, W_OK); in op_create()
2881 err = ext2fs_new_inode(fs, parent, mode, 0, &child); in op_create()
2883 ret = translate_error(fs, parent, err); in op_create()
2889 err = ext2fs_link(fs, parent, node_name, child, filetype); in op_create()
2891 err = ext2fs_expand_dir(fs, parent); in op_create()
2893 ret = translate_error(fs, parent, err); in op_create()
2897 err = ext2fs_link(fs, parent, node_name, child, in op_create()
2901 ret = translate_error(fs, parent, err); in op_create()
2905 ret = update_mtime(fs, parent, NULL); in op_create()
2912 inode.i_extra_isize = sizeof(struct ext2_inode_large) - in op_create()
2914 inode.i_uid = ctxt->uid; in op_create()
2915 inode.i_gid = ctxt->gid; in op_create()
2916 if (ext2fs_has_feature_extents(fs->super)) { in op_create()
2920 ret = ext2fs_extent_open2(fs, child, in op_create()
2927 err = ext2fs_write_new_inode(fs, child, (struct ext2_inode *)&inode); in op_create()
2929 ret = translate_error(fs, child, err); in op_create()
2933 inode.i_generation = ff->next_generation++; in op_create()
2935 err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode, in op_create()
2938 ret = translate_error(fs, child, err); in op_create()
2942 ext2fs_inode_alloc_stats2(fs, child, 1, 0); in op_create()
2948 pthread_mutex_unlock(&ff->bfl); in op_create()
2958 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_ftruncate()
2960 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh; in op_ftruncate()
2961 ext2_filsys fs; in op_ftruncate() local
2967 fs = ff->fs; in op_ftruncate()
2968 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in op_ftruncate()
2969 dbg_printf("%s: ino=%d len=%jd\n", __func__, fh->ino, len); in op_ftruncate()
2970 pthread_mutex_lock(&ff->bfl); in op_ftruncate()
2971 if (!fs_writeable(fs)) { in op_ftruncate()
2972 ret = -EROFS; in op_ftruncate()
2976 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp); in op_ftruncate()
2978 ret = translate_error(fs, fh->ino, err); in op_ftruncate()
2984 ret = translate_error(fs, fh->ino, err); in op_ftruncate()
2993 ret = translate_error(fs, fh->ino, err); in op_ftruncate()
2997 ret = update_mtime(fs, fh->ino, NULL); in op_ftruncate()
3002 pthread_mutex_unlock(&ff->bfl); in op_ftruncate()
3011 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_fgetattr()
3012 ext2_filsys fs; in op_fgetattr() local
3014 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh; in op_fgetattr()
3018 fs = ff->fs; in op_fgetattr()
3019 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in op_fgetattr()
3020 dbg_printf("%s: ino=%d\n", __func__, fh->ino); in op_fgetattr()
3021 pthread_mutex_lock(&ff->bfl); in op_fgetattr()
3022 ret = stat_inode(fs, fh->ino, statbuf); in op_fgetattr()
3023 pthread_mutex_unlock(&ff->bfl); in op_fgetattr()
3031 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_utimens()
3033 ext2_filsys fs; in op_utimens() local
3040 fs = ff->fs; in op_utimens()
3041 pthread_mutex_lock(&ff->bfl); in op_utimens()
3042 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_utimens()
3044 ret = translate_error(fs, 0, err); in op_utimens()
3049 ret = check_inum_access(fs, ino, W_OK); in op_utimens()
3054 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, in op_utimens()
3057 ret = translate_error(fs, ino, err); in op_utimens()
3075 ret = update_ctime(fs, ino, &inode); in op_utimens()
3079 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, in op_utimens()
3082 ret = translate_error(fs, ino, err); in op_utimens()
3087 pthread_mutex_unlock(&ff->bfl); in op_utimens()
3092 static int ioctl_getflags(ext2_filsys fs, struct fuse2fs_file_handle *fh, in ioctl_getflags() argument
3098 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in ioctl_getflags()
3099 dbg_printf("%s: ino=%d\n", __func__, fh->ino); in ioctl_getflags()
3101 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode, in ioctl_getflags()
3104 return translate_error(fs, fh->ino, err); in ioctl_getflags()
3115 static int ioctl_setflags(ext2_filsys fs, struct fuse2fs_file_handle *fh, in ioctl_setflags() argument
3124 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in ioctl_setflags()
3125 dbg_printf("%s: ino=%d\n", __func__, fh->ino); in ioctl_setflags()
3127 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode, in ioctl_setflags()
3130 return translate_error(fs, fh->ino, err); in ioctl_setflags()
3132 if (ctxt->uid != 0 && inode.i_uid != ctxt->uid) in ioctl_setflags()
3133 return -EPERM; in ioctl_setflags()
3136 return -EINVAL; in ioctl_setflags()
3141 ret = update_ctime(fs, fh->ino, &inode); in ioctl_setflags()
3145 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode, in ioctl_setflags()
3148 return translate_error(fs, fh->ino, err); in ioctl_setflags()
3153 static int ioctl_getversion(ext2_filsys fs, struct fuse2fs_file_handle *fh, in ioctl_getversion() argument
3159 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in ioctl_getversion()
3160 dbg_printf("%s: ino=%d\n", __func__, fh->ino); in ioctl_getversion()
3162 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode, in ioctl_getversion()
3165 return translate_error(fs, fh->ino, err); in ioctl_getversion()
3171 static int ioctl_setversion(ext2_filsys fs, struct fuse2fs_file_handle *fh, in ioctl_setversion() argument
3180 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in ioctl_setversion()
3181 dbg_printf("%s: ino=%d\n", __func__, fh->ino); in ioctl_setversion()
3183 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode, in ioctl_setversion()
3186 return translate_error(fs, fh->ino, err); in ioctl_setversion()
3188 if (ctxt->uid != 0 && inode.i_uid != ctxt->uid) in ioctl_setversion()
3189 return -EPERM; in ioctl_setversion()
3193 ret = update_ctime(fs, fh->ino, &inode); in ioctl_setversion()
3197 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode, in ioctl_setversion()
3200 return translate_error(fs, fh->ino, err); in ioctl_setversion()
3207 static int ioctl_fitrim(ext2_filsys fs, struct fuse2fs_file_handle *fh, in ioctl_fitrim() argument
3214 start = fr->start / fs->blocksize; in ioctl_fitrim()
3215 end = (fr->start + fr->len - 1) / fs->blocksize; in ioctl_fitrim()
3218 if (start < fs->super->s_first_data_block) in ioctl_fitrim()
3219 start = fs->super->s_first_data_block; in ioctl_fitrim()
3220 if (start >= ext2fs_blocks_count(fs->super)) in ioctl_fitrim()
3221 start = ext2fs_blocks_count(fs->super) - 1; in ioctl_fitrim()
3223 if (end < fs->super->s_first_data_block) in ioctl_fitrim()
3224 end = fs->super->s_first_data_block; in ioctl_fitrim()
3225 if (end >= ext2fs_blocks_count(fs->super)) in ioctl_fitrim()
3226 end = ext2fs_blocks_count(fs->super) - 1; in ioctl_fitrim()
3229 max_blocks = 2048ULL * 1024 * 1024 / fs->blocksize; in ioctl_fitrim()
3231 fr->len = 0; in ioctl_fitrim()
3233 err = ext2fs_find_first_zero_block_bitmap2(fs->block_map, in ioctl_fitrim()
3238 return translate_error(fs, fh->ino, err); in ioctl_fitrim()
3241 err = ext2fs_find_first_set_block_bitmap2(fs->block_map, in ioctl_fitrim()
3244 return translate_error(fs, fh->ino, err); in ioctl_fitrim()
3245 if (b - start >= fr->minlen) { in ioctl_fitrim()
3246 err = io_channel_discard(fs->io, start, b - start); in ioctl_fitrim()
3248 return translate_error(fs, fh->ino, err); in ioctl_fitrim()
3249 cleared += b - start; in ioctl_fitrim()
3250 fr->len = cleared * fs->blocksize; in ioctl_fitrim()
3266 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_ioctl()
3268 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh; in op_ioctl()
3269 ext2_filsys fs; in op_ioctl() local
3273 fs = ff->fs; in op_ioctl()
3274 pthread_mutex_lock(&ff->bfl); in op_ioctl()
3278 ret = ioctl_getflags(fs, fh, data); in op_ioctl()
3281 ret = ioctl_setflags(fs, fh, data); in op_ioctl()
3284 ret = ioctl_getversion(fs, fh, data); in op_ioctl()
3287 ret = ioctl_setversion(fs, fh, data); in op_ioctl()
3292 ret = ioctl_fitrim(fs, fh, data); in op_ioctl()
3297 ret = -ENOTTY; in op_ioctl()
3299 pthread_mutex_unlock(&ff->bfl); in op_ioctl()
3309 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_bmap()
3310 ext2_filsys fs; in op_bmap() local
3316 fs = ff->fs; in op_bmap()
3317 pthread_mutex_lock(&ff->bfl); in op_bmap()
3318 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino); in op_bmap()
3320 ret = translate_error(fs, 0, err); in op_bmap()
3325 err = ext2fs_bmap2(fs, ino, NULL, NULL, 0, *idx, 0, (blk64_t *)idx); in op_bmap()
3327 ret = translate_error(fs, ino, err); in op_bmap()
3332 pthread_mutex_unlock(&ff->bfl); in op_bmap()
3342 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in fallocate_helper()
3344 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh; in fallocate_helper()
3345 ext2_filsys fs; in fallocate_helper() local
3353 fs = ff->fs; in fallocate_helper()
3354 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in fallocate_helper()
3355 start = offset / fs->blocksize; in fallocate_helper()
3356 end = (offset + len - 1) / fs->blocksize; in fallocate_helper()
3358 fh->ino, mode, offset / fs->blocksize, end); in fallocate_helper()
3359 if (!fs_can_allocate(ff, len / fs->blocksize)) in fallocate_helper()
3360 return -ENOSPC; in fallocate_helper()
3363 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode, in fallocate_helper()
3372 err = ext2fs_fallocate(fs, flags, fh->ino, in fallocate_helper()
3374 ~0ULL, start, end - start + 1); in fallocate_helper()
3376 return translate_error(fs, fh->ino, err); in fallocate_helper()
3381 err = ext2fs_inode_size_set(fs, in fallocate_helper()
3385 return translate_error(fs, fh->ino, err); in fallocate_helper()
3389 err = update_mtime(fs, fh->ino, &inode); in fallocate_helper()
3393 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode, in fallocate_helper()
3396 return translate_error(fs, fh->ino, err); in fallocate_helper()
3401 static errcode_t clean_block_middle(ext2_filsys fs, ext2_ino_t ino, in clean_block_middle() argument
3410 residue = offset % fs->blocksize; in clean_block_middle()
3415 err = ext2fs_get_mem(fs->blocksize, buf); in clean_block_middle()
3420 err = ext2fs_bmap2(fs, ino, (struct ext2_inode *)inode, *buf, 0, in clean_block_middle()
3421 offset / fs->blocksize, &retflags, &blk); in clean_block_middle()
3427 err = io_channel_read_blk(fs->io, blk, 1, *buf); in clean_block_middle()
3433 return io_channel_write_blk(fs->io, blk, 1, *buf); in clean_block_middle()
3436 static errcode_t clean_block_edge(ext2_filsys fs, ext2_ino_t ino, in clean_block_edge() argument
3445 residue = offset % fs->blocksize; in clean_block_edge()
3450 err = ext2fs_get_mem(fs->blocksize, buf); in clean_block_edge()
3455 err = ext2fs_bmap2(fs, ino, (struct ext2_inode *)inode, *buf, 0, in clean_block_edge()
3456 offset / fs->blocksize, &retflags, &blk); in clean_block_edge()
3460 err = io_channel_read_blk(fs->io, blk, 1, *buf); in clean_block_edge()
3469 memset(*buf + residue, 0, fs->blocksize - residue); in clean_block_edge()
3471 return io_channel_write_blk(fs->io, blk, 1, *buf); in clean_block_edge()
3478 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in punch_helper()
3480 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh; in punch_helper()
3481 ext2_filsys fs; in punch_helper() local
3488 fs = ff->fs; in punch_helper()
3489 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC); in punch_helper()
3494 return -EINVAL; in punch_helper()
3497 start = (offset + fs->blocksize - 1) / fs->blocksize; in punch_helper()
3498 end = (offset + len - fs->blocksize) / fs->blocksize; in punch_helper()
3500 fh->ino, mode, start, end); in punch_helper()
3503 err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode, in punch_helper()
3506 return translate_error(fs, fh->ino, err); in punch_helper()
3509 if ((offset / fs->blocksize) == ((offset + len) / fs->blocksize)) in punch_helper()
3510 err = clean_block_middle(fs, fh->ino, &inode, offset, in punch_helper()
3513 err = clean_block_edge(fs, fh->ino, &inode, offset, 0, &buf); in punch_helper()
3515 err = clean_block_edge(fs, fh->ino, &inode, in punch_helper()
3521 return translate_error(fs, fh->ino, err); in punch_helper()
3525 err = ext2fs_punch(fs, fh->ino, (struct ext2_inode *)&inode, in punch_helper()
3528 return translate_error(fs, fh->ino, err); in punch_helper()
3531 err = update_mtime(fs, fh->ino, &inode); in punch_helper()
3535 err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode, in punch_helper()
3538 return translate_error(fs, fh->ino, err); in punch_helper()
3548 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; in op_fallocate()
3549 ext2_filsys fs = ff->fs; in op_fallocate() local
3554 return -EINVAL; in op_fallocate()
3556 pthread_mutex_lock(&ff->bfl); in op_fallocate()
3557 if (!fs_writeable(fs)) { in op_fallocate()
3558 ret = -EROFS; in op_fallocate()
3566 pthread_mutex_unlock(&ff->bfl); in op_fallocate()
3661 FUSE_OPT_KEY("-V", FUSE2FS_VERSION),
3662 FUSE_OPT_KEY("--version", FUSE2FS_VERSION),
3663 FUSE_OPT_KEY("-h", FUSE2FS_HELP),
3664 FUSE_OPT_KEY("--help", FUSE2FS_HELP),
3665 FUSE_OPT_KEY("--helpfull", FUSE2FS_HELPFULL),
3677 if (!ff->device) { in fuse2fs_opt_proc()
3678 ff->device = strdup(arg); in fuse2fs_opt_proc()
3688 " -o opt,[opt...] mount options\n" in fuse2fs_opt_proc()
3689 " -h --help print help\n" in fuse2fs_opt_proc()
3690 " -V --version print version\n" in fuse2fs_opt_proc()
3693 " -o ro read-only mount\n" in fuse2fs_opt_proc()
3694 " -o errors=panic dump core on error\n" in fuse2fs_opt_proc()
3695 " -o minixdf minix-style df\n" in fuse2fs_opt_proc()
3696 " -o no_default_opts do not include default fuse options\n" in fuse2fs_opt_proc()
3697 " -o fuse2fs_debug enable fuse2fs debugging\n" in fuse2fs_opt_proc()
3699 outargs->argv[0]); in fuse2fs_opt_proc()
3701 fuse_opt_add_arg(outargs, "-ho"); in fuse2fs_opt_proc()
3702 fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL); in fuse2fs_opt_proc()
3704 fprintf(stderr, "Try --helpfull to get a list of " in fuse2fs_opt_proc()
3712 fuse_opt_add_arg(outargs, "--version"); in fuse2fs_opt_proc()
3713 fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL); in fuse2fs_opt_proc()
3734 fprintf(stderr, "See '%s -h' for usage\n", argv[0]); in main()
3739 printf("%s", _("Mounting read-only.\n")); in main()
3768 /* Start up the fs (while we still can use stdout) */ in main()
3776 printf(_("Please run e2fsck -fy %s.\n"), fctx.device); in main()
3779 fctx.fs = global_fs; in main()
3780 global_fs->priv_data = &fctx; in main()
3784 if (ext2fs_has_feature_journal_needs_recovery(global_fs->super)) { in main()
3791 printf(_("Please run e2fsck -fy %s.\n"), in main()
3795 ext2fs_clear_feature_journal_needs_recovery(global_fs->super); in main()
3799 "`e2fsck -E journal_only' is required.\n")); in main()
3805 if (ext2fs_has_feature_journal(global_fs->super)) in main()
3820 if (!(global_fs->super->s_state & EXT2_VALID_FS)) in main()
3821 printf("%s", _("Warning: Mounting unchecked fs, running e2fsck " in main()
3823 if (global_fs->super->s_max_mnt_count > 0 && in main()
3824 global_fs->super->s_mnt_count >= global_fs->super->s_max_mnt_count) in main()
3827 if (global_fs->super->s_checkinterval > 0 && in main()
3828 (time_t) (global_fs->super->s_lastcheck + in main()
3829 global_fs->super->s_checkinterval) <= time(0)) in main()
3832 if (global_fs->super->s_last_orphan) in main()
3836 if (global_fs->super->s_state & EXT2_ERROR_FS) { in main()
3846 snprintf(extra_args, BUFSIZ, "-okernel_cache,subtype=ext4,use_ino," in main()
3870 com_err(argv[0], err, "while closing fs"); in main()
3876 static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino, in __translate_error() argument
3881 struct fuse2fs *ff = fs->priv_data; in __translate_error()
3890 ret = -ENOMEM; in __translate_error()
3894 ret = -EINVAL; in __translate_error()
3897 ret = -ENOTDIR; in __translate_error()
3900 ret = -ENOENT; in __translate_error()
3909 ret = -ENOSPC; in __translate_error()
3912 ret = -EMLINK; in __translate_error()
3915 ret = -EFBIG; in __translate_error()
3919 ret = -EEXIST; in __translate_error()
3923 ret = -EBUSY; in __translate_error()
3927 ret = -ENODATA; in __translate_error()
3929 ret = -ENOENT; in __translate_error()
3934 ret = -EFAULT; in __translate_error()
3937 ret = -EOPNOTSUPP; in __translate_error()
3941 ret = -EIO; in __translate_error()
3950 fprintf(ff->err_fp, "FUSE2FS (%s): %s (inode #%d) at %s:%d.\n", in __translate_error()
3951 fs->device_name ? fs->device_name : "???", in __translate_error()
3954 fprintf(ff->err_fp, "FUSE2FS (%s): %s at %s:%d.\n", in __translate_error()
3955 fs->device_name ? fs->device_name : "???", in __translate_error()
3957 fflush(ff->err_fp); in __translate_error()
3961 fs->super->s_last_error_time = now.tv_sec; in __translate_error()
3962 fs->super->s_last_error_ino = ino; in __translate_error()
3963 fs->super->s_last_error_line = line; in __translate_error()
3964 fs->super->s_last_error_block = err; /* Yeah... */ in __translate_error()
3965 strncpy((char *)fs->super->s_last_error_func, file, in __translate_error()
3966 sizeof(fs->super->s_last_error_func)); in __translate_error()
3967 if (fs->super->s_first_error_time == 0) { in __translate_error()
3968 fs->super->s_first_error_time = now.tv_sec; in __translate_error()
3969 fs->super->s_first_error_ino = ino; in __translate_error()
3970 fs->super->s_first_error_line = line; in __translate_error()
3971 fs->super->s_first_error_block = err; in __translate_error()
3972 strncpy((char *)fs->super->s_first_error_func, file, in __translate_error()
3973 sizeof(fs->super->s_first_error_func)); in __translate_error()
3976 fs->super->s_error_count++; in __translate_error()
3977 ext2fs_mark_super_dirty(fs); in __translate_error()
3978 ext2fs_flush(fs); in __translate_error()
3979 if (ff->panic_on_error) in __translate_error()