Home | History | Annotate | Download | only in misc
      1 /*
      2  * fuse2fs.c - FUSE server for e2fsprogs.
      3  *
      4  * Copyright (C) 2014 Oracle.
      5  *
      6  * %Begin-Header%
      7  * This file may be redistributed under the terms of the GNU Public
      8  * License.
      9  * %End-Header%
     10  */
     11 #define _FILE_OFFSET_BITS 64
     12 #define FUSE_USE_VERSION 29
     13 #ifndef _GNU_SOURCE
     14 #define _GNU_SOURCE
     15 #endif
     16 #include "config.h"
     17 #include <pthread.h>
     18 #ifdef __linux__
     19 # include <linux/fs.h>
     20 # include <linux/falloc.h>
     21 # include <linux/xattr.h>
     22 # define FUSE_PLATFORM_OPTS	",nonempty,big_writes"
     23 # ifdef HAVE_SYS_ACL_H
     24 #  define TRANSLATE_LINUX_ACLS
     25 # endif
     26 #else
     27 # define FUSE_PLATFORM_OPTS	""
     28 #endif
     29 #ifdef TRANSLATE_LINUX_ACLS
     30 # include <sys/acl.h>
     31 #endif
     32 #include <sys/ioctl.h>
     33 #include <unistd.h>
     34 #include <fuse.h>
     35 #include <inttypes.h>
     36 #include "ext2fs/ext2fs.h"
     37 #include "ext2fs/ext2_fs.h"
     38 
     39 #include "../version.h"
     40 
     41 #ifdef ENABLE_NLS
     42 #include <libintl.h>
     43 #include <locale.h>
     44 #define _(a) (gettext(a))
     45 #ifdef gettext_noop
     46 #define N_(a) gettext_noop(a)
     47 #else
     48 #define N_(a) (a)
     49 #endif
     50 #define P_(singular, plural, n) (ngettext(singular, plural, n))
     51 #ifndef NLS_CAT_NAME
     52 #define NLS_CAT_NAME "e2fsprogs"
     53 #endif
     54 #ifndef LOCALEDIR
     55 #define LOCALEDIR "/usr/share/locale"
     56 #endif
     57 #else
     58 #define _(a) (a)
     59 #define N_(a) a
     60 #define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural))
     61 #endif
     62 
     63 static ext2_filsys global_fs; /* Try not to use this directly */
     64 
     65 #undef DEBUG
     66 
     67 #ifdef DEBUG
     68 # define dbg_printf(f, a...)  do {printf("FUSE2FS-" f, ## a); \
     69 	fflush(stdout); \
     70 } while (0)
     71 #else
     72 # define dbg_printf(f, a...)
     73 #endif
     74 
     75 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
     76 # ifdef _IOR
     77 #  ifdef _IOW
     78 #   define SUPPORT_I_FLAGS
     79 #  endif
     80 # endif
     81 #endif
     82 
     83 #ifdef FALLOC_FL_KEEP_SIZE
     84 # define FL_KEEP_SIZE_FLAG FALLOC_FL_KEEP_SIZE
     85 # define SUPPORT_FALLOCATE
     86 #else
     87 # define FL_KEEP_SIZE_FLAG (0)
     88 #endif
     89 
     90 #ifdef FALLOC_FL_PUNCH_HOLE
     91 # define FL_PUNCH_HOLE_FLAG FALLOC_FL_PUNCH_HOLE
     92 #else
     93 # define FL_PUNCH_HOLE_FLAG (0)
     94 #endif
     95 
     96 errcode_t ext2fs_run_ext3_journal(ext2_filsys *fs);
     97 
     98 #ifdef CONFIG_JBD_DEBUG		/* Enabled by configure --enable-jbd-debug */
     99 int journal_enable_debug = -1;
    100 #endif
    101 
    102 /* ACL translation stuff */
    103 #ifdef TRANSLATE_LINUX_ACLS
    104 /*
    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.
    107  */
    108 #define ACL_EA_ACCESS		"system.posix_acl_access"
    109 #define ACL_EA_DEFAULT		"system.posix_acl_default"
    110 
    111 #define ACL_EA_VERSION		0x0002
    112 
    113 typedef struct {
    114 	u_int16_t	e_tag;
    115 	u_int16_t	e_perm;
    116 	u_int32_t	e_id;
    117 } acl_ea_entry;
    118 
    119 typedef struct {
    120 	u_int32_t	a_version;
    121 	acl_ea_entry	a_entries[0];
    122 } acl_ea_header;
    123 
    124 static inline size_t acl_ea_size(int count)
    125 {
    126 	return sizeof(acl_ea_header) + count * sizeof(acl_ea_entry);
    127 }
    128 
    129 static inline int acl_ea_count(size_t size)
    130 {
    131 	if (size < sizeof(acl_ea_header))
    132 		return -1;
    133 	size -= sizeof(acl_ea_header);
    134 	if (size % sizeof(acl_ea_entry))
    135 		return -1;
    136 	return size / sizeof(acl_ea_entry);
    137 }
    138 
    139 /*
    140  * ext4 ACL structures, copied from fs/ext4/acl.h.
    141  */
    142 #define EXT4_ACL_VERSION	0x0001
    143 
    144 typedef struct {
    145 	__u16		e_tag;
    146 	__u16		e_perm;
    147 	__u32		e_id;
    148 } ext4_acl_entry;
    149 
    150 typedef struct {
    151 	__u16		e_tag;
    152 	__u16		e_perm;
    153 } ext4_acl_entry_short;
    154 
    155 typedef struct {
    156 	__u32		a_version;
    157 } ext4_acl_header;
    158 
    159 static inline size_t ext4_acl_size(int count)
    160 {
    161 	if (count <= 4) {
    162 		return sizeof(ext4_acl_header) +
    163 		       count * sizeof(ext4_acl_entry_short);
    164 	} else {
    165 		return sizeof(ext4_acl_header) +
    166 		       4 * sizeof(ext4_acl_entry_short) +
    167 		       (count - 4) * sizeof(ext4_acl_entry);
    168 	}
    169 }
    170 
    171 static inline int ext4_acl_count(size_t size)
    172 {
    173 	ssize_t s;
    174 
    175 	size -= sizeof(ext4_acl_header);
    176 	s = size - 4 * sizeof(ext4_acl_entry_short);
    177 	if (s < 0) {
    178 		if (size % sizeof(ext4_acl_entry_short))
    179 			return -1;
    180 		return size / sizeof(ext4_acl_entry_short);
    181 	}
    182 	if (s % sizeof(ext4_acl_entry))
    183 		return -1;
    184 	return s / sizeof(ext4_acl_entry) + 4;
    185 }
    186 
    187 static errcode_t fuse_to_ext4_acl(acl_ea_header *facl, size_t facl_sz,
    188 				  ext4_acl_header **eacl, size_t *eacl_sz)
    189 {
    190 	int i, facl_count;
    191 	ext4_acl_header *h;
    192 	size_t h_sz;
    193 	ext4_acl_entry *e;
    194 	acl_ea_entry *a;
    195 	unsigned char *hptr;
    196 	errcode_t err;
    197 
    198 	facl_count = acl_ea_count(facl_sz);
    199 	h_sz = ext4_acl_size(facl_count);
    200 	if (facl_count < 0 || facl->a_version != ACL_EA_VERSION)
    201 		return EXT2_ET_INVALID_ARGUMENT;
    202 
    203 	err = ext2fs_get_mem(h_sz, &h);
    204 	if (err)
    205 		return err;
    206 
    207 	h->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION);
    208 	hptr = (unsigned char *) (h + 1);
    209 	for (i = 0, a = facl->a_entries; i < facl_count; i++, a++) {
    210 		e = (ext4_acl_entry *) hptr;
    211 		e->e_tag = ext2fs_cpu_to_le16(a->e_tag);
    212 		e->e_perm = ext2fs_cpu_to_le16(a->e_perm);
    213 
    214 		switch (a->e_tag) {
    215 		case ACL_USER:
    216 		case ACL_GROUP:
    217 			e->e_id = ext2fs_cpu_to_le32(a->e_id);
    218 			hptr += sizeof(ext4_acl_entry);
    219 			break;
    220 		case ACL_USER_OBJ:
    221 		case ACL_GROUP_OBJ:
    222 		case ACL_MASK:
    223 		case ACL_OTHER:
    224 			hptr += sizeof(ext4_acl_entry_short);
    225 			break;
    226 		default:
    227 			err = EXT2_ET_INVALID_ARGUMENT;
    228 			goto out;
    229 		}
    230 	}
    231 
    232 	*eacl = h;
    233 	*eacl_sz = h_sz;
    234 	return err;
    235 out:
    236 	ext2fs_free_mem(&h);
    237 	return err;
    238 }
    239 
    240 static errcode_t ext4_to_fuse_acl(acl_ea_header **facl, size_t *facl_sz,
    241 				  ext4_acl_header *eacl, size_t eacl_sz)
    242 {
    243 	int i, eacl_count;
    244 	acl_ea_header *f;
    245 	ext4_acl_entry *e;
    246 	acl_ea_entry *a;
    247 	size_t f_sz;
    248 	unsigned char *hptr;
    249 	errcode_t err;
    250 
    251 	eacl_count = ext4_acl_count(eacl_sz);
    252 	f_sz = acl_ea_size(eacl_count);
    253 	if (eacl_count < 0 ||
    254 	    eacl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION))
    255 		return EXT2_ET_INVALID_ARGUMENT;
    256 
    257 	err = ext2fs_get_mem(f_sz, &f);
    258 	if (err)
    259 		return err;
    260 
    261 	f->a_version = ACL_EA_VERSION;
    262 	hptr = (unsigned char *) (eacl + 1);
    263 	for (i = 0, a = f->a_entries; i < eacl_count; i++, a++) {
    264 		e = (ext4_acl_entry *) hptr;
    265 		a->e_tag = ext2fs_le16_to_cpu(e->e_tag);
    266 		a->e_perm = ext2fs_le16_to_cpu(e->e_perm);
    267 
    268 		switch (a->e_tag) {
    269 		case ACL_USER:
    270 		case ACL_GROUP:
    271 			a->e_id = ext2fs_le32_to_cpu(e->e_id);
    272 			hptr += sizeof(ext4_acl_entry);
    273 			break;
    274 		case ACL_USER_OBJ:
    275 		case ACL_GROUP_OBJ:
    276 		case ACL_MASK:
    277 		case ACL_OTHER:
    278 			hptr += sizeof(ext4_acl_entry_short);
    279 			break;
    280 		default:
    281 			err = EXT2_ET_INVALID_ARGUMENT;
    282 			goto out;
    283 		}
    284 	}
    285 
    286 	*facl = f;
    287 	*facl_sz = f_sz;
    288 	return err;
    289 out:
    290 	ext2fs_free_mem(&f);
    291 	return err;
    292 }
    293 #endif /* TRANSLATE_LINUX_ACLS */
    294 
    295 /*
    296  * ext2_file_t contains a struct inode, so we can't leave files open.
    297  * Use this as a proxy instead.
    298  */
    299 #define FUSE2FS_FILE_MAGIC	(0xEF53DEAFUL)
    300 struct fuse2fs_file_handle {
    301 	unsigned long magic;
    302 	ext2_ino_t ino;
    303 	int open_flags;
    304 };
    305 
    306 /* Main program context */
    307 #define FUSE2FS_MAGIC		(0xEF53DEADUL)
    308 struct fuse2fs {
    309 	unsigned long magic;
    310 	ext2_filsys fs;
    311 	pthread_mutex_t bfl;
    312 	char *device;
    313 	int ro;
    314 	int debug;
    315 	int no_default_opts;
    316 	int panic_on_error;
    317 	int minixdf;
    318 	int alloc_all_blocks;
    319 	FILE *err_fp;
    320 	unsigned int next_generation;
    321 };
    322 
    323 #define FUSE2FS_CHECK_MAGIC(fs, ptr, num) do {if ((ptr)->magic != (num)) \
    324 	return translate_error((fs), 0, EXT2_ET_MAGIC_EXT2_FILE); \
    325 } while (0)
    326 
    327 #define FUSE2FS_CHECK_CONTEXT(ptr) do {if ((ptr)->magic != FUSE2FS_MAGIC) \
    328 	return translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC); \
    329 } while (0)
    330 
    331 static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino,
    332 			     const char *file, int line);
    333 #define translate_error(fs, ino, err) __translate_error((fs), (err), (ino), \
    334 			__FILE__, __LINE__)
    335 
    336 /* for macosx */
    337 #ifndef W_OK
    338 #  define W_OK 2
    339 #endif
    340 
    341 #ifndef R_OK
    342 #  define R_OK 4
    343 #endif
    344 
    345 #define EXT4_EPOCH_BITS 2
    346 #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
    347 #define EXT4_NSEC_MASK  (~0UL << EXT4_EPOCH_BITS)
    348 
    349 /*
    350  * Extended fields will fit into an inode if the filesystem was formatted
    351  * with large inodes (-I 256 or larger) and there are not currently any EAs
    352  * consuming all of the available space. For new inodes we always reserve
    353  * enough space for the kernel's known extended fields, but for inodes
    354  * created with an old kernel this might not have been the case. None of
    355  * the extended inode fields is critical for correct filesystem operation.
    356  * This macro checks if a certain field fits in the inode. Note that
    357  * inode-size = GOOD_OLD_INODE_SIZE + i_extra_isize
    358  */
    359 #define EXT4_FITS_IN_INODE(ext4_inode, field)		\
    360 	((offsetof(typeof(*ext4_inode), field) +	\
    361 	  sizeof((ext4_inode)->field))			\
    362 	 <= ((size_t) EXT2_GOOD_OLD_INODE_SIZE +		\
    363 	    (ext4_inode)->i_extra_isize))		\
    364 
    365 static inline __u32 ext4_encode_extra_time(const struct timespec *time)
    366 {
    367 	__u32 extra = sizeof(time->tv_sec) > 4 ?
    368 			((time->tv_sec - (__s32)time->tv_sec) >> 32) &
    369 			EXT4_EPOCH_MASK : 0;
    370 	return extra | (time->tv_nsec << EXT4_EPOCH_BITS);
    371 }
    372 
    373 static inline void ext4_decode_extra_time(struct timespec *time, __u32 extra)
    374 {
    375 	if (sizeof(time->tv_sec) > 4 && (extra & EXT4_EPOCH_MASK)) {
    376 		__u64 extra_bits = extra & EXT4_EPOCH_MASK;
    377 		/*
    378 		 * Prior to kernel 3.14?, we had a broken decode function,
    379 		 * wherein we effectively did this:
    380 		 * if (extra_bits == 3)
    381 		 *     extra_bits = 0;
    382 		 */
    383 		time->tv_sec += extra_bits << 32;
    384 	}
    385 	time->tv_nsec = ((extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
    386 }
    387 
    388 #define EXT4_INODE_SET_XTIME(xtime, timespec, raw_inode)		       \
    389 do {									       \
    390 	(raw_inode)->xtime = (timespec)->tv_sec;			       \
    391 	if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra))		       \
    392 		(raw_inode)->xtime ## _extra =				       \
    393 				ext4_encode_extra_time(timespec);	       \
    394 } while (0)
    395 
    396 #define EXT4_EINODE_SET_XTIME(xtime, timespec, raw_inode)		       \
    397 do {									       \
    398 	if (EXT4_FITS_IN_INODE(raw_inode, xtime))			       \
    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);	       \
    403 } while (0)
    404 
    405 #define EXT4_INODE_GET_XTIME(xtime, timespec, raw_inode)		       \
    406 do {									       \
    407 	(timespec)->tv_sec = (signed)((raw_inode)->xtime);		       \
    408 	if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra))		       \
    409 		ext4_decode_extra_time((timespec),			       \
    410 				       (raw_inode)->xtime ## _extra);	       \
    411 	else								       \
    412 		(timespec)->tv_nsec = 0;				       \
    413 } while (0)
    414 
    415 #define EXT4_EINODE_GET_XTIME(xtime, timespec, raw_inode)		       \
    416 do {									       \
    417 	if (EXT4_FITS_IN_INODE(raw_inode, xtime))			       \
    418 		(timespec)->tv_sec =					       \
    419 			(signed)((raw_inode)->xtime);			       \
    420 	if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra))		       \
    421 		ext4_decode_extra_time((timespec),			       \
    422 				       raw_inode->xtime ## _extra);	       \
    423 	else								       \
    424 		(timespec)->tv_nsec = 0;				       \
    425 } while (0)
    426 
    427 static void get_now(struct timespec *now)
    428 {
    429 #ifdef CLOCK_REALTIME
    430 	if (!clock_gettime(CLOCK_REALTIME, now))
    431 		return;
    432 #endif
    433 
    434 	now->tv_sec = time(NULL);
    435 	now->tv_nsec = 0;
    436 }
    437 
    438 static void increment_version(struct ext2_inode_large *inode)
    439 {
    440 	__u64 ver;
    441 
    442 	ver = inode->osd1.linux1.l_i_version;
    443 	if (EXT4_FITS_IN_INODE(inode, i_version_hi))
    444 		ver |= (__u64)inode->i_version_hi << 32;
    445 	ver++;
    446 	inode->osd1.linux1.l_i_version = ver;
    447 	if (EXT4_FITS_IN_INODE(inode, i_version_hi))
    448 		inode->i_version_hi = ver >> 32;
    449 }
    450 
    451 static void init_times(struct ext2_inode_large *inode)
    452 {
    453 	struct timespec now;
    454 
    455 	get_now(&now);
    456 	EXT4_INODE_SET_XTIME(i_atime, &now, inode);
    457 	EXT4_INODE_SET_XTIME(i_ctime, &now, inode);
    458 	EXT4_INODE_SET_XTIME(i_mtime, &now, inode);
    459 	EXT4_EINODE_SET_XTIME(i_crtime, &now, inode);
    460 	increment_version(inode);
    461 }
    462 
    463 static int update_ctime(ext2_filsys fs, ext2_ino_t ino,
    464 			struct ext2_inode_large *pinode)
    465 {
    466 	errcode_t err;
    467 	struct timespec now;
    468 	struct ext2_inode_large inode;
    469 
    470 	get_now(&now);
    471 
    472 	/* If user already has a inode buffer, just update that */
    473 	if (pinode) {
    474 		increment_version(pinode);
    475 		EXT4_INODE_SET_XTIME(i_ctime, &now, pinode);
    476 		return 0;
    477 	}
    478 
    479 	/* Otherwise we have to read-modify-write the inode */
    480 	memset(&inode, 0, sizeof(inode));
    481 	err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
    482 				     sizeof(inode));
    483 	if (err)
    484 		return translate_error(fs, ino, err);
    485 
    486 	increment_version(&inode);
    487 	EXT4_INODE_SET_XTIME(i_ctime, &now, &inode);
    488 
    489 	err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
    490 				      sizeof(inode));
    491 	if (err)
    492 		return translate_error(fs, ino, err);
    493 
    494 	return 0;
    495 }
    496 
    497 static int update_atime(ext2_filsys fs, ext2_ino_t ino)
    498 {
    499 	errcode_t err;
    500 	struct ext2_inode_large inode, *pinode;
    501 	struct timespec atime, mtime, now;
    502 
    503 	if (!(fs->flags & EXT2_FLAG_RW))
    504 		return 0;
    505 	memset(&inode, 0, sizeof(inode));
    506 	err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
    507 				     sizeof(inode));
    508 	if (err)
    509 		return translate_error(fs, ino, err);
    510 
    511 	pinode = &inode;
    512 	EXT4_INODE_GET_XTIME(i_atime, &atime, pinode);
    513 	EXT4_INODE_GET_XTIME(i_mtime, &mtime, pinode);
    514 	get_now(&now);
    515 	/*
    516 	 * If atime is newer than mtime and atime hasn't been updated in thirty
    517 	 * seconds, skip the atime update.  Same idea as Linux "relatime".
    518 	 */
    519 	if (atime.tv_sec >= mtime.tv_sec && atime.tv_sec >= now.tv_sec - 30)
    520 		return 0;
    521 	EXT4_INODE_SET_XTIME(i_atime, &now, &inode);
    522 
    523 	err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
    524 				      sizeof(inode));
    525 	if (err)
    526 		return translate_error(fs, ino, err);
    527 
    528 	return 0;
    529 }
    530 
    531 static int update_mtime(ext2_filsys fs, ext2_ino_t ino,
    532 			struct ext2_inode_large *pinode)
    533 {
    534 	errcode_t err;
    535 	struct ext2_inode_large inode;
    536 	struct timespec now;
    537 
    538 	if (pinode) {
    539 		get_now(&now);
    540 		EXT4_INODE_SET_XTIME(i_mtime, &now, pinode);
    541 		EXT4_INODE_SET_XTIME(i_ctime, &now, pinode);
    542 		increment_version(pinode);
    543 		return 0;
    544 	}
    545 
    546 	memset(&inode, 0, sizeof(inode));
    547 	err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
    548 				     sizeof(inode));
    549 	if (err)
    550 		return translate_error(fs, ino, err);
    551 
    552 	get_now(&now);
    553 	EXT4_INODE_SET_XTIME(i_mtime, &now, &inode);
    554 	EXT4_INODE_SET_XTIME(i_ctime, &now, &inode);
    555 	increment_version(&inode);
    556 
    557 	err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
    558 				      sizeof(inode));
    559 	if (err)
    560 		return translate_error(fs, ino, err);
    561 
    562 	return 0;
    563 }
    564 
    565 static int ext2_file_type(unsigned int mode)
    566 {
    567 	if (LINUX_S_ISREG(mode))
    568 		return EXT2_FT_REG_FILE;
    569 
    570 	if (LINUX_S_ISDIR(mode))
    571 		return EXT2_FT_DIR;
    572 
    573 	if (LINUX_S_ISCHR(mode))
    574 		return EXT2_FT_CHRDEV;
    575 
    576 	if (LINUX_S_ISBLK(mode))
    577 		return EXT2_FT_BLKDEV;
    578 
    579 	if (LINUX_S_ISLNK(mode))
    580 		return EXT2_FT_SYMLINK;
    581 
    582 	if (LINUX_S_ISFIFO(mode))
    583 		return EXT2_FT_FIFO;
    584 
    585 	if (LINUX_S_ISSOCK(mode))
    586 		return EXT2_FT_SOCK;
    587 
    588 	return 0;
    589 }
    590 
    591 static int fs_can_allocate(struct fuse2fs *ff, blk64_t num)
    592 {
    593 	ext2_filsys fs = ff->fs;
    594 	blk64_t reserved;
    595 
    596 	dbg_printf("%s: Asking for %llu; alloc_all=%d total=%llu free=%llu "
    597 		   "rsvd=%llu\n", __func__, num, ff->alloc_all_blocks,
    598 		   ext2fs_blocks_count(fs->super),
    599 		   ext2fs_free_blocks_count(fs->super),
    600 		   ext2fs_r_blocks_count(fs->super));
    601 	if (num > ext2fs_blocks_count(fs->super))
    602 		return 0;
    603 
    604 	if (ff->alloc_all_blocks)
    605 		return 1;
    606 
    607 	/*
    608 	 * Different meaning for r_blocks -- libext2fs has bugs where the FS
    609 	 * can get corrupted if it totally runs out of blocks.  Avoid this
    610 	 * by refusing to allocate any of the reserve blocks to anybody.
    611 	 */
    612 	reserved = ext2fs_r_blocks_count(fs->super);
    613 	if (reserved == 0)
    614 		reserved = ext2fs_blocks_count(fs->super) / 10;
    615 	return ext2fs_free_blocks_count(fs->super) > reserved + num;
    616 }
    617 
    618 static int fs_writeable(ext2_filsys fs)
    619 {
    620 	return (fs->flags & EXT2_FLAG_RW) && (fs->super->s_error_count == 0);
    621 }
    622 
    623 static int check_inum_access(ext2_filsys fs, ext2_ino_t ino, mode_t mask)
    624 {
    625 	struct fuse_context *ctxt = fuse_get_context();
    626 	struct ext2_inode inode;
    627 	mode_t perms;
    628 	errcode_t err;
    629 
    630 	/* no writing to read-only or broken fs */
    631 	if ((mask & W_OK) && !fs_writeable(fs))
    632 		return -EROFS;
    633 
    634 	err = ext2fs_read_inode(fs, ino, &inode);
    635 	if (err)
    636 		return translate_error(fs, ino, err);
    637 	perms = inode.i_mode & 0777;
    638 
    639 	dbg_printf("access ino=%d mask=e%s%s%s perms=0%o fuid=%d fgid=%d "
    640 		   "uid=%d gid=%d\n", ino,
    641 		   (mask & R_OK ? "r" : ""), (mask & W_OK ? "w" : ""),
    642 		   (mask & X_OK ? "x" : ""), perms, inode.i_uid, inode.i_gid,
    643 		   ctxt->uid, ctxt->gid);
    644 
    645 	/* existence check */
    646 	if (mask == 0)
    647 		return 0;
    648 
    649 	/* is immutable? */
    650 	if ((mask & W_OK) &&
    651 	    (inode.i_flags & EXT2_IMMUTABLE_FL))
    652 		return -EACCES;
    653 
    654 	/* Figure out what root's allowed to do */
    655 	if (ctxt->uid == 0) {
    656 		/* Non-file access always ok */
    657 		if (!LINUX_S_ISREG(inode.i_mode))
    658 			return 0;
    659 
    660 		/* R/W access to a file always ok */
    661 		if (!(mask & X_OK))
    662 			return 0;
    663 
    664 		/* X access to a file ok if a user/group/other can X */
    665 		if (perms & 0111)
    666 			return 0;
    667 
    668 		/* Trying to execute a file that's not executable. BZZT! */
    669 		return -EACCES;
    670 	}
    671 
    672 	/* allow owner, if perms match */
    673 	if (inode.i_uid == ctxt->uid) {
    674 		if ((mask & (perms >> 6)) == mask)
    675 			return 0;
    676 		return -EACCES;
    677 	}
    678 
    679 	/* allow group, if perms match */
    680 	if (inode.i_gid == ctxt->gid) {
    681 		if ((mask & (perms >> 3)) == mask)
    682 			return 0;
    683 		return -EACCES;
    684 	}
    685 
    686 	/* otherwise check other */
    687 	if ((mask & perms) == mask)
    688 		return 0;
    689 	return -EACCES;
    690 }
    691 
    692 static void op_destroy(void *p EXT2FS_ATTR((unused)))
    693 {
    694 	struct fuse_context *ctxt = fuse_get_context();
    695 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
    696 	ext2_filsys fs;
    697 	errcode_t err;
    698 
    699 	if (ff->magic != FUSE2FS_MAGIC) {
    700 		translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC);
    701 		return;
    702 	}
    703 	fs = ff->fs;
    704 	dbg_printf("%s: dev=%s\n", __func__, fs->device_name);
    705 	if (fs->flags & EXT2_FLAG_RW) {
    706 		fs->super->s_state |= EXT2_VALID_FS;
    707 		if (fs->super->s_error_count)
    708 			fs->super->s_state |= EXT2_ERROR_FS;
    709 		ext2fs_mark_super_dirty(fs);
    710 		err = ext2fs_set_gdt_csum(fs);
    711 		if (err)
    712 			translate_error(fs, 0, err);
    713 
    714 		err = ext2fs_flush2(fs, 0);
    715 		if (err)
    716 			translate_error(fs, 0, err);
    717 	}
    718 }
    719 
    720 static void *op_init(struct fuse_conn_info *conn)
    721 {
    722 	struct fuse_context *ctxt = fuse_get_context();
    723 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
    724 	ext2_filsys fs;
    725 	errcode_t err;
    726 
    727 	if (ff->magic != FUSE2FS_MAGIC) {
    728 		translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC);
    729 		return NULL;
    730 	}
    731 	fs = ff->fs;
    732 	dbg_printf("%s: dev=%s\n", __func__, fs->device_name);
    733 #ifdef FUSE_CAP_IOCTL_DIR
    734 	conn->want |= FUSE_CAP_IOCTL_DIR;
    735 #endif
    736 	if (fs->flags & EXT2_FLAG_RW) {
    737 		fs->super->s_mnt_count++;
    738 		fs->super->s_mtime = time(NULL);
    739 		fs->super->s_state &= ~EXT2_VALID_FS;
    740 		ext2fs_mark_super_dirty(fs);
    741 		err = ext2fs_flush2(fs, 0);
    742 		if (err)
    743 			translate_error(fs, 0, err);
    744 	}
    745 	return ff;
    746 }
    747 
    748 static blkcnt_t blocks_from_inode(ext2_filsys fs,
    749 				  struct ext2_inode_large *inode)
    750 {
    751 	blkcnt_t b;
    752 
    753 	b = inode->i_blocks;
    754 	if (ext2fs_has_feature_huge_file(fs->super))
    755 		b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
    756 
    757 	if (!ext2fs_has_feature_huge_file(fs->super) ||
    758 	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
    759 		b *= fs->blocksize / 512;
    760 	b *= EXT2FS_CLUSTER_RATIO(fs);
    761 
    762 	return b;
    763 }
    764 
    765 static int stat_inode(ext2_filsys fs, ext2_ino_t ino, struct stat *statbuf)
    766 {
    767 	struct ext2_inode_large inode;
    768 	dev_t fakedev = 0;
    769 	errcode_t err;
    770 	int ret = 0;
    771 	struct timespec tv;
    772 
    773 	memset(&inode, 0, sizeof(inode));
    774 	err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
    775 				     sizeof(inode));
    776 	if (err)
    777 		return translate_error(fs, ino, err);
    778 
    779 	memcpy(&fakedev, fs->super->s_uuid, sizeof(fakedev));
    780 	statbuf->st_dev = fakedev;
    781 	statbuf->st_ino = ino;
    782 	statbuf->st_mode = inode.i_mode;
    783 	statbuf->st_nlink = inode.i_links_count;
    784 	statbuf->st_uid = inode.i_uid;
    785 	statbuf->st_gid = inode.i_gid;
    786 	statbuf->st_size = EXT2_I_SIZE(&inode);
    787 	statbuf->st_blksize = fs->blocksize;
    788 	statbuf->st_blocks = blocks_from_inode(fs, &inode);
    789 	EXT4_INODE_GET_XTIME(i_atime, &tv, &inode);
    790 	statbuf->st_atime = tv.tv_sec;
    791 	EXT4_INODE_GET_XTIME(i_mtime, &tv, &inode);
    792 	statbuf->st_mtime = tv.tv_sec;
    793 	EXT4_INODE_GET_XTIME(i_ctime, &tv, &inode);
    794 	statbuf->st_ctime = tv.tv_sec;
    795 	if (LINUX_S_ISCHR(inode.i_mode) ||
    796 	    LINUX_S_ISBLK(inode.i_mode)) {
    797 		if (inode.i_block[0])
    798 			statbuf->st_rdev = inode.i_block[0];
    799 		else
    800 			statbuf->st_rdev = inode.i_block[1];
    801 	}
    802 
    803 	return ret;
    804 }
    805 
    806 static int op_getattr(const char *path, struct stat *statbuf)
    807 {
    808 	struct fuse_context *ctxt = fuse_get_context();
    809 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
    810 	ext2_filsys fs;
    811 	ext2_ino_t ino;
    812 	errcode_t err;
    813 	int ret = 0;
    814 
    815 	FUSE2FS_CHECK_CONTEXT(ff);
    816 	fs = ff->fs;
    817 	dbg_printf("%s: path=%s\n", __func__, path);
    818 	pthread_mutex_lock(&ff->bfl);
    819 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
    820 	if (err) {
    821 		ret = translate_error(fs, 0, err);
    822 		goto out;
    823 	}
    824 	ret = stat_inode(fs, ino, statbuf);
    825 out:
    826 	pthread_mutex_unlock(&ff->bfl);
    827 	return ret;
    828 }
    829 
    830 static int op_readlink(const char *path, char *buf, size_t len)
    831 {
    832 	struct fuse_context *ctxt = fuse_get_context();
    833 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
    834 	ext2_filsys fs;
    835 	errcode_t err;
    836 	ext2_ino_t ino;
    837 	struct ext2_inode inode;
    838 	unsigned int got;
    839 	ext2_file_t file;
    840 	int ret = 0;
    841 
    842 	FUSE2FS_CHECK_CONTEXT(ff);
    843 	fs = ff->fs;
    844 	dbg_printf("%s: path=%s\n", __func__, path);
    845 	pthread_mutex_lock(&ff->bfl);
    846 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
    847 	if (err || ino == 0) {
    848 		ret = translate_error(fs, 0, err);
    849 		goto out;
    850 	}
    851 
    852 	err = ext2fs_read_inode(fs, ino, &inode);
    853 	if (err) {
    854 		ret = translate_error(fs, ino, err);
    855 		goto out;
    856 	}
    857 
    858 	if (!LINUX_S_ISLNK(inode.i_mode)) {
    859 		ret = -EINVAL;
    860 		goto out;
    861 	}
    862 
    863 	len--;
    864 	if (inode.i_size < len)
    865 		len = inode.i_size;
    866 	if (ext2fs_inode_data_blocks2(fs, &inode) ||
    867 	    (inode.i_flags & EXT4_INLINE_DATA_FL)) {
    868 		/* big/inline symlink */
    869 
    870 		err = ext2fs_file_open(fs, ino, 0, &file);
    871 		if (err) {
    872 			ret = translate_error(fs, ino, err);
    873 			goto out;
    874 		}
    875 
    876 		err = ext2fs_file_read(file, buf, len, &got);
    877 		if (err || got != len) {
    878 			ext2fs_file_close(file);
    879 			ret = translate_error(fs, ino, err);
    880 			goto out2;
    881 		}
    882 
    883 out2:
    884 		err = ext2fs_file_close(file);
    885 		if (ret)
    886 			goto out;
    887 		if (err) {
    888 			ret = translate_error(fs, ino, err);
    889 			goto out;
    890 		}
    891 	} else
    892 		/* inline symlink */
    893 		memcpy(buf, (char *)inode.i_block, len);
    894 	buf[len] = 0;
    895 
    896 	if (fs_writeable(fs)) {
    897 		ret = update_atime(fs, ino);
    898 		if (ret)
    899 			goto out;
    900 	}
    901 
    902 out:
    903 	pthread_mutex_unlock(&ff->bfl);
    904 	return ret;
    905 }
    906 
    907 static int op_mknod(const char *path, mode_t mode, dev_t dev)
    908 {
    909 	struct fuse_context *ctxt = fuse_get_context();
    910 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
    911 	ext2_filsys fs;
    912 	ext2_ino_t parent, child;
    913 	char *temp_path = strdup(path);
    914 	errcode_t err;
    915 	char *node_name, a;
    916 	int filetype;
    917 	struct ext2_inode_large inode;
    918 	int ret = 0;
    919 
    920 	FUSE2FS_CHECK_CONTEXT(ff);
    921 	fs = ff->fs;
    922 	dbg_printf("%s: path=%s mode=0%o dev=0x%x\n", __func__, path, mode,
    923 		   (unsigned int)dev);
    924 	if (!temp_path) {
    925 		ret = -ENOMEM;
    926 		goto out;
    927 	}
    928 	node_name = strrchr(temp_path, '/');
    929 	if (!node_name) {
    930 		ret = -ENOMEM;
    931 		goto out;
    932 	}
    933 	node_name++;
    934 	a = *node_name;
    935 	*node_name = 0;
    936 
    937 	pthread_mutex_lock(&ff->bfl);
    938 	if (!fs_can_allocate(ff, 2)) {
    939 		ret = -ENOSPC;
    940 		goto out2;
    941 	}
    942 
    943 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
    944 			   &parent);
    945 	if (err) {
    946 		ret = translate_error(fs, 0, err);
    947 		goto out2;
    948 	}
    949 
    950 	ret = check_inum_access(fs, parent, W_OK);
    951 	if (ret)
    952 		goto out2;
    953 
    954 	*node_name = a;
    955 
    956 	if (LINUX_S_ISCHR(mode))
    957 		filetype = EXT2_FT_CHRDEV;
    958 	else if (LINUX_S_ISBLK(mode))
    959 		filetype = EXT2_FT_BLKDEV;
    960 	else if (LINUX_S_ISFIFO(mode))
    961 		filetype = EXT2_FT_FIFO;
    962 	else if (LINUX_S_ISSOCK(mode))
    963 		filetype = EXT2_FT_SOCK;
    964 	else {
    965 		ret = -EINVAL;
    966 		goto out2;
    967 	}
    968 
    969 	err = ext2fs_new_inode(fs, parent, mode, 0, &child);
    970 	if (err) {
    971 		ret = translate_error(fs, 0, err);
    972 		goto out2;
    973 	}
    974 
    975 	dbg_printf("%s: create ino=%d/name=%s in dir=%d\n", __func__, child,
    976 		   node_name, parent);
    977 	err = ext2fs_link(fs, parent, node_name, child, filetype);
    978 	if (err == EXT2_ET_DIR_NO_SPACE) {
    979 		err = ext2fs_expand_dir(fs, parent);
    980 		if (err) {
    981 			ret = translate_error(fs, parent, err);
    982 			goto out2;
    983 		}
    984 
    985 		err = ext2fs_link(fs, parent, node_name, child,
    986 				     filetype);
    987 	}
    988 	if (err) {
    989 		ret = translate_error(fs, parent, err);
    990 		goto out2;
    991 	}
    992 
    993 	ret = update_mtime(fs, parent, NULL);
    994 	if (ret)
    995 		goto out2;
    996 
    997 	memset(&inode, 0, sizeof(inode));
    998 	inode.i_mode = mode;
    999 
   1000 	if (dev & ~0xFFFF)
   1001 		inode.i_block[1] = dev;
   1002 	else
   1003 		inode.i_block[0] = dev;
   1004 	inode.i_links_count = 1;
   1005 	inode.i_extra_isize = sizeof(struct ext2_inode_large) -
   1006 		EXT2_GOOD_OLD_INODE_SIZE;
   1007 	inode.i_uid = ctxt->uid;
   1008 	inode.i_gid = ctxt->gid;
   1009 
   1010 	err = ext2fs_write_new_inode(fs, child, (struct ext2_inode *)&inode);
   1011 	if (err) {
   1012 		ret = translate_error(fs, child, err);
   1013 		goto out2;
   1014 	}
   1015 
   1016 	inode.i_generation = ff->next_generation++;
   1017 	init_times(&inode);
   1018 	err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
   1019 				      sizeof(inode));
   1020 	if (err) {
   1021 		ret = translate_error(fs, child, err);
   1022 		goto out2;
   1023 	}
   1024 
   1025 	ext2fs_inode_alloc_stats2(fs, child, 1, 0);
   1026 
   1027 out2:
   1028 	pthread_mutex_unlock(&ff->bfl);
   1029 out:
   1030 	free(temp_path);
   1031 	return ret;
   1032 }
   1033 
   1034 static int op_mkdir(const char *path, mode_t mode)
   1035 {
   1036 	struct fuse_context *ctxt = fuse_get_context();
   1037 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   1038 	ext2_filsys fs;
   1039 	ext2_ino_t parent, child;
   1040 	char *temp_path = strdup(path);
   1041 	errcode_t err;
   1042 	char *node_name, a;
   1043 	struct ext2_inode_large inode;
   1044 	char *block;
   1045 	blk64_t blk;
   1046 	int ret = 0;
   1047 	mode_t parent_sgid;
   1048 
   1049 	FUSE2FS_CHECK_CONTEXT(ff);
   1050 	fs = ff->fs;
   1051 	dbg_printf("%s: path=%s mode=0%o\n", __func__, path, mode);
   1052 	if (!temp_path) {
   1053 		ret = -ENOMEM;
   1054 		goto out;
   1055 	}
   1056 	node_name = strrchr(temp_path, '/');
   1057 	if (!node_name) {
   1058 		ret = -ENOMEM;
   1059 		goto out;
   1060 	}
   1061 	node_name++;
   1062 	a = *node_name;
   1063 	*node_name = 0;
   1064 
   1065 	pthread_mutex_lock(&ff->bfl);
   1066 	if (!fs_can_allocate(ff, 1)) {
   1067 		ret = -ENOSPC;
   1068 		goto out2;
   1069 	}
   1070 
   1071 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
   1072 			   &parent);
   1073 	if (err) {
   1074 		ret = translate_error(fs, 0, err);
   1075 		goto out2;
   1076 	}
   1077 
   1078 	ret = check_inum_access(fs, parent, W_OK);
   1079 	if (ret)
   1080 		goto out2;
   1081 
   1082 	/* Is the parent dir sgid? */
   1083 	err = ext2fs_read_inode_full(fs, parent, (struct ext2_inode *)&inode,
   1084 				     sizeof(inode));
   1085 	if (err) {
   1086 		ret = translate_error(fs, parent, err);
   1087 		goto out2;
   1088 	}
   1089 	parent_sgid = inode.i_mode & S_ISGID;
   1090 
   1091 	*node_name = a;
   1092 
   1093 	err = ext2fs_mkdir(fs, parent, 0, node_name);
   1094 	if (err == EXT2_ET_DIR_NO_SPACE) {
   1095 		err = ext2fs_expand_dir(fs, parent);
   1096 		if (err) {
   1097 			ret = translate_error(fs, parent, err);
   1098 			goto out2;
   1099 		}
   1100 
   1101 		err = ext2fs_mkdir(fs, parent, 0, node_name);
   1102 	}
   1103 	if (err) {
   1104 		ret = translate_error(fs, parent, err);
   1105 		goto out2;
   1106 	}
   1107 
   1108 	ret = update_mtime(fs, parent, NULL);
   1109 	if (ret)
   1110 		goto out2;
   1111 
   1112 	/* Still have to update the uid/gid of the dir */
   1113 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
   1114 			   &child);
   1115 	if (err) {
   1116 		ret = translate_error(fs, 0, err);
   1117 		goto out2;
   1118 	}
   1119 	dbg_printf("%s: created ino=%d/path=%s in dir=%d\n", __func__, child,
   1120 		   node_name, parent);
   1121 
   1122 	memset(&inode, 0, sizeof(inode));
   1123 	err = ext2fs_read_inode_full(fs, child, (struct ext2_inode *)&inode,
   1124 				     sizeof(inode));
   1125 	if (err) {
   1126 		ret = translate_error(fs, child, err);
   1127 		goto out2;
   1128 	}
   1129 
   1130 	inode.i_uid = ctxt->uid;
   1131 	inode.i_gid = ctxt->gid;
   1132 	inode.i_mode = LINUX_S_IFDIR | (mode & ~(S_ISUID | fs->umask)) |
   1133 		       parent_sgid;
   1134 	inode.i_generation = ff->next_generation++;
   1135 
   1136 	err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
   1137 				      sizeof(inode));
   1138 	if (err) {
   1139 		ret = translate_error(fs, child, err);
   1140 		goto out2;
   1141 	}
   1142 
   1143 	/* Rewrite the directory block checksum, having set i_generation */
   1144 	if ((inode.i_flags & EXT4_INLINE_DATA_FL) ||
   1145 	    !ext2fs_has_feature_metadata_csum(fs->super))
   1146 		goto out2;
   1147 	err = ext2fs_new_dir_block(fs, child, parent, &block);
   1148 	if (err) {
   1149 		ret = translate_error(fs, child, err);
   1150 		goto out2;
   1151 	}
   1152 	err = ext2fs_bmap2(fs, child, (struct ext2_inode *)&inode, NULL, 0, 0,
   1153 			   NULL, &blk);
   1154 	if (err) {
   1155 		ret = translate_error(fs, child, err);
   1156 		goto out3;
   1157 	}
   1158 	err = ext2fs_write_dir_block4(fs, blk, block, 0, child);
   1159 	if (err) {
   1160 		ret = translate_error(fs, child, err);
   1161 		goto out3;
   1162 	}
   1163 
   1164 out3:
   1165 	ext2fs_free_mem(&block);
   1166 out2:
   1167 	pthread_mutex_unlock(&ff->bfl);
   1168 out:
   1169 	free(temp_path);
   1170 	return ret;
   1171 }
   1172 
   1173 static int unlink_file_by_name(ext2_filsys fs, const char *path)
   1174 {
   1175 	errcode_t err;
   1176 	ext2_ino_t dir;
   1177 	char *filename = strdup(path);
   1178 	char *base_name;
   1179 	int ret;
   1180 
   1181 	base_name = strrchr(filename, '/');
   1182 	if (base_name) {
   1183 		*base_name++ = '\0';
   1184 		err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, filename,
   1185 				   &dir);
   1186 		if (err) {
   1187 			free(filename);
   1188 			return translate_error(fs, 0, err);
   1189 		}
   1190 	} else {
   1191 		dir = EXT2_ROOT_INO;
   1192 		base_name = filename;
   1193 	}
   1194 
   1195 	ret = check_inum_access(fs, dir, W_OK);
   1196 	if (ret) {
   1197 		free(filename);
   1198 		return ret;
   1199 	}
   1200 
   1201 	dbg_printf("%s: unlinking name=%s from dir=%d\n", __func__,
   1202 		   base_name, dir);
   1203 	err = ext2fs_unlink(fs, dir, base_name, 0, 0);
   1204 	free(filename);
   1205 	if (err)
   1206 		return translate_error(fs, dir, err);
   1207 
   1208 	return update_mtime(fs, dir, NULL);
   1209 }
   1210 
   1211 static int remove_inode(struct fuse2fs *ff, ext2_ino_t ino)
   1212 {
   1213 	ext2_filsys fs = ff->fs;
   1214 	errcode_t err;
   1215 	struct ext2_inode_large inode;
   1216 	int ret = 0;
   1217 
   1218 	memset(&inode, 0, sizeof(inode));
   1219 	err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
   1220 				     sizeof(inode));
   1221 	if (err) {
   1222 		ret = translate_error(fs, ino, err);
   1223 		goto out;
   1224 	}
   1225 	dbg_printf("%s: put ino=%d links=%d\n", __func__, ino,
   1226 		   inode.i_links_count);
   1227 
   1228 	switch (inode.i_links_count) {
   1229 	case 0:
   1230 		return 0; /* XXX: already done? */
   1231 	case 1:
   1232 		inode.i_links_count--;
   1233 		inode.i_dtime = fs->now ? fs->now : time(0);
   1234 		break;
   1235 	default:
   1236 		inode.i_links_count--;
   1237 	}
   1238 
   1239 	ret = update_ctime(fs, ino, &inode);
   1240 	if (ret)
   1241 		goto out;
   1242 
   1243 	if (inode.i_links_count)
   1244 		goto write_out;
   1245 
   1246 	/* Nobody holds this file; free its blocks! */
   1247 	err = ext2fs_free_ext_attr(fs, ino, &inode);
   1248 	if (err)
   1249 		goto write_out;
   1250 
   1251 	if (ext2fs_inode_has_valid_blocks2(fs, (struct ext2_inode *)&inode)) {
   1252 		err = ext2fs_punch(fs, ino, (struct ext2_inode *)&inode, NULL,
   1253 				   0, ~0ULL);
   1254 		if (err) {
   1255 			ret = translate_error(fs, ino, err);
   1256 			goto write_out;
   1257 		}
   1258 	}
   1259 
   1260 	ext2fs_inode_alloc_stats2(fs, ino, -1,
   1261 				  LINUX_S_ISDIR(inode.i_mode));
   1262 
   1263 write_out:
   1264 	err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
   1265 				      sizeof(inode));
   1266 	if (err) {
   1267 		ret = translate_error(fs, ino, err);
   1268 		goto out;
   1269 	}
   1270 out:
   1271 	return ret;
   1272 }
   1273 
   1274 static int __op_unlink(struct fuse2fs *ff, const char *path)
   1275 {
   1276 	ext2_filsys fs = ff->fs;
   1277 	ext2_ino_t ino;
   1278 	errcode_t err;
   1279 	int ret = 0;
   1280 
   1281 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
   1282 	if (err) {
   1283 		ret = translate_error(fs, 0, err);
   1284 		goto out;
   1285 	}
   1286 
   1287 	ret = unlink_file_by_name(fs, path);
   1288 	if (ret)
   1289 		goto out;
   1290 
   1291 	ret = remove_inode(ff, ino);
   1292 	if (ret)
   1293 		goto out;
   1294 out:
   1295 	return ret;
   1296 }
   1297 
   1298 static int op_unlink(const char *path)
   1299 {
   1300 	struct fuse_context *ctxt = fuse_get_context();
   1301 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   1302 	int ret;
   1303 
   1304 	FUSE2FS_CHECK_CONTEXT(ff);
   1305 	pthread_mutex_lock(&ff->bfl);
   1306 	ret = __op_unlink(ff, path);
   1307 	pthread_mutex_unlock(&ff->bfl);
   1308 	return ret;
   1309 }
   1310 
   1311 struct rd_struct {
   1312 	ext2_ino_t	parent;
   1313 	int		empty;
   1314 };
   1315 
   1316 static int rmdir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
   1317 		      int	entry EXT2FS_ATTR((unused)),
   1318 		      struct ext2_dir_entry *dirent,
   1319 		      int	offset EXT2FS_ATTR((unused)),
   1320 		      int	blocksize EXT2FS_ATTR((unused)),
   1321 		      char	*buf EXT2FS_ATTR((unused)),
   1322 		      void	*private)
   1323 {
   1324 	struct rd_struct *rds = (struct rd_struct *) private;
   1325 
   1326 	if (dirent->inode == 0)
   1327 		return 0;
   1328 	if (((dirent->name_len & 0xFF) == 1) && (dirent->name[0] == '.'))
   1329 		return 0;
   1330 	if (((dirent->name_len & 0xFF) == 2) && (dirent->name[0] == '.') &&
   1331 	    (dirent->name[1] == '.')) {
   1332 		rds->parent = dirent->inode;
   1333 		return 0;
   1334 	}
   1335 	rds->empty = 0;
   1336 	return 0;
   1337 }
   1338 
   1339 static int __op_rmdir(struct fuse2fs *ff, const char *path)
   1340 {
   1341 	ext2_filsys fs = ff->fs;
   1342 	ext2_ino_t child;
   1343 	errcode_t err;
   1344 	struct ext2_inode_large inode;
   1345 	struct rd_struct rds;
   1346 	int ret = 0;
   1347 
   1348 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &child);
   1349 	if (err) {
   1350 		ret = translate_error(fs, 0, err);
   1351 		goto out;
   1352 	}
   1353 	dbg_printf("%s: rmdir path=%s ino=%d\n", __func__, path, child);
   1354 
   1355 	rds.parent = 0;
   1356 	rds.empty = 1;
   1357 
   1358 	err = ext2fs_dir_iterate2(fs, child, 0, 0, rmdir_proc, &rds);
   1359 	if (err) {
   1360 		ret = translate_error(fs, child, err);
   1361 		goto out;
   1362 	}
   1363 
   1364 	if (rds.empty == 0) {
   1365 		ret = -ENOTEMPTY;
   1366 		goto out;
   1367 	}
   1368 
   1369 	ret = unlink_file_by_name(fs, path);
   1370 	if (ret)
   1371 		goto out;
   1372 	/* Directories have to be "removed" twice. */
   1373 	ret = remove_inode(ff, child);
   1374 	if (ret)
   1375 		goto out;
   1376 	ret = remove_inode(ff, child);
   1377 	if (ret)
   1378 		goto out;
   1379 
   1380 	if (rds.parent) {
   1381 		dbg_printf("%s: decr dir=%d link count\n", __func__,
   1382 			   rds.parent);
   1383 		err = ext2fs_read_inode_full(fs, rds.parent,
   1384 					     (struct ext2_inode *)&inode,
   1385 					     sizeof(inode));
   1386 		if (err) {
   1387 			ret = translate_error(fs, rds.parent, err);
   1388 			goto out;
   1389 		}
   1390 		if (inode.i_links_count > 1)
   1391 			inode.i_links_count--;
   1392 		ret = update_mtime(fs, rds.parent, &inode);
   1393 		if (ret)
   1394 			goto out;
   1395 		err = ext2fs_write_inode_full(fs, rds.parent,
   1396 					      (struct ext2_inode *)&inode,
   1397 					      sizeof(inode));
   1398 		if (err) {
   1399 			ret = translate_error(fs, rds.parent, err);
   1400 			goto out;
   1401 		}
   1402 	}
   1403 
   1404 out:
   1405 	return ret;
   1406 }
   1407 
   1408 static int op_rmdir(const char *path)
   1409 {
   1410 	struct fuse_context *ctxt = fuse_get_context();
   1411 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   1412 	int ret;
   1413 
   1414 	FUSE2FS_CHECK_CONTEXT(ff);
   1415 	pthread_mutex_lock(&ff->bfl);
   1416 	ret = __op_rmdir(ff, path);
   1417 	pthread_mutex_unlock(&ff->bfl);
   1418 	return ret;
   1419 }
   1420 
   1421 static int op_symlink(const char *src, const char *dest)
   1422 {
   1423 	struct fuse_context *ctxt = fuse_get_context();
   1424 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   1425 	ext2_filsys fs;
   1426 	ext2_ino_t parent, child;
   1427 	char *temp_path = strdup(dest);
   1428 	errcode_t err;
   1429 	char *node_name, a;
   1430 	struct ext2_inode_large inode;
   1431 	int ret = 0;
   1432 
   1433 	FUSE2FS_CHECK_CONTEXT(ff);
   1434 	fs = ff->fs;
   1435 	dbg_printf("%s: symlink %s to %s\n", __func__, src, dest);
   1436 	if (!temp_path) {
   1437 		ret = -ENOMEM;
   1438 		goto out;
   1439 	}
   1440 	node_name = strrchr(temp_path, '/');
   1441 	if (!node_name) {
   1442 		ret = -ENOMEM;
   1443 		goto out;
   1444 	}
   1445 	node_name++;
   1446 	a = *node_name;
   1447 	*node_name = 0;
   1448 
   1449 	pthread_mutex_lock(&ff->bfl);
   1450 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
   1451 			   &parent);
   1452 	*node_name = a;
   1453 	if (err) {
   1454 		ret = translate_error(fs, 0, err);
   1455 		goto out2;
   1456 	}
   1457 
   1458 	ret = check_inum_access(fs, parent, W_OK);
   1459 	if (ret)
   1460 		goto out2;
   1461 
   1462 
   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);
   1467 		if (err) {
   1468 			ret = translate_error(fs, parent, err);
   1469 			goto out2;
   1470 		}
   1471 
   1472 		err = ext2fs_symlink(fs, parent, 0, node_name, src);
   1473 	}
   1474 	if (err) {
   1475 		ret = translate_error(fs, parent, err);
   1476 		goto out2;
   1477 	}
   1478 
   1479 	/* Update parent dir's mtime */
   1480 	ret = update_mtime(fs, parent, NULL);
   1481 	if (ret)
   1482 		goto out2;
   1483 
   1484 	/* Still have to update the uid/gid of the symlink */
   1485 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
   1486 			   &child);
   1487 	if (err) {
   1488 		ret = translate_error(fs, 0, err);
   1489 		goto out2;
   1490 	}
   1491 	dbg_printf("%s: symlinking ino=%d/name=%s to dir=%d\n", __func__,
   1492 		   child, node_name, parent);
   1493 
   1494 	memset(&inode, 0, sizeof(inode));
   1495 	err = ext2fs_read_inode_full(fs, child, (struct ext2_inode *)&inode,
   1496 				     sizeof(inode));
   1497 	if (err) {
   1498 		ret = translate_error(fs, child, err);
   1499 		goto out2;
   1500 	}
   1501 
   1502 	inode.i_uid = ctxt->uid;
   1503 	inode.i_gid = ctxt->gid;
   1504 	inode.i_generation = ff->next_generation++;
   1505 
   1506 	err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
   1507 				      sizeof(inode));
   1508 	if (err) {
   1509 		ret = translate_error(fs, child, err);
   1510 		goto out2;
   1511 	}
   1512 out2:
   1513 	pthread_mutex_unlock(&ff->bfl);
   1514 out:
   1515 	free(temp_path);
   1516 	return ret;
   1517 }
   1518 
   1519 struct update_dotdot {
   1520 	ext2_ino_t new_dotdot;
   1521 };
   1522 
   1523 static int update_dotdot_helper(ext2_ino_t dir EXT2FS_ATTR((unused)),
   1524 				int entry EXT2FS_ATTR((unused)),
   1525 				struct ext2_dir_entry *dirent,
   1526 				int offset EXT2FS_ATTR((unused)),
   1527 				int blocksize EXT2FS_ATTR((unused)),
   1528 				char *buf EXT2FS_ATTR((unused)),
   1529 				void *priv_data)
   1530 {
   1531 	struct update_dotdot *ud = priv_data;
   1532 
   1533 	if (ext2fs_dirent_name_len(dirent) == 2 &&
   1534 	    dirent->name[0] == '.' && dirent->name[1] == '.') {
   1535 		dirent->inode = ud->new_dotdot;
   1536 		return DIRENT_CHANGED | DIRENT_ABORT;
   1537 	}
   1538 
   1539 	return 0;
   1540 }
   1541 
   1542 static int op_rename(const char *from, const char *to)
   1543 {
   1544 	struct fuse_context *ctxt = fuse_get_context();
   1545 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   1546 	ext2_filsys fs;
   1547 	errcode_t err;
   1548 	ext2_ino_t from_ino, to_ino, to_dir_ino, from_dir_ino;
   1549 	char *temp_to = NULL, *temp_from = NULL;
   1550 	char *cp, a;
   1551 	struct ext2_inode inode;
   1552 	struct update_dotdot ud;
   1553 	int ret = 0;
   1554 
   1555 	FUSE2FS_CHECK_CONTEXT(ff);
   1556 	fs = ff->fs;
   1557 	dbg_printf("%s: renaming %s to %s\n", __func__, from, to);
   1558 	pthread_mutex_lock(&ff->bfl);
   1559 	if (!fs_can_allocate(ff, 5)) {
   1560 		ret = -ENOSPC;
   1561 		goto out;
   1562 	}
   1563 
   1564 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, from, &from_ino);
   1565 	if (err || from_ino == 0) {
   1566 		ret = translate_error(fs, 0, err);
   1567 		goto out;
   1568 	}
   1569 
   1570 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, to, &to_ino);
   1571 	if (err && err != EXT2_ET_FILE_NOT_FOUND) {
   1572 		ret = translate_error(fs, 0, err);
   1573 		goto out;
   1574 	}
   1575 
   1576 	if (err == EXT2_ET_FILE_NOT_FOUND)
   1577 		to_ino = 0;
   1578 
   1579 	/* Already the same file? */
   1580 	if (to_ino != 0 && to_ino == from_ino) {
   1581 		ret = 0;
   1582 		goto out;
   1583 	}
   1584 
   1585 	temp_to = strdup(to);
   1586 	if (!temp_to) {
   1587 		ret = -ENOMEM;
   1588 		goto out;
   1589 	}
   1590 
   1591 	temp_from = strdup(from);
   1592 	if (!temp_from) {
   1593 		ret = -ENOMEM;
   1594 		goto out2;
   1595 	}
   1596 
   1597 	/* Find parent dir of the source and check write access */
   1598 	cp = strrchr(temp_from, '/');
   1599 	if (!cp) {
   1600 		ret = -EINVAL;
   1601 		goto out2;
   1602 	}
   1603 
   1604 	a = *(cp + 1);
   1605 	*(cp + 1) = 0;
   1606 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_from,
   1607 			   &from_dir_ino);
   1608 	*(cp + 1) = a;
   1609 	if (err) {
   1610 		ret = translate_error(fs, 0, err);
   1611 		goto out2;
   1612 	}
   1613 	if (from_dir_ino == 0) {
   1614 		ret = -ENOENT;
   1615 		goto out2;
   1616 	}
   1617 
   1618 	ret = check_inum_access(fs, from_dir_ino, W_OK);
   1619 	if (ret)
   1620 		goto out2;
   1621 
   1622 	/* Find parent dir of the destination and check write access */
   1623 	cp = strrchr(temp_to, '/');
   1624 	if (!cp) {
   1625 		ret = -EINVAL;
   1626 		goto out2;
   1627 	}
   1628 
   1629 	a = *(cp + 1);
   1630 	*(cp + 1) = 0;
   1631 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_to,
   1632 			   &to_dir_ino);
   1633 	*(cp + 1) = a;
   1634 	if (err) {
   1635 		ret = translate_error(fs, 0, err);
   1636 		goto out2;
   1637 	}
   1638 	if (to_dir_ino == 0) {
   1639 		ret = -ENOENT;
   1640 		goto out2;
   1641 	}
   1642 
   1643 	ret = check_inum_access(fs, to_dir_ino, W_OK);
   1644 	if (ret)
   1645 		goto out2;
   1646 
   1647 	/* If the target exists, unlink it first */
   1648 	if (to_ino != 0) {
   1649 		err = ext2fs_read_inode(fs, to_ino, &inode);
   1650 		if (err) {
   1651 			ret = translate_error(fs, to_ino, err);
   1652 			goto out2;
   1653 		}
   1654 
   1655 		dbg_printf("%s: unlinking %s ino=%d\n", __func__,
   1656 			   LINUX_S_ISDIR(inode.i_mode) ? "dir" : "file",
   1657 			   to_ino);
   1658 		if (LINUX_S_ISDIR(inode.i_mode))
   1659 			ret = __op_rmdir(ff, to);
   1660 		else
   1661 			ret = __op_unlink(ff, to);
   1662 		if (ret)
   1663 			goto out2;
   1664 	}
   1665 
   1666 	/* Get ready to do the move */
   1667 	err = ext2fs_read_inode(fs, from_ino, &inode);
   1668 	if (err) {
   1669 		ret = translate_error(fs, from_ino, err);
   1670 		goto out2;
   1671 	}
   1672 
   1673 	/* Link in the new file */
   1674 	dbg_printf("%s: linking ino=%d/path=%s to dir=%d\n", __func__,
   1675 		   from_ino, cp + 1, to_dir_ino);
   1676 	err = ext2fs_link(fs, to_dir_ino, cp + 1, from_ino,
   1677 			  ext2_file_type(inode.i_mode));
   1678 	if (err == EXT2_ET_DIR_NO_SPACE) {
   1679 		err = ext2fs_expand_dir(fs, to_dir_ino);
   1680 		if (err) {
   1681 			ret = translate_error(fs, to_dir_ino, err);
   1682 			goto out2;
   1683 		}
   1684 
   1685 		err = ext2fs_link(fs, to_dir_ino, cp + 1, from_ino,
   1686 				     ext2_file_type(inode.i_mode));
   1687 	}
   1688 	if (err) {
   1689 		ret = translate_error(fs, to_dir_ino, err);
   1690 		goto out2;
   1691 	}
   1692 
   1693 	/* Update '..' pointer if dir */
   1694 	err = ext2fs_read_inode(fs, from_ino, &inode);
   1695 	if (err) {
   1696 		ret = translate_error(fs, from_ino, err);
   1697 		goto out2;
   1698 	}
   1699 
   1700 	if (LINUX_S_ISDIR(inode.i_mode)) {
   1701 		ud.new_dotdot = to_dir_ino;
   1702 		dbg_printf("%s: updating .. entry for dir=%d\n", __func__,
   1703 			   to_dir_ino);
   1704 		err = ext2fs_dir_iterate2(fs, from_ino, 0, NULL,
   1705 					  update_dotdot_helper, &ud);
   1706 		if (err) {
   1707 			ret = translate_error(fs, from_ino, err);
   1708 			goto out2;
   1709 		}
   1710 
   1711 		/* Decrease from_dir_ino's links_count */
   1712 		dbg_printf("%s: moving linkcount from dir=%d to dir=%d\n",
   1713 			   __func__, from_dir_ino, to_dir_ino);
   1714 		err = ext2fs_read_inode(fs, from_dir_ino, &inode);
   1715 		if (err) {
   1716 			ret = translate_error(fs, from_dir_ino, err);
   1717 			goto out2;
   1718 		}
   1719 		inode.i_links_count--;
   1720 		err = ext2fs_write_inode(fs, from_dir_ino, &inode);
   1721 		if (err) {
   1722 			ret = translate_error(fs, from_dir_ino, err);
   1723 			goto out2;
   1724 		}
   1725 
   1726 		/* Increase to_dir_ino's links_count */
   1727 		err = ext2fs_read_inode(fs, to_dir_ino, &inode);
   1728 		if (err) {
   1729 			ret = translate_error(fs, to_dir_ino, err);
   1730 			goto out2;
   1731 		}
   1732 		inode.i_links_count++;
   1733 		err = ext2fs_write_inode(fs, to_dir_ino, &inode);
   1734 		if (err) {
   1735 			ret = translate_error(fs, to_dir_ino, err);
   1736 			goto out2;
   1737 		}
   1738 	}
   1739 
   1740 	/* Update timestamps */
   1741 	ret = update_ctime(fs, from_ino, NULL);
   1742 	if (ret)
   1743 		goto out2;
   1744 
   1745 	ret = update_mtime(fs, to_dir_ino, NULL);
   1746 	if (ret)
   1747 		goto out2;
   1748 
   1749 	/* Remove the old file */
   1750 	ret = unlink_file_by_name(fs, from);
   1751 	if (ret)
   1752 		goto out2;
   1753 
   1754 	/* Flush the whole mess out */
   1755 	err = ext2fs_flush2(fs, 0);
   1756 	if (err)
   1757 		ret = translate_error(fs, 0, err);
   1758 
   1759 out2:
   1760 	free(temp_from);
   1761 	free(temp_to);
   1762 out:
   1763 	pthread_mutex_unlock(&ff->bfl);
   1764 	return ret;
   1765 }
   1766 
   1767 static int op_link(const char *src, const char *dest)
   1768 {
   1769 	struct fuse_context *ctxt = fuse_get_context();
   1770 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   1771 	ext2_filsys fs;
   1772 	char *temp_path = strdup(dest);
   1773 	errcode_t err;
   1774 	char *node_name, a;
   1775 	ext2_ino_t parent, ino;
   1776 	struct ext2_inode_large inode;
   1777 	int ret = 0;
   1778 
   1779 	FUSE2FS_CHECK_CONTEXT(ff);
   1780 	fs = ff->fs;
   1781 	dbg_printf("%s: src=%s dest=%s\n", __func__, src, dest);
   1782 	if (!temp_path) {
   1783 		ret = -ENOMEM;
   1784 		goto out;
   1785 	}
   1786 	node_name = strrchr(temp_path, '/');
   1787 	if (!node_name) {
   1788 		ret = -ENOMEM;
   1789 		goto out;
   1790 	}
   1791 	node_name++;
   1792 	a = *node_name;
   1793 	*node_name = 0;
   1794 
   1795 	pthread_mutex_lock(&ff->bfl);
   1796 	if (!fs_can_allocate(ff, 2)) {
   1797 		ret = -ENOSPC;
   1798 		goto out2;
   1799 	}
   1800 
   1801 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
   1802 			   &parent);
   1803 	*node_name = a;
   1804 	if (err) {
   1805 		err = -ENOENT;
   1806 		goto out2;
   1807 	}
   1808 
   1809 	ret = check_inum_access(fs, parent, W_OK);
   1810 	if (ret)
   1811 		goto out2;
   1812 
   1813 
   1814 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, src, &ino);
   1815 	if (err || ino == 0) {
   1816 		ret = translate_error(fs, 0, err);
   1817 		goto out2;
   1818 	}
   1819 
   1820 	memset(&inode, 0, sizeof(inode));
   1821 	err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
   1822 				     sizeof(inode));
   1823 	if (err) {
   1824 		ret = translate_error(fs, ino, err);
   1825 		goto out2;
   1826 	}
   1827 
   1828 	inode.i_links_count++;
   1829 	ret = update_ctime(fs, ino, &inode);
   1830 	if (ret)
   1831 		goto out2;
   1832 
   1833 	err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
   1834 				      sizeof(inode));
   1835 	if (err) {
   1836 		ret = translate_error(fs, ino, err);
   1837 		goto out2;
   1838 	}
   1839 
   1840 	dbg_printf("%s: linking ino=%d/name=%s to dir=%d\n", __func__, ino,
   1841 		   node_name, parent);
   1842 	err = ext2fs_link(fs, parent, node_name, ino,
   1843 			  ext2_file_type(inode.i_mode));
   1844 	if (err == EXT2_ET_DIR_NO_SPACE) {
   1845 		err = ext2fs_expand_dir(fs, parent);
   1846 		if (err) {
   1847 			ret = translate_error(fs, parent, err);
   1848 			goto out2;
   1849 		}
   1850 
   1851 		err = ext2fs_link(fs, parent, node_name, ino,
   1852 				     ext2_file_type(inode.i_mode));
   1853 	}
   1854 	if (err) {
   1855 		ret = translate_error(fs, parent, err);
   1856 		goto out2;
   1857 	}
   1858 
   1859 	ret = update_mtime(fs, parent, NULL);
   1860 	if (ret)
   1861 		goto out2;
   1862 
   1863 out2:
   1864 	pthread_mutex_unlock(&ff->bfl);
   1865 out:
   1866 	free(temp_path);
   1867 	return ret;
   1868 }
   1869 
   1870 static int op_chmod(const char *path, mode_t mode)
   1871 {
   1872 	struct fuse_context *ctxt = fuse_get_context();
   1873 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   1874 	ext2_filsys fs;
   1875 	errcode_t err;
   1876 	ext2_ino_t ino;
   1877 	struct ext2_inode_large inode;
   1878 	int ret = 0;
   1879 
   1880 	FUSE2FS_CHECK_CONTEXT(ff);
   1881 	fs = ff->fs;
   1882 	pthread_mutex_lock(&ff->bfl);
   1883 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
   1884 	if (err) {
   1885 		ret = translate_error(fs, 0, err);
   1886 		goto out;
   1887 	}
   1888 	dbg_printf("%s: path=%s mode=0%o ino=%d\n", __func__, path, mode, ino);
   1889 
   1890 	memset(&inode, 0, sizeof(inode));
   1891 	err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
   1892 				     sizeof(inode));
   1893 	if (err) {
   1894 		ret = translate_error(fs, ino, err);
   1895 		goto out;
   1896 	}
   1897 
   1898 	if (ctxt->uid != 0 && ctxt->uid != inode.i_uid) {
   1899 		ret = -EPERM;
   1900 		goto out;
   1901 	}
   1902 
   1903 	/*
   1904 	 * XXX: We should really check that the inode gid is not in /any/
   1905 	 * of the user's groups, but FUSE only tells us about the primary
   1906 	 * group.
   1907 	 */
   1908 	if (ctxt->uid != 0 && ctxt->gid != inode.i_gid)
   1909 		mode &= ~S_ISGID;
   1910 
   1911 	inode.i_mode &= ~0xFFF;
   1912 	inode.i_mode |= mode & 0xFFF;
   1913 	ret = update_ctime(fs, ino, &inode);
   1914 	if (ret)
   1915 		goto out;
   1916 
   1917 	err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
   1918 				      sizeof(inode));
   1919 	if (err) {
   1920 		ret = translate_error(fs, ino, err);
   1921 		goto out;
   1922 	}
   1923 
   1924 out:
   1925 	pthread_mutex_unlock(&ff->bfl);
   1926 	return ret;
   1927 }
   1928 
   1929 static int op_chown(const char *path, uid_t owner, gid_t group)
   1930 {
   1931 	struct fuse_context *ctxt = fuse_get_context();
   1932 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   1933 	ext2_filsys fs;
   1934 	errcode_t err;
   1935 	ext2_ino_t ino;
   1936 	struct ext2_inode_large inode;
   1937 	int ret = 0;
   1938 
   1939 	FUSE2FS_CHECK_CONTEXT(ff);
   1940 	fs = ff->fs;
   1941 	pthread_mutex_lock(&ff->bfl);
   1942 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
   1943 	if (err) {
   1944 		ret = translate_error(fs, 0, err);
   1945 		goto out;
   1946 	}
   1947 	dbg_printf("%s: path=%s owner=%d group=%d ino=%d\n", __func__,
   1948 		   path, owner, group, ino);
   1949 
   1950 	memset(&inode, 0, sizeof(inode));
   1951 	err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
   1952 				     sizeof(inode));
   1953 	if (err) {
   1954 		ret = translate_error(fs, ino, err);
   1955 		goto out;
   1956 	}
   1957 
   1958 	/* FUSE seems to feed us ~0 to mean "don't change" */
   1959 	if (owner != (uid_t) ~0) {
   1960 		/* Only root gets to change UID. */
   1961 		if (ctxt->uid != 0 &&
   1962 		    !(inode.i_uid == ctxt->uid && owner == ctxt->uid)) {
   1963 			ret = -EPERM;
   1964 			goto out;
   1965 		}
   1966 		inode.i_uid = owner;
   1967 	}
   1968 
   1969 	if (group != (gid_t) ~0) {
   1970 		/* Only root or the owner get to change GID. */
   1971 		if (ctxt->uid != 0 && inode.i_uid != ctxt->uid) {
   1972 			ret = -EPERM;
   1973 			goto out;
   1974 		}
   1975 
   1976 		/* XXX: We /should/ check group membership but FUSE */
   1977 		inode.i_gid = group;
   1978 	}
   1979 
   1980 	ret = update_ctime(fs, ino, &inode);
   1981 	if (ret)
   1982 		goto out;
   1983 
   1984 	err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
   1985 				      sizeof(inode));
   1986 	if (err) {
   1987 		ret = translate_error(fs, ino, err);
   1988 		goto out;
   1989 	}
   1990 
   1991 out:
   1992 	pthread_mutex_unlock(&ff->bfl);
   1993 	return ret;
   1994 }
   1995 
   1996 static int op_truncate(const char *path, off_t len)
   1997 {
   1998 	struct fuse_context *ctxt = fuse_get_context();
   1999 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2000 	ext2_filsys fs;
   2001 	errcode_t err;
   2002 	ext2_ino_t ino;
   2003 	ext2_file_t file;
   2004 	int ret = 0;
   2005 
   2006 	FUSE2FS_CHECK_CONTEXT(ff);
   2007 	fs = ff->fs;
   2008 	pthread_mutex_lock(&ff->bfl);
   2009 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
   2010 	if (err || ino == 0) {
   2011 		ret = translate_error(fs, 0, err);
   2012 		goto out;
   2013 	}
   2014 	dbg_printf("%s: ino=%d len=%jd\n", __func__, ino, len);
   2015 
   2016 	ret = check_inum_access(fs, ino, W_OK);
   2017 	if (ret)
   2018 		goto out;
   2019 
   2020 	err = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &file);
   2021 	if (err) {
   2022 		ret = translate_error(fs, ino, err);
   2023 		goto out;
   2024 	}
   2025 
   2026 	err = ext2fs_file_set_size2(file, len);
   2027 	if (err) {
   2028 		ret = translate_error(fs, ino, err);
   2029 		goto out2;
   2030 	}
   2031 
   2032 out2:
   2033 	err = ext2fs_file_close(file);
   2034 	if (ret)
   2035 		goto out;
   2036 	if (err) {
   2037 		ret = translate_error(fs, ino, err);
   2038 		goto out;
   2039 	}
   2040 
   2041 	ret = update_mtime(fs, ino, NULL);
   2042 
   2043 out:
   2044 	pthread_mutex_unlock(&ff->bfl);
   2045 	return err;
   2046 }
   2047 
   2048 #ifdef __linux__
   2049 static void detect_linux_executable_open(int kernel_flags, int *access_check,
   2050 				  int *e2fs_open_flags)
   2051 {
   2052 	/*
   2053 	 * On Linux, execve will bleed __FMODE_EXEC into the file mode flags,
   2054 	 * and FUSE is more than happy to let that slip through.
   2055 	 */
   2056 	if (kernel_flags & 0x20) {
   2057 		*access_check = X_OK;
   2058 		*e2fs_open_flags &= ~EXT2_FILE_WRITE;
   2059 	}
   2060 }
   2061 #else
   2062 static void detect_linux_executable_open(int kernel_flags, int *access_check,
   2063 				  int *e2fs_open_flags)
   2064 {
   2065 	/* empty */
   2066 }
   2067 #endif /* __linux__ */
   2068 
   2069 static int __op_open(struct fuse2fs *ff, const char *path,
   2070 		     struct fuse_file_info *fp)
   2071 {
   2072 	ext2_filsys fs = ff->fs;
   2073 	errcode_t err;
   2074 	struct fuse2fs_file_handle *file;
   2075 	int check = 0, ret = 0;
   2076 
   2077 	dbg_printf("%s: path=%s\n", __func__, path);
   2078 	err = ext2fs_get_mem(sizeof(*file), &file);
   2079 	if (err)
   2080 		return translate_error(fs, 0, err);
   2081 	file->magic = FUSE2FS_FILE_MAGIC;
   2082 
   2083 	file->open_flags = 0;
   2084 	switch (fp->flags & O_ACCMODE) {
   2085 	case O_RDONLY:
   2086 		check = R_OK;
   2087 		break;
   2088 	case O_WRONLY:
   2089 		check = W_OK;
   2090 		file->open_flags |= EXT2_FILE_WRITE;
   2091 		break;
   2092 	case O_RDWR:
   2093 		check = R_OK | W_OK;
   2094 		file->open_flags |= EXT2_FILE_WRITE;
   2095 		break;
   2096 	}
   2097 
   2098 	detect_linux_executable_open(fp->flags, &check, &file->open_flags);
   2099 
   2100 	if (fp->flags & O_CREAT)
   2101 		file->open_flags |= EXT2_FILE_CREATE;
   2102 
   2103 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &file->ino);
   2104 	if (err || file->ino == 0) {
   2105 		ret = translate_error(fs, 0, err);
   2106 		goto out;
   2107 	}
   2108 	dbg_printf("%s: ino=%d\n", __func__, file->ino);
   2109 
   2110 	ret = check_inum_access(fs, file->ino, check);
   2111 	if (ret) {
   2112 		/*
   2113 		 * In a regular (Linux) fs driver, the kernel will open
   2114 		 * binaries for reading if the user has --x privileges (i.e.
   2115 		 * execute without read).  Since the kernel doesn't have any
   2116 		 * way to tell us if it's opening a file via execve, we'll
   2117 		 * just assume that allowing access is ok if asking for ro mode
   2118 		 * fails but asking for x mode succeeds.  Of course we can
   2119 		 * also employ undocumented hacks (see above).
   2120 		 */
   2121 		if (check == R_OK) {
   2122 			ret = check_inum_access(fs, file->ino, X_OK);
   2123 			if (ret)
   2124 				goto out;
   2125 		} else
   2126 			goto out;
   2127 	}
   2128 	fp->fh = (uintptr_t)file;
   2129 
   2130 out:
   2131 	if (ret)
   2132 		ext2fs_free_mem(&file);
   2133 	return ret;
   2134 }
   2135 
   2136 static int op_open(const char *path, struct fuse_file_info *fp)
   2137 {
   2138 	struct fuse_context *ctxt = fuse_get_context();
   2139 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2140 	int ret;
   2141 
   2142 	FUSE2FS_CHECK_CONTEXT(ff);
   2143 	pthread_mutex_lock(&ff->bfl);
   2144 	ret = __op_open(ff, path, fp);
   2145 	pthread_mutex_unlock(&ff->bfl);
   2146 	return ret;
   2147 }
   2148 
   2149 static int op_read(const char *path EXT2FS_ATTR((unused)), char *buf,
   2150 		   size_t len, off_t offset,
   2151 		   struct fuse_file_info *fp)
   2152 {
   2153 	struct fuse_context *ctxt = fuse_get_context();
   2154 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2155 	struct fuse2fs_file_handle *fh =
   2156 		(struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
   2157 	ext2_filsys fs;
   2158 	ext2_file_t efp;
   2159 	errcode_t err;
   2160 	unsigned int got = 0;
   2161 	int ret = 0;
   2162 
   2163 	FUSE2FS_CHECK_CONTEXT(ff);
   2164 	fs = ff->fs;
   2165 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   2166 	dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino, offset,
   2167 		   len);
   2168 	pthread_mutex_lock(&ff->bfl);
   2169 	err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
   2170 	if (err) {
   2171 		ret = translate_error(fs, fh->ino, err);
   2172 		goto out;
   2173 	}
   2174 
   2175 	err = ext2fs_file_llseek(efp, offset, SEEK_SET, NULL);
   2176 	if (err) {
   2177 		ret = translate_error(fs, fh->ino, err);
   2178 		goto out2;
   2179 	}
   2180 
   2181 	err = ext2fs_file_read(efp, buf, len, &got);
   2182 	if (err) {
   2183 		ret = translate_error(fs, fh->ino, err);
   2184 		goto out2;
   2185 	}
   2186 
   2187 out2:
   2188 	err = ext2fs_file_close(efp);
   2189 	if (ret)
   2190 		goto out;
   2191 	if (err) {
   2192 		ret = translate_error(fs, fh->ino, err);
   2193 		goto out;
   2194 	}
   2195 
   2196 	if (fs_writeable(fs)) {
   2197 		ret = update_atime(fs, fh->ino);
   2198 		if (ret)
   2199 			goto out;
   2200 	}
   2201 out:
   2202 	pthread_mutex_unlock(&ff->bfl);
   2203 	return got ? (int) got : ret;
   2204 }
   2205 
   2206 static int op_write(const char *path EXT2FS_ATTR((unused)),
   2207 		    const char *buf, size_t len, off_t offset,
   2208 		    struct fuse_file_info *fp)
   2209 {
   2210 	struct fuse_context *ctxt = fuse_get_context();
   2211 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2212 	struct fuse2fs_file_handle *fh =
   2213 		(struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
   2214 	ext2_filsys fs;
   2215 	ext2_file_t efp;
   2216 	errcode_t err;
   2217 	unsigned int got = 0;
   2218 	int ret = 0;
   2219 
   2220 	FUSE2FS_CHECK_CONTEXT(ff);
   2221 	fs = ff->fs;
   2222 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   2223 	dbg_printf("%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino, offset,
   2224 		   len);
   2225 	pthread_mutex_lock(&ff->bfl);
   2226 	if (!fs_writeable(fs)) {
   2227 		ret = -EROFS;
   2228 		goto out;
   2229 	}
   2230 
   2231 	if (!fs_can_allocate(ff, len / fs->blocksize)) {
   2232 		ret = -ENOSPC;
   2233 		goto out;
   2234 	}
   2235 
   2236 	err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
   2237 	if (err) {
   2238 		ret = translate_error(fs, fh->ino, err);
   2239 		goto out;
   2240 	}
   2241 
   2242 	err = ext2fs_file_llseek(efp, offset, SEEK_SET, NULL);
   2243 	if (err) {
   2244 		ret = translate_error(fs, fh->ino, err);
   2245 		goto out2;
   2246 	}
   2247 
   2248 	err = ext2fs_file_write(efp, buf, len, &got);
   2249 	if (err) {
   2250 		ret = translate_error(fs, fh->ino, err);
   2251 		goto out2;
   2252 	}
   2253 
   2254 	err = ext2fs_file_flush(efp);
   2255 	if (err) {
   2256 		got = 0;
   2257 		ret = translate_error(fs, fh->ino, err);
   2258 		goto out2;
   2259 	}
   2260 
   2261 out2:
   2262 	err = ext2fs_file_close(efp);
   2263 	if (ret)
   2264 		goto out;
   2265 	if (err) {
   2266 		ret = translate_error(fs, fh->ino, err);
   2267 		goto out;
   2268 	}
   2269 
   2270 	ret = update_mtime(fs, fh->ino, NULL);
   2271 	if (ret)
   2272 		goto out;
   2273 
   2274 out:
   2275 	pthread_mutex_unlock(&ff->bfl);
   2276 	return got ? (int) got : ret;
   2277 }
   2278 
   2279 static int op_release(const char *path EXT2FS_ATTR((unused)),
   2280 		      struct fuse_file_info *fp)
   2281 {
   2282 	struct fuse_context *ctxt = fuse_get_context();
   2283 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2284 	struct fuse2fs_file_handle *fh =
   2285 		(struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
   2286 	ext2_filsys fs;
   2287 	errcode_t err;
   2288 	int ret = 0;
   2289 
   2290 	FUSE2FS_CHECK_CONTEXT(ff);
   2291 	fs = ff->fs;
   2292 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   2293 	dbg_printf("%s: ino=%d\n", __func__, fh->ino);
   2294 	pthread_mutex_lock(&ff->bfl);
   2295 	if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) {
   2296 		err = ext2fs_flush2(fs, EXT2_FLAG_FLUSH_NO_SYNC);
   2297 		if (err)
   2298 			ret = translate_error(fs, fh->ino, err);
   2299 	}
   2300 	fp->fh = 0;
   2301 	pthread_mutex_unlock(&ff->bfl);
   2302 
   2303 	ext2fs_free_mem(&fh);
   2304 
   2305 	return ret;
   2306 }
   2307 
   2308 static int op_fsync(const char *path EXT2FS_ATTR((unused)),
   2309 		    int datasync EXT2FS_ATTR((unused)),
   2310 		    struct fuse_file_info *fp)
   2311 {
   2312 	struct fuse_context *ctxt = fuse_get_context();
   2313 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2314 	struct fuse2fs_file_handle *fh =
   2315 		(struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
   2316 	ext2_filsys fs;
   2317 	errcode_t err;
   2318 	int ret = 0;
   2319 
   2320 	FUSE2FS_CHECK_CONTEXT(ff);
   2321 	fs = ff->fs;
   2322 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   2323 	dbg_printf("%s: ino=%d\n", __func__, fh->ino);
   2324 	/* For now, flush everything, even if it's slow */
   2325 	pthread_mutex_lock(&ff->bfl);
   2326 	if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) {
   2327 		err = ext2fs_flush2(fs, 0);
   2328 		if (err)
   2329 			ret = translate_error(fs, fh->ino, err);
   2330 	}
   2331 	pthread_mutex_unlock(&ff->bfl);
   2332 
   2333 	return ret;
   2334 }
   2335 
   2336 static int op_statfs(const char *path EXT2FS_ATTR((unused)),
   2337 		     struct statvfs *buf)
   2338 {
   2339 	struct fuse_context *ctxt = fuse_get_context();
   2340 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2341 	ext2_filsys fs;
   2342 	uint64_t fsid, *f;
   2343 	blk64_t overhead, reserved, free;
   2344 
   2345 	FUSE2FS_CHECK_CONTEXT(ff);
   2346 	fs = ff->fs;
   2347 	dbg_printf("%s: path=%s\n", __func__, path);
   2348 	buf->f_bsize = fs->blocksize;
   2349 	buf->f_frsize = 0;
   2350 
   2351 	if (ff->minixdf)
   2352 		overhead = 0;
   2353 	else
   2354 		overhead = fs->desc_blocks +
   2355 			   fs->group_desc_count *
   2356 			   (fs->inode_blocks_per_group + 2);
   2357 	reserved = ext2fs_r_blocks_count(fs->super);
   2358 	if (!reserved)
   2359 		reserved = ext2fs_blocks_count(fs->super) / 10;
   2360 	free = ext2fs_free_blocks_count(fs->super);
   2361 
   2362 	buf->f_blocks = ext2fs_blocks_count(fs->super) - overhead;
   2363 	buf->f_bfree = free;
   2364 	if (free < reserved)
   2365 		buf->f_bavail = 0;
   2366 	else
   2367 		buf->f_bavail = free - reserved;
   2368 	buf->f_files = fs->super->s_inodes_count;
   2369 	buf->f_ffree = fs->super->s_free_inodes_count;
   2370 	buf->f_favail = fs->super->s_free_inodes_count;
   2371 	f = (uint64_t *)fs->super->s_uuid;
   2372 	fsid = *f;
   2373 	f++;
   2374 	fsid ^= *f;
   2375 	buf->f_fsid = fsid;
   2376 	buf->f_flag = 0;
   2377 	if (fs->flags & EXT2_FLAG_RW)
   2378 		buf->f_flag |= ST_RDONLY;
   2379 	buf->f_namemax = EXT2_NAME_LEN;
   2380 
   2381 	return 0;
   2382 }
   2383 
   2384 typedef errcode_t (*xattr_xlate_get)(void **cooked_buf, size_t *cooked_sz,
   2385 				     const void *raw_buf, size_t raw_sz);
   2386 typedef errcode_t (*xattr_xlate_set)(const void *cooked_buf, size_t cooked_sz,
   2387 				     const void **raw_buf, size_t *raw_sz);
   2388 struct xattr_translate {
   2389 	const char *prefix;
   2390 	xattr_xlate_get get;
   2391 	xattr_xlate_set set;
   2392 };
   2393 
   2394 #define XATTR_TRANSLATOR(p, g, s) \
   2395 	{.prefix = (p), \
   2396 	 .get = (xattr_xlate_get)(g), \
   2397 	 .set = (xattr_xlate_set)(s)}
   2398 
   2399 static struct xattr_translate xattr_translators[] = {
   2400 #ifdef TRANSLATE_LINUX_ACLS
   2401 	XATTR_TRANSLATOR(ACL_EA_ACCESS, ext4_to_fuse_acl, fuse_to_ext4_acl),
   2402 	XATTR_TRANSLATOR(ACL_EA_DEFAULT, ext4_to_fuse_acl, fuse_to_ext4_acl),
   2403 #endif
   2404 	XATTR_TRANSLATOR(NULL, NULL, NULL),
   2405 };
   2406 #undef XATTR_TRANSLATOR
   2407 
   2408 static int op_getxattr(const char *path, const char *key, char *value,
   2409 		       size_t len)
   2410 {
   2411 	struct fuse_context *ctxt = fuse_get_context();
   2412 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2413 	ext2_filsys fs;
   2414 	struct ext2_xattr_handle *h;
   2415 	struct xattr_translate *xt;
   2416 	void *ptr, *cptr;
   2417 	size_t plen, clen;
   2418 	ext2_ino_t ino;
   2419 	errcode_t err;
   2420 	int ret = 0;
   2421 
   2422 	FUSE2FS_CHECK_CONTEXT(ff);
   2423 	fs = ff->fs;
   2424 	pthread_mutex_lock(&ff->bfl);
   2425 	if (!ext2fs_has_feature_xattr(fs->super)) {
   2426 		ret = -ENOTSUP;
   2427 		goto out;
   2428 	}
   2429 
   2430 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
   2431 	if (err || ino == 0) {
   2432 		ret = translate_error(fs, 0, err);
   2433 		goto out;
   2434 	}
   2435 	dbg_printf("%s: ino=%d\n", __func__, ino);
   2436 
   2437 	ret = check_inum_access(fs, ino, R_OK);
   2438 	if (ret)
   2439 		goto out;
   2440 
   2441 	err = ext2fs_xattrs_open(fs, ino, &h);
   2442 	if (err) {
   2443 		ret = translate_error(fs, ino, err);
   2444 		goto out;
   2445 	}
   2446 
   2447 	err = ext2fs_xattrs_read(h);
   2448 	if (err) {
   2449 		ret = translate_error(fs, ino, err);
   2450 		goto out2;
   2451 	}
   2452 
   2453 	err = ext2fs_xattr_get(h, key, &ptr, &plen);
   2454 	if (err) {
   2455 		ret = translate_error(fs, ino, err);
   2456 		goto out2;
   2457 	}
   2458 
   2459 	for (xt = xattr_translators; xt->prefix != NULL; xt++) {
   2460 		if (strncmp(key, xt->prefix, strlen(xt->prefix)) == 0) {
   2461 			err = xt->get(&cptr, &clen, ptr, plen);
   2462 			if (err)
   2463 				goto out3;
   2464 			ext2fs_free_mem(&ptr);
   2465 			ptr = cptr;
   2466 			plen = clen;
   2467 		}
   2468 	}
   2469 
   2470 	if (!len) {
   2471 		ret = plen;
   2472 	} else if (len < plen) {
   2473 		ret = -ERANGE;
   2474 	} else {
   2475 		memcpy(value, ptr, plen);
   2476 		ret = plen;
   2477 	}
   2478 
   2479 out3:
   2480 	ext2fs_free_mem(&ptr);
   2481 out2:
   2482 	err = ext2fs_xattrs_close(&h);
   2483 	if (err)
   2484 		ret = translate_error(fs, ino, err);
   2485 out:
   2486 	pthread_mutex_unlock(&ff->bfl);
   2487 
   2488 	return ret;
   2489 }
   2490 
   2491 static int count_buffer_space(char *name, char *value EXT2FS_ATTR((unused)),
   2492 			      size_t value_len EXT2FS_ATTR((unused)),
   2493 			      void *data)
   2494 {
   2495 	unsigned int *x = data;
   2496 
   2497 	*x = *x + strlen(name) + 1;
   2498 	return 0;
   2499 }
   2500 
   2501 static int copy_names(char *name, char *value EXT2FS_ATTR((unused)),
   2502 		      size_t value_len EXT2FS_ATTR((unused)), void *data)
   2503 {
   2504 	char **b = data;
   2505 
   2506 	strncpy(*b, name, strlen(name));
   2507 	*b = *b + strlen(name) + 1;
   2508 
   2509 	return 0;
   2510 }
   2511 
   2512 static int op_listxattr(const char *path, char *names, size_t len)
   2513 {
   2514 	struct fuse_context *ctxt = fuse_get_context();
   2515 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2516 	ext2_filsys fs;
   2517 	struct ext2_xattr_handle *h;
   2518 	unsigned int bufsz;
   2519 	ext2_ino_t ino;
   2520 	errcode_t err;
   2521 	int ret = 0;
   2522 
   2523 	FUSE2FS_CHECK_CONTEXT(ff);
   2524 	fs = ff->fs;
   2525 	pthread_mutex_lock(&ff->bfl);
   2526 	if (!ext2fs_has_feature_xattr(fs->super)) {
   2527 		ret = -ENOTSUP;
   2528 		goto out;
   2529 	}
   2530 
   2531 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
   2532 	if (err || ino == 0) {
   2533 		ret = translate_error(fs, ino, err);
   2534 		goto out;
   2535 	}
   2536 	dbg_printf("%s: ino=%d\n", __func__, ino);
   2537 
   2538 	ret = check_inum_access(fs, ino, R_OK);
   2539 	if (ret)
   2540 		goto out2;
   2541 
   2542 	err = ext2fs_xattrs_open(fs, ino, &h);
   2543 	if (err) {
   2544 		ret = translate_error(fs, ino, err);
   2545 		goto out;
   2546 	}
   2547 
   2548 	err = ext2fs_xattrs_read(h);
   2549 	if (err) {
   2550 		ret = translate_error(fs, ino, err);
   2551 		goto out2;
   2552 	}
   2553 
   2554 	/* Count buffer space needed for names */
   2555 	bufsz = 0;
   2556 	err = ext2fs_xattrs_iterate(h, count_buffer_space, &bufsz);
   2557 	if (err) {
   2558 		ret = translate_error(fs, ino, err);
   2559 		goto out2;
   2560 	}
   2561 
   2562 	if (len == 0) {
   2563 		ret = bufsz;
   2564 		goto out2;
   2565 	} else if (len < bufsz) {
   2566 		ret = -ERANGE;
   2567 		goto out2;
   2568 	}
   2569 
   2570 	/* Copy names out */
   2571 	memset(names, 0, len);
   2572 	err = ext2fs_xattrs_iterate(h, copy_names, &names);
   2573 	if (err) {
   2574 		ret = translate_error(fs, ino, err);
   2575 		goto out2;
   2576 	}
   2577 	ret = bufsz;
   2578 out2:
   2579 	err = ext2fs_xattrs_close(&h);
   2580 	if (err)
   2581 		ret = translate_error(fs, ino, err);
   2582 out:
   2583 	pthread_mutex_unlock(&ff->bfl);
   2584 
   2585 	return ret;
   2586 }
   2587 
   2588 static int op_setxattr(const char *path EXT2FS_ATTR((unused)),
   2589 		       const char *key, const char *value,
   2590 		       size_t len, int flags EXT2FS_ATTR((unused)))
   2591 {
   2592 	struct fuse_context *ctxt = fuse_get_context();
   2593 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2594 	ext2_filsys fs;
   2595 	struct ext2_xattr_handle *h;
   2596 	struct xattr_translate *xt;
   2597 	const void *cvalue;
   2598 	size_t clen;
   2599 	ext2_ino_t ino;
   2600 	errcode_t err;
   2601 	int ret = 0;
   2602 
   2603 	FUSE2FS_CHECK_CONTEXT(ff);
   2604 	fs = ff->fs;
   2605 	pthread_mutex_lock(&ff->bfl);
   2606 	if (!ext2fs_has_feature_xattr(fs->super)) {
   2607 		ret = -ENOTSUP;
   2608 		goto out;
   2609 	}
   2610 
   2611 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
   2612 	if (err || ino == 0) {
   2613 		ret = translate_error(fs, 0, err);
   2614 		goto out;
   2615 	}
   2616 	dbg_printf("%s: ino=%d\n", __func__, ino);
   2617 
   2618 	ret = check_inum_access(fs, ino, W_OK);
   2619 	if (ret == -EACCES) {
   2620 		ret = -EPERM;
   2621 		goto out;
   2622 	} else if (ret)
   2623 		goto out;
   2624 
   2625 	err = ext2fs_xattrs_open(fs, ino, &h);
   2626 	if (err) {
   2627 		ret = translate_error(fs, ino, err);
   2628 		goto out;
   2629 	}
   2630 
   2631 	err = ext2fs_xattrs_read(h);
   2632 	if (err) {
   2633 		ret = translate_error(fs, ino, err);
   2634 		goto out2;
   2635 	}
   2636 
   2637 	cvalue = value;
   2638 	clen = len;
   2639 	for (xt = xattr_translators; xt->prefix != NULL; xt++) {
   2640 		if (strncmp(key, xt->prefix, strlen(xt->prefix)) == 0) {
   2641 			err = xt->set(value, len, &cvalue, &clen);
   2642 			if (err)
   2643 				goto out3;
   2644 		}
   2645 	}
   2646 
   2647 	err = ext2fs_xattr_set(h, key, cvalue, clen);
   2648 	if (err) {
   2649 		ret = translate_error(fs, ino, err);
   2650 		goto out3;
   2651 	}
   2652 
   2653 	err = ext2fs_xattrs_write(h);
   2654 	if (err) {
   2655 		ret = translate_error(fs, ino, err);
   2656 		goto out3;
   2657 	}
   2658 
   2659 	ret = update_ctime(fs, ino, NULL);
   2660 out3:
   2661 	if (cvalue != value)
   2662 		ext2fs_free_mem(&cvalue);
   2663 out2:
   2664 	err = ext2fs_xattrs_close(&h);
   2665 	if (!ret && err)
   2666 		ret = translate_error(fs, ino, err);
   2667 out:
   2668 	pthread_mutex_unlock(&ff->bfl);
   2669 
   2670 	return ret;
   2671 }
   2672 
   2673 static int op_removexattr(const char *path, const char *key)
   2674 {
   2675 	struct fuse_context *ctxt = fuse_get_context();
   2676 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2677 	ext2_filsys fs;
   2678 	struct ext2_xattr_handle *h;
   2679 	ext2_ino_t ino;
   2680 	errcode_t err;
   2681 	int ret = 0;
   2682 
   2683 	FUSE2FS_CHECK_CONTEXT(ff);
   2684 	fs = ff->fs;
   2685 	pthread_mutex_lock(&ff->bfl);
   2686 	if (!ext2fs_has_feature_xattr(fs->super)) {
   2687 		ret = -ENOTSUP;
   2688 		goto out;
   2689 	}
   2690 
   2691 	if (!fs_can_allocate(ff, 1)) {
   2692 		ret = -ENOSPC;
   2693 		goto out;
   2694 	}
   2695 
   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);
   2699 		goto out;
   2700 	}
   2701 	dbg_printf("%s: ino=%d\n", __func__, ino);
   2702 
   2703 	ret = check_inum_access(fs, ino, W_OK);
   2704 	if (ret)
   2705 		goto out;
   2706 
   2707 	err = ext2fs_xattrs_open(fs, ino, &h);
   2708 	if (err) {
   2709 		ret = translate_error(fs, ino, err);
   2710 		goto out;
   2711 	}
   2712 
   2713 	err = ext2fs_xattrs_read(h);
   2714 	if (err) {
   2715 		ret = translate_error(fs, ino, err);
   2716 		goto out2;
   2717 	}
   2718 
   2719 	err = ext2fs_xattr_remove(h, key);
   2720 	if (err) {
   2721 		ret = translate_error(fs, ino, err);
   2722 		goto out2;
   2723 	}
   2724 
   2725 	err = ext2fs_xattrs_write(h);
   2726 	if (err) {
   2727 		ret = translate_error(fs, ino, err);
   2728 		goto out2;
   2729 	}
   2730 
   2731 	ret = update_ctime(fs, ino, NULL);
   2732 out2:
   2733 	err = ext2fs_xattrs_close(&h);
   2734 	if (err)
   2735 		ret = translate_error(fs, ino, err);
   2736 out:
   2737 	pthread_mutex_unlock(&ff->bfl);
   2738 
   2739 	return ret;
   2740 }
   2741 
   2742 struct readdir_iter {
   2743 	void *buf;
   2744 	fuse_fill_dir_t func;
   2745 };
   2746 
   2747 static int op_readdir_iter(ext2_ino_t dir EXT2FS_ATTR((unused)),
   2748 			   int entry EXT2FS_ATTR((unused)),
   2749 			   struct ext2_dir_entry *dirent,
   2750 			   int offset EXT2FS_ATTR((unused)),
   2751 			   int blocksize EXT2FS_ATTR((unused)),
   2752 			   char *buf EXT2FS_ATTR((unused)), void *data)
   2753 {
   2754 	struct readdir_iter *i = data;
   2755 	char namebuf[EXT2_NAME_LEN + 1];
   2756 	int ret;
   2757 
   2758 	memcpy(namebuf, dirent->name, dirent->name_len & 0xFF);
   2759 	namebuf[dirent->name_len & 0xFF] = 0;
   2760 	ret = i->func(i->buf, namebuf, NULL, 0);
   2761 	if (ret)
   2762 		return DIRENT_ABORT;
   2763 
   2764 	return 0;
   2765 }
   2766 
   2767 static int op_readdir(const char *path EXT2FS_ATTR((unused)),
   2768 		      void *buf, fuse_fill_dir_t fill_func,
   2769 		      off_t offset EXT2FS_ATTR((unused)),
   2770 		      struct fuse_file_info *fp)
   2771 {
   2772 	struct fuse_context *ctxt = fuse_get_context();
   2773 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2774 	struct fuse2fs_file_handle *fh =
   2775 		(struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
   2776 	ext2_filsys fs;
   2777 	errcode_t err;
   2778 	struct readdir_iter i;
   2779 	int ret = 0;
   2780 
   2781 	FUSE2FS_CHECK_CONTEXT(ff);
   2782 	fs = ff->fs;
   2783 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   2784 	dbg_printf("%s: ino=%d\n", __func__, fh->ino);
   2785 	pthread_mutex_lock(&ff->bfl);
   2786 	i.buf = buf;
   2787 	i.func = fill_func;
   2788 	err = ext2fs_dir_iterate2(fs, fh->ino, 0, NULL, op_readdir_iter, &i);
   2789 	if (err) {
   2790 		ret = translate_error(fs, fh->ino, err);
   2791 		goto out;
   2792 	}
   2793 
   2794 	if (fs_writeable(fs)) {
   2795 		ret = update_atime(fs, fh->ino);
   2796 		if (ret)
   2797 			goto out;
   2798 	}
   2799 out:
   2800 	pthread_mutex_unlock(&ff->bfl);
   2801 	return ret;
   2802 }
   2803 
   2804 static int op_access(const char *path, int mask)
   2805 {
   2806 	struct fuse_context *ctxt = fuse_get_context();
   2807 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2808 	ext2_filsys fs;
   2809 	errcode_t err;
   2810 	ext2_ino_t ino;
   2811 	int ret = 0;
   2812 
   2813 	FUSE2FS_CHECK_CONTEXT(ff);
   2814 	fs = ff->fs;
   2815 	dbg_printf("%s: path=%s mask=0x%x\n", __func__, path, mask);
   2816 	pthread_mutex_lock(&ff->bfl);
   2817 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
   2818 	if (err || ino == 0) {
   2819 		ret = translate_error(fs, 0, err);
   2820 		goto out;
   2821 	}
   2822 
   2823 	ret = check_inum_access(fs, ino, mask);
   2824 	if (ret)
   2825 		goto out;
   2826 
   2827 out:
   2828 	pthread_mutex_unlock(&ff->bfl);
   2829 	return ret;
   2830 }
   2831 
   2832 static int op_create(const char *path, mode_t mode, struct fuse_file_info *fp)
   2833 {
   2834 	struct fuse_context *ctxt = fuse_get_context();
   2835 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2836 	ext2_filsys fs;
   2837 	ext2_ino_t parent, child;
   2838 	char *temp_path = strdup(path);
   2839 	errcode_t err;
   2840 	char *node_name, a;
   2841 	int filetype;
   2842 	struct ext2_inode_large inode;
   2843 	int ret = 0;
   2844 
   2845 	FUSE2FS_CHECK_CONTEXT(ff);
   2846 	fs = ff->fs;
   2847 	dbg_printf("%s: path=%s mode=0%o\n", __func__, path, mode);
   2848 	if (!temp_path) {
   2849 		ret = -ENOMEM;
   2850 		goto out;
   2851 	}
   2852 	node_name = strrchr(temp_path, '/');
   2853 	if (!node_name) {
   2854 		ret = -ENOMEM;
   2855 		goto out;
   2856 	}
   2857 	node_name++;
   2858 	a = *node_name;
   2859 	*node_name = 0;
   2860 
   2861 	pthread_mutex_lock(&ff->bfl);
   2862 	if (!fs_can_allocate(ff, 1)) {
   2863 		ret = -ENOSPC;
   2864 		goto out2;
   2865 	}
   2866 
   2867 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
   2868 			   &parent);
   2869 	if (err) {
   2870 		ret = translate_error(fs, 0, err);
   2871 		goto out2;
   2872 	}
   2873 
   2874 	ret = check_inum_access(fs, parent, W_OK);
   2875 	if (ret)
   2876 		goto out2;
   2877 
   2878 	*node_name = a;
   2879 
   2880 	filetype = ext2_file_type(mode);
   2881 
   2882 	err = ext2fs_new_inode(fs, parent, mode, 0, &child);
   2883 	if (err) {
   2884 		ret = translate_error(fs, parent, err);
   2885 		goto out2;
   2886 	}
   2887 
   2888 	dbg_printf("%s: creating ino=%d/name=%s in dir=%d\n", __func__, child,
   2889 		   node_name, parent);
   2890 	err = ext2fs_link(fs, parent, node_name, child, filetype);
   2891 	if (err == EXT2_ET_DIR_NO_SPACE) {
   2892 		err = ext2fs_expand_dir(fs, parent);
   2893 		if (err) {
   2894 			ret = translate_error(fs, parent, err);
   2895 			goto out2;
   2896 		}
   2897 
   2898 		err = ext2fs_link(fs, parent, node_name, child,
   2899 				     filetype);
   2900 	}
   2901 	if (err) {
   2902 		ret = translate_error(fs, parent, err);
   2903 		goto out2;
   2904 	}
   2905 
   2906 	ret = update_mtime(fs, parent, NULL);
   2907 	if (ret)
   2908 		goto out2;
   2909 
   2910 	memset(&inode, 0, sizeof(inode));
   2911 	inode.i_mode = mode;
   2912 	inode.i_links_count = 1;
   2913 	inode.i_extra_isize = sizeof(struct ext2_inode_large) -
   2914 		EXT2_GOOD_OLD_INODE_SIZE;
   2915 	inode.i_uid = ctxt->uid;
   2916 	inode.i_gid = ctxt->gid;
   2917 	if (ext2fs_has_feature_extents(fs->super)) {
   2918 		ext2_extent_handle_t handle;
   2919 
   2920 		inode.i_flags &= ~EXT4_EXTENTS_FL;
   2921 		ret = ext2fs_extent_open2(fs, child,
   2922 					  (struct ext2_inode *)&inode, &handle);
   2923 		if (ret)
   2924 			return ret;
   2925 		ext2fs_extent_free(handle);
   2926 	}
   2927 
   2928 	err = ext2fs_write_new_inode(fs, child, (struct ext2_inode *)&inode);
   2929 	if (err) {
   2930 		ret = translate_error(fs, child, err);
   2931 		goto out2;
   2932 	}
   2933 
   2934 	inode.i_generation = ff->next_generation++;
   2935 	init_times(&inode);
   2936 	err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
   2937 				      sizeof(inode));
   2938 	if (err) {
   2939 		ret = translate_error(fs, child, err);
   2940 		goto out2;
   2941 	}
   2942 
   2943 	ext2fs_inode_alloc_stats2(fs, child, 1, 0);
   2944 
   2945 	ret = __op_open(ff, path, fp);
   2946 	if (ret)
   2947 		goto out2;
   2948 out2:
   2949 	pthread_mutex_unlock(&ff->bfl);
   2950 out:
   2951 	free(temp_path);
   2952 	return ret;
   2953 }
   2954 
   2955 static int op_ftruncate(const char *path EXT2FS_ATTR((unused)),
   2956 			off_t len, struct fuse_file_info *fp)
   2957 {
   2958 	struct fuse_context *ctxt = fuse_get_context();
   2959 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   2960 	struct fuse2fs_file_handle *fh =
   2961 		(struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
   2962 	ext2_filsys fs;
   2963 	ext2_file_t efp;
   2964 	errcode_t err;
   2965 	int ret = 0;
   2966 
   2967 	FUSE2FS_CHECK_CONTEXT(ff);
   2968 	fs = ff->fs;
   2969 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   2970 	dbg_printf("%s: ino=%d len=%jd\n", __func__, fh->ino, len);
   2971 	pthread_mutex_lock(&ff->bfl);
   2972 	if (!fs_writeable(fs)) {
   2973 		ret = -EROFS;
   2974 		goto out;
   2975 	}
   2976 
   2977 	err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
   2978 	if (err) {
   2979 		ret = translate_error(fs, fh->ino, err);
   2980 		goto out;
   2981 	}
   2982 
   2983 	err = ext2fs_file_set_size2(efp, len);
   2984 	if (err) {
   2985 		ret = translate_error(fs, fh->ino, err);
   2986 		goto out2;
   2987 	}
   2988 
   2989 out2:
   2990 	err = ext2fs_file_close(efp);
   2991 	if (ret)
   2992 		goto out;
   2993 	if (err) {
   2994 		ret = translate_error(fs, fh->ino, err);
   2995 		goto out;
   2996 	}
   2997 
   2998 	ret = update_mtime(fs, fh->ino, NULL);
   2999 	if (ret)
   3000 		goto out;
   3001 
   3002 out:
   3003 	pthread_mutex_unlock(&ff->bfl);
   3004 	return 0;
   3005 }
   3006 
   3007 static int op_fgetattr(const char *path EXT2FS_ATTR((unused)),
   3008 		       struct stat *statbuf,
   3009 		       struct fuse_file_info *fp)
   3010 {
   3011 	struct fuse_context *ctxt = fuse_get_context();
   3012 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   3013 	ext2_filsys fs;
   3014 	struct fuse2fs_file_handle *fh =
   3015 		(struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
   3016 	int ret = 0;
   3017 
   3018 	FUSE2FS_CHECK_CONTEXT(ff);
   3019 	fs = ff->fs;
   3020 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   3021 	dbg_printf("%s: ino=%d\n", __func__, fh->ino);
   3022 	pthread_mutex_lock(&ff->bfl);
   3023 	ret = stat_inode(fs, fh->ino, statbuf);
   3024 	pthread_mutex_unlock(&ff->bfl);
   3025 
   3026 	return ret;
   3027 }
   3028 
   3029 static int op_utimens(const char *path, const struct timespec ctv[2])
   3030 {
   3031 	struct fuse_context *ctxt = fuse_get_context();
   3032 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   3033 	struct timespec tv[2];
   3034 	ext2_filsys fs;
   3035 	errcode_t err;
   3036 	ext2_ino_t ino;
   3037 	struct ext2_inode_large inode;
   3038 	int ret = 0;
   3039 
   3040 	FUSE2FS_CHECK_CONTEXT(ff);
   3041 	fs = ff->fs;
   3042 	pthread_mutex_lock(&ff->bfl);
   3043 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
   3044 	if (err) {
   3045 		ret = translate_error(fs, 0, err);
   3046 		goto out;
   3047 	}
   3048 	dbg_printf("%s: ino=%d\n", __func__, ino);
   3049 
   3050 	ret = check_inum_access(fs, ino, W_OK);
   3051 	if (ret)
   3052 		goto out;
   3053 
   3054 	memset(&inode, 0, sizeof(inode));
   3055 	err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
   3056 				     sizeof(inode));
   3057 	if (err) {
   3058 		ret = translate_error(fs, ino, err);
   3059 		goto out;
   3060 	}
   3061 
   3062 	tv[0] = ctv[0];
   3063 	tv[1] = ctv[1];
   3064 #ifdef UTIME_NOW
   3065 	if (tv[0].tv_nsec == UTIME_NOW)
   3066 		get_now(tv);
   3067 	if (tv[1].tv_nsec == UTIME_NOW)
   3068 		get_now(tv + 1);
   3069 #endif /* UTIME_NOW */
   3070 #ifdef UTIME_OMIT
   3071 	if (tv[0].tv_nsec != UTIME_OMIT)
   3072 		EXT4_INODE_SET_XTIME(i_atime, tv, &inode);
   3073 	if (tv[1].tv_nsec != UTIME_OMIT)
   3074 		EXT4_INODE_SET_XTIME(i_mtime, tv + 1, &inode);
   3075 #endif /* UTIME_OMIT */
   3076 	ret = update_ctime(fs, ino, &inode);
   3077 	if (ret)
   3078 		goto out;
   3079 
   3080 	err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
   3081 				      sizeof(inode));
   3082 	if (err) {
   3083 		ret = translate_error(fs, ino, err);
   3084 		goto out;
   3085 	}
   3086 
   3087 out:
   3088 	pthread_mutex_unlock(&ff->bfl);
   3089 	return ret;
   3090 }
   3091 
   3092 #ifdef SUPPORT_I_FLAGS
   3093 static int ioctl_getflags(ext2_filsys fs, struct fuse2fs_file_handle *fh,
   3094 			  void *data)
   3095 {
   3096 	errcode_t err;
   3097 	struct ext2_inode_large inode;
   3098 
   3099 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   3100 	dbg_printf("%s: ino=%d\n", __func__, fh->ino);
   3101 	memset(&inode, 0, sizeof(inode));
   3102 	err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
   3103 				     sizeof(inode));
   3104 	if (err)
   3105 		return translate_error(fs, fh->ino, err);
   3106 
   3107 	*(__u32 *)data = inode.i_flags & EXT2_FL_USER_VISIBLE;
   3108 	return 0;
   3109 }
   3110 
   3111 #define FUSE2FS_MODIFIABLE_IFLAGS \
   3112 	(EXT2_IMMUTABLE_FL | EXT2_APPEND_FL | EXT2_NODUMP_FL | \
   3113 	 EXT2_NOATIME_FL | EXT3_JOURNAL_DATA_FL | EXT2_DIRSYNC_FL | \
   3114 	 EXT2_TOPDIR_FL)
   3115 
   3116 static int ioctl_setflags(ext2_filsys fs, struct fuse2fs_file_handle *fh,
   3117 			  void *data)
   3118 {
   3119 	errcode_t err;
   3120 	struct ext2_inode_large inode;
   3121 	int ret;
   3122 	__u32 flags = *(__u32 *)data;
   3123 	struct fuse_context *ctxt = fuse_get_context();
   3124 
   3125 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   3126 	dbg_printf("%s: ino=%d\n", __func__, fh->ino);
   3127 	memset(&inode, 0, sizeof(inode));
   3128 	err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
   3129 				     sizeof(inode));
   3130 	if (err)
   3131 		return translate_error(fs, fh->ino, err);
   3132 
   3133 	if (ctxt->uid != 0 && inode.i_uid != ctxt->uid)
   3134 		return -EPERM;
   3135 
   3136 	if ((inode.i_flags ^ flags) & ~FUSE2FS_MODIFIABLE_IFLAGS)
   3137 		return -EINVAL;
   3138 
   3139 	inode.i_flags = (inode.i_flags & ~FUSE2FS_MODIFIABLE_IFLAGS) |
   3140 			(flags & FUSE2FS_MODIFIABLE_IFLAGS);
   3141 
   3142 	ret = update_ctime(fs, fh->ino, &inode);
   3143 	if (ret)
   3144 		return ret;
   3145 
   3146 	err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
   3147 				      sizeof(inode));
   3148 	if (err)
   3149 		return translate_error(fs, fh->ino, err);
   3150 
   3151 	return 0;
   3152 }
   3153 
   3154 static int ioctl_getversion(ext2_filsys fs, struct fuse2fs_file_handle *fh,
   3155 			    void *data)
   3156 {
   3157 	errcode_t err;
   3158 	struct ext2_inode_large inode;
   3159 
   3160 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   3161 	dbg_printf("%s: ino=%d\n", __func__, fh->ino);
   3162 	memset(&inode, 0, sizeof(inode));
   3163 	err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
   3164 				     sizeof(inode));
   3165 	if (err)
   3166 		return translate_error(fs, fh->ino, err);
   3167 
   3168 	*(__u32 *)data = inode.i_generation;
   3169 	return 0;
   3170 }
   3171 
   3172 static int ioctl_setversion(ext2_filsys fs, struct fuse2fs_file_handle *fh,
   3173 			    void *data)
   3174 {
   3175 	errcode_t err;
   3176 	struct ext2_inode_large inode;
   3177 	int ret;
   3178 	__u32 generation = *(__u32 *)data;
   3179 	struct fuse_context *ctxt = fuse_get_context();
   3180 
   3181 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   3182 	dbg_printf("%s: ino=%d\n", __func__, fh->ino);
   3183 	memset(&inode, 0, sizeof(inode));
   3184 	err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
   3185 				     sizeof(inode));
   3186 	if (err)
   3187 		return translate_error(fs, fh->ino, err);
   3188 
   3189 	if (ctxt->uid != 0 && inode.i_uid != ctxt->uid)
   3190 		return -EPERM;
   3191 
   3192 	inode.i_generation = generation;
   3193 
   3194 	ret = update_ctime(fs, fh->ino, &inode);
   3195 	if (ret)
   3196 		return ret;
   3197 
   3198 	err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
   3199 				      sizeof(inode));
   3200 	if (err)
   3201 		return translate_error(fs, fh->ino, err);
   3202 
   3203 	return 0;
   3204 }
   3205 #endif /* SUPPORT_I_FLAGS */
   3206 
   3207 #ifdef FITRIM
   3208 static int ioctl_fitrim(ext2_filsys fs, struct fuse2fs_file_handle *fh,
   3209 			void *data)
   3210 {
   3211 	struct fstrim_range *fr = data;
   3212 	blk64_t start, end, max_blocks, b, cleared;
   3213 	errcode_t err = 0;
   3214 
   3215 	start = fr->start / fs->blocksize;
   3216 	end = (fr->start + fr->len - 1) / fs->blocksize;
   3217 	dbg_printf("%s: start=%llu end=%llu\n", __func__, start, end);
   3218 
   3219 	if (start < fs->super->s_first_data_block)
   3220 		start = fs->super->s_first_data_block;
   3221 	if (start >= ext2fs_blocks_count(fs->super))
   3222 		start = ext2fs_blocks_count(fs->super) - 1;
   3223 
   3224 	if (end < fs->super->s_first_data_block)
   3225 		end = fs->super->s_first_data_block;
   3226 	if (end >= ext2fs_blocks_count(fs->super))
   3227 		end = ext2fs_blocks_count(fs->super) - 1;
   3228 
   3229 	cleared = 0;
   3230 	max_blocks = 2048ULL * 1024 * 1024 / fs->blocksize;
   3231 
   3232 	fr->len = 0;
   3233 	while (start <= end) {
   3234 		err = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
   3235 							   start, end, &start);
   3236 		if (err == ENOENT)
   3237 			return 0;
   3238 		else if (err)
   3239 			return translate_error(fs, fh->ino, err);
   3240 
   3241 		b = start + max_blocks < end ? start + max_blocks : end;
   3242 		err =  ext2fs_find_first_set_block_bitmap2(fs->block_map,
   3243 							   start, b, &b);
   3244 		if (err && err != ENOENT)
   3245 			return translate_error(fs, fh->ino, err);
   3246 		if (b - start >= fr->minlen) {
   3247 			err = io_channel_discard(fs->io, start, b - start);
   3248 			if (err)
   3249 				return translate_error(fs, fh->ino, err);
   3250 			cleared += b - start;
   3251 			fr->len = cleared * fs->blocksize;
   3252 		}
   3253 		start = b + 1;
   3254 	}
   3255 
   3256 	return err;
   3257 }
   3258 #endif /* FITRIM */
   3259 
   3260 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
   3261 static int op_ioctl(const char *path EXT2FS_ATTR((unused)), int cmd,
   3262 		    void *arg EXT2FS_ATTR((unused)),
   3263 		    struct fuse_file_info *fp,
   3264 		    unsigned int flags EXT2FS_ATTR((unused)), void *data)
   3265 {
   3266 	struct fuse_context *ctxt = fuse_get_context();
   3267 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   3268 	struct fuse2fs_file_handle *fh =
   3269 		(struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
   3270 	ext2_filsys fs;
   3271 	int ret = 0;
   3272 
   3273 	FUSE2FS_CHECK_CONTEXT(ff);
   3274 	fs = ff->fs;
   3275 	pthread_mutex_lock(&ff->bfl);
   3276 	switch ((unsigned long) cmd) {
   3277 #ifdef SUPPORT_I_FLAGS
   3278 	case EXT2_IOC_GETFLAGS:
   3279 		ret = ioctl_getflags(fs, fh, data);
   3280 		break;
   3281 	case EXT2_IOC_SETFLAGS:
   3282 		ret = ioctl_setflags(fs, fh, data);
   3283 		break;
   3284 	case EXT2_IOC_GETVERSION:
   3285 		ret = ioctl_getversion(fs, fh, data);
   3286 		break;
   3287 	case EXT2_IOC_SETVERSION:
   3288 		ret = ioctl_setversion(fs, fh, data);
   3289 		break;
   3290 #endif
   3291 #ifdef FITRIM
   3292 	case FITRIM:
   3293 		ret = ioctl_fitrim(fs, fh, data);
   3294 		break;
   3295 #endif
   3296 	default:
   3297 		dbg_printf("%s: Unknown ioctl %d\n", __func__, cmd);
   3298 		ret = -ENOTTY;
   3299 	}
   3300 	pthread_mutex_unlock(&ff->bfl);
   3301 
   3302 	return ret;
   3303 }
   3304 #endif /* FUSE 28 */
   3305 
   3306 static int op_bmap(const char *path, size_t blocksize EXT2FS_ATTR((unused)),
   3307 		   uint64_t *idx)
   3308 {
   3309 	struct fuse_context *ctxt = fuse_get_context();
   3310 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   3311 	ext2_filsys fs;
   3312 	ext2_ino_t ino;
   3313 	errcode_t err;
   3314 	int ret = 0;
   3315 
   3316 	FUSE2FS_CHECK_CONTEXT(ff);
   3317 	fs = ff->fs;
   3318 	pthread_mutex_lock(&ff->bfl);
   3319 	err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
   3320 	if (err) {
   3321 		ret = translate_error(fs, 0, err);
   3322 		goto out;
   3323 	}
   3324 	dbg_printf("%s: ino=%d blk=%"PRIu64"\n", __func__, ino, *idx);
   3325 
   3326 	err = ext2fs_bmap2(fs, ino, NULL, NULL, 0, *idx, 0, (blk64_t *)idx);
   3327 	if (err) {
   3328 		ret = translate_error(fs, ino, err);
   3329 		goto out;
   3330 	}
   3331 
   3332 out:
   3333 	pthread_mutex_unlock(&ff->bfl);
   3334 	return ret;
   3335 }
   3336 
   3337 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
   3338 # ifdef SUPPORT_FALLOCATE
   3339 static int fallocate_helper(struct fuse_file_info *fp, int mode, off_t offset,
   3340 			    off_t len)
   3341 {
   3342 	struct fuse_context *ctxt = fuse_get_context();
   3343 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   3344 	struct fuse2fs_file_handle *fh =
   3345 		(struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
   3346 	ext2_filsys fs;
   3347 	struct ext2_inode_large inode;
   3348 	blk64_t start, end;
   3349 	__u64 fsize;
   3350 	errcode_t err;
   3351 	int flags;
   3352 
   3353 	FUSE2FS_CHECK_CONTEXT(ff);
   3354 	fs = ff->fs;
   3355 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   3356 	start = offset / fs->blocksize;
   3357 	end = (offset + len - 1) / fs->blocksize;
   3358 	dbg_printf("%s: ino=%d mode=0x%x start=%jd end=%llu\n", __func__,
   3359 		   fh->ino, mode, offset / fs->blocksize, end);
   3360 	if (!fs_can_allocate(ff, len / fs->blocksize))
   3361 		return -ENOSPC;
   3362 
   3363 	memset(&inode, 0, sizeof(inode));
   3364 	err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
   3365 				     sizeof(inode));
   3366 	if (err)
   3367 		return err;
   3368 	fsize = EXT2_I_SIZE(&inode);
   3369 
   3370 	/* Allocate a bunch of blocks */
   3371 	flags = (mode & FL_KEEP_SIZE_FLAG ? 0 :
   3372 			EXT2_FALLOCATE_INIT_BEYOND_EOF);
   3373 	err = ext2fs_fallocate(fs, flags, fh->ino,
   3374 			       (struct ext2_inode *)&inode,
   3375 			       ~0ULL, start, end - start + 1);
   3376 	if (err && err != EXT2_ET_BLOCK_ALLOC_FAIL)
   3377 		return translate_error(fs, fh->ino, err);
   3378 
   3379 	/* Update i_size */
   3380 	if (!(mode & FL_KEEP_SIZE_FLAG)) {
   3381 		if ((__u64) offset + len > fsize) {
   3382 			err = ext2fs_inode_size_set(fs,
   3383 						(struct ext2_inode *)&inode,
   3384 						offset + len);
   3385 			if (err)
   3386 				return translate_error(fs, fh->ino, err);
   3387 		}
   3388 	}
   3389 
   3390 	err = update_mtime(fs, fh->ino, &inode);
   3391 	if (err)
   3392 		return err;
   3393 
   3394 	err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
   3395 				      sizeof(inode));
   3396 	if (err)
   3397 		return translate_error(fs, fh->ino, err);
   3398 
   3399 	return err;
   3400 }
   3401 
   3402 static errcode_t clean_block_middle(ext2_filsys fs, ext2_ino_t ino,
   3403 				  struct ext2_inode_large *inode, off_t offset,
   3404 				  off_t len, char **buf)
   3405 {
   3406 	blk64_t blk;
   3407 	off_t residue;
   3408 	int retflags;
   3409 	errcode_t err;
   3410 
   3411 	residue = offset % fs->blocksize;
   3412 	if (residue == 0)
   3413 		return 0;
   3414 
   3415 	if (!*buf) {
   3416 		err = ext2fs_get_mem(fs->blocksize, buf);
   3417 		if (err)
   3418 			return err;
   3419 	}
   3420 
   3421 	err = ext2fs_bmap2(fs, ino, (struct ext2_inode *)inode, *buf, 0,
   3422 			   offset / fs->blocksize, &retflags, &blk);
   3423 	if (err)
   3424 		return err;
   3425 	if (!blk || (retflags & BMAP_RET_UNINIT))
   3426 		return 0;
   3427 
   3428 	err = io_channel_read_blk(fs->io, blk, 1, *buf);
   3429 	if (err)
   3430 		return err;
   3431 
   3432 	memset(*buf + residue, 0, len);
   3433 
   3434 	return io_channel_write_blk(fs->io, blk, 1, *buf);
   3435 }
   3436 
   3437 static errcode_t clean_block_edge(ext2_filsys fs, ext2_ino_t ino,
   3438 				  struct ext2_inode_large *inode, off_t offset,
   3439 				  int clean_before, char **buf)
   3440 {
   3441 	blk64_t blk;
   3442 	int retflags;
   3443 	off_t residue;
   3444 	errcode_t err;
   3445 
   3446 	residue = offset % fs->blocksize;
   3447 	if (residue == 0)
   3448 		return 0;
   3449 
   3450 	if (!*buf) {
   3451 		err = ext2fs_get_mem(fs->blocksize, buf);
   3452 		if (err)
   3453 			return err;
   3454 	}
   3455 
   3456 	err = ext2fs_bmap2(fs, ino, (struct ext2_inode *)inode, *buf, 0,
   3457 			   offset / fs->blocksize, &retflags, &blk);
   3458 	if (err)
   3459 		return err;
   3460 
   3461 	err = io_channel_read_blk(fs->io, blk, 1, *buf);
   3462 	if (err)
   3463 		return err;
   3464 	if (!blk || (retflags & BMAP_RET_UNINIT))
   3465 		return 0;
   3466 
   3467 	if (clean_before)
   3468 		memset(*buf, 0, residue);
   3469 	else
   3470 		memset(*buf + residue, 0, fs->blocksize - residue);
   3471 
   3472 	return io_channel_write_blk(fs->io, blk, 1, *buf);
   3473 }
   3474 
   3475 static int punch_helper(struct fuse_file_info *fp, int mode, off_t offset,
   3476 			off_t len)
   3477 {
   3478 	struct fuse_context *ctxt = fuse_get_context();
   3479 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   3480 	struct fuse2fs_file_handle *fh =
   3481 		(struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
   3482 	ext2_filsys fs;
   3483 	struct ext2_inode_large inode;
   3484 	blk64_t start, end;
   3485 	errcode_t err;
   3486 	char *buf = NULL;
   3487 
   3488 	FUSE2FS_CHECK_CONTEXT(ff);
   3489 	fs = ff->fs;
   3490 	FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
   3491 	dbg_printf("%s: offset=%jd len=%jd\n", __func__, offset, len);
   3492 
   3493 	/* kernel ext4 punch requires this flag to be set */
   3494 	if (!(mode & FL_KEEP_SIZE_FLAG))
   3495 		return -EINVAL;
   3496 
   3497 	/* Punch out a bunch of blocks */
   3498 	start = (offset + fs->blocksize - 1) / fs->blocksize;
   3499 	end = (offset + len - fs->blocksize) / fs->blocksize;
   3500 	dbg_printf("%s: ino=%d mode=0x%x start=%llu end=%llu\n", __func__,
   3501 		   fh->ino, mode, start, end);
   3502 
   3503 	memset(&inode, 0, sizeof(inode));
   3504 	err = ext2fs_read_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
   3505 				     sizeof(inode));
   3506 	if (err)
   3507 		return translate_error(fs, fh->ino, err);
   3508 
   3509 	/* Zero everything before the first block and after the last block */
   3510 	if ((offset / fs->blocksize) == ((offset + len) / fs->blocksize))
   3511 		err = clean_block_middle(fs, fh->ino, &inode, offset,
   3512 					 len, &buf);
   3513 	else {
   3514 		err = clean_block_edge(fs, fh->ino, &inode, offset, 0, &buf);
   3515 		if (!err)
   3516 			err = clean_block_edge(fs, fh->ino, &inode,
   3517 					       offset + len, 1, &buf);
   3518 	}
   3519 	if (buf)
   3520 		ext2fs_free_mem(&buf);
   3521 	if (err)
   3522 		return translate_error(fs, fh->ino, err);
   3523 
   3524 	/* Unmap full blocks in the middle */
   3525 	if (start <= end) {
   3526 		err = ext2fs_punch(fs, fh->ino, (struct ext2_inode *)&inode,
   3527 				   NULL, start, end);
   3528 		if (err)
   3529 			return translate_error(fs, fh->ino, err);
   3530 	}
   3531 
   3532 	err = update_mtime(fs, fh->ino, &inode);
   3533 	if (err)
   3534 		return err;
   3535 
   3536 	err = ext2fs_write_inode_full(fs, fh->ino, (struct ext2_inode *)&inode,
   3537 				      sizeof(inode));
   3538 	if (err)
   3539 		return translate_error(fs, fh->ino, err);
   3540 
   3541 	return 0;
   3542 }
   3543 
   3544 static int op_fallocate(const char *path EXT2FS_ATTR((unused)), int mode,
   3545 			off_t offset, off_t len,
   3546 			struct fuse_file_info *fp)
   3547 {
   3548 	struct fuse_context *ctxt = fuse_get_context();
   3549 	struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
   3550 	ext2_filsys fs = ff->fs;
   3551 	int ret;
   3552 
   3553 	/* Catch unknown flags */
   3554 	if (mode & ~(FL_PUNCH_HOLE_FLAG | FL_KEEP_SIZE_FLAG))
   3555 		return -EINVAL;
   3556 
   3557 	pthread_mutex_lock(&ff->bfl);
   3558 	if (!fs_writeable(fs)) {
   3559 		ret = -EROFS;
   3560 		goto out;
   3561 	}
   3562 	if (mode & FL_PUNCH_HOLE_FLAG)
   3563 		ret = punch_helper(fp, mode, offset, len);
   3564 	else
   3565 		ret = fallocate_helper(fp, mode, offset, len);
   3566 out:
   3567 	pthread_mutex_unlock(&ff->bfl);
   3568 
   3569 	return ret;
   3570 }
   3571 # endif /* SUPPORT_FALLOCATE */
   3572 #endif /* FUSE 29 */
   3573 
   3574 static struct fuse_operations fs_ops = {
   3575 	.init = op_init,
   3576 	.destroy = op_destroy,
   3577 	.getattr = op_getattr,
   3578 	.readlink = op_readlink,
   3579 	.mknod = op_mknod,
   3580 	.mkdir = op_mkdir,
   3581 	.unlink = op_unlink,
   3582 	.rmdir = op_rmdir,
   3583 	.symlink = op_symlink,
   3584 	.rename = op_rename,
   3585 	.link = op_link,
   3586 	.chmod = op_chmod,
   3587 	.chown = op_chown,
   3588 	.truncate = op_truncate,
   3589 	.open = op_open,
   3590 	.read = op_read,
   3591 	.write = op_write,
   3592 	.statfs = op_statfs,
   3593 	.release = op_release,
   3594 	.fsync = op_fsync,
   3595 	.setxattr = op_setxattr,
   3596 	.getxattr = op_getxattr,
   3597 	.listxattr = op_listxattr,
   3598 	.removexattr = op_removexattr,
   3599 	.opendir = op_open,
   3600 	.readdir = op_readdir,
   3601 	.releasedir = op_release,
   3602 	.fsyncdir = op_fsync,
   3603 	.access = op_access,
   3604 	.create = op_create,
   3605 	.ftruncate = op_ftruncate,
   3606 	.fgetattr = op_fgetattr,
   3607 	.utimens = op_utimens,
   3608 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
   3609 # if defined(UTIME_NOW) || defined(UTIME_OMIT)
   3610 	.flag_utime_omit_ok = 1,
   3611 # endif
   3612 #endif
   3613 	.bmap = op_bmap,
   3614 #ifdef SUPERFLUOUS
   3615 	.lock = op_lock,
   3616 	.poll = op_poll,
   3617 #endif
   3618 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
   3619 	.ioctl = op_ioctl,
   3620 	.flag_nullpath_ok = 1,
   3621 #endif
   3622 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
   3623 	.flag_nopath = 1,
   3624 # ifdef SUPPORT_FALLOCATE
   3625 	.fallocate = op_fallocate,
   3626 # endif
   3627 #endif
   3628 };
   3629 
   3630 static int get_random_bytes(void *p, size_t sz)
   3631 {
   3632 	int fd;
   3633 	ssize_t r;
   3634 
   3635 	fd = open("/dev/urandom", O_RDONLY);
   3636 	if (fd < 0) {
   3637 		perror("/dev/urandom");
   3638 		return 0;
   3639 	}
   3640 
   3641 	r = read(fd, p, sz);
   3642 
   3643 	close(fd);
   3644 	return (size_t) r == sz;
   3645 }
   3646 
   3647 enum {
   3648 	FUSE2FS_VERSION,
   3649 	FUSE2FS_HELP,
   3650 	FUSE2FS_HELPFULL,
   3651 };
   3652 
   3653 #define FUSE2FS_OPT(t, p, v) { t, offsetof(struct fuse2fs, p), v }
   3654 
   3655 static struct fuse_opt fuse2fs_opts[] = {
   3656 	FUSE2FS_OPT("ro",		ro,			1),
   3657 	FUSE2FS_OPT("errors=panic",	panic_on_error,		1),
   3658 	FUSE2FS_OPT("minixdf",		minixdf,		1),
   3659 	FUSE2FS_OPT("fuse2fs_debug",	debug,			1),
   3660 	FUSE2FS_OPT("no_default_opts",	no_default_opts,	1),
   3661 
   3662 	FUSE_OPT_KEY("-V",             FUSE2FS_VERSION),
   3663 	FUSE_OPT_KEY("--version",      FUSE2FS_VERSION),
   3664 	FUSE_OPT_KEY("-h",             FUSE2FS_HELP),
   3665 	FUSE_OPT_KEY("--help",         FUSE2FS_HELP),
   3666 	FUSE_OPT_KEY("--helpfull",     FUSE2FS_HELPFULL),
   3667 	FUSE_OPT_END
   3668 };
   3669 
   3670 
   3671 static int fuse2fs_opt_proc(void *data, const char *arg,
   3672 			    int key, struct fuse_args *outargs)
   3673 {
   3674 	struct fuse2fs *ff = data;
   3675 
   3676 	switch (key) {
   3677 	case FUSE_OPT_KEY_NONOPT:
   3678 		if (!ff->device) {
   3679 			ff->device = strdup(arg);
   3680 			return 0;
   3681 		}
   3682 		return 1;
   3683 	case FUSE2FS_HELP:
   3684 	case FUSE2FS_HELPFULL:
   3685 		fprintf(stderr,
   3686 	"usage: %s device/image mountpoint [options]\n"
   3687 	"\n"
   3688 	"general options:\n"
   3689 	"    -o opt,[opt...]  mount options\n"
   3690 	"    -h   --help      print help\n"
   3691 	"    -V   --version   print version\n"
   3692 	"\n"
   3693 	"fuse2fs options:\n"
   3694 	"    -o ro                  read-only mount\n"
   3695 	"    -o errors=panic        dump core on error\n"
   3696 	"    -o minixdf             minix-style df\n"
   3697 	"    -o no_default_opts     do not include default fuse options\n"
   3698 	"    -o fuse2fs_debug       enable fuse2fs debugging\n"
   3699 	"\n",
   3700 			outargs->argv[0]);
   3701 		if (key == FUSE2FS_HELPFULL) {
   3702 			fuse_opt_add_arg(outargs, "-ho");
   3703 			fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL);
   3704 		} else {
   3705 			fprintf(stderr, "Try --helpfull to get a list of "
   3706 				"all flags, including the FUSE options.\n");
   3707 		}
   3708 		exit(1);
   3709 
   3710 	case FUSE2FS_VERSION:
   3711 		fprintf(stderr, "fuse2fs %s (%s)\n", E2FSPROGS_VERSION,
   3712 			E2FSPROGS_DATE);
   3713 		fuse_opt_add_arg(outargs, "--version");
   3714 		fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL);
   3715 		exit(0);
   3716 	}
   3717 	return 1;
   3718 }
   3719 
   3720 int main(int argc, char *argv[])
   3721 {
   3722 	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
   3723 	struct fuse2fs fctx;
   3724 	errcode_t err;
   3725 	char *logfile;
   3726 	char extra_args[BUFSIZ];
   3727 	int ret = 0, flags = EXT2_FLAG_64BITS | EXT2_FLAG_EXCLUSIVE;
   3728 
   3729 	memset(&fctx, 0, sizeof(fctx));
   3730 	fctx.magic = FUSE2FS_MAGIC;
   3731 
   3732 	fuse_opt_parse(&args, &fctx, fuse2fs_opts, fuse2fs_opt_proc);
   3733 	if (fctx.device == NULL) {
   3734 		fprintf(stderr, "Missing ext4 device/image\n");
   3735 		fprintf(stderr, "See '%s -h' for usage\n", argv[0]);
   3736 		exit(1);
   3737 	}
   3738 
   3739 	if (fctx.ro)
   3740 		printf("%s", _("Mounting read-only.\n"));
   3741 
   3742 #ifdef ENABLE_NLS
   3743 	setlocale(LC_MESSAGES, "");
   3744 	setlocale(LC_CTYPE, "");
   3745 	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
   3746 	textdomain(NLS_CAT_NAME);
   3747 	set_com_err_gettext(gettext);
   3748 #endif
   3749 	add_error_table(&et_ext2_error_table);
   3750 
   3751 	/* Set up error logging */
   3752 	logfile = getenv("FUSE2FS_LOGFILE");
   3753 	if (logfile) {
   3754 		fctx.err_fp = fopen(logfile, "a");
   3755 		if (!fctx.err_fp) {
   3756 			perror(logfile);
   3757 			goto out_nofs;
   3758 		}
   3759 	} else
   3760 		fctx.err_fp = stderr;
   3761 
   3762 	/* Will we allow users to allocate every last block? */
   3763 	if (getenv("FUSE2FS_ALLOC_ALL_BLOCKS")) {
   3764 		printf(_("%s: Allowing users to allocate all blocks. "
   3765 		       "This is dangerous!\n"), fctx.device);
   3766 		fctx.alloc_all_blocks = 1;
   3767 	}
   3768 
   3769 	/* Start up the fs (while we still can use stdout) */
   3770 	ret = 2;
   3771 	if (!fctx.ro)
   3772 		flags |= EXT2_FLAG_RW;
   3773 	err = ext2fs_open2(fctx.device, NULL, flags, 0, 0, unix_io_manager,
   3774 			   &global_fs);
   3775 	if (err) {
   3776 		printf(_("%s: %s.\n"), fctx.device, error_message(err));
   3777 		printf(_("Please run e2fsck -fy %s.\n"), fctx.device);
   3778 		goto out_nofs;
   3779 	}
   3780 	fctx.fs = global_fs;
   3781 	global_fs->priv_data = &fctx;
   3782 
   3783 	ret = 3;
   3784 	if (ext2fs_has_feature_journal_needs_recovery(global_fs->super)) {
   3785 		if (!fctx.ro) {
   3786 			printf(_("%s: recovering journal\n"), fctx.device);
   3787 			err = ext2fs_run_ext3_journal(&global_fs);
   3788 			if (err) {
   3789 				printf(_("%s: %s.\n"), fctx.device,
   3790 				       error_message(err));
   3791 				printf(_("Please run e2fsck -fy %s.\n"),
   3792 				       fctx.device);
   3793 				goto out;
   3794 			}
   3795 			ext2fs_clear_feature_journal_needs_recovery(global_fs->super);
   3796 			ext2fs_mark_super_dirty(global_fs);
   3797 		} else {
   3798 			printf("%s", _("Journal needs recovery; running "
   3799 			       "`e2fsck -E journal_only' is required.\n"));
   3800 			goto out;
   3801 		}
   3802 	}
   3803 
   3804 	if (!fctx.ro) {
   3805 		if (ext2fs_has_feature_journal(global_fs->super))
   3806 			printf(_("%s: Writing to the journal is not supported.\n"),
   3807 			       fctx.device);
   3808 		err = ext2fs_read_inode_bitmap(global_fs);
   3809 		if (err) {
   3810 			translate_error(global_fs, 0, err);
   3811 			goto out;
   3812 		}
   3813 		err = ext2fs_read_block_bitmap(global_fs);
   3814 		if (err) {
   3815 			translate_error(global_fs, 0, err);
   3816 			goto out;
   3817 		}
   3818 	}
   3819 
   3820 	if (!(global_fs->super->s_state & EXT2_VALID_FS))
   3821 		printf("%s", _("Warning: Mounting unchecked fs, running e2fsck "
   3822 		       "is recommended.\n"));
   3823 	if (global_fs->super->s_max_mnt_count > 0 &&
   3824 	    global_fs->super->s_mnt_count >= global_fs->super->s_max_mnt_count)
   3825 		printf("%s", _("Warning: Maximal mount count reached, running "
   3826 		       "e2fsck is recommended.\n"));
   3827 	if (global_fs->super->s_checkinterval > 0 &&
   3828 	    (time_t) (global_fs->super->s_lastcheck +
   3829 		      global_fs->super->s_checkinterval) <= time(0))
   3830 		printf("%s", _("Warning: Check time reached; running e2fsck "
   3831 		       "is recommended.\n"));
   3832 	if (global_fs->super->s_last_orphan)
   3833 		printf("%s",
   3834 		       _("Orphans detected; running e2fsck is recommended.\n"));
   3835 
   3836 	if (global_fs->super->s_state & EXT2_ERROR_FS) {
   3837 		printf("%s",
   3838 		       _("Errors detected; running e2fsck is required.\n"));
   3839 		goto out;
   3840 	}
   3841 
   3842 	/* Initialize generation counter */
   3843 	get_random_bytes(&fctx.next_generation, sizeof(unsigned int));
   3844 
   3845 	/* Set up default fuse parameters */
   3846 	snprintf(extra_args, BUFSIZ, "-okernel_cache,subtype=ext4,use_ino,"
   3847 		 "fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS,
   3848 		 argv[1]);
   3849 	if (fctx.no_default_opts == 0)
   3850 		fuse_opt_add_arg(&args, extra_args);
   3851 
   3852 	if (fctx.debug) {
   3853 		int	i;
   3854 
   3855 		printf("fuse arguments:");
   3856 		for (i = 0; i < args.argc; i++)
   3857 			printf(" '%s'", args.argv[i]);
   3858 		printf("\n");
   3859 	}
   3860 
   3861 	pthread_mutex_init(&fctx.bfl, NULL);
   3862 	fuse_main(args.argc, args.argv, &fs_ops, &fctx);
   3863 	pthread_mutex_destroy(&fctx.bfl);
   3864 
   3865 	ret = 0;
   3866 out:
   3867 	err = ext2fs_close(global_fs);
   3868 	if (err)
   3869 		com_err(argv[0], err, "while closing fs");
   3870 	global_fs = NULL;
   3871 out_nofs:
   3872 
   3873 	return ret;
   3874 }
   3875 
   3876 static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino,
   3877 			     const char *file, int line)
   3878 {
   3879 	struct timespec now;
   3880 	int ret = err;
   3881 	struct fuse2fs *ff = fs->priv_data;
   3882 	int is_err = 0;
   3883 
   3884 	/* Translate ext2 error to unix error code */
   3885 	if (err < EXT2_ET_BASE)
   3886 		goto no_translation;
   3887 	switch (err) {
   3888 	case EXT2_ET_NO_MEMORY:
   3889 	case EXT2_ET_TDB_ERR_OOM:
   3890 		ret = -ENOMEM;
   3891 		break;
   3892 	case EXT2_ET_INVALID_ARGUMENT:
   3893 	case EXT2_ET_LLSEEK_FAILED:
   3894 		ret = -EINVAL;
   3895 		break;
   3896 	case EXT2_ET_NO_DIRECTORY:
   3897 		ret = -ENOTDIR;
   3898 		break;
   3899 	case EXT2_ET_FILE_NOT_FOUND:
   3900 		ret = -ENOENT;
   3901 		break;
   3902 	case EXT2_ET_DIR_NO_SPACE:
   3903 		is_err = 1;
   3904 	case EXT2_ET_TOOSMALL:
   3905 	case EXT2_ET_BLOCK_ALLOC_FAIL:
   3906 	case EXT2_ET_INODE_ALLOC_FAIL:
   3907 	case EXT2_ET_EA_NO_SPACE:
   3908 		ret = -ENOSPC;
   3909 		break;
   3910 	case EXT2_ET_SYMLINK_LOOP:
   3911 		ret = -EMLINK;
   3912 		break;
   3913 	case EXT2_ET_FILE_TOO_BIG:
   3914 		ret = -EFBIG;
   3915 		break;
   3916 	case EXT2_ET_TDB_ERR_EXISTS:
   3917 	case EXT2_ET_FILE_EXISTS:
   3918 		ret = -EEXIST;
   3919 		break;
   3920 	case EXT2_ET_MMP_FAILED:
   3921 	case EXT2_ET_MMP_FSCK_ON:
   3922 		ret = -EBUSY;
   3923 		break;
   3924 	case EXT2_ET_EA_KEY_NOT_FOUND:
   3925 #ifdef ENODATA
   3926 		ret = -ENODATA;
   3927 #else
   3928 		ret = -ENOENT;
   3929 #endif
   3930 		break;
   3931 	/* Sometimes fuse returns a garbage file handle pointer to us... */
   3932 	case EXT2_ET_MAGIC_EXT2_FILE:
   3933 		ret = -EFAULT;
   3934 		break;
   3935 	case EXT2_ET_UNIMPLEMENTED:
   3936 		ret = -EOPNOTSUPP;
   3937 		break;
   3938 	default:
   3939 		is_err = 1;
   3940 		ret = -EIO;
   3941 		break;
   3942 	}
   3943 
   3944 no_translation:
   3945 	if (!is_err)
   3946 		return ret;
   3947 
   3948 	if (ino)
   3949 		fprintf(ff->err_fp, "FUSE2FS (%s): %s (inode #%d) at %s:%d.\n",
   3950 			fs && fs->device_name ? fs->device_name : "???",
   3951 			error_message(err), ino, file, line);
   3952 	else
   3953 		fprintf(ff->err_fp, "FUSE2FS (%s): %s at %s:%d.\n",
   3954 			fs && fs->device_name ? fs->device_name : "???",
   3955 			error_message(err), file, line);
   3956 	fflush(ff->err_fp);
   3957 
   3958 	/* Make a note in the error log */
   3959 	get_now(&now);
   3960 	fs->super->s_last_error_time = now.tv_sec;
   3961 	fs->super->s_last_error_ino = ino;
   3962 	fs->super->s_last_error_line = line;
   3963 	fs->super->s_last_error_block = err; /* Yeah... */
   3964 	strncpy((char *)fs->super->s_last_error_func, file,
   3965 		sizeof(fs->super->s_last_error_func));
   3966 	if (fs->super->s_first_error_time == 0) {
   3967 		fs->super->s_first_error_time = now.tv_sec;
   3968 		fs->super->s_first_error_ino = ino;
   3969 		fs->super->s_first_error_line = line;
   3970 		fs->super->s_first_error_block = err;
   3971 		strncpy((char *)fs->super->s_first_error_func, file,
   3972 			sizeof(fs->super->s_first_error_func));
   3973 	}
   3974 
   3975 	fs->super->s_error_count++;
   3976 	ext2fs_mark_super_dirty(fs);
   3977 	ext2fs_flush(fs);
   3978 	if (ff->panic_on_error)
   3979 		abort();
   3980 
   3981 	return ret;
   3982 }
   3983