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