]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blob - misc/fuse2fs.c
4d42a634bf377b7dd60ddadfa085134e82584e67
[thirdparty/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 #ifndef _GNU_SOURCE
12 #define _GNU_SOURCE
13 #endif
14 #include "config.h"
15 #include <pthread.h>
16 #ifdef __linux__
17 # include <linux/fs.h>
18 # include <linux/falloc.h>
19 # include <linux/xattr.h>
20 #endif
21 #ifdef HAVE_SYS_XATTR_H
22 #include <sys/xattr.h>
23 #endif
24 #include <sys/ioctl.h>
25 #include <unistd.h>
26 #include <ctype.h>
27 #define FUSE_DARWIN_ENABLE_EXTENSIONS 0
28 #ifdef __SET_FOB_FOR_FUSE
29 # error Do not set magic value __SET_FOB_FOR_FUSE!!!!
30 #endif
31 #ifndef _FILE_OFFSET_BITS
32 /*
33 * Old versions of libfuse (e.g. Debian 2.9.9 package) required that the build
34 * system set _FILE_OFFSET_BITS explicitly, even if doing so isn't required to
35 * get a 64-bit off_t. AC_SYS_LARGEFILE doesn't set any _FILE_OFFSET_BITS if
36 * it's not required (such as on aarch64), so we must inject it here.
37 */
38 # define __SET_FOB_FOR_FUSE
39 # define _FILE_OFFSET_BITS 64
40 #endif /* _FILE_OFFSET_BITS */
41 #include <fuse.h>
42 #ifdef __SET_FOB_FOR_FUSE
43 # undef _FILE_OFFSET_BITS
44 #endif /* __SET_FOB_FOR_FUSE */
45 #include <inttypes.h>
46 #include "ext2fs/ext2fs.h"
47 #include "ext2fs/ext2_fs.h"
48 #include "ext2fs/ext2fsP.h"
49 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
50 # define FUSE_PLATFORM_OPTS ""
51 #else
52 # ifdef __linux__
53 # define FUSE_PLATFORM_OPTS ",use_ino,big_writes"
54 # else
55 # define FUSE_PLATFORM_OPTS ",use_ino"
56 # endif
57 #endif
58
59 #include "../version.h"
60 #include "uuid/uuid.h"
61 #include "e2p/e2p.h"
62
63 #ifdef ENABLE_NLS
64 #include <libintl.h>
65 #include <locale.h>
66 #define _(a) (gettext(a))
67 #ifdef gettext_noop
68 #define N_(a) gettext_noop(a)
69 #else
70 #define N_(a) (a)
71 #endif
72 #define P_(singular, plural, n) (ngettext(singular, plural, n))
73 #ifndef NLS_CAT_NAME
74 #define NLS_CAT_NAME "e2fsprogs"
75 #endif
76 #ifndef LOCALEDIR
77 #define LOCALEDIR "/usr/share/locale"
78 #endif
79 #else
80 #define _(a) (a)
81 #define N_(a) a
82 #define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural))
83 #endif
84
85 #ifndef XATTR_NAME_POSIX_ACL_DEFAULT
86 #define XATTR_NAME_POSIX_ACL_DEFAULT "posix_acl_default"
87 #endif
88 #ifndef XATTR_SECURITY_PREFIX
89 #define XATTR_SECURITY_PREFIX "security."
90 #define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1)
91 #endif
92
93 /*
94 * Linux and MacOS implement the setxattr(2) interface, which defines
95 * XATTR_CREATE and XATTR_REPLACE. However, FreeBSD uses
96 * extattr_set_file(2), which does not have a flags or options
97 * parameter, and does not define XATTR_CREATE and XATTR_REPLACE.
98 */
99 #ifndef XATTR_CREATE
100 #define XATTR_CREATE 0
101 #endif
102
103 #ifndef XATTR_REPLACE
104 #define XATTR_REPLACE 0
105 #endif
106
107 #if !defined(EUCLEAN)
108 #if !defined(EBADMSG)
109 #define EUCLEAN EBADMSG
110 #elif !defined(EPROTO)
111 #define EUCLEAN EPROTO
112 #else
113 #define EUCLEAN EIO
114 #endif
115 #endif /* !defined(EUCLEAN) */
116
117 #if !defined(ENODATA)
118 #ifdef ENOATTR
119 #define ENODATA ENOATTR
120 #else
121 #define ENODATA ENOENT
122 #endif
123 #endif /* !defined(ENODATA) */
124
125 static ext2_filsys global_fs; /* Try not to use this directly */
126
127 static inline uint64_t round_up(uint64_t b, unsigned int align)
128 {
129 unsigned int m;
130
131 if (align == 0)
132 return b;
133 m = b % align;
134 if (m)
135 b += align - m;
136 return b;
137 }
138
139 static inline uint64_t round_down(uint64_t b, unsigned int align)
140 {
141 unsigned int m;
142
143 if (align == 0)
144 return b;
145 m = b % align;
146 return b - m;
147 }
148
149 #define dbg_printf(fuse2fs, format, ...) \
150 while ((fuse2fs)->debug) { \
151 printf("FUSE2FS (%s): " format, (fuse2fs)->shortdev, ##__VA_ARGS__); \
152 fflush(stdout); \
153 break; \
154 }
155
156 #define log_printf(fuse2fs, format, ...) \
157 do { \
158 printf("FUSE2FS (%s): " format, (fuse2fs)->shortdev, ##__VA_ARGS__); \
159 fflush(stdout); \
160 } while (0)
161
162 #define err_printf(fuse2fs, format, ...) \
163 do { \
164 fprintf(stderr, "FUSE2FS (%s): " format, (fuse2fs)->shortdev, ##__VA_ARGS__); \
165 fflush(stderr); \
166 } while (0)
167
168 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
169 # ifdef _IOR
170 # ifdef _IOW
171 # define SUPPORT_I_FLAGS
172 # endif
173 # endif
174 #endif
175
176 #ifdef FALLOC_FL_KEEP_SIZE
177 # define FL_KEEP_SIZE_FLAG FALLOC_FL_KEEP_SIZE
178 # define SUPPORT_FALLOCATE
179 #else
180 # define FL_KEEP_SIZE_FLAG (0)
181 #endif
182
183 #ifdef FALLOC_FL_PUNCH_HOLE
184 # define FL_PUNCH_HOLE_FLAG FALLOC_FL_PUNCH_HOLE
185 #else
186 # define FL_PUNCH_HOLE_FLAG (0)
187 #endif
188
189 #ifdef FALLOC_FL_ZERO_RANGE
190 # define FL_ZERO_RANGE_FLAG FALLOC_FL_ZERO_RANGE
191 #else
192 # define FL_ZERO_RANGE_FLAG (0)
193 #endif
194
195 errcode_t ext2fs_run_ext3_journal(ext2_filsys *fs);
196
197 #ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jbd-debug */
198 int journal_enable_debug = -1;
199 #endif
200
201 /*
202 * ext2_file_t contains a struct inode, so we can't leave files open.
203 * Use this as a proxy instead.
204 */
205 #define FUSE2FS_FILE_MAGIC (0xEF53DEAFUL)
206 struct fuse2fs_file_handle {
207 unsigned long magic;
208 ext2_ino_t ino;
209 int open_flags;
210 };
211
212 /* Main program context */
213 #define FUSE2FS_MAGIC (0xEF53DEADUL)
214 struct fuse2fs {
215 unsigned long magic;
216 ext2_filsys fs;
217 pthread_mutex_t bfl;
218 char *device;
219 char *shortdev;
220 uint8_t ro;
221 uint8_t debug;
222 uint8_t no_default_opts;
223 uint8_t panic_on_error;
224 uint8_t minixdf;
225 uint8_t fakeroot;
226 uint8_t alloc_all_blocks;
227 uint8_t norecovery;
228 uint8_t kernel;
229 uint8_t directio;
230 uint8_t acl;
231
232 int logfd;
233 int blocklog;
234 unsigned int blockmask;
235 unsigned long offset;
236 unsigned int next_generation;
237 unsigned long long cache_size;
238 char *lockfile;
239 };
240
241 #define FUSE2FS_CHECK_MAGIC(fs, ptr, num) do {if ((ptr)->magic != (num)) \
242 return translate_error((fs), 0, EXT2_ET_FILESYSTEM_CORRUPTED); \
243 } while (0)
244
245 #define FUSE2FS_CHECK_CONTEXT(ptr) do {if ((ptr)->magic != FUSE2FS_MAGIC) \
246 return translate_error(global_fs, 0, EXT2_ET_FILESYSTEM_CORRUPTED); \
247 } while (0)
248
249 static int __translate_error(ext2_filsys fs, ext2_ino_t ino, errcode_t err,
250 const char *file, int line);
251 #define translate_error(fs, ino, err) __translate_error((fs), (ino), (err), \
252 __FILE__, __LINE__)
253
254 /* for macosx */
255 #ifndef W_OK
256 # define W_OK 2
257 #endif
258
259 #ifndef R_OK
260 # define R_OK 4
261 #endif
262
263 static inline int u_log2(unsigned int arg)
264 {
265 int l = 0;
266
267 arg >>= 1;
268 while (arg) {
269 l++;
270 arg >>= 1;
271 }
272 return l;
273 }
274
275 static inline blk64_t FUSE2FS_B_TO_FSBT(const struct fuse2fs *ff, off_t pos)
276 {
277 return pos >> ff->blocklog;
278 }
279
280 static inline blk64_t FUSE2FS_B_TO_FSB(const struct fuse2fs *ff, off_t pos)
281 {
282 return (pos + ff->blockmask) >> ff->blocklog;
283 }
284
285 static inline unsigned int FUSE2FS_OFF_IN_FSB(const struct fuse2fs *ff,
286 off_t pos)
287 {
288 return pos & ff->blockmask;
289 }
290
291 static inline off_t FUSE2FS_FSB_TO_B(const struct fuse2fs *ff, blk64_t bno)
292 {
293 return bno << ff->blocklog;
294 }
295
296 #define EXT4_EPOCH_BITS 2
297 #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
298 #define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS)
299
300 /*
301 * Extended fields will fit into an inode if the filesystem was formatted
302 * with large inodes (-I 256 or larger) and there are not currently any EAs
303 * consuming all of the available space. For new inodes we always reserve
304 * enough space for the kernel's known extended fields, but for inodes
305 * created with an old kernel this might not have been the case. None of
306 * the extended inode fields is critical for correct filesystem operation.
307 * This macro checks if a certain field fits in the inode. Note that
308 * inode-size = GOOD_OLD_INODE_SIZE + i_extra_isize
309 */
310 #define EXT4_FITS_IN_INODE(ext4_inode, field) \
311 ((offsetof(typeof(*ext4_inode), field) + \
312 sizeof((ext4_inode)->field)) \
313 <= ((size_t) EXT2_GOOD_OLD_INODE_SIZE + \
314 (ext4_inode)->i_extra_isize)) \
315
316 static inline __u32 ext4_encode_extra_time(const struct timespec *time)
317 {
318 __u32 extra = sizeof(time->tv_sec) > 4 ?
319 ((time->tv_sec - (__s32)time->tv_sec) >> 32) &
320 EXT4_EPOCH_MASK : 0;
321 return extra | (time->tv_nsec << EXT4_EPOCH_BITS);
322 }
323
324 static inline void ext4_decode_extra_time(struct timespec *time, __u32 extra)
325 {
326 if (sizeof(time->tv_sec) > 4 && (extra & EXT4_EPOCH_MASK)) {
327 __u64 extra_bits = extra & EXT4_EPOCH_MASK;
328 /*
329 * Prior to kernel 3.14?, we had a broken decode function,
330 * wherein we effectively did this:
331 * if (extra_bits == 3)
332 * extra_bits = 0;
333 */
334 time->tv_sec += extra_bits << 32;
335 }
336 time->tv_nsec = ((extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
337 }
338
339 #define EXT4_CLAMP_TIMESTAMP(xtime, timespec, raw_inode) \
340 do { \
341 if ((timespec)->tv_sec < EXT4_TIMESTAMP_MIN) \
342 (timespec)->tv_sec = EXT4_TIMESTAMP_MIN; \
343 if ((timespec)->tv_sec < EXT4_TIMESTAMP_MIN) \
344 (timespec)->tv_sec = EXT4_TIMESTAMP_MIN; \
345 \
346 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) { \
347 if ((timespec)->tv_sec > EXT4_EXTRA_TIMESTAMP_MAX) \
348 (timespec)->tv_sec = EXT4_EXTRA_TIMESTAMP_MAX; \
349 } else { \
350 if ((timespec)->tv_sec > EXT4_NON_EXTRA_TIMESTAMP_MAX) \
351 (timespec)->tv_sec = EXT4_NON_EXTRA_TIMESTAMP_MAX; \
352 } \
353 } while (0)
354
355 #define EXT4_INODE_SET_XTIME(xtime, timespec, raw_inode) \
356 do { \
357 typeof(*(timespec)) _ts = *(timespec); \
358 \
359 EXT4_CLAMP_TIMESTAMP(xtime, &_ts, raw_inode); \
360 (raw_inode)->xtime = _ts.tv_sec; \
361 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
362 (raw_inode)->xtime ## _extra = \
363 ext4_encode_extra_time(&_ts); \
364 } while (0)
365
366 #define EXT4_EINODE_SET_XTIME(xtime, timespec, raw_inode) \
367 do { \
368 typeof(*(timespec)) _ts = *(timespec); \
369 \
370 EXT4_CLAMP_TIMESTAMP(xtime, &_ts, raw_inode); \
371 if (EXT4_FITS_IN_INODE(raw_inode, xtime)) \
372 (raw_inode)->xtime = _ts.tv_sec; \
373 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
374 (raw_inode)->xtime ## _extra = \
375 ext4_encode_extra_time(&_ts); \
376 } while (0)
377
378 #define EXT4_INODE_GET_XTIME(xtime, timespec, raw_inode) \
379 do { \
380 (timespec)->tv_sec = (signed)((raw_inode)->xtime); \
381 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
382 ext4_decode_extra_time((timespec), \
383 (raw_inode)->xtime ## _extra); \
384 else \
385 (timespec)->tv_nsec = 0; \
386 } while (0)
387
388 #define EXT4_EINODE_GET_XTIME(xtime, timespec, raw_inode) \
389 do { \
390 if (EXT4_FITS_IN_INODE(raw_inode, xtime)) \
391 (timespec)->tv_sec = \
392 (signed)((raw_inode)->xtime); \
393 if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
394 ext4_decode_extra_time((timespec), \
395 raw_inode->xtime ## _extra); \
396 else \
397 (timespec)->tv_nsec = 0; \
398 } while (0)
399
400 static inline errcode_t fuse2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
401 struct ext2_inode_large *inode)
402 {
403 memset(inode, 0, sizeof(*inode));
404 return ext2fs_read_inode_full(fs, ino, EXT2_INODE(inode),
405 sizeof(*inode));
406 }
407
408 static inline errcode_t fuse2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
409 struct ext2_inode_large *inode)
410 {
411 return ext2fs_write_inode_full(fs, ino, EXT2_INODE(inode),
412 sizeof(*inode));
413 }
414
415 static void get_now(struct timespec *now)
416 {
417 #ifdef CLOCK_REALTIME
418 if (!clock_gettime(CLOCK_REALTIME, now))
419 return;
420 #endif
421
422 now->tv_sec = time(NULL);
423 now->tv_nsec = 0;
424 }
425
426 static void increment_version(struct ext2_inode_large *inode)
427 {
428 __u64 ver;
429
430 ver = inode->osd1.linux1.l_i_version;
431 if (EXT4_FITS_IN_INODE(inode, i_version_hi))
432 ver |= (__u64)inode->i_version_hi << 32;
433 ver++;
434 inode->osd1.linux1.l_i_version = ver;
435 if (EXT4_FITS_IN_INODE(inode, i_version_hi))
436 inode->i_version_hi = ver >> 32;
437 }
438
439 static void init_times(struct ext2_inode_large *inode)
440 {
441 struct timespec now;
442
443 get_now(&now);
444 EXT4_INODE_SET_XTIME(i_atime, &now, inode);
445 EXT4_INODE_SET_XTIME(i_ctime, &now, inode);
446 EXT4_INODE_SET_XTIME(i_mtime, &now, inode);
447 EXT4_EINODE_SET_XTIME(i_crtime, &now, inode);
448 increment_version(inode);
449 }
450
451 static int update_ctime(ext2_filsys fs, ext2_ino_t ino,
452 struct ext2_inode_large *pinode)
453 {
454 errcode_t err;
455 struct timespec now;
456 struct ext2_inode_large inode;
457
458 get_now(&now);
459
460 /* If user already has a inode buffer, just update that */
461 if (pinode) {
462 increment_version(pinode);
463 EXT4_INODE_SET_XTIME(i_ctime, &now, pinode);
464 return 0;
465 }
466
467 /* Otherwise we have to read-modify-write the inode */
468 err = fuse2fs_read_inode(fs, ino, &inode);
469 if (err)
470 return translate_error(fs, ino, err);
471
472 increment_version(&inode);
473 EXT4_INODE_SET_XTIME(i_ctime, &now, &inode);
474
475 err = fuse2fs_write_inode(fs, ino, &inode);
476 if (err)
477 return translate_error(fs, ino, err);
478
479 return 0;
480 }
481
482 static int update_atime(ext2_filsys fs, ext2_ino_t ino)
483 {
484 errcode_t err;
485 struct ext2_inode_large inode, *pinode;
486 struct timespec atime, mtime, now;
487 double datime, dmtime, dnow;
488
489 if (!(fs->flags & EXT2_FLAG_RW))
490 return 0;
491 err = fuse2fs_read_inode(fs, ino, &inode);
492 if (err)
493 return translate_error(fs, ino, err);
494
495 pinode = &inode;
496 EXT4_INODE_GET_XTIME(i_atime, &atime, pinode);
497 EXT4_INODE_GET_XTIME(i_mtime, &mtime, pinode);
498 get_now(&now);
499
500 datime = atime.tv_sec + ((double)atime.tv_nsec / 1000000000);
501 dmtime = mtime.tv_sec + ((double)mtime.tv_nsec / 1000000000);
502 dnow = now.tv_sec + ((double)now.tv_nsec / 1000000000);
503
504 /*
505 * If atime is newer than mtime and atime hasn't been updated in thirty
506 * seconds, skip the atime update. Same idea as Linux "relatime". Use
507 * doubles to account for nanosecond resolution.
508 */
509 if (datime >= dmtime && datime >= dnow - 30)
510 return 0;
511 EXT4_INODE_SET_XTIME(i_atime, &now, &inode);
512
513 err = fuse2fs_write_inode(fs, ino, &inode);
514 if (err)
515 return translate_error(fs, ino, err);
516
517 return 0;
518 }
519
520 static int update_mtime(ext2_filsys fs, ext2_ino_t ino,
521 struct ext2_inode_large *pinode)
522 {
523 errcode_t err;
524 struct ext2_inode_large inode;
525 struct timespec now;
526
527 if (pinode) {
528 get_now(&now);
529 EXT4_INODE_SET_XTIME(i_mtime, &now, pinode);
530 EXT4_INODE_SET_XTIME(i_ctime, &now, pinode);
531 increment_version(pinode);
532 return 0;
533 }
534
535 err = fuse2fs_read_inode(fs, ino, &inode);
536 if (err)
537 return translate_error(fs, ino, err);
538
539 get_now(&now);
540 EXT4_INODE_SET_XTIME(i_mtime, &now, &inode);
541 EXT4_INODE_SET_XTIME(i_ctime, &now, &inode);
542 increment_version(&inode);
543
544 err = fuse2fs_write_inode(fs, ino, &inode);
545 if (err)
546 return translate_error(fs, ino, err);
547
548 return 0;
549 }
550
551 static int ext2_file_type(unsigned int mode)
552 {
553 if (LINUX_S_ISREG(mode))
554 return EXT2_FT_REG_FILE;
555
556 if (LINUX_S_ISDIR(mode))
557 return EXT2_FT_DIR;
558
559 if (LINUX_S_ISCHR(mode))
560 return EXT2_FT_CHRDEV;
561
562 if (LINUX_S_ISBLK(mode))
563 return EXT2_FT_BLKDEV;
564
565 if (LINUX_S_ISLNK(mode))
566 return EXT2_FT_SYMLINK;
567
568 if (LINUX_S_ISFIFO(mode))
569 return EXT2_FT_FIFO;
570
571 if (LINUX_S_ISSOCK(mode))
572 return EXT2_FT_SOCK;
573
574 return 0;
575 }
576
577 static int fs_can_allocate(struct fuse2fs *ff, blk64_t num)
578 {
579 ext2_filsys fs = ff->fs;
580 blk64_t reserved;
581
582 dbg_printf(ff, "%s: Asking for %llu; alloc_all=%d total=%llu free=%llu "
583 "rsvd=%llu\n", __func__, num, ff->alloc_all_blocks,
584 ext2fs_blocks_count(fs->super),
585 ext2fs_free_blocks_count(fs->super),
586 ext2fs_r_blocks_count(fs->super));
587 if (num > ext2fs_blocks_count(fs->super))
588 return 0;
589
590 if (ff->alloc_all_blocks)
591 return 1;
592
593 /*
594 * Different meaning for r_blocks -- libext2fs has bugs where the FS
595 * can get corrupted if it totally runs out of blocks. Avoid this
596 * by refusing to allocate any of the reserve blocks to anybody.
597 */
598 reserved = ext2fs_r_blocks_count(fs->super);
599 if (reserved == 0)
600 reserved = ext2fs_blocks_count(fs->super) / 10;
601 return ext2fs_free_blocks_count(fs->super) > reserved + num;
602 }
603
604 static int fs_writeable(ext2_filsys fs)
605 {
606 return (fs->flags & EXT2_FLAG_RW) && (fs->super->s_error_count == 0);
607 }
608
609 static inline int is_superuser(struct fuse2fs *ff, struct fuse_context *ctxt)
610 {
611 if (ff->fakeroot)
612 return 1;
613 return ctxt->uid == 0;
614 }
615
616 static inline int want_check_owner(struct fuse2fs *ff,
617 struct fuse_context *ctxt)
618 {
619 /*
620 * The kernel is responsible for access control, so we allow anything
621 * that the superuser can do.
622 */
623 if (ff->kernel)
624 return 0;
625 return !is_superuser(ff, ctxt);
626 }
627
628 /* Test for append permission */
629 #define A_OK 16
630
631 static int check_iflags_access(struct fuse2fs *ff, ext2_ino_t ino,
632 const struct ext2_inode *inode, int mask)
633 {
634 ext2_filsys fs = ff->fs;
635
636 EXT2FS_BUILD_BUG_ON((A_OK & (R_OK | W_OK | X_OK | F_OK)) != 0);
637
638 /* no writing or metadata changes to read-only or broken fs */
639 if ((mask & (W_OK | A_OK)) && !fs_writeable(fs))
640 return -EROFS;
641
642 dbg_printf(ff, "access ino=%d mask=e%s%s%s%s iflags=0x%x\n",
643 ino,
644 (mask & R_OK ? "r" : ""),
645 (mask & W_OK ? "w" : ""),
646 (mask & X_OK ? "x" : ""),
647 (mask & A_OK ? "a" : ""),
648 inode->i_flags);
649
650 /* is immutable? */
651 if ((mask & W_OK) &&
652 (inode->i_flags & EXT2_IMMUTABLE_FL))
653 return -EPERM;
654
655 /* is append-only? */
656 if ((inode->i_flags & EXT2_APPEND_FL) && (mask & W_OK) && !(mask & A_OK))
657 return -EPERM;
658
659 return 0;
660 }
661
662 static int check_inum_access(struct fuse2fs *ff, ext2_ino_t ino, int mask)
663 {
664 struct fuse_context *ctxt = fuse_get_context();
665 ext2_filsys fs = ff->fs;
666 struct ext2_inode inode;
667 mode_t perms;
668 errcode_t err;
669 int ret;
670
671 /* no writing to read-only or broken fs */
672 if ((mask & (W_OK | A_OK)) && !fs_writeable(fs))
673 return -EROFS;
674
675 err = ext2fs_read_inode(fs, ino, &inode);
676 if (err)
677 return translate_error(fs, ino, err);
678 perms = inode.i_mode & 0777;
679
680 dbg_printf(ff, "access ino=%d mask=e%s%s%s%s perms=0%o iflags=0x%x "
681 "fuid=%d fgid=%d uid=%d gid=%d\n", ino,
682 (mask & R_OK ? "r" : ""),
683 (mask & W_OK ? "w" : ""),
684 (mask & X_OK ? "x" : ""),
685 (mask & A_OK ? "a" : ""),
686 perms, inode.i_flags,
687 inode_uid(inode), inode_gid(inode),
688 ctxt->uid, ctxt->gid);
689
690 /* existence check */
691 if (mask == 0)
692 return 0;
693
694 ret = check_iflags_access(ff, ino, &inode, mask);
695 if (ret)
696 return ret;
697
698 /* If kernel is responsible for mode and acl checks, we're done. */
699 if (ff->kernel)
700 return 0;
701
702 /* Figure out what root's allowed to do */
703 if (is_superuser(ff, ctxt)) {
704 /* Non-file access always ok */
705 if (!LINUX_S_ISREG(inode.i_mode))
706 return 0;
707
708 /* R/W access to a file always ok */
709 if (!(mask & X_OK))
710 return 0;
711
712 /* X access to a file ok if a user/group/other can X */
713 if (perms & 0111)
714 return 0;
715
716 /* Trying to execute a file that's not executable. BZZT! */
717 return -EACCES;
718 }
719
720 /* Remove the O_APPEND flag before testing permissions */
721 mask &= ~A_OK;
722
723 /* allow owner, if perms match */
724 if (inode_uid(inode) == ctxt->uid) {
725 if ((mask & (perms >> 6)) == mask)
726 return 0;
727 return -EACCES;
728 }
729
730 /* allow group, if perms match */
731 if (inode_gid(inode) == ctxt->gid) {
732 if ((mask & (perms >> 3)) == mask)
733 return 0;
734 return -EACCES;
735 }
736
737 /* otherwise check other */
738 if ((mask & perms) == mask)
739 return 0;
740 return -EACCES;
741 }
742
743 static void op_destroy(void *p EXT2FS_ATTR((unused)))
744 {
745 struct fuse_context *ctxt = fuse_get_context();
746 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
747 ext2_filsys fs;
748 errcode_t err;
749
750 if (ff->magic != FUSE2FS_MAGIC) {
751 translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC);
752 return;
753 }
754
755 pthread_mutex_lock(&ff->bfl);
756 fs = ff->fs;
757
758 dbg_printf(ff, "%s: dev=%s\n", __func__, fs->device_name);
759 if (fs->flags & EXT2_FLAG_RW) {
760 fs->super->s_state |= EXT2_VALID_FS;
761 if (fs->super->s_error_count)
762 fs->super->s_state |= EXT2_ERROR_FS;
763 ext2fs_mark_super_dirty(fs);
764 err = ext2fs_set_gdt_csum(fs);
765 if (err)
766 translate_error(fs, 0, err);
767
768 err = ext2fs_flush2(fs, 0);
769 if (err)
770 translate_error(fs, 0, err);
771 }
772
773 if (ff->debug && fs->io->manager->get_stats) {
774 io_stats stats = NULL;
775
776 fs->io->manager->get_stats(fs->io, &stats);
777 dbg_printf(ff, "read: %lluk\n", stats->bytes_read >> 10);
778 dbg_printf(ff, "write: %lluk\n", stats->bytes_written >> 10);
779 dbg_printf(ff, "hits: %llu\n", stats->cache_hits);
780 dbg_printf(ff, "misses: %llu\n", stats->cache_misses);
781 dbg_printf(ff, "hit_ratio: %.1f%%\n",
782 (100.0 * stats->cache_hits) /
783 (stats->cache_hits + stats->cache_misses));
784 }
785
786 if (ff->kernel) {
787 char uuid[UUID_STR_SIZE];
788
789 uuid_unparse(fs->super->s_uuid, uuid);
790 log_printf(ff, "%s %s.\n", _("unmounting filesystem"), uuid);
791 }
792
793 pthread_mutex_unlock(&ff->bfl);
794 }
795
796 /* Reopen @stream with @fileno */
797 static int fuse2fs_freopen_stream(const char *path, int fileno, FILE *stream)
798 {
799 char _fdpath[256];
800 const char *fdpath;
801 FILE *fp;
802 int ret;
803
804 ret = snprintf(_fdpath, sizeof(_fdpath), "/dev/fd/%d", fileno);
805 if (ret >= sizeof(_fdpath))
806 fdpath = path;
807 else
808 fdpath = _fdpath;
809
810 /*
811 * C23 defines std{out,err} as an expression of type FILE* that need
812 * not be an lvalue. What this means is that we can't just assign to
813 * stdout: we have to use freopen, which takes a path.
814 *
815 * There's no guarantee that the OS provides a /dev/fd/X alias for open
816 * file descriptors, so if that fails, fall back to the original log
817 * file path. We'd rather not do a path-based reopen because that
818 * exposes us to rename race attacks.
819 */
820 fp = freopen(fdpath, "a", stream);
821 if (!fp && errno == ENOENT && fdpath == _fdpath)
822 fp = freopen(path, "a", stream);
823 if (!fp) {
824 perror(fdpath);
825 return -1;
826 }
827
828 return 0;
829 }
830
831 /* Redirect stdout/stderr to a file, or return a mount-compatible error. */
832 static int fuse2fs_capture_output(struct fuse2fs *ff, const char *path)
833 {
834 int ret;
835 int fd;
836
837 /*
838 * First, open the log file path with system calls so that we can
839 * redirect the stdout/stderr file numbers (typically 1 and 2) to our
840 * logfile descriptor. We'd like to avoid allocating extra file
841 * objects in the kernel if we can because pos will be the same between
842 * stdout and stderr.
843 */
844 if (ff->logfd < 0) {
845 fd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0600);
846 if (fd < 0) {
847 perror(path);
848 return -1;
849 }
850
851 /*
852 * Save the newly opened fd in case we have to do this again in
853 * op_init.
854 */
855 ff->logfd = fd;
856 }
857
858 ret = dup2(ff->logfd, STDOUT_FILENO);
859 if (ret < 0) {
860 perror(path);
861 return -1;
862 }
863
864 ret = dup2(ff->logfd, STDERR_FILENO);
865 if (ret < 0) {
866 perror(path);
867 return -1;
868 }
869
870 /*
871 * Now that we've changed STD{OUT,ERR}_FILENO to be the log file, use
872 * freopen to make sure that std{out,err} (the C library abstractions)
873 * point to the STDXXX_FILENO because any of our library dependencies
874 * might decide to printf to one of those streams and we want to
875 * capture all output in the log.
876 */
877 ret = fuse2fs_freopen_stream(path, STDOUT_FILENO, stdout);
878 if (ret)
879 return ret;
880 ret = fuse2fs_freopen_stream(path, STDERR_FILENO, stderr);
881 if (ret)
882 return ret;
883
884 return 0;
885 }
886
887 /* Set up debug and error logging files */
888 static int fuse2fs_setup_logging(struct fuse2fs *ff)
889 {
890 char *logfile = getenv("FUSE2FS_LOGFILE");
891 if (logfile)
892 return fuse2fs_capture_output(ff, logfile);
893
894 /* in kernel mode, try to log errors to the kernel log */
895 if (ff->kernel)
896 fuse2fs_capture_output(ff, "/dev/ttyprintk");
897
898 return 0;
899 }
900
901 static void *op_init(struct fuse_conn_info *conn
902 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
903 , struct fuse_config *cfg EXT2FS_ATTR((unused))
904 #endif
905 )
906 {
907 struct fuse_context *ctxt = fuse_get_context();
908 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
909 ext2_filsys fs;
910 errcode_t err;
911
912 if (ff->magic != FUSE2FS_MAGIC) {
913 translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC);
914 return NULL;
915 }
916
917 /*
918 * Configure logging a second time, because libfuse might have
919 * redirected std{out,err} as part of daemonization. If this fails,
920 * give up and move on.
921 */
922 fuse2fs_setup_logging(ff);
923 if (ff->logfd >= 0)
924 close(ff->logfd);
925 ff->logfd = -1;
926
927 fs = ff->fs;
928 dbg_printf(ff, "%s: dev=%s\n", __func__, fs->device_name);
929 #ifdef FUSE_CAP_IOCTL_DIR
930 conn->want |= FUSE_CAP_IOCTL_DIR;
931 #endif
932 #ifdef FUSE_CAP_POSIX_ACL
933 if (ff->acl)
934 conn->want |= FUSE_CAP_POSIX_ACL;
935 #endif
936 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
937 conn->time_gran = 1;
938 cfg->use_ino = 1;
939 if (ff->debug)
940 cfg->debug = 1;
941 #endif
942 if (fs->flags & EXT2_FLAG_RW) {
943 fs->super->s_mnt_count++;
944 ext2fs_set_tstamp(fs->super, s_mtime, time(NULL));
945 fs->super->s_state &= ~EXT2_VALID_FS;
946 ext2fs_mark_super_dirty(fs);
947 err = ext2fs_flush2(fs, 0);
948 if (err)
949 translate_error(fs, 0, err);
950 }
951
952 if (ff->kernel) {
953 char uuid[UUID_STR_SIZE];
954
955 uuid_unparse(fs->super->s_uuid, uuid);
956 log_printf(ff, "%s %s.\n", _("mounted filesystem"), uuid);
957 }
958 return ff;
959 }
960
961 static int stat_inode(ext2_filsys fs, ext2_ino_t ino, struct stat *statbuf)
962 {
963 struct ext2_inode_large inode;
964 dev_t fakedev = 0;
965 errcode_t err;
966 int ret = 0;
967 struct timespec tv;
968
969 err = fuse2fs_read_inode(fs, ino, &inode);
970 if (err)
971 return translate_error(fs, ino, err);
972
973 memcpy(&fakedev, fs->super->s_uuid, sizeof(fakedev));
974 statbuf->st_dev = fakedev;
975 statbuf->st_ino = ino;
976 statbuf->st_mode = inode.i_mode;
977 statbuf->st_nlink = inode.i_links_count;
978 statbuf->st_uid = inode_uid(inode);
979 statbuf->st_gid = inode_gid(inode);
980 statbuf->st_size = EXT2_I_SIZE(&inode);
981 statbuf->st_blksize = fs->blocksize;
982 statbuf->st_blocks = ext2fs_get_stat_i_blocks(fs,
983 EXT2_INODE(&inode));
984 EXT4_INODE_GET_XTIME(i_atime, &tv, &inode);
985 #if HAVE_STRUCT_STAT_ST_ATIM
986 statbuf->st_atim = tv;
987 #else
988 statbuf->st_atime = tv.tv_sec;
989 #endif
990 EXT4_INODE_GET_XTIME(i_mtime, &tv, &inode);
991 #if HAVE_STRUCT_STAT_ST_ATIM
992 statbuf->st_mtim = tv;
993 #else
994 statbuf->st_mtime = tv.tv_sec;
995 #endif
996 EXT4_INODE_GET_XTIME(i_ctime, &tv, &inode);
997 #if HAVE_STRUCT_STAT_ST_ATIM
998 statbuf->st_ctim = tv;
999 #else
1000 statbuf->st_ctime = tv.tv_sec;
1001 #endif
1002 if (LINUX_S_ISCHR(inode.i_mode) ||
1003 LINUX_S_ISBLK(inode.i_mode)) {
1004 if (inode.i_block[0])
1005 statbuf->st_rdev = inode.i_block[0];
1006 else
1007 statbuf->st_rdev = inode.i_block[1];
1008 }
1009
1010 return ret;
1011 }
1012
1013 static int op_getattr(const char *path, struct stat *statbuf
1014 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1015 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
1016 #endif
1017 )
1018 {
1019 struct fuse_context *ctxt = fuse_get_context();
1020 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1021 ext2_filsys fs;
1022 ext2_ino_t ino;
1023 errcode_t err;
1024 int ret = 0;
1025
1026 FUSE2FS_CHECK_CONTEXT(ff);
1027 fs = ff->fs;
1028 dbg_printf(ff, "%s: path=%s\n", __func__, path);
1029 pthread_mutex_lock(&ff->bfl);
1030 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1031 if (err) {
1032 ret = translate_error(fs, 0, err);
1033 goto out;
1034 }
1035 ret = stat_inode(fs, ino, statbuf);
1036 out:
1037 pthread_mutex_unlock(&ff->bfl);
1038 return ret;
1039 }
1040
1041 static int op_readlink(const char *path, char *buf, size_t len)
1042 {
1043 struct fuse_context *ctxt = fuse_get_context();
1044 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1045 ext2_filsys fs;
1046 errcode_t err;
1047 ext2_ino_t ino;
1048 struct ext2_inode inode;
1049 unsigned int got;
1050 ext2_file_t file;
1051 int ret = 0;
1052
1053 FUSE2FS_CHECK_CONTEXT(ff);
1054 fs = ff->fs;
1055 dbg_printf(ff, "%s: path=%s\n", __func__, path);
1056 pthread_mutex_lock(&ff->bfl);
1057 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1058 if (err || ino == 0) {
1059 ret = translate_error(fs, 0, err);
1060 goto out;
1061 }
1062
1063 err = ext2fs_read_inode(fs, ino, &inode);
1064 if (err) {
1065 ret = translate_error(fs, ino, err);
1066 goto out;
1067 }
1068
1069 if (!LINUX_S_ISLNK(inode.i_mode)) {
1070 ret = -EINVAL;
1071 goto out;
1072 }
1073
1074 len--;
1075 if (inode.i_size < len)
1076 len = inode.i_size;
1077 if (ext2fs_is_fast_symlink(&inode))
1078 memcpy(buf, (char *)inode.i_block, len);
1079 else {
1080 /* big/inline symlink */
1081
1082 err = ext2fs_file_open(fs, ino, 0, &file);
1083 if (err) {
1084 ret = translate_error(fs, ino, err);
1085 goto out;
1086 }
1087
1088 err = ext2fs_file_read(file, buf, len, &got);
1089 if (err || got != len) {
1090 ext2fs_file_close(file);
1091 ret = translate_error(fs, ino, err);
1092 goto out2;
1093 }
1094
1095 out2:
1096 err = ext2fs_file_close(file);
1097 if (ret)
1098 goto out;
1099 if (err) {
1100 ret = translate_error(fs, ino, err);
1101 goto out;
1102 }
1103 }
1104 buf[len] = 0;
1105
1106 if (fs_writeable(fs)) {
1107 ret = update_atime(fs, ino);
1108 if (ret)
1109 goto out;
1110 }
1111
1112 out:
1113 pthread_mutex_unlock(&ff->bfl);
1114 return ret;
1115 }
1116
1117 static int __getxattr(struct fuse2fs *ff, ext2_ino_t ino, const char *name,
1118 void **value, size_t *value_len)
1119 {
1120 ext2_filsys fs = ff->fs;
1121 struct ext2_xattr_handle *h;
1122 errcode_t err;
1123 int ret = 0;
1124
1125 err = ext2fs_xattrs_open(fs, ino, &h);
1126 if (err)
1127 return translate_error(fs, ino, err);
1128
1129 err = ext2fs_xattrs_read(h);
1130 if (err) {
1131 ret = translate_error(fs, ino, err);
1132 goto out_close;
1133 }
1134
1135 err = ext2fs_xattr_get(h, name, value, value_len);
1136 if (err) {
1137 ret = translate_error(fs, ino, err);
1138 goto out_close;
1139 }
1140
1141 out_close:
1142 err = ext2fs_xattrs_close(&h);
1143 if (err && !ret)
1144 ret = translate_error(fs, ino, err);
1145 return ret;
1146 }
1147
1148 static int __setxattr(struct fuse2fs *ff, ext2_ino_t ino, const char *name,
1149 void *value, size_t valuelen)
1150 {
1151 ext2_filsys fs = ff->fs;
1152 struct ext2_xattr_handle *h;
1153 errcode_t err;
1154 int ret = 0;
1155
1156 err = ext2fs_xattrs_open(fs, ino, &h);
1157 if (err)
1158 return translate_error(fs, ino, err);
1159
1160 err = ext2fs_xattrs_read(h);
1161 if (err) {
1162 ret = translate_error(fs, ino, err);
1163 goto out_close;
1164 }
1165
1166 err = ext2fs_xattr_set(h, name, value, valuelen);
1167 if (err) {
1168 ret = translate_error(fs, ino, err);
1169 goto out_close;
1170 }
1171
1172 out_close:
1173 err = ext2fs_xattrs_close(&h);
1174 if (err && !ret)
1175 ret = translate_error(fs, ino, err);
1176 return ret;
1177 }
1178
1179 static int propagate_default_acls(struct fuse2fs *ff, ext2_ino_t parent,
1180 ext2_ino_t child)
1181 {
1182 void *def;
1183 size_t deflen;
1184 int ret;
1185
1186 if (!ff->acl)
1187 return 0;
1188
1189 ret = __getxattr(ff, parent, XATTR_NAME_POSIX_ACL_DEFAULT, &def,
1190 &deflen);
1191 switch (ret) {
1192 case -ENODATA:
1193 case -ENOENT:
1194 /* no default acl */
1195 return 0;
1196 case 0:
1197 break;
1198 default:
1199 return ret;
1200 }
1201
1202 ret = __setxattr(ff, child, XATTR_NAME_POSIX_ACL_DEFAULT, def, deflen);
1203 ext2fs_free_mem(&def);
1204 return ret;
1205 }
1206
1207 static inline void fuse2fs_set_uid(struct ext2_inode_large *inode, uid_t uid)
1208 {
1209 inode->i_uid = uid;
1210 ext2fs_set_i_uid_high(*inode, uid >> 16);
1211 }
1212
1213 static inline void fuse2fs_set_gid(struct ext2_inode_large *inode, gid_t gid)
1214 {
1215 inode->i_gid = gid;
1216 ext2fs_set_i_gid_high(*inode, gid >> 16);
1217 }
1218
1219 static int fuse2fs_new_child_gid(struct fuse2fs *ff, ext2_ino_t parent,
1220 gid_t *gid, int *parent_sgid)
1221 {
1222 struct ext2_inode_large inode;
1223 struct fuse_context *ctxt = fuse_get_context();
1224 errcode_t err;
1225
1226 err = fuse2fs_read_inode(ff->fs, parent, &inode);
1227 if (err)
1228 return translate_error(ff->fs, parent, err);
1229
1230 if (inode.i_mode & S_ISGID) {
1231 if (parent_sgid)
1232 *parent_sgid = 1;
1233 *gid = inode.i_gid;
1234 } else {
1235 if (parent_sgid)
1236 *parent_sgid = 0;
1237 *gid = ctxt->gid;
1238 }
1239
1240 return 0;
1241 }
1242
1243 static int op_mknod(const char *path, mode_t mode, dev_t dev)
1244 {
1245 struct fuse_context *ctxt = fuse_get_context();
1246 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1247 ext2_filsys fs;
1248 ext2_ino_t parent, child;
1249 char *temp_path;
1250 errcode_t err;
1251 char *node_name, a;
1252 int filetype;
1253 struct ext2_inode_large inode;
1254 gid_t gid;
1255 int ret = 0;
1256
1257 FUSE2FS_CHECK_CONTEXT(ff);
1258 fs = ff->fs;
1259 dbg_printf(ff, "%s: path=%s mode=0%o dev=0x%x\n", __func__, path, mode,
1260 (unsigned int)dev);
1261 temp_path = strdup(path);
1262 if (!temp_path) {
1263 ret = -ENOMEM;
1264 goto out;
1265 }
1266 node_name = strrchr(temp_path, '/');
1267 if (!node_name) {
1268 ret = -ENOMEM;
1269 goto out;
1270 }
1271 node_name++;
1272 a = *node_name;
1273 *node_name = 0;
1274
1275 pthread_mutex_lock(&ff->bfl);
1276 if (!fs_can_allocate(ff, 2)) {
1277 ret = -ENOSPC;
1278 goto out2;
1279 }
1280
1281 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1282 &parent);
1283 if (err) {
1284 ret = translate_error(fs, 0, err);
1285 goto out2;
1286 }
1287
1288 ret = check_inum_access(ff, parent, A_OK | W_OK);
1289 if (ret)
1290 goto out2;
1291
1292 *node_name = a;
1293
1294 if (LINUX_S_ISCHR(mode))
1295 filetype = EXT2_FT_CHRDEV;
1296 else if (LINUX_S_ISBLK(mode))
1297 filetype = EXT2_FT_BLKDEV;
1298 else if (LINUX_S_ISFIFO(mode))
1299 filetype = EXT2_FT_FIFO;
1300 else if (LINUX_S_ISSOCK(mode))
1301 filetype = EXT2_FT_SOCK;
1302 else {
1303 ret = -EINVAL;
1304 goto out2;
1305 }
1306
1307 err = fuse2fs_new_child_gid(ff, parent, &gid, NULL);
1308 if (err)
1309 goto out2;
1310
1311 err = ext2fs_new_inode(fs, parent, mode, 0, &child);
1312 if (err) {
1313 ret = translate_error(fs, 0, err);
1314 goto out2;
1315 }
1316
1317 dbg_printf(ff, "%s: create ino=%d/name=%s in dir=%d\n", __func__, child,
1318 node_name, parent);
1319 err = ext2fs_link(fs, parent, node_name, child,
1320 filetype | EXT2FS_LINK_EXPAND);
1321 if (err) {
1322 ret = translate_error(fs, parent, err);
1323 goto out2;
1324 }
1325
1326 ret = update_mtime(fs, parent, NULL);
1327 if (ret)
1328 goto out2;
1329
1330 memset(&inode, 0, sizeof(inode));
1331 inode.i_mode = mode;
1332
1333 if (dev & ~0xFFFF)
1334 inode.i_block[1] = dev;
1335 else
1336 inode.i_block[0] = dev;
1337 inode.i_links_count = 1;
1338 inode.i_extra_isize = sizeof(struct ext2_inode_large) -
1339 EXT2_GOOD_OLD_INODE_SIZE;
1340 fuse2fs_set_uid(&inode, ctxt->uid);
1341 fuse2fs_set_gid(&inode, gid);
1342
1343 err = ext2fs_write_new_inode(fs, child, EXT2_INODE(&inode));
1344 if (err) {
1345 ret = translate_error(fs, child, err);
1346 goto out2;
1347 }
1348
1349 inode.i_generation = ff->next_generation++;
1350 init_times(&inode);
1351 err = fuse2fs_write_inode(fs, child, &inode);
1352 if (err) {
1353 ret = translate_error(fs, child, err);
1354 goto out2;
1355 }
1356
1357 ext2fs_inode_alloc_stats2(fs, child, 1, 0);
1358
1359 ret = propagate_default_acls(ff, parent, child);
1360 if (ret)
1361 goto out2;
1362 out2:
1363 pthread_mutex_unlock(&ff->bfl);
1364 out:
1365 free(temp_path);
1366 return ret;
1367 }
1368
1369 static int op_mkdir(const char *path, mode_t mode)
1370 {
1371 struct fuse_context *ctxt = fuse_get_context();
1372 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1373 ext2_filsys fs;
1374 ext2_ino_t parent, child;
1375 char *temp_path;
1376 errcode_t err;
1377 char *node_name, a;
1378 struct ext2_inode_large inode;
1379 char *block;
1380 blk64_t blk;
1381 int ret = 0;
1382 gid_t gid;
1383 int parent_sgid;
1384
1385 FUSE2FS_CHECK_CONTEXT(ff);
1386 fs = ff->fs;
1387 dbg_printf(ff, "%s: path=%s mode=0%o\n", __func__, path, mode);
1388 temp_path = strdup(path);
1389 if (!temp_path) {
1390 ret = -ENOMEM;
1391 goto out;
1392 }
1393 node_name = strrchr(temp_path, '/');
1394 if (!node_name) {
1395 ret = -ENOMEM;
1396 goto out;
1397 }
1398 node_name++;
1399 a = *node_name;
1400 *node_name = 0;
1401
1402 pthread_mutex_lock(&ff->bfl);
1403 if (!fs_can_allocate(ff, 1)) {
1404 ret = -ENOSPC;
1405 goto out2;
1406 }
1407
1408 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1409 &parent);
1410 if (err) {
1411 ret = translate_error(fs, 0, err);
1412 goto out2;
1413 }
1414
1415 ret = check_inum_access(ff, parent, A_OK | W_OK);
1416 if (ret)
1417 goto out2;
1418
1419 err = fuse2fs_new_child_gid(ff, parent, &gid, &parent_sgid);
1420 if (err)
1421 goto out2;
1422
1423 *node_name = a;
1424
1425 err = ext2fs_mkdir2(fs, parent, 0, 0, EXT2FS_LINK_EXPAND,
1426 node_name, NULL);
1427 if (err) {
1428 ret = translate_error(fs, parent, err);
1429 goto out2;
1430 }
1431
1432 ret = update_mtime(fs, parent, NULL);
1433 if (ret)
1434 goto out2;
1435
1436 /* Still have to update the uid/gid of the dir */
1437 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1438 &child);
1439 if (err) {
1440 ret = translate_error(fs, 0, err);
1441 goto out2;
1442 }
1443 dbg_printf(ff, "%s: created ino=%d/path=%s in dir=%d\n", __func__, child,
1444 node_name, parent);
1445
1446 err = fuse2fs_read_inode(fs, child, &inode);
1447 if (err) {
1448 ret = translate_error(fs, child, err);
1449 goto out2;
1450 }
1451
1452 fuse2fs_set_uid(&inode, ctxt->uid);
1453 fuse2fs_set_gid(&inode, gid);
1454 inode.i_mode = LINUX_S_IFDIR | (mode & ~S_ISUID);
1455 if (parent_sgid)
1456 inode.i_mode |= S_ISGID;
1457 inode.i_generation = ff->next_generation++;
1458 init_times(&inode);
1459
1460 err = fuse2fs_write_inode(fs, child, &inode);
1461 if (err) {
1462 ret = translate_error(fs, child, err);
1463 goto out2;
1464 }
1465
1466 /* Rewrite the directory block checksum, having set i_generation */
1467 if ((inode.i_flags & EXT4_INLINE_DATA_FL) ||
1468 !ext2fs_has_feature_metadata_csum(fs->super))
1469 goto out2;
1470 err = ext2fs_new_dir_block(fs, child, parent, &block);
1471 if (err) {
1472 ret = translate_error(fs, child, err);
1473 goto out2;
1474 }
1475 err = ext2fs_bmap2(fs, child, EXT2_INODE(&inode), NULL, 0, 0,
1476 NULL, &blk);
1477 if (err) {
1478 ret = translate_error(fs, child, err);
1479 goto out3;
1480 }
1481 err = ext2fs_write_dir_block4(fs, blk, block, 0, child);
1482 if (err) {
1483 ret = translate_error(fs, child, err);
1484 goto out3;
1485 }
1486
1487 ret = propagate_default_acls(ff, parent, child);
1488 if (ret)
1489 goto out3;
1490
1491 out3:
1492 ext2fs_free_mem(&block);
1493 out2:
1494 pthread_mutex_unlock(&ff->bfl);
1495 out:
1496 free(temp_path);
1497 return ret;
1498 }
1499
1500 static int unlink_file_by_name(struct fuse2fs *ff, const char *path)
1501 {
1502 ext2_filsys fs = ff->fs;
1503 errcode_t err;
1504 ext2_ino_t dir;
1505 char *filename = strdup(path);
1506 char *base_name;
1507 int ret;
1508
1509 base_name = strrchr(filename, '/');
1510 if (base_name) {
1511 *base_name++ = '\0';
1512 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, filename,
1513 &dir);
1514 if (err) {
1515 free(filename);
1516 return translate_error(fs, 0, err);
1517 }
1518 } else {
1519 dir = EXT2_ROOT_INO;
1520 base_name = filename;
1521 }
1522
1523 ret = check_inum_access(ff, dir, W_OK);
1524 if (ret) {
1525 free(filename);
1526 return ret;
1527 }
1528
1529 dbg_printf(ff, "%s: unlinking name=%s from dir=%d\n", __func__,
1530 base_name, dir);
1531 err = ext2fs_unlink(fs, dir, base_name, 0, 0);
1532 free(filename);
1533 if (err)
1534 return translate_error(fs, dir, err);
1535
1536 return update_mtime(fs, dir, NULL);
1537 }
1538
1539 static errcode_t remove_ea_inodes(struct fuse2fs *ff, ext2_ino_t ino,
1540 struct ext2_inode_large *inode)
1541 {
1542 ext2_filsys fs = ff->fs;
1543 struct ext2_xattr_handle *h;
1544 errcode_t err;
1545
1546 /*
1547 * The xattr handle maintains its own private copy of the inode, so
1548 * write ours to disk so that we can read it.
1549 */
1550 err = fuse2fs_write_inode(fs, ino, inode);
1551 if (err)
1552 return err;
1553
1554 err = ext2fs_xattrs_open(fs, ino, &h);
1555 if (err)
1556 return err;
1557
1558 err = ext2fs_xattrs_read(h);
1559 if (err)
1560 goto out_close;
1561
1562 err = ext2fs_xattr_remove_all(h);
1563 if (err)
1564 goto out_close;
1565
1566 out_close:
1567 ext2fs_xattrs_close(&h);
1568
1569 /* Now read the inode back in. */
1570 return fuse2fs_read_inode(fs, ino, inode);
1571 }
1572
1573 static int remove_inode(struct fuse2fs *ff, ext2_ino_t ino)
1574 {
1575 ext2_filsys fs = ff->fs;
1576 errcode_t err;
1577 struct ext2_inode_large inode;
1578 int ret = 0;
1579
1580 err = fuse2fs_read_inode(fs, ino, &inode);
1581 if (err) {
1582 ret = translate_error(fs, ino, err);
1583 goto out;
1584 }
1585 dbg_printf(ff, "%s: put ino=%d links=%d\n", __func__, ino,
1586 inode.i_links_count);
1587
1588 switch (inode.i_links_count) {
1589 case 0:
1590 return 0; /* XXX: already done? */
1591 case 1:
1592 inode.i_links_count--;
1593 ext2fs_set_dtime(fs, EXT2_INODE(&inode));
1594 break;
1595 default:
1596 inode.i_links_count--;
1597 }
1598
1599 ret = update_ctime(fs, ino, &inode);
1600 if (ret)
1601 goto out;
1602
1603 if (inode.i_links_count)
1604 goto write_out;
1605
1606 if (ext2fs_has_feature_ea_inode(fs->super)) {
1607 err = remove_ea_inodes(ff, ino, &inode);
1608 if (err)
1609 goto write_out;
1610 }
1611
1612 /* Nobody holds this file; free its blocks! */
1613 err = ext2fs_free_ext_attr(fs, ino, &inode);
1614 if (err)
1615 goto write_out;
1616
1617 if (ext2fs_inode_has_valid_blocks2(fs, EXT2_INODE(&inode))) {
1618 err = ext2fs_punch(fs, ino, EXT2_INODE(&inode), NULL,
1619 0, ~0ULL);
1620 if (err) {
1621 ret = translate_error(fs, ino, err);
1622 goto write_out;
1623 }
1624 }
1625
1626 ext2fs_inode_alloc_stats2(fs, ino, -1,
1627 LINUX_S_ISDIR(inode.i_mode));
1628
1629 write_out:
1630 err = fuse2fs_write_inode(fs, ino, &inode);
1631 if (err) {
1632 ret = translate_error(fs, ino, err);
1633 goto out;
1634 }
1635 out:
1636 return ret;
1637 }
1638
1639 static int __op_unlink(struct fuse2fs *ff, const char *path)
1640 {
1641 ext2_filsys fs = ff->fs;
1642 ext2_ino_t ino;
1643 errcode_t err;
1644 int ret = 0;
1645
1646 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
1647 if (err) {
1648 ret = translate_error(fs, 0, err);
1649 goto out;
1650 }
1651
1652 ret = check_inum_access(ff, ino, W_OK);
1653 if (ret)
1654 goto out;
1655
1656 ret = unlink_file_by_name(ff, path);
1657 if (ret)
1658 goto out;
1659
1660 ret = remove_inode(ff, ino);
1661 if (ret)
1662 goto out;
1663 out:
1664 return ret;
1665 }
1666
1667 static int op_unlink(const char *path)
1668 {
1669 struct fuse_context *ctxt = fuse_get_context();
1670 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1671 int ret;
1672
1673 FUSE2FS_CHECK_CONTEXT(ff);
1674 pthread_mutex_lock(&ff->bfl);
1675 ret = __op_unlink(ff, path);
1676 pthread_mutex_unlock(&ff->bfl);
1677 return ret;
1678 }
1679
1680 struct rd_struct {
1681 ext2_ino_t parent;
1682 int empty;
1683 };
1684
1685 static int rmdir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
1686 int entry EXT2FS_ATTR((unused)),
1687 struct ext2_dir_entry *dirent,
1688 int offset EXT2FS_ATTR((unused)),
1689 int blocksize EXT2FS_ATTR((unused)),
1690 char *buf EXT2FS_ATTR((unused)),
1691 void *private)
1692 {
1693 struct rd_struct *rds = (struct rd_struct *) private;
1694
1695 if (dirent->inode == 0)
1696 return 0;
1697 if (((dirent->name_len & 0xFF) == 1) && (dirent->name[0] == '.'))
1698 return 0;
1699 if (((dirent->name_len & 0xFF) == 2) && (dirent->name[0] == '.') &&
1700 (dirent->name[1] == '.')) {
1701 rds->parent = dirent->inode;
1702 return 0;
1703 }
1704 rds->empty = 0;
1705 return 0;
1706 }
1707
1708 static int __op_rmdir(struct fuse2fs *ff, const char *path)
1709 {
1710 ext2_filsys fs = ff->fs;
1711 ext2_ino_t child;
1712 errcode_t err;
1713 struct ext2_inode_large inode;
1714 struct rd_struct rds;
1715 int ret = 0;
1716
1717 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &child);
1718 if (err) {
1719 ret = translate_error(fs, 0, err);
1720 goto out;
1721 }
1722 dbg_printf(ff, "%s: rmdir path=%s ino=%d\n", __func__, path, child);
1723
1724 ret = check_inum_access(ff, child, W_OK);
1725 if (ret)
1726 goto out;
1727
1728 rds.parent = 0;
1729 rds.empty = 1;
1730
1731 err = ext2fs_dir_iterate2(fs, child, 0, 0, rmdir_proc, &rds);
1732 if (err) {
1733 ret = translate_error(fs, child, err);
1734 goto out;
1735 }
1736
1737 /* the kernel checks parent permissions before emptiness */
1738 if (rds.parent == 0) {
1739 ret = translate_error(fs, child, EXT2_ET_FILESYSTEM_CORRUPTED);
1740 goto out;
1741 }
1742
1743 ret = check_inum_access(ff, rds.parent, W_OK);
1744 if (ret)
1745 goto out;
1746
1747 if (rds.empty == 0) {
1748 ret = -ENOTEMPTY;
1749 goto out;
1750 }
1751
1752 ret = unlink_file_by_name(ff, path);
1753 if (ret)
1754 goto out;
1755 /* Directories have to be "removed" twice. */
1756 ret = remove_inode(ff, child);
1757 if (ret)
1758 goto out;
1759 ret = remove_inode(ff, child);
1760 if (ret)
1761 goto out;
1762
1763 if (rds.parent) {
1764 dbg_printf(ff, "%s: decr dir=%d link count\n", __func__,
1765 rds.parent);
1766 err = fuse2fs_read_inode(fs, rds.parent, &inode);
1767 if (err) {
1768 ret = translate_error(fs, rds.parent, err);
1769 goto out;
1770 }
1771 if (inode.i_links_count > 1)
1772 inode.i_links_count--;
1773 ret = update_mtime(fs, rds.parent, &inode);
1774 if (ret)
1775 goto out;
1776 err = fuse2fs_write_inode(fs, rds.parent, &inode);
1777 if (err) {
1778 ret = translate_error(fs, rds.parent, err);
1779 goto out;
1780 }
1781 }
1782
1783 out:
1784 return ret;
1785 }
1786
1787 static int op_rmdir(const char *path)
1788 {
1789 struct fuse_context *ctxt = fuse_get_context();
1790 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1791 int ret;
1792
1793 FUSE2FS_CHECK_CONTEXT(ff);
1794 pthread_mutex_lock(&ff->bfl);
1795 ret = __op_rmdir(ff, path);
1796 pthread_mutex_unlock(&ff->bfl);
1797 return ret;
1798 }
1799
1800 static int op_symlink(const char *src, const char *dest)
1801 {
1802 struct fuse_context *ctxt = fuse_get_context();
1803 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1804 ext2_filsys fs;
1805 ext2_ino_t parent, child;
1806 char *temp_path;
1807 errcode_t err;
1808 char *node_name, a;
1809 struct ext2_inode_large inode;
1810 gid_t gid;
1811 int ret = 0;
1812
1813 FUSE2FS_CHECK_CONTEXT(ff);
1814 fs = ff->fs;
1815 dbg_printf(ff, "%s: symlink %s to %s\n", __func__, src, dest);
1816 temp_path = strdup(dest);
1817 if (!temp_path) {
1818 ret = -ENOMEM;
1819 goto out;
1820 }
1821 node_name = strrchr(temp_path, '/');
1822 if (!node_name) {
1823 ret = -ENOMEM;
1824 goto out;
1825 }
1826 node_name++;
1827 a = *node_name;
1828 *node_name = 0;
1829
1830 pthread_mutex_lock(&ff->bfl);
1831 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1832 &parent);
1833 *node_name = a;
1834 if (err) {
1835 ret = translate_error(fs, 0, err);
1836 goto out2;
1837 }
1838
1839 ret = check_inum_access(ff, parent, A_OK | W_OK);
1840 if (ret)
1841 goto out2;
1842
1843 err = fuse2fs_new_child_gid(ff, parent, &gid, NULL);
1844 if (err)
1845 goto out2;
1846
1847 /* Create symlink */
1848 err = ext2fs_symlink(fs, parent, 0, node_name, src);
1849 if (err == EXT2_ET_DIR_NO_SPACE) {
1850 err = ext2fs_expand_dir(fs, parent);
1851 if (err) {
1852 ret = translate_error(fs, parent, err);
1853 goto out2;
1854 }
1855
1856 err = ext2fs_symlink(fs, parent, 0, node_name, src);
1857 }
1858 if (err) {
1859 ret = translate_error(fs, parent, err);
1860 goto out2;
1861 }
1862
1863 /* Update parent dir's mtime */
1864 ret = update_mtime(fs, parent, NULL);
1865 if (ret)
1866 goto out2;
1867
1868 /* Still have to update the uid/gid of the symlink */
1869 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
1870 &child);
1871 if (err) {
1872 ret = translate_error(fs, 0, err);
1873 goto out2;
1874 }
1875 dbg_printf(ff, "%s: symlinking ino=%d/name=%s to dir=%d\n", __func__,
1876 child, node_name, parent);
1877
1878 err = fuse2fs_read_inode(fs, child, &inode);
1879 if (err) {
1880 ret = translate_error(fs, child, err);
1881 goto out2;
1882 }
1883
1884 fuse2fs_set_uid(&inode, ctxt->uid);
1885 fuse2fs_set_gid(&inode, gid);
1886 inode.i_generation = ff->next_generation++;
1887 init_times(&inode);
1888
1889 err = fuse2fs_write_inode(fs, child, &inode);
1890 if (err) {
1891 ret = translate_error(fs, child, err);
1892 goto out2;
1893 }
1894 out2:
1895 pthread_mutex_unlock(&ff->bfl);
1896 out:
1897 free(temp_path);
1898 return ret;
1899 }
1900
1901 struct update_dotdot {
1902 ext2_ino_t new_dotdot;
1903 };
1904
1905 static int update_dotdot_helper(ext2_ino_t dir EXT2FS_ATTR((unused)),
1906 int entry EXT2FS_ATTR((unused)),
1907 struct ext2_dir_entry *dirent,
1908 int offset EXT2FS_ATTR((unused)),
1909 int blocksize EXT2FS_ATTR((unused)),
1910 char *buf EXT2FS_ATTR((unused)),
1911 void *priv_data)
1912 {
1913 struct update_dotdot *ud = priv_data;
1914
1915 if (ext2fs_dirent_name_len(dirent) == 2 &&
1916 dirent->name[0] == '.' && dirent->name[1] == '.') {
1917 dirent->inode = ud->new_dotdot;
1918 return DIRENT_CHANGED | DIRENT_ABORT;
1919 }
1920
1921 return 0;
1922 }
1923
1924 static int op_rename(const char *from, const char *to
1925 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1926 , unsigned int flags EXT2FS_ATTR((unused))
1927 #endif
1928 )
1929 {
1930 struct fuse_context *ctxt = fuse_get_context();
1931 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
1932 ext2_filsys fs;
1933 errcode_t err;
1934 ext2_ino_t from_ino, to_ino, to_dir_ino, from_dir_ino;
1935 char *temp_to = NULL, *temp_from = NULL;
1936 char *cp, a;
1937 struct ext2_inode inode;
1938 struct update_dotdot ud;
1939 int ret = 0;
1940
1941 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1942 /* renameat2 is not supported */
1943 if (flags)
1944 return -ENOSYS;
1945 #endif
1946
1947 FUSE2FS_CHECK_CONTEXT(ff);
1948 fs = ff->fs;
1949 dbg_printf(ff, "%s: renaming %s to %s\n", __func__, from, to);
1950 pthread_mutex_lock(&ff->bfl);
1951 if (!fs_can_allocate(ff, 5)) {
1952 ret = -ENOSPC;
1953 goto out;
1954 }
1955
1956 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, from, &from_ino);
1957 if (err || from_ino == 0) {
1958 ret = translate_error(fs, 0, err);
1959 goto out;
1960 }
1961
1962 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, to, &to_ino);
1963 if (err && err != EXT2_ET_FILE_NOT_FOUND) {
1964 ret = translate_error(fs, 0, err);
1965 goto out;
1966 }
1967
1968 if (err == EXT2_ET_FILE_NOT_FOUND)
1969 to_ino = 0;
1970
1971 /* Already the same file? */
1972 if (to_ino != 0 && to_ino == from_ino) {
1973 ret = 0;
1974 goto out;
1975 }
1976
1977 ret = check_inum_access(ff, from_ino, W_OK);
1978 if (ret)
1979 goto out;
1980
1981 if (to_ino) {
1982 ret = check_inum_access(ff, to_ino, W_OK);
1983 if (ret)
1984 goto out;
1985 }
1986
1987 temp_to = strdup(to);
1988 if (!temp_to) {
1989 ret = -ENOMEM;
1990 goto out;
1991 }
1992
1993 temp_from = strdup(from);
1994 if (!temp_from) {
1995 ret = -ENOMEM;
1996 goto out2;
1997 }
1998
1999 /* Find parent dir of the source and check write access */
2000 cp = strrchr(temp_from, '/');
2001 if (!cp) {
2002 ret = -EINVAL;
2003 goto out2;
2004 }
2005
2006 a = *(cp + 1);
2007 *(cp + 1) = 0;
2008 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_from,
2009 &from_dir_ino);
2010 *(cp + 1) = a;
2011 if (err) {
2012 ret = translate_error(fs, 0, err);
2013 goto out2;
2014 }
2015 if (from_dir_ino == 0) {
2016 ret = -ENOENT;
2017 goto out2;
2018 }
2019
2020 ret = check_inum_access(ff, from_dir_ino, W_OK);
2021 if (ret)
2022 goto out2;
2023
2024 /* Find parent dir of the destination and check write access */
2025 cp = strrchr(temp_to, '/');
2026 if (!cp) {
2027 ret = -EINVAL;
2028 goto out2;
2029 }
2030
2031 a = *(cp + 1);
2032 *(cp + 1) = 0;
2033 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_to,
2034 &to_dir_ino);
2035 *(cp + 1) = a;
2036 if (err) {
2037 ret = translate_error(fs, 0, err);
2038 goto out2;
2039 }
2040 if (to_dir_ino == 0) {
2041 ret = -ENOENT;
2042 goto out2;
2043 }
2044
2045 ret = check_inum_access(ff, to_dir_ino, W_OK);
2046 if (ret)
2047 goto out2;
2048
2049 /* If the target exists, unlink it first */
2050 if (to_ino != 0) {
2051 err = ext2fs_read_inode(fs, to_ino, &inode);
2052 if (err) {
2053 ret = translate_error(fs, to_ino, err);
2054 goto out2;
2055 }
2056
2057 dbg_printf(ff, "%s: unlinking %s ino=%d\n", __func__,
2058 LINUX_S_ISDIR(inode.i_mode) ? "dir" : "file",
2059 to_ino);
2060 if (LINUX_S_ISDIR(inode.i_mode))
2061 ret = __op_rmdir(ff, to);
2062 else
2063 ret = __op_unlink(ff, to);
2064 if (ret)
2065 goto out2;
2066 }
2067
2068 /* Get ready to do the move */
2069 err = ext2fs_read_inode(fs, from_ino, &inode);
2070 if (err) {
2071 ret = translate_error(fs, from_ino, err);
2072 goto out2;
2073 }
2074
2075 /* Link in the new file */
2076 dbg_printf(ff, "%s: linking ino=%d/path=%s to dir=%d\n", __func__,
2077 from_ino, cp + 1, to_dir_ino);
2078 err = ext2fs_link(fs, to_dir_ino, cp + 1, from_ino,
2079 ext2_file_type(inode.i_mode) | EXT2FS_LINK_EXPAND);
2080 if (err) {
2081 ret = translate_error(fs, to_dir_ino, err);
2082 goto out2;
2083 }
2084
2085 /* Update '..' pointer if dir */
2086 err = ext2fs_read_inode(fs, from_ino, &inode);
2087 if (err) {
2088 ret = translate_error(fs, from_ino, err);
2089 goto out2;
2090 }
2091
2092 if (LINUX_S_ISDIR(inode.i_mode)) {
2093 ud.new_dotdot = to_dir_ino;
2094 dbg_printf(ff, "%s: updating .. entry for dir=%d\n", __func__,
2095 to_dir_ino);
2096 err = ext2fs_dir_iterate2(fs, from_ino, 0, NULL,
2097 update_dotdot_helper, &ud);
2098 if (err) {
2099 ret = translate_error(fs, from_ino, err);
2100 goto out2;
2101 }
2102
2103 /* Decrease from_dir_ino's links_count */
2104 dbg_printf(ff, "%s: moving linkcount from dir=%d to dir=%d\n",
2105 __func__, from_dir_ino, to_dir_ino);
2106 err = ext2fs_read_inode(fs, from_dir_ino, &inode);
2107 if (err) {
2108 ret = translate_error(fs, from_dir_ino, err);
2109 goto out2;
2110 }
2111 inode.i_links_count--;
2112 err = ext2fs_write_inode(fs, from_dir_ino, &inode);
2113 if (err) {
2114 ret = translate_error(fs, from_dir_ino, err);
2115 goto out2;
2116 }
2117
2118 /* Increase to_dir_ino's links_count */
2119 err = ext2fs_read_inode(fs, to_dir_ino, &inode);
2120 if (err) {
2121 ret = translate_error(fs, to_dir_ino, err);
2122 goto out2;
2123 }
2124 inode.i_links_count++;
2125 err = ext2fs_write_inode(fs, to_dir_ino, &inode);
2126 if (err) {
2127 ret = translate_error(fs, to_dir_ino, err);
2128 goto out2;
2129 }
2130 }
2131
2132 /* Update timestamps */
2133 ret = update_ctime(fs, from_ino, NULL);
2134 if (ret)
2135 goto out2;
2136
2137 ret = update_mtime(fs, to_dir_ino, NULL);
2138 if (ret)
2139 goto out2;
2140
2141 /* Remove the old file */
2142 ret = unlink_file_by_name(ff, from);
2143 if (ret)
2144 goto out2;
2145
2146 /* Flush the whole mess out */
2147 err = ext2fs_flush2(fs, 0);
2148 if (err)
2149 ret = translate_error(fs, 0, err);
2150
2151 out2:
2152 free(temp_from);
2153 free(temp_to);
2154 out:
2155 pthread_mutex_unlock(&ff->bfl);
2156 return ret;
2157 }
2158
2159 static int op_link(const char *src, const char *dest)
2160 {
2161 struct fuse_context *ctxt = fuse_get_context();
2162 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2163 ext2_filsys fs;
2164 char *temp_path;
2165 errcode_t err;
2166 char *node_name, a;
2167 ext2_ino_t parent, ino;
2168 struct ext2_inode_large inode;
2169 int ret = 0;
2170
2171 FUSE2FS_CHECK_CONTEXT(ff);
2172 fs = ff->fs;
2173 dbg_printf(ff, "%s: src=%s dest=%s\n", __func__, src, dest);
2174 temp_path = strdup(dest);
2175 if (!temp_path) {
2176 ret = -ENOMEM;
2177 goto out;
2178 }
2179 node_name = strrchr(temp_path, '/');
2180 if (!node_name) {
2181 ret = -ENOMEM;
2182 goto out;
2183 }
2184 node_name++;
2185 a = *node_name;
2186 *node_name = 0;
2187
2188 pthread_mutex_lock(&ff->bfl);
2189 if (!fs_can_allocate(ff, 2)) {
2190 ret = -ENOSPC;
2191 goto out2;
2192 }
2193
2194 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
2195 &parent);
2196 *node_name = a;
2197 if (err) {
2198 err = -ENOENT;
2199 goto out2;
2200 }
2201
2202 ret = check_inum_access(ff, parent, A_OK | W_OK);
2203 if (ret)
2204 goto out2;
2205
2206 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, src, &ino);
2207 if (err || ino == 0) {
2208 ret = translate_error(fs, 0, err);
2209 goto out2;
2210 }
2211
2212 err = fuse2fs_read_inode(fs, ino, &inode);
2213 if (err) {
2214 ret = translate_error(fs, ino, err);
2215 goto out2;
2216 }
2217
2218 ret = check_iflags_access(ff, ino, EXT2_INODE(&inode), W_OK);
2219 if (ret)
2220 goto out2;
2221
2222 inode.i_links_count++;
2223 ret = update_ctime(fs, ino, &inode);
2224 if (ret)
2225 goto out2;
2226
2227 err = fuse2fs_write_inode(fs, ino, &inode);
2228 if (err) {
2229 ret = translate_error(fs, ino, err);
2230 goto out2;
2231 }
2232
2233 dbg_printf(ff, "%s: linking ino=%d/name=%s to dir=%d\n", __func__, ino,
2234 node_name, parent);
2235 err = ext2fs_link(fs, parent, node_name, ino,
2236 ext2_file_type(inode.i_mode) | EXT2FS_LINK_EXPAND);
2237 if (err) {
2238 ret = translate_error(fs, parent, err);
2239 goto out2;
2240 }
2241
2242 ret = update_mtime(fs, parent, NULL);
2243 if (ret)
2244 goto out2;
2245
2246 out2:
2247 pthread_mutex_unlock(&ff->bfl);
2248 out:
2249 free(temp_path);
2250 return ret;
2251 }
2252
2253 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
2254 /* Obtain group ids of the process that sent us a command(?) */
2255 static int get_req_groups(struct fuse2fs *ff, gid_t **gids, size_t *nr_gids)
2256 {
2257 ext2_filsys fs = ff->fs;
2258 errcode_t err;
2259 gid_t *array;
2260 int nr = 32; /* nobody has more than 32 groups right? */
2261 int ret;
2262
2263 do {
2264 err = ext2fs_get_array(nr, sizeof(gid_t), &array);
2265 if (err)
2266 return translate_error(fs, 0, err);
2267
2268 ret = fuse_getgroups(nr, array);
2269 if (ret < 0)
2270 return ret;
2271
2272 if (ret <= nr) {
2273 *gids = array;
2274 *nr_gids = ret;
2275 return 0;
2276 }
2277
2278 ext2fs_free_mem(&array);
2279 nr = ret;
2280 } while (0);
2281
2282 /* shut up gcc */
2283 return -ENOMEM;
2284 }
2285
2286 /*
2287 * Is this file's group id in the set of groups associated with the process
2288 * that initiated the fuse request? Returns 1 for yes, 0 for no, or a negative
2289 * errno.
2290 */
2291 static int in_file_group(struct fuse_context *ctxt,
2292 const struct ext2_inode_large *inode)
2293 {
2294 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2295 gid_t *gids = NULL;
2296 size_t i, nr_gids = 0;
2297 gid_t gid = inode_gid(*inode);
2298 int ret;
2299
2300 ret = get_req_groups(ff, &gids, &nr_gids);
2301 if (ret < 0)
2302 return ret;
2303
2304 for (i = 0; i < nr_gids; i++)
2305 if (gids[i] == gid)
2306 return 1;
2307 return 0;
2308 }
2309 #else
2310 static int in_file_group(struct fuse_context *ctxt,
2311 const struct ext2_inode_large *inode)
2312 {
2313 return ctxt->gid == inode_gid(*inode);
2314 }
2315 #endif
2316
2317 static int op_chmod(const char *path, mode_t mode
2318 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
2319 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
2320 #endif
2321 )
2322 {
2323 struct fuse_context *ctxt = fuse_get_context();
2324 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2325 ext2_filsys fs;
2326 errcode_t err;
2327 ext2_ino_t ino;
2328 struct ext2_inode_large inode;
2329 int ret = 0;
2330
2331 FUSE2FS_CHECK_CONTEXT(ff);
2332 fs = ff->fs;
2333 pthread_mutex_lock(&ff->bfl);
2334 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2335 if (err) {
2336 ret = translate_error(fs, 0, err);
2337 goto out;
2338 }
2339 dbg_printf(ff, "%s: path=%s mode=0%o ino=%d\n", __func__, path, mode, ino);
2340
2341 err = fuse2fs_read_inode(fs, ino, &inode);
2342 if (err) {
2343 ret = translate_error(fs, ino, err);
2344 goto out;
2345 }
2346
2347 ret = check_iflags_access(ff, ino, EXT2_INODE(&inode), W_OK);
2348 if (ret)
2349 goto out;
2350
2351 if (want_check_owner(ff, ctxt) && ctxt->uid != inode_uid(inode)) {
2352 ret = -EPERM;
2353 goto out;
2354 }
2355
2356 /*
2357 * XXX: We should really check that the inode gid is not in /any/
2358 * of the user's groups, but FUSE only tells us about the primary
2359 * group.
2360 */
2361 if (!is_superuser(ff, ctxt)) {
2362 ret = in_file_group(ctxt, &inode);
2363 if (ret < 0)
2364 goto out;
2365
2366 if (!ret)
2367 mode &= ~S_ISGID;
2368 }
2369
2370 inode.i_mode &= ~0xFFF;
2371 inode.i_mode |= mode & 0xFFF;
2372
2373 dbg_printf(ff, "%s: path=%s new_mode=0%o ino=%d\n", __func__,
2374 path, inode.i_mode, ino);
2375
2376 ret = update_ctime(fs, ino, &inode);
2377 if (ret)
2378 goto out;
2379
2380 err = fuse2fs_write_inode(fs, ino, &inode);
2381 if (err) {
2382 ret = translate_error(fs, ino, err);
2383 goto out;
2384 }
2385
2386 out:
2387 pthread_mutex_unlock(&ff->bfl);
2388 return ret;
2389 }
2390
2391 static int op_chown(const char *path, uid_t owner, gid_t group
2392 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
2393 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
2394 #endif
2395 )
2396 {
2397 struct fuse_context *ctxt = fuse_get_context();
2398 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2399 ext2_filsys fs;
2400 errcode_t err;
2401 ext2_ino_t ino;
2402 struct ext2_inode_large inode;
2403 int ret = 0;
2404
2405 FUSE2FS_CHECK_CONTEXT(ff);
2406 fs = ff->fs;
2407 pthread_mutex_lock(&ff->bfl);
2408 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2409 if (err) {
2410 ret = translate_error(fs, 0, err);
2411 goto out;
2412 }
2413 dbg_printf(ff, "%s: path=%s owner=%d group=%d ino=%d\n", __func__,
2414 path, owner, group, ino);
2415
2416 err = fuse2fs_read_inode(fs, ino, &inode);
2417 if (err) {
2418 ret = translate_error(fs, ino, err);
2419 goto out;
2420 }
2421
2422 ret = check_iflags_access(ff, ino, EXT2_INODE(&inode), W_OK);
2423 if (ret)
2424 goto out;
2425
2426 /* FUSE seems to feed us ~0 to mean "don't change" */
2427 if (owner != (uid_t) ~0) {
2428 /* Only root gets to change UID. */
2429 if (want_check_owner(ff, ctxt) &&
2430 !(inode_uid(inode) == ctxt->uid && owner == ctxt->uid)) {
2431 ret = -EPERM;
2432 goto out;
2433 }
2434 fuse2fs_set_uid(&inode, owner);
2435 }
2436
2437 if (group != (gid_t) ~0) {
2438 /* Only root or the owner get to change GID. */
2439 if (want_check_owner(ff, ctxt) &&
2440 inode_uid(inode) != ctxt->uid) {
2441 ret = -EPERM;
2442 goto out;
2443 }
2444
2445 /* XXX: We /should/ check group membership but FUSE */
2446 fuse2fs_set_gid(&inode, group);
2447 }
2448
2449 ret = update_ctime(fs, ino, &inode);
2450 if (ret)
2451 goto out;
2452
2453 err = fuse2fs_write_inode(fs, ino, &inode);
2454 if (err) {
2455 ret = translate_error(fs, ino, err);
2456 goto out;
2457 }
2458
2459 out:
2460 pthread_mutex_unlock(&ff->bfl);
2461 return ret;
2462 }
2463
2464 static int fuse2fs_punch_posteof(struct fuse2fs *ff, ext2_ino_t ino,
2465 off_t new_size)
2466 {
2467 ext2_filsys fs = ff->fs;
2468 struct ext2_inode_large inode;
2469 blk64_t truncate_block = FUSE2FS_B_TO_FSB(ff, new_size);
2470 errcode_t err;
2471
2472 err = fuse2fs_read_inode(fs, ino, &inode);
2473 if (err)
2474 return translate_error(fs, ino, err);
2475
2476 err = ext2fs_punch(fs, ino, EXT2_INODE(&inode), 0, truncate_block,
2477 ~0ULL);
2478 if (err)
2479 return translate_error(fs, ino, err);
2480
2481 err = fuse2fs_write_inode(fs, ino, &inode);
2482 if (err)
2483 return translate_error(fs, ino, err);
2484
2485 return 0;
2486 }
2487
2488 static int fuse2fs_truncate(struct fuse2fs *ff, ext2_ino_t ino, off_t new_size)
2489 {
2490 ext2_filsys fs = ff->fs;
2491 ext2_file_t file;
2492 __u64 old_isize;
2493 errcode_t err;
2494 int ret = 0;
2495
2496 err = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &file);
2497 if (err)
2498 return translate_error(fs, ino, err);
2499
2500 err = ext2fs_file_get_lsize(file, &old_isize);
2501 if (err) {
2502 ret = translate_error(fs, ino, err);
2503 goto out_close;
2504 }
2505
2506 dbg_printf(ff, "%s: ino=%u isize=0x%llx new_size=0x%llx\n", __func__,
2507 ino,
2508 (unsigned long long)old_isize,
2509 (unsigned long long)new_size);
2510
2511 err = ext2fs_file_set_size2(file, new_size);
2512 if (err)
2513 ret = translate_error(fs, ino, err);
2514
2515 out_close:
2516 err = ext2fs_file_close(file);
2517 if (ret)
2518 return ret;
2519 if (err)
2520 return translate_error(fs, ino, err);
2521
2522 ret = update_mtime(fs, ino, NULL);
2523 if (ret)
2524 return ret;
2525
2526 /*
2527 * Truncating to the current size is usually understood to mean that
2528 * we should clear out post-EOF preallocations.
2529 */
2530 if (new_size == old_isize)
2531 return fuse2fs_punch_posteof(ff, ino, new_size);
2532
2533 return 0;
2534 }
2535
2536 static int op_truncate(const char *path, off_t len
2537 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
2538 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
2539 #endif
2540 )
2541 {
2542 struct fuse_context *ctxt = fuse_get_context();
2543 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2544 ext2_filsys fs;
2545 ext2_ino_t ino;
2546 errcode_t err;
2547 int ret = 0;
2548
2549 FUSE2FS_CHECK_CONTEXT(ff);
2550 fs = ff->fs;
2551 pthread_mutex_lock(&ff->bfl);
2552 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2553 if (err) {
2554 ret = translate_error(fs, 0, err);
2555 goto out;
2556 }
2557 if (!ino) {
2558 ret = -ESTALE;
2559 goto out;
2560 }
2561 dbg_printf(ff, "%s: ino=%d len=%jd\n", __func__, ino, (intmax_t) len);
2562
2563 ret = check_inum_access(ff, ino, W_OK);
2564 if (ret)
2565 goto out;
2566
2567 ret = fuse2fs_truncate(ff, ino, len);
2568 if (ret)
2569 goto out;
2570
2571 out:
2572 pthread_mutex_unlock(&ff->bfl);
2573 return err;
2574 }
2575
2576 #ifdef __linux__
2577 static void detect_linux_executable_open(int kernel_flags, int *access_check,
2578 int *e2fs_open_flags)
2579 {
2580 /*
2581 * On Linux, execve will bleed __FMODE_EXEC into the file mode flags,
2582 * and FUSE is more than happy to let that slip through.
2583 */
2584 if (kernel_flags & 0x20) {
2585 *access_check = X_OK;
2586 *e2fs_open_flags &= ~EXT2_FILE_WRITE;
2587 }
2588 }
2589 #else
2590 static void detect_linux_executable_open(int kernel_flags, int *access_check,
2591 int *e2fs_open_flags)
2592 {
2593 /* empty */
2594 }
2595 #endif /* __linux__ */
2596
2597 static int __op_open(struct fuse2fs *ff, const char *path,
2598 struct fuse_file_info *fp)
2599 {
2600 ext2_filsys fs = ff->fs;
2601 errcode_t err;
2602 struct fuse2fs_file_handle *file;
2603 int check = 0, ret = 0;
2604
2605 dbg_printf(ff, "%s: path=%s oflags=0o%o\n", __func__, path, fp->flags);
2606 err = ext2fs_get_mem(sizeof(*file), &file);
2607 if (err)
2608 return translate_error(fs, 0, err);
2609 file->magic = FUSE2FS_FILE_MAGIC;
2610
2611 file->open_flags = 0;
2612 switch (fp->flags & O_ACCMODE) {
2613 case O_RDONLY:
2614 check = R_OK;
2615 break;
2616 case O_WRONLY:
2617 check = W_OK;
2618 file->open_flags |= EXT2_FILE_WRITE;
2619 break;
2620 case O_RDWR:
2621 check = R_OK | W_OK;
2622 file->open_flags |= EXT2_FILE_WRITE;
2623 break;
2624 }
2625 if (fp->flags & O_APPEND) {
2626 /* the kernel doesn't allow truncation of an append-only file */
2627 if (fp->flags & O_TRUNC) {
2628 ret = -EPERM;
2629 goto out;
2630 }
2631
2632 check |= A_OK;
2633 }
2634
2635 detect_linux_executable_open(fp->flags, &check, &file->open_flags);
2636
2637 if (fp->flags & O_CREAT)
2638 file->open_flags |= EXT2_FILE_CREATE;
2639
2640 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &file->ino);
2641 if (err || file->ino == 0) {
2642 ret = translate_error(fs, 0, err);
2643 goto out;
2644 }
2645 dbg_printf(ff, "%s: ino=%d\n", __func__, file->ino);
2646
2647 ret = check_inum_access(ff, file->ino, check);
2648 if (ret) {
2649 /*
2650 * In a regular (Linux) fs driver, the kernel will open
2651 * binaries for reading if the user has --x privileges (i.e.
2652 * execute without read). Since the kernel doesn't have any
2653 * way to tell us if it's opening a file via execve, we'll
2654 * just assume that allowing access is ok if asking for ro mode
2655 * fails but asking for x mode succeeds. Of course we can
2656 * also employ undocumented hacks (see above).
2657 */
2658 if (check == R_OK) {
2659 ret = check_inum_access(ff, file->ino, X_OK);
2660 if (ret)
2661 goto out;
2662 } else
2663 goto out;
2664 }
2665
2666 if (fp->flags & O_TRUNC) {
2667 ret = fuse2fs_truncate(ff, file->ino, 0);
2668 if (ret)
2669 goto out;
2670 }
2671
2672 fp->fh = (uintptr_t)file;
2673
2674 out:
2675 if (ret)
2676 ext2fs_free_mem(&file);
2677 return ret;
2678 }
2679
2680 static int op_open(const char *path, struct fuse_file_info *fp)
2681 {
2682 struct fuse_context *ctxt = fuse_get_context();
2683 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2684 int ret;
2685
2686 FUSE2FS_CHECK_CONTEXT(ff);
2687 pthread_mutex_lock(&ff->bfl);
2688 ret = __op_open(ff, path, fp);
2689 pthread_mutex_unlock(&ff->bfl);
2690 return ret;
2691 }
2692
2693 static int op_read(const char *path EXT2FS_ATTR((unused)), char *buf,
2694 size_t len, off_t offset,
2695 struct fuse_file_info *fp)
2696 {
2697 struct fuse_context *ctxt = fuse_get_context();
2698 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2699 struct fuse2fs_file_handle *fh =
2700 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2701 ext2_filsys fs;
2702 ext2_file_t efp;
2703 errcode_t err;
2704 unsigned int got = 0;
2705 int ret = 0;
2706
2707 FUSE2FS_CHECK_CONTEXT(ff);
2708 fs = ff->fs;
2709 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2710 dbg_printf(ff, "%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino,
2711 (intmax_t) offset, len);
2712 pthread_mutex_lock(&ff->bfl);
2713 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
2714 if (err) {
2715 ret = translate_error(fs, fh->ino, err);
2716 goto out;
2717 }
2718
2719 err = ext2fs_file_llseek(efp, offset, SEEK_SET, NULL);
2720 if (err) {
2721 ret = translate_error(fs, fh->ino, err);
2722 goto out2;
2723 }
2724
2725 err = ext2fs_file_read(efp, buf, len, &got);
2726 if (err) {
2727 ret = translate_error(fs, fh->ino, err);
2728 goto out2;
2729 }
2730
2731 out2:
2732 err = ext2fs_file_close(efp);
2733 if (ret)
2734 goto out;
2735 if (err) {
2736 ret = translate_error(fs, fh->ino, err);
2737 goto out;
2738 }
2739
2740 if (fs_writeable(fs)) {
2741 ret = update_atime(fs, fh->ino);
2742 if (ret)
2743 goto out;
2744 }
2745 out:
2746 pthread_mutex_unlock(&ff->bfl);
2747 return got ? (int) got : ret;
2748 }
2749
2750 static int op_write(const char *path EXT2FS_ATTR((unused)),
2751 const char *buf, size_t len, off_t offset,
2752 struct fuse_file_info *fp)
2753 {
2754 struct fuse_context *ctxt = fuse_get_context();
2755 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2756 struct fuse2fs_file_handle *fh =
2757 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2758 ext2_filsys fs;
2759 ext2_file_t efp;
2760 errcode_t err;
2761 unsigned int got = 0;
2762 int ret = 0;
2763
2764 FUSE2FS_CHECK_CONTEXT(ff);
2765 fs = ff->fs;
2766 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2767 dbg_printf(ff, "%s: ino=%d off=%jd len=%jd\n", __func__, fh->ino,
2768 (intmax_t) offset, (intmax_t) len);
2769 pthread_mutex_lock(&ff->bfl);
2770 if (!fs_writeable(fs)) {
2771 ret = -EROFS;
2772 goto out;
2773 }
2774
2775 if (!fs_can_allocate(ff, FUSE2FS_B_TO_FSB(ff, len))) {
2776 ret = -ENOSPC;
2777 goto out;
2778 }
2779
2780 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
2781 if (err) {
2782 ret = translate_error(fs, fh->ino, err);
2783 goto out;
2784 }
2785
2786 err = ext2fs_file_llseek(efp, offset, SEEK_SET, NULL);
2787 if (err) {
2788 ret = translate_error(fs, fh->ino, err);
2789 goto out2;
2790 }
2791
2792 err = ext2fs_file_write(efp, buf, len, &got);
2793 if (err) {
2794 ret = translate_error(fs, fh->ino, err);
2795 goto out2;
2796 }
2797
2798 err = ext2fs_file_flush(efp);
2799 if (err) {
2800 got = 0;
2801 ret = translate_error(fs, fh->ino, err);
2802 goto out2;
2803 }
2804
2805 out2:
2806 err = ext2fs_file_close(efp);
2807 if (ret)
2808 goto out;
2809 if (err) {
2810 ret = translate_error(fs, fh->ino, err);
2811 goto out;
2812 }
2813
2814 ret = update_mtime(fs, fh->ino, NULL);
2815 if (ret)
2816 goto out;
2817
2818 out:
2819 pthread_mutex_unlock(&ff->bfl);
2820 return got ? (int) got : ret;
2821 }
2822
2823 static int op_release(const char *path EXT2FS_ATTR((unused)),
2824 struct fuse_file_info *fp)
2825 {
2826 struct fuse_context *ctxt = fuse_get_context();
2827 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2828 struct fuse2fs_file_handle *fh =
2829 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2830 ext2_filsys fs;
2831 errcode_t err;
2832 int ret = 0;
2833
2834 FUSE2FS_CHECK_CONTEXT(ff);
2835 fs = ff->fs;
2836 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2837 dbg_printf(ff, "%s: ino=%d\n", __func__, fh->ino);
2838 pthread_mutex_lock(&ff->bfl);
2839 if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) {
2840 err = ext2fs_flush2(fs, EXT2_FLAG_FLUSH_NO_SYNC);
2841 if (err)
2842 ret = translate_error(fs, fh->ino, err);
2843 }
2844 fp->fh = 0;
2845 pthread_mutex_unlock(&ff->bfl);
2846
2847 ext2fs_free_mem(&fh);
2848
2849 return ret;
2850 }
2851
2852 static int op_fsync(const char *path EXT2FS_ATTR((unused)),
2853 int datasync EXT2FS_ATTR((unused)),
2854 struct fuse_file_info *fp)
2855 {
2856 struct fuse_context *ctxt = fuse_get_context();
2857 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2858 struct fuse2fs_file_handle *fh =
2859 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
2860 ext2_filsys fs;
2861 errcode_t err;
2862 int ret = 0;
2863
2864 FUSE2FS_CHECK_CONTEXT(ff);
2865 fs = ff->fs;
2866 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
2867 dbg_printf(ff, "%s: ino=%d\n", __func__, fh->ino);
2868 /* For now, flush everything, even if it's slow */
2869 pthread_mutex_lock(&ff->bfl);
2870 if (fs_writeable(fs) && fh->open_flags & EXT2_FILE_WRITE) {
2871 err = ext2fs_flush2(fs, 0);
2872 if (err)
2873 ret = translate_error(fs, fh->ino, err);
2874 }
2875 pthread_mutex_unlock(&ff->bfl);
2876
2877 return ret;
2878 }
2879
2880 static int op_statfs(const char *path EXT2FS_ATTR((unused)),
2881 struct statvfs *buf)
2882 {
2883 struct fuse_context *ctxt = fuse_get_context();
2884 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2885 ext2_filsys fs;
2886 uint64_t fsid, *f;
2887 blk64_t overhead, reserved, free;
2888
2889 FUSE2FS_CHECK_CONTEXT(ff);
2890 dbg_printf(ff, "%s: path=%s\n", __func__, path);
2891 fs = ff->fs;
2892 pthread_mutex_lock(&ff->bfl);
2893 buf->f_bsize = fs->blocksize;
2894 buf->f_frsize = 0;
2895
2896 if (ff->minixdf)
2897 overhead = 0;
2898 else
2899 overhead = fs->desc_blocks +
2900 (blk64_t)fs->group_desc_count *
2901 (fs->inode_blocks_per_group + 2);
2902 reserved = ext2fs_r_blocks_count(fs->super);
2903 if (!reserved)
2904 reserved = ext2fs_blocks_count(fs->super) / 10;
2905 free = ext2fs_free_blocks_count(fs->super);
2906
2907 buf->f_blocks = ext2fs_blocks_count(fs->super) - overhead;
2908 buf->f_bfree = free;
2909 if (free < reserved)
2910 buf->f_bavail = 0;
2911 else
2912 buf->f_bavail = free - reserved;
2913 buf->f_files = fs->super->s_inodes_count;
2914 buf->f_ffree = fs->super->s_free_inodes_count;
2915 buf->f_favail = fs->super->s_free_inodes_count;
2916 f = (uint64_t *)fs->super->s_uuid;
2917 fsid = *f;
2918 f++;
2919 fsid ^= *f;
2920 buf->f_fsid = fsid;
2921 buf->f_flag = 0;
2922 if (!(fs->flags & EXT2_FLAG_RW))
2923 buf->f_flag |= ST_RDONLY;
2924 buf->f_namemax = EXT2_NAME_LEN;
2925 pthread_mutex_unlock(&ff->bfl);
2926
2927 return 0;
2928 }
2929
2930 static const char *valid_xattr_prefixes[] = {
2931 "user.",
2932 "trusted.",
2933 "security.",
2934 "gnu.",
2935 "system.",
2936 };
2937
2938 static int validate_xattr_name(const char *name)
2939 {
2940 int i;
2941
2942 for (i = 0; i < ARRAY_SIZE(valid_xattr_prefixes); i++) {
2943 if (!strncmp(name, valid_xattr_prefixes[i],
2944 strlen(valid_xattr_prefixes[i])))
2945 return 1;
2946 }
2947
2948 return 0;
2949 }
2950
2951 static int op_getxattr(const char *path, const char *key, char *value,
2952 size_t len)
2953 {
2954 struct fuse_context *ctxt = fuse_get_context();
2955 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
2956 ext2_filsys fs;
2957 void *ptr;
2958 size_t plen;
2959 ext2_ino_t ino;
2960 errcode_t err;
2961 int ret = 0;
2962
2963 if (!validate_xattr_name(key))
2964 return -ENODATA;
2965
2966 FUSE2FS_CHECK_CONTEXT(ff);
2967 fs = ff->fs;
2968 pthread_mutex_lock(&ff->bfl);
2969 if (!ext2fs_has_feature_xattr(fs->super)) {
2970 ret = -ENOTSUP;
2971 goto out;
2972 }
2973
2974 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
2975 if (err || ino == 0) {
2976 ret = translate_error(fs, 0, err);
2977 goto out;
2978 }
2979 dbg_printf(ff, "%s: ino=%d name=%s\n", __func__, ino, key);
2980
2981 ret = check_inum_access(ff, ino, R_OK);
2982 if (ret)
2983 goto out;
2984
2985 ret = __getxattr(ff, ino, key, &ptr, &plen);
2986 if (ret)
2987 goto out;
2988
2989 if (!len) {
2990 ret = plen;
2991 } else if (len < plen) {
2992 ret = -ERANGE;
2993 } else {
2994 memcpy(value, ptr, plen);
2995 ret = plen;
2996 }
2997
2998 ext2fs_free_mem(&ptr);
2999 out:
3000 pthread_mutex_unlock(&ff->bfl);
3001
3002 return ret;
3003 }
3004
3005 static int count_buffer_space(char *name, char *value EXT2FS_ATTR((unused)),
3006 size_t value_len EXT2FS_ATTR((unused)),
3007 void *data)
3008 {
3009 unsigned int *x = data;
3010
3011 *x = *x + strlen(name) + 1;
3012 return 0;
3013 }
3014
3015 static int copy_names(char *name, char *value EXT2FS_ATTR((unused)),
3016 size_t value_len EXT2FS_ATTR((unused)), void *data)
3017 {
3018 char **b = data;
3019 size_t name_len = strlen(name);
3020
3021 memcpy(*b, name, name_len + 1);
3022 *b = *b + name_len + 1;
3023
3024 return 0;
3025 }
3026
3027 static int op_listxattr(const char *path, char *names, size_t len)
3028 {
3029 struct fuse_context *ctxt = fuse_get_context();
3030 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3031 ext2_filsys fs;
3032 struct ext2_xattr_handle *h;
3033 unsigned int bufsz;
3034 ext2_ino_t ino;
3035 errcode_t err;
3036 int ret = 0;
3037
3038 FUSE2FS_CHECK_CONTEXT(ff);
3039 fs = ff->fs;
3040 pthread_mutex_lock(&ff->bfl);
3041 if (!ext2fs_has_feature_xattr(fs->super)) {
3042 ret = -ENOTSUP;
3043 goto out;
3044 }
3045
3046 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
3047 if (err || ino == 0) {
3048 ret = translate_error(fs, ino, err);
3049 goto out;
3050 }
3051 dbg_printf(ff, "%s: ino=%d\n", __func__, ino);
3052
3053 ret = check_inum_access(ff, ino, R_OK);
3054 if (ret)
3055 goto out;
3056
3057 err = ext2fs_xattrs_open(fs, ino, &h);
3058 if (err) {
3059 ret = translate_error(fs, ino, err);
3060 goto out;
3061 }
3062
3063 err = ext2fs_xattrs_read(h);
3064 if (err) {
3065 ret = translate_error(fs, ino, err);
3066 goto out2;
3067 }
3068
3069 /* Count buffer space needed for names */
3070 bufsz = 0;
3071 err = ext2fs_xattrs_iterate(h, count_buffer_space, &bufsz);
3072 if (err) {
3073 ret = translate_error(fs, ino, err);
3074 goto out2;
3075 }
3076
3077 if (len == 0) {
3078 ret = bufsz;
3079 goto out2;
3080 } else if (len < bufsz) {
3081 ret = -ERANGE;
3082 goto out2;
3083 }
3084
3085 /* Copy names out */
3086 memset(names, 0, len);
3087 err = ext2fs_xattrs_iterate(h, copy_names, &names);
3088 if (err) {
3089 ret = translate_error(fs, ino, err);
3090 goto out2;
3091 }
3092 ret = bufsz;
3093 out2:
3094 err = ext2fs_xattrs_close(&h);
3095 if (err && !ret)
3096 ret = translate_error(fs, ino, err);
3097 out:
3098 pthread_mutex_unlock(&ff->bfl);
3099
3100 return ret;
3101 }
3102
3103 static int op_setxattr(const char *path EXT2FS_ATTR((unused)),
3104 const char *key, const char *value,
3105 size_t len, int flags)
3106 {
3107 struct fuse_context *ctxt = fuse_get_context();
3108 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3109 ext2_filsys fs;
3110 struct ext2_xattr_handle *h;
3111 ext2_ino_t ino;
3112 errcode_t err;
3113 int ret = 0;
3114
3115 if (flags & ~(XATTR_CREATE | XATTR_REPLACE))
3116 return -EOPNOTSUPP;
3117
3118 if (!validate_xattr_name(key))
3119 return -EINVAL;
3120
3121 FUSE2FS_CHECK_CONTEXT(ff);
3122 fs = ff->fs;
3123 pthread_mutex_lock(&ff->bfl);
3124 if (!ext2fs_has_feature_xattr(fs->super)) {
3125 ret = -ENOTSUP;
3126 goto out;
3127 }
3128
3129 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
3130 if (err || ino == 0) {
3131 ret = translate_error(fs, 0, err);
3132 goto out;
3133 }
3134 dbg_printf(ff, "%s: ino=%d name=%s\n", __func__, ino, key);
3135
3136 ret = check_inum_access(ff, ino, W_OK);
3137 if (ret == -EACCES) {
3138 ret = -EPERM;
3139 goto out;
3140 } else if (ret)
3141 goto out;
3142
3143 err = ext2fs_xattrs_open(fs, ino, &h);
3144 if (err) {
3145 ret = translate_error(fs, ino, err);
3146 goto out;
3147 }
3148
3149 err = ext2fs_xattrs_read(h);
3150 if (err) {
3151 ret = translate_error(fs, ino, err);
3152 goto out2;
3153 }
3154
3155 if (flags & (XATTR_CREATE | XATTR_REPLACE)) {
3156 void *buf;
3157 size_t buflen;
3158
3159 err = ext2fs_xattr_get(h, key, &buf, &buflen);
3160 switch (err) {
3161 case EXT2_ET_EA_KEY_NOT_FOUND:
3162 if (flags & XATTR_REPLACE) {
3163 ret = -ENODATA;
3164 goto out2;
3165 }
3166 break;
3167 case 0:
3168 ext2fs_free_mem(&buf);
3169 if (flags & XATTR_CREATE) {
3170 ret = -EEXIST;
3171 goto out2;
3172 }
3173 break;
3174 default:
3175 ret = translate_error(fs, ino, err);
3176 goto out2;
3177 }
3178 }
3179
3180 err = ext2fs_xattr_set(h, key, value, len);
3181 if (err) {
3182 ret = translate_error(fs, ino, err);
3183 goto out2;
3184 }
3185
3186 ret = update_ctime(fs, ino, NULL);
3187 out2:
3188 err = ext2fs_xattrs_close(&h);
3189 if (!ret && err)
3190 ret = translate_error(fs, ino, err);
3191 out:
3192 pthread_mutex_unlock(&ff->bfl);
3193
3194 return ret;
3195 }
3196
3197 static int op_removexattr(const char *path, const char *key)
3198 {
3199 struct fuse_context *ctxt = fuse_get_context();
3200 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3201 ext2_filsys fs;
3202 struct ext2_xattr_handle *h;
3203 void *buf;
3204 size_t buflen;
3205 ext2_ino_t ino;
3206 errcode_t err;
3207 int ret = 0;
3208
3209 /*
3210 * Once in a while libfuse gives us a no-name xattr to delete as part
3211 * of clearing ACLs. Just pretend we cleared them.
3212 */
3213 if (key[0] == 0)
3214 return 0;
3215
3216 if (!validate_xattr_name(key))
3217 return -ENODATA;
3218
3219 FUSE2FS_CHECK_CONTEXT(ff);
3220 fs = ff->fs;
3221 pthread_mutex_lock(&ff->bfl);
3222 if (!ext2fs_has_feature_xattr(fs->super)) {
3223 ret = -ENOTSUP;
3224 goto out;
3225 }
3226
3227 if (!fs_can_allocate(ff, 1)) {
3228 ret = -ENOSPC;
3229 goto out;
3230 }
3231
3232 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
3233 if (err || ino == 0) {
3234 ret = translate_error(fs, 0, err);
3235 goto out;
3236 }
3237 dbg_printf(ff, "%s: ino=%d name=%s\n", __func__, ino, key);
3238
3239 ret = check_inum_access(ff, ino, W_OK);
3240 if (ret)
3241 goto out;
3242
3243 err = ext2fs_xattrs_open(fs, ino, &h);
3244 if (err) {
3245 ret = translate_error(fs, ino, err);
3246 goto out;
3247 }
3248
3249 err = ext2fs_xattrs_read(h);
3250 if (err) {
3251 ret = translate_error(fs, ino, err);
3252 goto out2;
3253 }
3254
3255 err = ext2fs_xattr_get(h, key, &buf, &buflen);
3256 switch (err) {
3257 case EXT2_ET_EA_KEY_NOT_FOUND:
3258 /*
3259 * ACLs are special snowflakes that require a 0 return when
3260 * the ACL never existed in the first place.
3261 */
3262 if (!strncmp(XATTR_SECURITY_PREFIX, key,
3263 XATTR_SECURITY_PREFIX_LEN))
3264 ret = 0;
3265 else
3266 ret = -ENODATA;
3267 goto out2;
3268 case 0:
3269 ext2fs_free_mem(&buf);
3270 break;
3271 default:
3272 ret = translate_error(fs, ino, err);
3273 goto out2;
3274 }
3275
3276 err = ext2fs_xattr_remove(h, key);
3277 if (err) {
3278 ret = translate_error(fs, ino, err);
3279 goto out2;
3280 }
3281
3282 ret = update_ctime(fs, ino, NULL);
3283 out2:
3284 err = ext2fs_xattrs_close(&h);
3285 if (err && !ret)
3286 ret = translate_error(fs, ino, err);
3287 out:
3288 pthread_mutex_unlock(&ff->bfl);
3289
3290 return ret;
3291 }
3292
3293 struct readdir_iter {
3294 void *buf;
3295 ext2_filsys fs;
3296 fuse_fill_dir_t func;
3297 };
3298
3299 static inline mode_t dirent_fmode(ext2_filsys fs,
3300 const struct ext2_dir_entry *dirent)
3301 {
3302 if (!ext2fs_has_feature_filetype(fs->super))
3303 return 0;
3304
3305 switch (ext2fs_dirent_file_type(dirent)) {
3306 case EXT2_FT_REG_FILE:
3307 return S_IFREG;
3308 case EXT2_FT_DIR:
3309 return S_IFDIR;
3310 case EXT2_FT_CHRDEV:
3311 return S_IFCHR;
3312 case EXT2_FT_BLKDEV:
3313 return S_IFBLK;
3314 case EXT2_FT_FIFO:
3315 return S_IFIFO;
3316 case EXT2_FT_SOCK:
3317 return S_IFSOCK;
3318 case EXT2_FT_SYMLINK:
3319 return S_IFLNK;
3320 }
3321
3322 return 0;
3323 }
3324
3325 static int op_readdir_iter(ext2_ino_t dir EXT2FS_ATTR((unused)),
3326 int entry EXT2FS_ATTR((unused)),
3327 struct ext2_dir_entry *dirent,
3328 int offset EXT2FS_ATTR((unused)),
3329 int blocksize EXT2FS_ATTR((unused)),
3330 char *buf EXT2FS_ATTR((unused)), void *data)
3331 {
3332 struct readdir_iter *i = data;
3333 char namebuf[EXT2_NAME_LEN + 1];
3334 struct stat stat = {
3335 .st_ino = dirent->inode,
3336 .st_mode = dirent_fmode(i->fs, dirent),
3337 };
3338 int ret;
3339
3340 memcpy(namebuf, dirent->name, dirent->name_len & 0xFF);
3341 namebuf[dirent->name_len & 0xFF] = 0;
3342 ret = i->func(i->buf, namebuf, &stat, 0
3343 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
3344 , 0
3345 #endif
3346 );
3347 if (ret)
3348 return DIRENT_ABORT;
3349
3350 return 0;
3351 }
3352
3353 static int op_readdir(const char *path EXT2FS_ATTR((unused)),
3354 void *buf, fuse_fill_dir_t fill_func,
3355 off_t offset EXT2FS_ATTR((unused)),
3356 struct fuse_file_info *fp
3357 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
3358 , enum fuse_readdir_flags flags EXT2FS_ATTR((unused))
3359 #endif
3360 )
3361 {
3362 struct fuse_context *ctxt = fuse_get_context();
3363 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3364 struct fuse2fs_file_handle *fh =
3365 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3366 errcode_t err;
3367 struct readdir_iter i;
3368 int ret = 0;
3369
3370 FUSE2FS_CHECK_CONTEXT(ff);
3371 i.fs = ff->fs;
3372 FUSE2FS_CHECK_MAGIC(i.fs, fh, FUSE2FS_FILE_MAGIC);
3373 dbg_printf(ff, "%s: ino=%d\n", __func__, fh->ino);
3374 pthread_mutex_lock(&ff->bfl);
3375 i.buf = buf;
3376 i.func = fill_func;
3377 err = ext2fs_dir_iterate2(i.fs, fh->ino, 0, NULL, op_readdir_iter, &i);
3378 if (err) {
3379 ret = translate_error(i.fs, fh->ino, err);
3380 goto out;
3381 }
3382
3383 if (fs_writeable(i.fs)) {
3384 ret = update_atime(i.fs, fh->ino);
3385 if (ret)
3386 goto out;
3387 }
3388 out:
3389 pthread_mutex_unlock(&ff->bfl);
3390 return ret;
3391 }
3392
3393 static int op_access(const char *path, int mask)
3394 {
3395 struct fuse_context *ctxt = fuse_get_context();
3396 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3397 ext2_filsys fs;
3398 errcode_t err;
3399 ext2_ino_t ino;
3400 int ret = 0;
3401
3402 FUSE2FS_CHECK_CONTEXT(ff);
3403 fs = ff->fs;
3404 dbg_printf(ff, "%s: path=%s mask=0x%x\n", __func__, path, mask);
3405 pthread_mutex_lock(&ff->bfl);
3406 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
3407 if (err || ino == 0) {
3408 ret = translate_error(fs, 0, err);
3409 goto out;
3410 }
3411
3412 ret = check_inum_access(ff, ino, mask);
3413 if (ret)
3414 goto out;
3415
3416 out:
3417 pthread_mutex_unlock(&ff->bfl);
3418 return ret;
3419 }
3420
3421 static int op_create(const char *path, mode_t mode, struct fuse_file_info *fp)
3422 {
3423 struct fuse_context *ctxt = fuse_get_context();
3424 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3425 ext2_filsys fs;
3426 ext2_ino_t parent, child;
3427 char *temp_path;
3428 errcode_t err;
3429 char *node_name, a;
3430 int filetype;
3431 struct ext2_inode_large inode;
3432 gid_t gid;
3433 int ret = 0;
3434
3435 FUSE2FS_CHECK_CONTEXT(ff);
3436 fs = ff->fs;
3437 dbg_printf(ff, "%s: path=%s mode=0%o\n", __func__, path, mode);
3438 temp_path = strdup(path);
3439 if (!temp_path) {
3440 ret = -ENOMEM;
3441 goto out;
3442 }
3443 node_name = strrchr(temp_path, '/');
3444 if (!node_name) {
3445 ret = -ENOMEM;
3446 goto out;
3447 }
3448 node_name++;
3449 a = *node_name;
3450 *node_name = 0;
3451
3452 pthread_mutex_lock(&ff->bfl);
3453 if (!fs_can_allocate(ff, 1)) {
3454 ret = -ENOSPC;
3455 goto out2;
3456 }
3457
3458 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
3459 &parent);
3460 if (err) {
3461 ret = translate_error(fs, 0, err);
3462 goto out2;
3463 }
3464
3465 ret = check_inum_access(ff, parent, A_OK | W_OK);
3466 if (ret)
3467 goto out2;
3468
3469 err = fuse2fs_new_child_gid(ff, parent, &gid, NULL);
3470 if (err)
3471 goto out2;
3472
3473 *node_name = a;
3474
3475 filetype = ext2_file_type(mode);
3476
3477 err = ext2fs_new_inode(fs, parent, mode, 0, &child);
3478 if (err) {
3479 ret = translate_error(fs, parent, err);
3480 goto out2;
3481 }
3482
3483 dbg_printf(ff, "%s: creating ino=%d/name=%s in dir=%d\n", __func__, child,
3484 node_name, parent);
3485 err = ext2fs_link(fs, parent, node_name, child,
3486 filetype | EXT2FS_LINK_EXPAND);
3487 if (err) {
3488 ret = translate_error(fs, parent, err);
3489 goto out2;
3490 }
3491
3492 ret = update_mtime(fs, parent, NULL);
3493 if (ret)
3494 goto out2;
3495
3496 memset(&inode, 0, sizeof(inode));
3497 inode.i_mode = mode;
3498 inode.i_links_count = 1;
3499 inode.i_extra_isize = sizeof(struct ext2_inode_large) -
3500 EXT2_GOOD_OLD_INODE_SIZE;
3501 fuse2fs_set_uid(&inode, ctxt->uid);
3502 fuse2fs_set_gid(&inode, gid);
3503 if (ext2fs_has_feature_extents(fs->super)) {
3504 ext2_extent_handle_t handle;
3505
3506 inode.i_flags &= ~EXT4_EXTENTS_FL;
3507 ret = ext2fs_extent_open2(fs, child,
3508 EXT2_INODE(&inode), &handle);
3509 if (ret) {
3510 ret = translate_error(fs, child, err);
3511 goto out2;
3512 }
3513
3514 ext2fs_extent_free(handle);
3515 }
3516
3517 err = ext2fs_write_new_inode(fs, child, EXT2_INODE(&inode));
3518 if (err) {
3519 ret = translate_error(fs, child, err);
3520 goto out2;
3521 }
3522
3523 inode.i_generation = ff->next_generation++;
3524 init_times(&inode);
3525 err = fuse2fs_write_inode(fs, child, &inode);
3526 if (err) {
3527 ret = translate_error(fs, child, err);
3528 goto out2;
3529 }
3530
3531 ext2fs_inode_alloc_stats2(fs, child, 1, 0);
3532
3533 ret = propagate_default_acls(ff, parent, child);
3534 if (ret)
3535 goto out2;
3536
3537 fp->flags &= ~O_TRUNC;
3538 ret = __op_open(ff, path, fp);
3539 if (ret)
3540 goto out2;
3541 out2:
3542 pthread_mutex_unlock(&ff->bfl);
3543 out:
3544 free(temp_path);
3545 return ret;
3546 }
3547
3548 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
3549 static int op_ftruncate(const char *path EXT2FS_ATTR((unused)),
3550 off_t len, struct fuse_file_info *fp)
3551 {
3552 struct fuse_context *ctxt = fuse_get_context();
3553 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3554 struct fuse2fs_file_handle *fh =
3555 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3556 ext2_filsys fs;
3557 ext2_file_t efp;
3558 errcode_t err;
3559 int ret = 0;
3560
3561 FUSE2FS_CHECK_CONTEXT(ff);
3562 fs = ff->fs;
3563 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3564 dbg_printf(ff, "%s: ino=%d len=%jd\n", __func__, fh->ino,
3565 (intmax_t) len);
3566 pthread_mutex_lock(&ff->bfl);
3567 if (!fs_writeable(fs)) {
3568 ret = -EROFS;
3569 goto out;
3570 }
3571
3572 err = ext2fs_file_open(fs, fh->ino, fh->open_flags, &efp);
3573 if (err) {
3574 ret = translate_error(fs, fh->ino, err);
3575 goto out;
3576 }
3577
3578 err = ext2fs_file_set_size2(efp, len);
3579 if (err) {
3580 ret = translate_error(fs, fh->ino, err);
3581 goto out2;
3582 }
3583
3584 out2:
3585 err = ext2fs_file_close(efp);
3586 if (ret)
3587 goto out;
3588 if (err) {
3589 ret = translate_error(fs, fh->ino, err);
3590 goto out;
3591 }
3592
3593 ret = update_mtime(fs, fh->ino, NULL);
3594 if (ret)
3595 goto out;
3596
3597 out:
3598 pthread_mutex_unlock(&ff->bfl);
3599 return ret;
3600 }
3601
3602 static int op_fgetattr(const char *path EXT2FS_ATTR((unused)),
3603 struct stat *statbuf,
3604 struct fuse_file_info *fp)
3605 {
3606 struct fuse_context *ctxt = fuse_get_context();
3607 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3608 ext2_filsys fs;
3609 struct fuse2fs_file_handle *fh =
3610 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
3611 int ret = 0;
3612
3613 FUSE2FS_CHECK_CONTEXT(ff);
3614 fs = ff->fs;
3615 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3616 dbg_printf(ff, "%s: ino=%d\n", __func__, fh->ino);
3617 pthread_mutex_lock(&ff->bfl);
3618 ret = stat_inode(fs, fh->ino, statbuf);
3619 pthread_mutex_unlock(&ff->bfl);
3620
3621 return ret;
3622 }
3623 #endif /* FUSE_VERSION < FUSE_MAKE_VERSION(3, 0) */
3624
3625 static int op_utimens(const char *path, const struct timespec ctv[2]
3626 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
3627 , struct fuse_file_info *fi EXT2FS_ATTR((unused))
3628 #endif
3629 )
3630 {
3631 struct fuse_context *ctxt = fuse_get_context();
3632 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
3633 struct timespec tv[2];
3634 ext2_filsys fs;
3635 errcode_t err;
3636 ext2_ino_t ino;
3637 struct ext2_inode_large inode;
3638 int access = W_OK;
3639 int ret = 0;
3640
3641 FUSE2FS_CHECK_CONTEXT(ff);
3642 fs = ff->fs;
3643 pthread_mutex_lock(&ff->bfl);
3644 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
3645 if (err) {
3646 ret = translate_error(fs, 0, err);
3647 goto out;
3648 }
3649 dbg_printf(ff, "%s: ino=%d atime=%lld.%ld mtime=%lld.%ld\n", __func__,
3650 ino,
3651 (long long int)ctv[0].tv_sec, ctv[0].tv_nsec,
3652 (long long int)ctv[1].tv_sec, ctv[1].tv_nsec);
3653
3654 /*
3655 * ext4 allows timestamp updates of append-only files but only if we're
3656 * setting to current time
3657 */
3658 if (ctv[0].tv_nsec == UTIME_NOW && ctv[1].tv_nsec == UTIME_NOW)
3659 access |= A_OK;
3660 ret = check_inum_access(ff, ino, access);
3661 if (ret)
3662 goto out;
3663
3664 err = fuse2fs_read_inode(fs, ino, &inode);
3665 if (err) {
3666 ret = translate_error(fs, ino, err);
3667 goto out;
3668 }
3669
3670 tv[0] = ctv[0];
3671 tv[1] = ctv[1];
3672 #ifdef UTIME_NOW
3673 if (tv[0].tv_nsec == UTIME_NOW)
3674 get_now(tv);
3675 if (tv[1].tv_nsec == UTIME_NOW)
3676 get_now(tv + 1);
3677 #endif /* UTIME_NOW */
3678 #ifdef UTIME_OMIT
3679 if (tv[0].tv_nsec != UTIME_OMIT)
3680 EXT4_INODE_SET_XTIME(i_atime, &tv[0], &inode);
3681 if (tv[1].tv_nsec != UTIME_OMIT)
3682 EXT4_INODE_SET_XTIME(i_mtime, &tv[1], &inode);
3683 #endif /* UTIME_OMIT */
3684 ret = update_ctime(fs, ino, &inode);
3685 if (ret)
3686 goto out;
3687
3688 err = fuse2fs_write_inode(fs, ino, &inode);
3689 if (err) {
3690 ret = translate_error(fs, ino, err);
3691 goto out;
3692 }
3693
3694 out:
3695 pthread_mutex_unlock(&ff->bfl);
3696 return ret;
3697 }
3698
3699 #define FUSE2FS_MODIFIABLE_IFLAGS \
3700 (EXT2_FL_USER_MODIFIABLE & ~(EXT4_EXTENTS_FL | EXT4_CASEFOLD_FL | \
3701 EXT3_JOURNAL_DATA_FL))
3702
3703 static inline int set_iflags(struct ext2_inode_large *inode, __u32 iflags)
3704 {
3705 if ((inode->i_flags ^ iflags) & ~FUSE2FS_MODIFIABLE_IFLAGS)
3706 return -EINVAL;
3707
3708 inode->i_flags = (inode->i_flags & ~FUSE2FS_MODIFIABLE_IFLAGS) |
3709 (iflags & FUSE2FS_MODIFIABLE_IFLAGS);
3710 return 0;
3711 }
3712
3713 #ifdef SUPPORT_I_FLAGS
3714 static int ioctl_getflags(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
3715 void *data)
3716 {
3717 ext2_filsys fs = ff->fs;
3718 errcode_t err;
3719 struct ext2_inode_large inode;
3720
3721 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3722 dbg_printf(ff, "%s: ino=%d\n", __func__, fh->ino);
3723 err = fuse2fs_read_inode(fs, fh->ino, &inode);
3724 if (err)
3725 return translate_error(fs, fh->ino, err);
3726
3727 *(__u32 *)data = inode.i_flags & EXT2_FL_USER_VISIBLE;
3728 return 0;
3729 }
3730
3731 static int ioctl_setflags(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
3732 void *data)
3733 {
3734 ext2_filsys fs = ff->fs;
3735 errcode_t err;
3736 struct ext2_inode_large inode;
3737 int ret;
3738 __u32 flags = *(__u32 *)data;
3739 struct fuse_context *ctxt = fuse_get_context();
3740
3741 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3742 dbg_printf(ff, "%s: ino=%d\n", __func__, fh->ino);
3743 err = fuse2fs_read_inode(fs, fh->ino, &inode);
3744 if (err)
3745 return translate_error(fs, fh->ino, err);
3746
3747 if (want_check_owner(ff, ctxt) && inode_uid(inode) != ctxt->uid)
3748 return -EPERM;
3749
3750 ret = set_iflags(&inode, flags);
3751 if (ret)
3752 return ret;
3753
3754 ret = update_ctime(fs, fh->ino, &inode);
3755 if (ret)
3756 return ret;
3757
3758 err = fuse2fs_write_inode(fs, fh->ino, &inode);
3759 if (err)
3760 return translate_error(fs, fh->ino, err);
3761
3762 return 0;
3763 }
3764
3765 static int ioctl_getversion(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
3766 void *data)
3767 {
3768 ext2_filsys fs = ff->fs;
3769 errcode_t err;
3770 struct ext2_inode_large inode;
3771
3772 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3773 dbg_printf(ff, "%s: ino=%d\n", __func__, fh->ino);
3774 err = fuse2fs_read_inode(fs, fh->ino, &inode);
3775 if (err)
3776 return translate_error(fs, fh->ino, err);
3777
3778 *(__u32 *)data = inode.i_generation;
3779 return 0;
3780 }
3781
3782 static int ioctl_setversion(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
3783 void *data)
3784 {
3785 ext2_filsys fs = ff->fs;
3786 errcode_t err;
3787 struct ext2_inode_large inode;
3788 int ret;
3789 __u32 generation = *(__u32 *)data;
3790 struct fuse_context *ctxt = fuse_get_context();
3791
3792 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3793 dbg_printf(ff, "%s: ino=%d\n", __func__, fh->ino);
3794 err = fuse2fs_read_inode(fs, fh->ino, &inode);
3795 if (err)
3796 return translate_error(fs, fh->ino, err);
3797
3798 if (want_check_owner(ff, ctxt) && inode_uid(inode) != ctxt->uid)
3799 return -EPERM;
3800
3801 inode.i_generation = generation;
3802
3803 ret = update_ctime(fs, fh->ino, &inode);
3804 if (ret)
3805 return ret;
3806
3807 err = fuse2fs_write_inode(fs, fh->ino, &inode);
3808 if (err)
3809 return translate_error(fs, fh->ino, err);
3810
3811 return 0;
3812 }
3813 #endif /* SUPPORT_I_FLAGS */
3814
3815 #ifdef FS_IOC_FSGETXATTR
3816 static __u32 iflags_to_fsxflags(__u32 iflags)
3817 {
3818 __u32 xflags = 0;
3819
3820 if (iflags & FS_SYNC_FL)
3821 xflags |= FS_XFLAG_SYNC;
3822 if (iflags & FS_IMMUTABLE_FL)
3823 xflags |= FS_XFLAG_IMMUTABLE;
3824 if (iflags & FS_APPEND_FL)
3825 xflags |= FS_XFLAG_APPEND;
3826 if (iflags & FS_NODUMP_FL)
3827 xflags |= FS_XFLAG_NODUMP;
3828 if (iflags & FS_NOATIME_FL)
3829 xflags |= FS_XFLAG_NOATIME;
3830 if (iflags & FS_DAX_FL)
3831 xflags |= FS_XFLAG_DAX;
3832 if (iflags & FS_PROJINHERIT_FL)
3833 xflags |= FS_XFLAG_PROJINHERIT;
3834 return xflags;
3835 }
3836
3837 static int ioctl_fsgetxattr(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
3838 void *data)
3839 {
3840 ext2_filsys fs = ff->fs;
3841 errcode_t err;
3842 struct ext2_inode_large inode;
3843 struct fsxattr *fsx = data;
3844 unsigned int inode_size;
3845
3846 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3847 dbg_printf(ff, "%s: ino=%d\n", __func__, fh->ino);
3848 err = fuse2fs_read_inode(fs, fh->ino, &inode);
3849 if (err)
3850 return translate_error(fs, fh->ino, err);
3851
3852 memset(fsx, 0, sizeof(*fsx));
3853 inode_size = EXT2_GOOD_OLD_INODE_SIZE + inode.i_extra_isize;
3854 if (ext2fs_inode_includes(inode_size, i_projid))
3855 fsx->fsx_projid = inode_projid(inode);
3856 fsx->fsx_xflags = iflags_to_fsxflags(inode.i_flags);
3857 return 0;
3858 }
3859
3860 static __u32 fsxflags_to_iflags(__u32 xflags)
3861 {
3862 __u32 iflags = 0;
3863
3864 if (xflags & FS_XFLAG_IMMUTABLE)
3865 iflags |= FS_IMMUTABLE_FL;
3866 if (xflags & FS_XFLAG_APPEND)
3867 iflags |= FS_APPEND_FL;
3868 if (xflags & FS_XFLAG_SYNC)
3869 iflags |= FS_SYNC_FL;
3870 if (xflags & FS_XFLAG_NOATIME)
3871 iflags |= FS_NOATIME_FL;
3872 if (xflags & FS_XFLAG_NODUMP)
3873 iflags |= FS_NODUMP_FL;
3874 if (xflags & FS_XFLAG_DAX)
3875 iflags |= FS_DAX_FL;
3876 if (xflags & FS_XFLAG_PROJINHERIT)
3877 iflags |= FS_PROJINHERIT_FL;
3878 return iflags;
3879 }
3880
3881 static int ioctl_fssetxattr(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
3882 void *data)
3883 {
3884 ext2_filsys fs = ff->fs;
3885 errcode_t err;
3886 struct ext2_inode_large inode;
3887 int ret;
3888 struct fuse_context *ctxt = fuse_get_context();
3889 struct fsxattr *fsx = data;
3890 __u32 flags = fsxflags_to_iflags(fsx->fsx_xflags);
3891 unsigned int inode_size;
3892
3893 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
3894 dbg_printf(ff, "%s: ino=%d\n", __func__, fh->ino);
3895 err = fuse2fs_read_inode(fs, fh->ino, &inode);
3896 if (err)
3897 return translate_error(fs, fh->ino, err);
3898
3899 if (want_check_owner(ff, ctxt) && inode_uid(inode) != ctxt->uid)
3900 return -EPERM;
3901
3902 ret = set_iflags(&inode, flags);
3903 if (ret)
3904 return ret;
3905
3906 inode_size = EXT2_GOOD_OLD_INODE_SIZE + inode.i_extra_isize;
3907 if (ext2fs_inode_includes(inode_size, i_projid))
3908 inode.i_projid = fsx->fsx_projid;
3909
3910 ret = update_ctime(fs, fh->ino, &inode);
3911 if (ret)
3912 return ret;
3913
3914 err = fuse2fs_write_inode(fs, fh->ino, &inode);
3915 if (err)
3916 return translate_error(fs, fh->ino, err);
3917
3918 return 0;
3919 }
3920 #endif /* FS_IOC_FSGETXATTR */
3921
3922 #ifdef FITRIM
3923 static int ioctl_fitrim(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
3924 void *data)
3925 {
3926 ext2_filsys fs = ff->fs;
3927 struct fstrim_range *fr = data;
3928 blk64_t start, end, max_blocks, b, cleared, minlen;
3929 blk64_t max_blks = ext2fs_blocks_count(fs->super);
3930 errcode_t err = 0;
3931
3932 if (!fs_writeable(fs))
3933 return -EROFS;
3934
3935 start = FUSE2FS_B_TO_FSBT(ff, fr->start);
3936 if (fr->len == -1ULL)
3937 end = -1ULL;
3938 else
3939 end = FUSE2FS_B_TO_FSBT(ff, fr->start + fr->len - 1);
3940 minlen = FUSE2FS_B_TO_FSBT(ff, fr->minlen);
3941
3942 if (EXT2FS_NUM_B2C(fs, minlen) > EXT2_CLUSTERS_PER_GROUP(fs->super) ||
3943 start >= max_blks ||
3944 fr->len < fs->blocksize)
3945 return -EINVAL;
3946
3947 dbg_printf(ff, "%s: start=%llu end=%llu minlen=%llu\n", __func__,
3948 start, end, minlen);
3949
3950 if (start < fs->super->s_first_data_block)
3951 start = fs->super->s_first_data_block;
3952
3953 if (end < fs->super->s_first_data_block)
3954 end = fs->super->s_first_data_block;
3955 if (end >= ext2fs_blocks_count(fs->super))
3956 end = ext2fs_blocks_count(fs->super) - 1;
3957
3958 cleared = 0;
3959 max_blocks = FUSE2FS_B_TO_FSBT(ff, 2048ULL * 1024 * 1024);
3960
3961 fr->len = 0;
3962 while (start <= end) {
3963 err = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
3964 start, end, &start);
3965 switch (err) {
3966 case 0:
3967 break;
3968 case ENOENT:
3969 /* no free blocks found, so we're done */
3970 err = 0;
3971 goto out;
3972 default:
3973 return translate_error(fs, fh->ino, err);
3974 }
3975
3976 b = start + max_blocks < end ? start + max_blocks : end;
3977 err = ext2fs_find_first_set_block_bitmap2(fs->block_map,
3978 start, b, &b);
3979 if (err && err != ENOENT)
3980 return translate_error(fs, fh->ino, err);
3981 if (b - start >= minlen) {
3982 err = io_channel_discard(fs->io, start, b - start);
3983 if (err)
3984 return translate_error(fs, fh->ino, err);
3985 cleared += b - start;
3986 fr->len = FUSE2FS_FSB_TO_B(ff, cleared);
3987 }
3988 start = b + 1;
3989 }
3990
3991 out:
3992 fr->len = FUSE2FS_FSB_TO_B(ff, cleared);
3993 dbg_printf(ff, "%s: len=%llu err=%ld\n", __func__, fr->len, err);
3994 return err;
3995 }
3996 #endif /* FITRIM */
3997
3998 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
3999 static int op_ioctl(const char *path EXT2FS_ATTR((unused)),
4000 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
4001 unsigned int cmd,
4002 #else
4003 int cmd,
4004 #endif
4005 void *arg EXT2FS_ATTR((unused)),
4006 struct fuse_file_info *fp,
4007 unsigned int flags EXT2FS_ATTR((unused)), void *data)
4008 {
4009 struct fuse_context *ctxt = fuse_get_context();
4010 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
4011 struct fuse2fs_file_handle *fh =
4012 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
4013 int ret = 0;
4014
4015 FUSE2FS_CHECK_CONTEXT(ff);
4016 pthread_mutex_lock(&ff->bfl);
4017 switch ((unsigned long) cmd) {
4018 #ifdef SUPPORT_I_FLAGS
4019 case EXT2_IOC_GETFLAGS:
4020 ret = ioctl_getflags(ff, fh, data);
4021 break;
4022 case EXT2_IOC_SETFLAGS:
4023 ret = ioctl_setflags(ff, fh, data);
4024 break;
4025 case EXT2_IOC_GETVERSION:
4026 ret = ioctl_getversion(ff, fh, data);
4027 break;
4028 case EXT2_IOC_SETVERSION:
4029 ret = ioctl_setversion(ff, fh, data);
4030 break;
4031 #endif
4032 #ifdef FS_IOC_FSGETXATTR
4033 case FS_IOC_FSGETXATTR:
4034 ret = ioctl_fsgetxattr(ff, fh, data);
4035 break;
4036 case FS_IOC_FSSETXATTR:
4037 ret = ioctl_fssetxattr(ff, fh, data);
4038 break;
4039 #endif
4040 #ifdef FITRIM
4041 case FITRIM:
4042 ret = ioctl_fitrim(ff, fh, data);
4043 break;
4044 #endif
4045 default:
4046 dbg_printf(ff, "%s: Unknown ioctl %d\n", __func__, cmd);
4047 ret = -ENOTTY;
4048 }
4049 pthread_mutex_unlock(&ff->bfl);
4050
4051 return ret;
4052 }
4053 #endif /* FUSE 28 */
4054
4055 static int op_bmap(const char *path, size_t blocksize EXT2FS_ATTR((unused)),
4056 uint64_t *idx)
4057 {
4058 struct fuse_context *ctxt = fuse_get_context();
4059 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
4060 ext2_filsys fs;
4061 ext2_ino_t ino;
4062 errcode_t err;
4063 int ret = 0;
4064
4065 FUSE2FS_CHECK_CONTEXT(ff);
4066 fs = ff->fs;
4067 pthread_mutex_lock(&ff->bfl);
4068 err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, &ino);
4069 if (err) {
4070 ret = translate_error(fs, 0, err);
4071 goto out;
4072 }
4073 dbg_printf(ff, "%s: ino=%d blk=%"PRIu64"\n", __func__, ino, *idx);
4074
4075 err = ext2fs_bmap2(fs, ino, NULL, NULL, 0, *idx, 0, (blk64_t *)idx);
4076 if (err) {
4077 ret = translate_error(fs, ino, err);
4078 goto out;
4079 }
4080
4081 out:
4082 pthread_mutex_unlock(&ff->bfl);
4083 return ret;
4084 }
4085
4086 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
4087 # ifdef SUPPORT_FALLOCATE
4088 static int fallocate_helper(struct fuse_file_info *fp, int mode, off_t offset,
4089 off_t len)
4090 {
4091 struct fuse_context *ctxt = fuse_get_context();
4092 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
4093 struct fuse2fs_file_handle *fh =
4094 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
4095 ext2_filsys fs;
4096 struct ext2_inode_large inode;
4097 blk64_t start, end;
4098 __u64 fsize;
4099 errcode_t err;
4100 int flags;
4101
4102 FUSE2FS_CHECK_CONTEXT(ff);
4103 fs = ff->fs;
4104 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
4105 start = FUSE2FS_B_TO_FSBT(ff, offset);
4106 end = FUSE2FS_B_TO_FSBT(ff, offset + len - 1);
4107 dbg_printf(ff, "%s: ino=%d mode=0x%x start=%llu end=%llu\n", __func__,
4108 fh->ino, mode, start, end);
4109 if (!fs_can_allocate(ff, FUSE2FS_B_TO_FSB(ff, len)))
4110 return -ENOSPC;
4111
4112 err = fuse2fs_read_inode(fs, fh->ino, &inode);
4113 if (err)
4114 return err;
4115 fsize = EXT2_I_SIZE(&inode);
4116
4117 /* Allocate a bunch of blocks */
4118 flags = (mode & FL_KEEP_SIZE_FLAG ? 0 :
4119 EXT2_FALLOCATE_INIT_BEYOND_EOF);
4120 err = ext2fs_fallocate(fs, flags, fh->ino,
4121 EXT2_INODE(&inode),
4122 ~0ULL, start, end - start + 1);
4123 if (err && err != EXT2_ET_BLOCK_ALLOC_FAIL)
4124 return translate_error(fs, fh->ino, err);
4125
4126 /* Update i_size */
4127 if (!(mode & FL_KEEP_SIZE_FLAG)) {
4128 if ((__u64) offset + len > fsize) {
4129 err = ext2fs_inode_size_set(fs,
4130 EXT2_INODE(&inode),
4131 offset + len);
4132 if (err)
4133 return translate_error(fs, fh->ino, err);
4134 }
4135 }
4136
4137 err = update_mtime(fs, fh->ino, &inode);
4138 if (err)
4139 return err;
4140
4141 err = fuse2fs_write_inode(fs, fh->ino, &inode);
4142 if (err)
4143 return translate_error(fs, fh->ino, err);
4144
4145 return err;
4146 }
4147
4148 static errcode_t clean_block_middle(struct fuse2fs *ff, ext2_ino_t ino,
4149 struct ext2_inode_large *inode,
4150 off_t offset, off_t len, char **buf)
4151 {
4152 ext2_filsys fs = ff->fs;
4153 blk64_t blk;
4154 off_t residue = FUSE2FS_OFF_IN_FSB(ff, offset);
4155 int retflags;
4156 errcode_t err;
4157
4158 if (!*buf) {
4159 err = ext2fs_get_mem(fs->blocksize, buf);
4160 if (err)
4161 return err;
4162 }
4163
4164 err = ext2fs_bmap2(fs, ino, EXT2_INODE(inode), *buf, 0,
4165 FUSE2FS_B_TO_FSBT(ff, offset), &retflags, &blk);
4166 if (err)
4167 return err;
4168 if (!blk || (retflags & BMAP_RET_UNINIT))
4169 return 0;
4170
4171 err = io_channel_read_blk64(fs->io, blk, 1, *buf);
4172 if (err)
4173 return err;
4174
4175 memset(*buf + residue, 0, len);
4176
4177 return io_channel_write_blk64(fs->io, blk, 1, *buf);
4178 }
4179
4180 static errcode_t clean_block_edge(struct fuse2fs *ff, ext2_ino_t ino,
4181 struct ext2_inode_large *inode, off_t offset,
4182 int clean_before, char **buf)
4183 {
4184 ext2_filsys fs = ff->fs;
4185 blk64_t blk;
4186 int retflags;
4187 off_t residue;
4188 errcode_t err;
4189
4190 residue = FUSE2FS_OFF_IN_FSB(ff, offset);
4191 if (residue == 0)
4192 return 0;
4193
4194 if (!*buf) {
4195 err = ext2fs_get_mem(fs->blocksize, buf);
4196 if (err)
4197 return err;
4198 }
4199
4200 err = ext2fs_bmap2(fs, ino, EXT2_INODE(inode), *buf, 0,
4201 FUSE2FS_B_TO_FSBT(ff, offset), &retflags, &blk);
4202 if (err)
4203 return err;
4204
4205 err = io_channel_read_blk64(fs->io, blk, 1, *buf);
4206 if (err)
4207 return err;
4208 if (!blk || (retflags & BMAP_RET_UNINIT))
4209 return 0;
4210
4211 if (clean_before)
4212 memset(*buf, 0, residue);
4213 else
4214 memset(*buf + residue, 0, fs->blocksize - residue);
4215
4216 return io_channel_write_blk64(fs->io, blk, 1, *buf);
4217 }
4218
4219 static int punch_helper(struct fuse_file_info *fp, int mode, off_t offset,
4220 off_t len)
4221 {
4222 struct fuse_context *ctxt = fuse_get_context();
4223 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
4224 struct fuse2fs_file_handle *fh =
4225 (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
4226 ext2_filsys fs;
4227 struct ext2_inode_large inode;
4228 blk64_t start, end;
4229 errcode_t err;
4230 char *buf = NULL;
4231
4232 FUSE2FS_CHECK_CONTEXT(ff);
4233 fs = ff->fs;
4234 FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
4235 dbg_printf(ff, "%s: offset=%jd len=%jd\n", __func__,
4236 (intmax_t) offset, (intmax_t) len);
4237
4238 /* kernel ext4 punch requires this flag to be set */
4239 if (!(mode & FL_KEEP_SIZE_FLAG))
4240 return -EINVAL;
4241
4242 /*
4243 * Unmap out all full blocks in the middle of the range being punched.
4244 * The start of the unmap range should be the first byte of the first
4245 * fsblock that starts within the range. The end of the range should
4246 * be the next byte after the last fsblock to end in the range.
4247 */
4248 start = FUSE2FS_B_TO_FSBT(ff, round_up(offset, fs->blocksize));
4249 end = FUSE2FS_B_TO_FSBT(ff, round_down(offset + len, fs->blocksize));
4250
4251 dbg_printf(ff,
4252 "%s: ino=%d mode=0x%x offset=0x%jx len=0x%jx start=0x%llx end=0x%llx\n",
4253 __func__, fh->ino, mode, offset, len, start, end);
4254
4255 err = fuse2fs_read_inode(fs, fh->ino, &inode);
4256 if (err)
4257 return translate_error(fs, fh->ino, err);
4258
4259 /* Zero everything before the first block and after the last block */
4260 if (FUSE2FS_B_TO_FSBT(ff, offset) == FUSE2FS_B_TO_FSBT(ff, offset + len))
4261 err = clean_block_middle(ff, fh->ino, &inode, offset,
4262 len, &buf);
4263 else {
4264 err = clean_block_edge(ff, fh->ino, &inode, offset, 0, &buf);
4265 if (!err)
4266 err = clean_block_edge(ff, fh->ino, &inode,
4267 offset + len, 1, &buf);
4268 }
4269 if (buf)
4270 ext2fs_free_mem(&buf);
4271 if (err)
4272 return translate_error(fs, fh->ino, err);
4273
4274 /*
4275 * Unmap full blocks in the middle, which is to say that start - end
4276 * must be at least one fsblock. ext2fs_punch takes a closed interval
4277 * as its argument, so we pass [start, end - 1].
4278 */
4279 if (start < end) {
4280 err = ext2fs_punch(fs, fh->ino, EXT2_INODE(&inode),
4281 NULL, start, end - 1);
4282 if (err)
4283 return translate_error(fs, fh->ino, err);
4284 }
4285
4286 err = update_mtime(fs, fh->ino, &inode);
4287 if (err)
4288 return err;
4289
4290 err = fuse2fs_write_inode(fs, fh->ino, &inode);
4291 if (err)
4292 return translate_error(fs, fh->ino, err);
4293
4294 return 0;
4295 }
4296
4297 static int zero_helper(struct fuse_file_info *fp, int mode, off_t offset,
4298 off_t len)
4299 {
4300 int ret = punch_helper(fp, mode | FL_KEEP_SIZE_FLAG, offset, len);
4301
4302 if (!ret)
4303 ret = fallocate_helper(fp, mode, offset, len);
4304 return ret;
4305 }
4306
4307 static int op_fallocate(const char *path EXT2FS_ATTR((unused)), int mode,
4308 off_t offset, off_t len,
4309 struct fuse_file_info *fp)
4310 {
4311 struct fuse_context *ctxt = fuse_get_context();
4312 struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
4313 ext2_filsys fs = ff->fs;
4314 int ret;
4315
4316 /* Catch unknown flags */
4317 if (mode & ~(FL_ZERO_RANGE_FLAG | FL_PUNCH_HOLE_FLAG | FL_KEEP_SIZE_FLAG))
4318 return -EOPNOTSUPP;
4319
4320 pthread_mutex_lock(&ff->bfl);
4321 if (!fs_writeable(fs)) {
4322 ret = -EROFS;
4323 goto out;
4324 }
4325 if (mode & FL_ZERO_RANGE_FLAG)
4326 ret = zero_helper(fp, mode, offset, len);
4327 else if (mode & FL_PUNCH_HOLE_FLAG)
4328 ret = punch_helper(fp, mode, offset, len);
4329 else
4330 ret = fallocate_helper(fp, mode, offset, len);
4331 out:
4332 pthread_mutex_unlock(&ff->bfl);
4333
4334 return ret;
4335 }
4336 # endif /* SUPPORT_FALLOCATE */
4337 #endif /* FUSE 29 */
4338
4339 static struct fuse_operations fs_ops = {
4340 .init = op_init,
4341 .destroy = op_destroy,
4342 .getattr = op_getattr,
4343 .readlink = op_readlink,
4344 .mknod = op_mknod,
4345 .mkdir = op_mkdir,
4346 .unlink = op_unlink,
4347 .rmdir = op_rmdir,
4348 .symlink = op_symlink,
4349 .rename = op_rename,
4350 .link = op_link,
4351 .chmod = op_chmod,
4352 .chown = op_chown,
4353 .truncate = op_truncate,
4354 .open = op_open,
4355 .read = op_read,
4356 .write = op_write,
4357 .statfs = op_statfs,
4358 .release = op_release,
4359 .fsync = op_fsync,
4360 .setxattr = op_setxattr,
4361 .getxattr = op_getxattr,
4362 .listxattr = op_listxattr,
4363 .removexattr = op_removexattr,
4364 .opendir = op_open,
4365 .readdir = op_readdir,
4366 .releasedir = op_release,
4367 .fsyncdir = op_fsync,
4368 .access = op_access,
4369 .create = op_create,
4370 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
4371 .ftruncate = op_ftruncate,
4372 .fgetattr = op_fgetattr,
4373 #endif
4374 .utimens = op_utimens,
4375 #if (FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)) && (FUSE_VERSION < FUSE_MAKE_VERSION(3, 0))
4376 # if defined(UTIME_NOW) || defined(UTIME_OMIT)
4377 .flag_utime_omit_ok = 1,
4378 # endif
4379 #endif
4380 .bmap = op_bmap,
4381 #ifdef SUPERFLUOUS
4382 .lock = op_lock,
4383 .poll = op_poll,
4384 #endif
4385 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
4386 .ioctl = op_ioctl,
4387 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
4388 .flag_nullpath_ok = 1,
4389 #endif
4390 #endif
4391 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 9)
4392 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
4393 .flag_nopath = 1,
4394 #endif
4395 # ifdef SUPPORT_FALLOCATE
4396 .fallocate = op_fallocate,
4397 # endif
4398 #endif
4399 };
4400
4401 static int get_random_bytes(void *p, size_t sz)
4402 {
4403 int fd;
4404 ssize_t r;
4405
4406 fd = open("/dev/urandom", O_RDONLY);
4407 if (fd < 0) {
4408 perror("/dev/urandom");
4409 return 0;
4410 }
4411
4412 r = read(fd, p, sz);
4413
4414 close(fd);
4415 return (size_t) r == sz;
4416 }
4417
4418 enum {
4419 FUSE2FS_IGNORED,
4420 FUSE2FS_VERSION,
4421 FUSE2FS_HELP,
4422 FUSE2FS_HELPFULL,
4423 FUSE2FS_CACHE_SIZE,
4424 };
4425
4426 #define FUSE2FS_OPT(t, p, v) { t, offsetof(struct fuse2fs, p), v }
4427
4428 static struct fuse_opt fuse2fs_opts[] = {
4429 FUSE2FS_OPT("ro", ro, 1),
4430 FUSE2FS_OPT("rw", ro, 0),
4431 FUSE2FS_OPT("errors=panic", panic_on_error, 1),
4432 FUSE2FS_OPT("minixdf", minixdf, 1),
4433 FUSE2FS_OPT("bsddf", minixdf, 0),
4434 FUSE2FS_OPT("fakeroot", fakeroot, 1),
4435 FUSE2FS_OPT("fuse2fs_debug", debug, 1),
4436 FUSE2FS_OPT("no_default_opts", no_default_opts, 1),
4437 FUSE2FS_OPT("norecovery", norecovery, 1),
4438 FUSE2FS_OPT("noload", norecovery, 1),
4439 FUSE2FS_OPT("offset=%lu", offset, 0),
4440 FUSE2FS_OPT("kernel", kernel, 1),
4441 FUSE2FS_OPT("directio", directio, 1),
4442 FUSE2FS_OPT("acl", acl, 1),
4443 FUSE2FS_OPT("noacl", acl, 0),
4444
4445 FUSE_OPT_KEY("user_xattr", FUSE2FS_IGNORED),
4446 FUSE_OPT_KEY("noblock_validity", FUSE2FS_IGNORED),
4447 FUSE_OPT_KEY("nodelalloc", FUSE2FS_IGNORED),
4448 FUSE_OPT_KEY("cache_size=%s", FUSE2FS_CACHE_SIZE),
4449 FUSE2FS_OPT("lockfile=%s", lockfile, 0),
4450
4451 FUSE_OPT_KEY("-V", FUSE2FS_VERSION),
4452 FUSE_OPT_KEY("--version", FUSE2FS_VERSION),
4453 FUSE_OPT_KEY("-h", FUSE2FS_HELP),
4454 FUSE_OPT_KEY("--help", FUSE2FS_HELP),
4455 FUSE_OPT_KEY("--helpfull", FUSE2FS_HELPFULL),
4456 FUSE_OPT_END
4457 };
4458
4459
4460 static int fuse2fs_opt_proc(void *data, const char *arg,
4461 int key, struct fuse_args *outargs)
4462 {
4463 struct fuse2fs *ff = data;
4464
4465 switch (key) {
4466 case FUSE_OPT_KEY_NONOPT:
4467 if (!ff->device) {
4468 ff->device = strdup(arg);
4469 return 0;
4470 }
4471 return 1;
4472 case FUSE2FS_CACHE_SIZE:
4473 ff->cache_size = parse_num_blocks2(arg + 11, -1);
4474 if (ff->cache_size < 1 || ff->cache_size > INT32_MAX) {
4475 fprintf(stderr, "%s: %s\n", arg,
4476 _("cache size must be between 1 block and 2GB."));
4477 return -1;
4478 }
4479
4480 /* do not pass through to libfuse */
4481 return 0;
4482 case FUSE2FS_IGNORED:
4483 return 0;
4484 case FUSE2FS_HELP:
4485 case FUSE2FS_HELPFULL:
4486 fprintf(stderr,
4487 "usage: %s device/image mountpoint [options]\n"
4488 "\n"
4489 "general options:\n"
4490 " -o opt,[opt...] mount options\n"
4491 " -h --help print help\n"
4492 " -V --version print version\n"
4493 "\n"
4494 "fuse2fs options:\n"
4495 " -o errors=panic dump core on error\n"
4496 " -o minixdf minix-style df\n"
4497 " -o fakeroot pretend to be root for permission checks\n"
4498 " -o no_default_opts do not include default fuse options\n"
4499 " -o offset=<bytes> similar to mount -o offset=<bytes>, mount the partition starting at <bytes>\n"
4500 " -o norecovery don't replay the journal\n"
4501 " -o fuse2fs_debug enable fuse2fs debugging\n"
4502 " -o lockfile=<file> file to show that fuse is still using the file system image\n"
4503 " -o kernel run this as if it were the kernel, which sets:\n"
4504 " allow_others,default_permissions,suid,dev\n"
4505 " -o directio use O_DIRECT to read and write the disk\n"
4506 " -o cache_size=N[KMG] use a disk cache of this size\n"
4507 "\n",
4508 outargs->argv[0]);
4509 if (key == FUSE2FS_HELPFULL) {
4510 fuse_opt_add_arg(outargs, "-h");
4511 fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL);
4512 } else {
4513 fprintf(stderr, "Try --helpfull to get a list of "
4514 "all flags, including the FUSE options.\n");
4515 }
4516 exit(1);
4517
4518 case FUSE2FS_VERSION:
4519 fprintf(stderr, "fuse2fs %s (%s)\n", E2FSPROGS_VERSION,
4520 E2FSPROGS_DATE);
4521 fuse_opt_add_arg(outargs, "--version");
4522 fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL);
4523 exit(0);
4524 }
4525 return 1;
4526 }
4527
4528 static const char *get_subtype(const char *argv0)
4529 {
4530 size_t argvlen = strlen(argv0);
4531
4532 if (argvlen < 4)
4533 goto out_default;
4534
4535 if (argv0[argvlen - 4] == 'e' &&
4536 argv0[argvlen - 3] == 'x' &&
4537 argv0[argvlen - 2] == 't' &&
4538 isdigit(argv0[argvlen - 1]))
4539 return &argv0[argvlen - 4];
4540
4541 out_default:
4542 return "ext4";
4543 }
4544
4545 /* Figure out a reasonable default size for the disk cache */
4546 static unsigned long long default_cache_size(void)
4547 {
4548 long pages = 0, pagesize = 0;
4549 unsigned long long max_cache;
4550 unsigned long long ret = 32ULL << 20; /* 32 MB */
4551
4552 #ifdef _SC_PHYS_PAGES
4553 pages = sysconf(_SC_PHYS_PAGES);
4554 #endif
4555 #ifdef _SC_PAGESIZE
4556 pagesize = sysconf(_SC_PAGESIZE);
4557 #endif
4558 if (pages > 0 && pagesize > 0) {
4559 max_cache = (unsigned long long)pagesize * pages / 20;
4560
4561 if (max_cache > 0 && ret > max_cache)
4562 ret = max_cache;
4563 }
4564 return ret;
4565 }
4566
4567 int main(int argc, char *argv[])
4568 {
4569 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
4570 struct fuse2fs fctx;
4571 errcode_t err;
4572 FILE *orig_stderr = stderr;
4573 char extra_args[BUFSIZ];
4574 int ret;
4575 int flags = EXT2_FLAG_64BITS | EXT2_FLAG_THREADS | EXT2_FLAG_EXCLUSIVE |
4576 EXT2_FLAG_RW;
4577
4578 memset(&fctx, 0, sizeof(fctx));
4579 fctx.magic = FUSE2FS_MAGIC;
4580 fctx.logfd = -1;
4581
4582 ret = fuse_opt_parse(&args, &fctx, fuse2fs_opts, fuse2fs_opt_proc);
4583 if (ret)
4584 exit(1);
4585 if (fctx.device == NULL) {
4586 fprintf(stderr, "Missing ext4 device/image\n");
4587 fprintf(stderr, "See '%s -h' for usage\n", argv[0]);
4588 exit(1);
4589 }
4590
4591 /* /dev/sda -> sda for reporting */
4592 fctx.shortdev = strrchr(fctx.device, '/');
4593 if (fctx.shortdev)
4594 fctx.shortdev++;
4595 else
4596 fctx.shortdev = fctx.device;
4597
4598 #ifdef ENABLE_NLS
4599 setlocale(LC_MESSAGES, "");
4600 setlocale(LC_CTYPE, "");
4601 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
4602 textdomain(NLS_CAT_NAME);
4603 set_com_err_gettext(gettext);
4604 #endif
4605 add_error_table(&et_ext2_error_table);
4606
4607 ret = fuse2fs_setup_logging(&fctx);
4608 if (ret) {
4609 /* operational error */
4610 ret = 2;
4611 goto out;
4612 }
4613
4614 /* Will we allow users to allocate every last block? */
4615 if (getenv("FUSE2FS_ALLOC_ALL_BLOCKS")) {
4616 log_printf(&fctx, "%s\n",
4617 _("Allowing users to allocate all blocks. This is dangerous!"));
4618 fctx.alloc_all_blocks = 1;
4619 }
4620
4621 if (fctx.lockfile) {
4622 char *resolved;
4623 int lockfd;
4624
4625 lockfd = open(fctx.lockfile, O_RDWR | O_CREAT | O_EXCL, 0400);
4626 if (lockfd < 0) {
4627 if (errno == EEXIST)
4628 err = EWOULDBLOCK;
4629 else
4630 err = errno;
4631 err_printf(&fctx, "%s: %s: %s\n", fctx.lockfile,
4632 _("opening lockfile failed"),
4633 strerror(err));
4634 fctx.lockfile = NULL;
4635 ret |= 32;
4636 goto out;
4637 }
4638 close(lockfd);
4639
4640 resolved = realpath(fctx.lockfile, NULL);
4641 if (!resolved) {
4642 err = errno;
4643 err_printf(&fctx, "%s: %s: %s\n", fctx.lockfile,
4644 _("resolving lockfile failed"),
4645 strerror(err));
4646 unlink(fctx.lockfile);
4647 fctx.lockfile = NULL;
4648 ret |= 32;
4649 goto out;
4650 }
4651 free(fctx.lockfile);
4652 fctx.lockfile = resolved;
4653 }
4654
4655 /* Start up the fs (while we still can use stdout) */
4656 ret = 2;
4657 char options[50];
4658 sprintf(options, "offset=%lu", fctx.offset);
4659 if (fctx.directio)
4660 flags |= EXT2_FLAG_DIRECT_IO;
4661 err = ext2fs_open2(fctx.device, options, flags, 0, 0, unix_io_manager,
4662 &global_fs);
4663 if (err) {
4664 err_printf(&fctx, "%s.\n", error_message(err));
4665 err_printf(&fctx, "%s\n", _("Please run e2fsck -fy."));
4666 goto out;
4667 }
4668 fctx.fs = global_fs;
4669 global_fs->priv_data = &fctx;
4670 fctx.blocklog = u_log2(fctx.fs->blocksize);
4671 fctx.blockmask = fctx.fs->blocksize - 1;
4672
4673 if (!fctx.cache_size)
4674 fctx.cache_size = default_cache_size();
4675 if (fctx.cache_size) {
4676 char buf[55];
4677
4678 snprintf(buf, sizeof(buf), "cache_blocks=%llu",
4679 FUSE2FS_B_TO_FSBT(&fctx, fctx.cache_size));
4680 err = io_channel_set_options(global_fs->io, buf);
4681 if (err) {
4682 err_printf(&fctx, "%s %lluk: %s\n",
4683 _("cannot set disk cache size to"),
4684 fctx.cache_size >> 10,
4685 error_message(err));
4686 goto out;
4687 }
4688 }
4689
4690 ret = 3;
4691
4692 if (ext2fs_has_feature_quota(global_fs->super)) {
4693 err_printf(&fctx, "%s", _("quotas not supported."));
4694 goto out;
4695 }
4696 if (ext2fs_has_feature_verity(global_fs->super)) {
4697 err_printf(&fctx, "%s", _("verity not supported."));
4698 goto out;
4699 }
4700 if (ext2fs_has_feature_encrypt(global_fs->super)) {
4701 err_printf(&fctx, "%s", _("encryption not supported."));
4702 goto out;
4703 }
4704 if (ext2fs_has_feature_casefold(global_fs->super)) {
4705 err_printf(&fctx, "%s", _("casefolding not supported."));
4706 goto out;
4707 }
4708
4709 if (ext2fs_has_feature_shared_blocks(global_fs->super))
4710 fctx.ro = 1;
4711
4712 if (ext2fs_has_feature_journal_needs_recovery(global_fs->super)) {
4713 if (fctx.norecovery) {
4714 log_printf(&fctx, "%s\n",
4715 _("Mounting read-only without recovering journal."));
4716 fctx.ro = 1;
4717 global_fs->flags &= ~EXT2_FLAG_RW;
4718 } else {
4719 log_printf(&fctx, "%s\n", _("Recovering journal."));
4720 err = ext2fs_run_ext3_journal(&global_fs);
4721 if (err) {
4722 err_printf(&fctx, "%s.\n", error_message(err));
4723 err_printf(&fctx, "%s\n",
4724 _("Please run e2fsck -fy."));
4725 goto out;
4726 }
4727 ext2fs_clear_feature_journal_needs_recovery(global_fs->super);
4728 ext2fs_mark_super_dirty(global_fs);
4729 }
4730 }
4731
4732 if (global_fs->flags & EXT2_FLAG_RW) {
4733 if (ext2fs_has_feature_journal(global_fs->super))
4734 log_printf(&fctx, "%s",
4735 _("Warning: fuse2fs does not support using the journal.\n"
4736 "There may be file system corruption or data loss if\n"
4737 "the file system is not gracefully unmounted.\n"));
4738 err = ext2fs_read_inode_bitmap(global_fs);
4739 if (err) {
4740 translate_error(global_fs, 0, err);
4741 goto out;
4742 }
4743 err = ext2fs_read_block_bitmap(global_fs);
4744 if (err) {
4745 translate_error(global_fs, 0, err);
4746 goto out;
4747 }
4748 }
4749
4750 if (!(global_fs->super->s_state & EXT2_VALID_FS))
4751 err_printf(&fctx, "%s\n",
4752 _("Warning: Mounting unchecked fs, running e2fsck is recommended."));
4753 if (global_fs->super->s_max_mnt_count > 0 &&
4754 global_fs->super->s_mnt_count >= global_fs->super->s_max_mnt_count)
4755 err_printf(&fctx, "%s\n",
4756 _("Warning: Maximal mount count reached, running e2fsck is recommended."));
4757 if (global_fs->super->s_checkinterval > 0 &&
4758 (time_t) (global_fs->super->s_lastcheck +
4759 global_fs->super->s_checkinterval) <= time(0))
4760 err_printf(&fctx, "%s\n",
4761 _("Warning: Check time reached; running e2fsck is recommended."));
4762 if (global_fs->super->s_last_orphan)
4763 err_printf(&fctx, "%s\n",
4764 _("Orphans detected; running e2fsck is recommended."));
4765
4766 if (global_fs->super->s_state & EXT2_ERROR_FS) {
4767 err_printf(&fctx, "%s\n",
4768 _("Errors detected; running e2fsck is required."));
4769 goto out;
4770 }
4771
4772 /* Initialize generation counter */
4773 get_random_bytes(&fctx.next_generation, sizeof(unsigned int));
4774
4775 /* Set up default fuse parameters */
4776 snprintf(extra_args, BUFSIZ, "-okernel_cache,subtype=%s,"
4777 "fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS,
4778 get_subtype(argv[0]),
4779 fctx.device);
4780 if (fctx.no_default_opts == 0)
4781 fuse_opt_add_arg(&args, extra_args);
4782
4783 if (fctx.ro)
4784 fuse_opt_add_arg(&args, "-oro");
4785
4786 if (fctx.fakeroot) {
4787 #ifdef HAVE_MOUNT_NODEV
4788 fuse_opt_add_arg(&args,"-onodev");
4789 #endif
4790 #ifdef HAVE_MOUNT_NOSUID
4791 fuse_opt_add_arg(&args,"-onosuid");
4792 #endif
4793 }
4794
4795 if (fctx.kernel) {
4796 /*
4797 * ACLs are always enforced when kernel mode is enabled, to
4798 * match the kernel ext4 driver which always enables ACLs.
4799 */
4800 fctx.acl = 1;
4801 fuse_opt_insert_arg(&args, 1,
4802 "-oallow_other,default_permissions,suid,dev");
4803 }
4804
4805 if (fctx.debug) {
4806 int i;
4807
4808 printf("FUSE2FS (%s): fuse arguments:", fctx.shortdev);
4809 for (i = 0; i < args.argc; i++)
4810 printf(" '%s'", args.argv[i]);
4811 printf("\n");
4812 fflush(stdout);
4813 }
4814
4815 pthread_mutex_init(&fctx.bfl, NULL);
4816 ret = fuse_main(args.argc, args.argv, &fs_ops, &fctx);
4817 pthread_mutex_destroy(&fctx.bfl);
4818
4819 switch(ret) {
4820 case 0:
4821 /* success */
4822 ret = 0;
4823 break;
4824 case 1:
4825 case 2:
4826 /* invalid option or no mountpoint */
4827 ret = 1;
4828 break;
4829 case 3:
4830 case 4:
4831 case 5:
4832 case 6:
4833 case 7:
4834 /* setup or mounting failed */
4835 ret = 32;
4836 break;
4837 default:
4838 /* fuse started up enough to call op_init */
4839 ret = 0;
4840 break;
4841 }
4842 out:
4843 if (ret & 1) {
4844 fprintf(orig_stderr, "%s\n",
4845 _("Mount failed due to unrecognized options. Check dmesg(1) for details."));
4846 fflush(orig_stderr);
4847 }
4848 if (ret & 32) {
4849 fprintf(orig_stderr, "%s\n",
4850 _("Mount failed while opening filesystem. Check dmesg(1) for details."));
4851 fflush(orig_stderr);
4852 }
4853 if (global_fs) {
4854 err = ext2fs_close(global_fs);
4855 if (err)
4856 com_err(argv[0], err, "while closing fs");
4857 global_fs = NULL;
4858 }
4859 if (fctx.lockfile) {
4860 if (unlink(fctx.lockfile)) {
4861 err = errno;
4862 err_printf(&fctx, "%s: %s: %s\n", fctx.lockfile,
4863 _("removing lockfile failed"),
4864 strerror(err));
4865 }
4866 free(fctx.lockfile);
4867 }
4868 if (fctx.device)
4869 free(fctx.device);
4870 fuse_opt_free_args(&args);
4871 return ret;
4872 }
4873
4874 static int __translate_error(ext2_filsys fs, ext2_ino_t ino, errcode_t err,
4875 const char *file, int line)
4876 {
4877 struct timespec now;
4878 int ret = err;
4879 struct fuse2fs *ff = fs->priv_data;
4880 int is_err = 0;
4881
4882 /* Translate ext2 error to unix error code */
4883 switch (err) {
4884 case 0:
4885 break;
4886 case EXT2_ET_NO_MEMORY:
4887 case EXT2_ET_TDB_ERR_OOM:
4888 ret = -ENOMEM;
4889 break;
4890 case EXT2_ET_INVALID_ARGUMENT:
4891 case EXT2_ET_LLSEEK_FAILED:
4892 ret = -EINVAL;
4893 break;
4894 case EXT2_ET_NO_DIRECTORY:
4895 ret = -ENOTDIR;
4896 break;
4897 case EXT2_ET_FILE_NOT_FOUND:
4898 ret = -ENOENT;
4899 break;
4900 case EXT2_ET_DIR_NO_SPACE:
4901 is_err = 1;
4902 /* fallthrough */
4903 case EXT2_ET_TOOSMALL:
4904 case EXT2_ET_BLOCK_ALLOC_FAIL:
4905 case EXT2_ET_INODE_ALLOC_FAIL:
4906 case EXT2_ET_EA_NO_SPACE:
4907 ret = -ENOSPC;
4908 break;
4909 case EXT2_ET_SYMLINK_LOOP:
4910 ret = -EMLINK;
4911 break;
4912 case EXT2_ET_FILE_TOO_BIG:
4913 ret = -EFBIG;
4914 break;
4915 case EXT2_ET_TDB_ERR_EXISTS:
4916 case EXT2_ET_FILE_EXISTS:
4917 ret = -EEXIST;
4918 break;
4919 case EXT2_ET_MMP_FAILED:
4920 case EXT2_ET_MMP_FSCK_ON:
4921 ret = -EBUSY;
4922 break;
4923 case EXT2_ET_EA_KEY_NOT_FOUND:
4924 ret = -ENODATA;
4925 break;
4926 /* Sometimes fuse returns a garbage file handle pointer to us... */
4927 case EXT2_ET_MAGIC_EXT2_FILE:
4928 ret = -EFAULT;
4929 break;
4930 case EXT2_ET_UNIMPLEMENTED:
4931 ret = -EOPNOTSUPP;
4932 break;
4933 case EXT2_ET_MAGIC_EXT2FS_FILSYS:
4934 case EXT2_ET_MAGIC_BADBLOCKS_LIST:
4935 case EXT2_ET_MAGIC_BADBLOCKS_ITERATE:
4936 case EXT2_ET_MAGIC_INODE_SCAN:
4937 case EXT2_ET_MAGIC_IO_CHANNEL:
4938 case EXT2_ET_MAGIC_UNIX_IO_CHANNEL:
4939 case EXT2_ET_MAGIC_IO_MANAGER:
4940 case EXT2_ET_MAGIC_BLOCK_BITMAP:
4941 case EXT2_ET_MAGIC_INODE_BITMAP:
4942 case EXT2_ET_MAGIC_GENERIC_BITMAP:
4943 case EXT2_ET_MAGIC_TEST_IO_CHANNEL:
4944 case EXT2_ET_MAGIC_DBLIST:
4945 case EXT2_ET_MAGIC_ICOUNT:
4946 case EXT2_ET_MAGIC_PQ_IO_CHANNEL:
4947 case EXT2_ET_MAGIC_E2IMAGE:
4948 case EXT2_ET_MAGIC_INODE_IO_CHANNEL:
4949 case EXT2_ET_MAGIC_EXTENT_HANDLE:
4950 case EXT2_ET_BAD_MAGIC:
4951 case EXT2_ET_MAGIC_EXTENT_PATH:
4952 case EXT2_ET_MAGIC_GENERIC_BITMAP64:
4953 case EXT2_ET_MAGIC_BLOCK_BITMAP64:
4954 case EXT2_ET_MAGIC_INODE_BITMAP64:
4955 case EXT2_ET_MAGIC_RESERVED_13:
4956 case EXT2_ET_MAGIC_RESERVED_14:
4957 case EXT2_ET_MAGIC_RESERVED_15:
4958 case EXT2_ET_MAGIC_RESERVED_16:
4959 case EXT2_ET_MAGIC_RESERVED_17:
4960 case EXT2_ET_MAGIC_RESERVED_18:
4961 case EXT2_ET_MAGIC_RESERVED_19:
4962 case EXT2_ET_MMP_MAGIC_INVALID:
4963 case EXT2_ET_MAGIC_EA_HANDLE:
4964 case EXT2_ET_DIR_CORRUPTED:
4965 case EXT2_ET_CORRUPT_SUPERBLOCK:
4966 case EXT2_ET_RESIZE_INODE_CORRUPT:
4967 case EXT2_ET_TDB_ERR_CORRUPT:
4968 case EXT2_ET_UNDO_FILE_CORRUPT:
4969 case EXT2_ET_FILESYSTEM_CORRUPTED:
4970 case EXT2_ET_CORRUPT_JOURNAL_SB:
4971 case EXT2_ET_INODE_CORRUPTED:
4972 case EXT2_ET_EA_INODE_CORRUPTED:
4973 /* same errno that linux uses */
4974 is_err = 1;
4975 ret = -EUCLEAN;
4976 break;
4977 case EIO:
4978 #ifdef EILSEQ
4979 case EILSEQ:
4980 #endif
4981 case EUCLEAN:
4982 /* these errnos usually denote corruption or persistence fail */
4983 is_err = 1;
4984 ret = -err;
4985 break;
4986 default:
4987 if (err < 256) {
4988 /* other errno are usually operational errors */
4989 ret = -err;
4990 } else {
4991 is_err = 1;
4992 ret = -EIO;
4993 }
4994 break;
4995 }
4996
4997 if (!is_err)
4998 return ret;
4999
5000 if (ino)
5001 err_printf(ff, "%s (inode #%d) at %s:%d.\n",
5002 error_message(err), ino, file, line);
5003 else
5004 err_printf(ff, "%s at %s:%d.\n",
5005 error_message(err), file, line);
5006
5007 /* Make a note in the error log */
5008 get_now(&now);
5009 ext2fs_set_tstamp(fs->super, s_last_error_time, now.tv_sec);
5010 fs->super->s_last_error_ino = ino;
5011 fs->super->s_last_error_line = line;
5012 fs->super->s_last_error_block = err; /* Yeah... */
5013 strncpy((char *)fs->super->s_last_error_func, file,
5014 sizeof(fs->super->s_last_error_func));
5015 if (ext2fs_get_tstamp(fs->super, s_first_error_time) == 0) {
5016 ext2fs_set_tstamp(fs->super, s_first_error_time, now.tv_sec);
5017 fs->super->s_first_error_ino = ino;
5018 fs->super->s_first_error_line = line;
5019 fs->super->s_first_error_block = err;
5020 strncpy((char *)fs->super->s_first_error_func, file,
5021 sizeof(fs->super->s_first_error_func));
5022 }
5023
5024 fs->super->s_error_count++;
5025 ext2fs_mark_super_dirty(fs);
5026 ext2fs_flush(fs);
5027 if (ff->panic_on_error)
5028 abort();
5029
5030 return ret;
5031 }