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