1 /*
2 * Mount tool fuse functions
3 *
4 * Copyright (C) 2009-2021, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <narrow_string.h>
24 #include <types.h>
25
26 #if defined( HAVE_ERRNO_H ) || defined( WINAPI )
27 #include <errno.h>
28 #endif
29
30 #if defined( HAVE_STDLIB_H ) || defined( WINAPI )
31 #include <stdlib.h>
32 #endif
33
34 #if defined( HAVE_UNISTD_H )
35 #include <unistd.h>
36 #endif
37
38 #include "mount_fuse.h"
39 #include "mount_handle.h"
40 #include "regftools_libcerror.h"
41 #include "regftools_libcnotify.h"
42 #include "regftools_libregf.h"
43 #include "regftools_unused.h"
44
45 extern mount_handle_t *regfmount_mount_handle;
46
47 #if defined( HAVE_LIBFUSE ) || defined( HAVE_LIBOSXFUSE )
48
49 #if ( SIZEOF_OFF_T != 8 ) && ( SIZEOF_OFF_T != 4 )
50 #error Size of off_t not supported
51 #endif
52
53 /* Sets the values in a stat info structure
54 * The time values are a signed 64-bit POSIX date and time value in number of nanoseconds
55 * Returns 1 if successful or -1 on error
56 */
mount_fuse_set_stat_info(struct stat * stat_info,size64_t size,uint16_t file_mode,int64_t access_time,int64_t inode_change_time,int64_t modification_time,libcerror_error_t ** error)57 int mount_fuse_set_stat_info(
58 struct stat *stat_info,
59 size64_t size,
60 uint16_t file_mode,
61 int64_t access_time,
62 int64_t inode_change_time,
63 int64_t modification_time,
64 libcerror_error_t **error )
65 {
66 static char *function = "mount_fuse_set_stat_info";
67
68 if( stat_info == NULL )
69 {
70 libcerror_error_set(
71 error,
72 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
73 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
74 "%s: invalid stat info.",
75 function );
76
77 return( -1 );
78 }
79 #if SIZEOF_OFF_T <= 4
80 if( size > (size64_t) UINT32_MAX )
81 #else
82 if( size > (size64_t) INT64_MAX )
83 #endif
84 {
85 libcerror_error_set(
86 error,
87 LIBCERROR_ERROR_DOMAIN_RUNTIME,
88 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
89 "%s: invalid size value out of bounds.",
90 function );
91
92 return( -1 );
93 }
94 stat_info->st_size = (off_t) size;
95 stat_info->st_mode = file_mode;
96
97 if( ( file_mode & 0x4000 ) != 0 )
98 {
99 stat_info->st_nlink = 2;
100 }
101 else
102 {
103 stat_info->st_nlink = 1;
104 }
105 #if defined( HAVE_GETEUID )
106 stat_info->st_uid = geteuid();
107 #endif
108 #if defined( HAVE_GETEGID )
109 stat_info->st_gid = getegid();
110 #endif
111
112 stat_info->st_atime = access_time / 1000000000;
113 stat_info->st_ctime = inode_change_time / 1000000000;
114 stat_info->st_mtime = modification_time / 1000000000;
115
116 #if defined( STAT_HAVE_NSEC )
117 stat_info->st_atime_nsec = access_time % 1000000000;
118 stat_info->st_ctime_nsec = inode_change_time % 1000000000;
119 stat_info->st_mtime_nsec = modification_time % 1000000000;
120 #endif
121 return( 1 );
122 }
123
124 /* Fills a directory entry
125 * Returns 1 if successful or -1 on error
126 */
mount_fuse_filldir(void * buffer,fuse_fill_dir_t filler,const char * name,struct stat * stat_info,mount_file_entry_t * file_entry,libcerror_error_t ** error)127 int mount_fuse_filldir(
128 void *buffer,
129 fuse_fill_dir_t filler,
130 const char *name,
131 struct stat *stat_info,
132 mount_file_entry_t *file_entry,
133 libcerror_error_t **error )
134 {
135 static char *function = "mount_fuse_filldir";
136 size64_t file_size = 0;
137 uint64_t access_time = 0;
138 uint64_t inode_change_time = 0;
139 uint64_t modification_time = 0;
140 uint16_t file_mode = 0;
141
142 if( filler == NULL )
143 {
144 libcerror_error_set(
145 error,
146 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
147 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
148 "%s: invalid filler.",
149 function );
150
151 return( -1 );
152 }
153 if( file_entry != NULL )
154 {
155 if( mount_file_entry_get_size(
156 file_entry,
157 &file_size,
158 error ) != 1 )
159 {
160 libcerror_error_set(
161 error,
162 LIBCERROR_ERROR_DOMAIN_RUNTIME,
163 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
164 "%s: unable to retrieve file entry size.",
165 function );
166
167 return( -1 );
168 }
169 if( mount_file_entry_get_file_mode(
170 file_entry,
171 &file_mode,
172 error ) != 1 )
173 {
174 libcerror_error_set(
175 error,
176 LIBCERROR_ERROR_DOMAIN_RUNTIME,
177 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
178 "%s: unable to retrieve file mode.",
179 function );
180
181 return( -1 );
182 }
183 if( mount_file_entry_get_access_time(
184 file_entry,
185 &access_time,
186 error ) != 1 )
187 {
188 libcerror_error_set(
189 error,
190 LIBCERROR_ERROR_DOMAIN_RUNTIME,
191 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
192 "%s: unable to retrieve access time.",
193 function );
194
195 return( -1 );
196 }
197 if( mount_file_entry_get_modification_time(
198 file_entry,
199 &modification_time,
200 error ) != 1 )
201 {
202 libcerror_error_set(
203 error,
204 LIBCERROR_ERROR_DOMAIN_RUNTIME,
205 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
206 "%s: unable to retrieve modification time.",
207 function );
208
209 return( -1 );
210 }
211 if( mount_file_entry_get_inode_change_time(
212 file_entry,
213 &inode_change_time,
214 error ) != 1 )
215 {
216 libcerror_error_set(
217 error,
218 LIBCERROR_ERROR_DOMAIN_RUNTIME,
219 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
220 "%s: unable to retrieve inode change time.",
221 function );
222
223 return( -1 );
224 }
225 }
226 if( memory_set(
227 stat_info,
228 0,
229 sizeof( struct stat ) ) == NULL )
230 {
231 libcerror_error_set(
232 error,
233 LIBCERROR_ERROR_DOMAIN_MEMORY,
234 LIBCERROR_MEMORY_ERROR_SET_FAILED,
235 "%s: unable to clear stat info.",
236 function );
237
238 return( -1 );
239 }
240 if( mount_fuse_set_stat_info(
241 stat_info,
242 file_size,
243 file_mode,
244 (int64_t) access_time,
245 (int64_t) inode_change_time,
246 (int64_t) modification_time,
247 error ) != 1 )
248 {
249 libcerror_error_set(
250 error,
251 LIBCERROR_ERROR_DOMAIN_RUNTIME,
252 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
253 "%s: unable to set stat info.",
254 function );
255
256 return( -1 );
257 }
258 if( filler(
259 buffer,
260 name,
261 stat_info,
262 0 ) == 1 )
263 {
264 libcerror_error_set(
265 error,
266 LIBCERROR_ERROR_DOMAIN_RUNTIME,
267 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
268 "%s: unable to set directory entry.",
269 function );
270
271 return( -1 );
272 }
273 return( 1 );
274 }
275
276 /* Opens a file or directory
277 * Returns 0 if successful or a negative errno value otherwise
278 */
mount_fuse_open(const char * path,struct fuse_file_info * file_info)279 int mount_fuse_open(
280 const char *path,
281 struct fuse_file_info *file_info )
282 {
283 libcerror_error_t *error = NULL;
284 static char *function = "mount_fuse_open";
285 int result = 0;
286
287 #if defined( HAVE_DEBUG_OUTPUT )
288 if( libcnotify_verbose != 0 )
289 {
290 libcnotify_printf(
291 "%s: %s\n",
292 function,
293 path );
294 }
295 #endif
296 if( path == NULL )
297 {
298 libcerror_error_set(
299 &error,
300 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
301 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
302 "%s: invalid path.",
303 function );
304
305 result = -EINVAL;
306
307 goto on_error;
308 }
309 if( file_info == NULL )
310 {
311 libcerror_error_set(
312 &error,
313 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
314 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
315 "%s: invalid file information.",
316 function );
317
318 result = -EINVAL;
319
320 goto on_error;
321 }
322 if( file_info->fh != (uint64_t) NULL )
323 {
324 libcerror_error_set(
325 &error,
326 LIBCERROR_ERROR_DOMAIN_RUNTIME,
327 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
328 "%s: invalid file information - file handle already set.",
329 function );
330
331 result = -EINVAL;
332
333 goto on_error;
334 }
335 if( ( file_info->flags & 0x03 ) != O_RDONLY )
336 {
337 libcerror_error_set(
338 &error,
339 LIBCERROR_ERROR_DOMAIN_RUNTIME,
340 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
341 "%s: write access currently not supported.",
342 function );
343
344 result = -EACCES;
345
346 goto on_error;
347 }
348 if( mount_handle_get_file_entry_by_path(
349 regfmount_mount_handle,
350 path,
351 (mount_file_entry_t **) &( file_info->fh ),
352 &error ) != 1 )
353 {
354 libcerror_error_set(
355 &error,
356 LIBCERROR_ERROR_DOMAIN_RUNTIME,
357 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
358 "%s: unable to retrieve file entry for path: %s.",
359 function,
360 path );
361
362 result = -ENOENT;
363
364 goto on_error;
365 }
366 return( 0 );
367
368 on_error:
369 if( error != NULL )
370 {
371 libcnotify_print_error_backtrace(
372 error );
373 libcerror_error_free(
374 &error );
375 }
376 return( result );
377 }
378
379 /* Reads a buffer of data at the specified offset
380 * Returns number of bytes read if successful or a negative errno value otherwise
381 */
mount_fuse_read(const char * path,char * buffer,size_t size,off_t offset,struct fuse_file_info * file_info)382 int mount_fuse_read(
383 const char *path,
384 char *buffer,
385 size_t size,
386 off_t offset,
387 struct fuse_file_info *file_info )
388 {
389 libcerror_error_t *error = NULL;
390 static char *function = "mount_fuse_read";
391 ssize_t read_count = 0;
392 int result = 0;
393
394 #if defined( HAVE_DEBUG_OUTPUT )
395 if( libcnotify_verbose != 0 )
396 {
397 libcnotify_printf(
398 "%s: %s\n",
399 function,
400 path );
401 }
402 #endif
403 if( path == NULL )
404 {
405 libcerror_error_set(
406 &error,
407 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
408 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
409 "%s: invalid path.",
410 function );
411
412 result = -EINVAL;
413
414 goto on_error;
415 }
416 if( size > (size_t) INT_MAX )
417 {
418 libcerror_error_set(
419 &error,
420 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
421 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
422 "%s: invalid size value exceeds maximum.",
423 function );
424
425 result = -EINVAL;
426
427 goto on_error;
428 }
429 if( file_info == NULL )
430 {
431 libcerror_error_set(
432 &error,
433 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
434 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
435 "%s: invalid file information.",
436 function );
437
438 result = -EINVAL;
439
440 goto on_error;
441 }
442 if( file_info->fh == (uint64_t) NULL )
443 {
444 libcerror_error_set(
445 &error,
446 LIBCERROR_ERROR_DOMAIN_RUNTIME,
447 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
448 "%s: invalid file information - missing file handle.",
449 function );
450
451 result = -EINVAL;
452
453 goto on_error;
454 }
455 read_count = mount_file_entry_read_buffer_at_offset(
456 (mount_file_entry_t *) file_info->fh,
457 (void *) buffer,
458 size,
459 (off64_t) offset,
460 &error );
461
462 if( read_count < 0 )
463 {
464 libcerror_error_set(
465 &error,
466 LIBCERROR_ERROR_DOMAIN_IO,
467 LIBCERROR_IO_ERROR_READ_FAILED,
468 "%s: unable to read from file entry.",
469 function );
470
471 result = -EIO;
472
473 goto on_error;
474 }
475 return( (int) read_count );
476
477 on_error:
478 if( error != NULL )
479 {
480 libcnotify_print_error_backtrace(
481 error );
482 libcerror_error_free(
483 &error );
484 }
485 return( result );
486 }
487
488 /* Releases a file entry
489 * Returns 0 if successful or a negative errno value otherwise
490 */
mount_fuse_release(const char * path,struct fuse_file_info * file_info)491 int mount_fuse_release(
492 const char *path,
493 struct fuse_file_info *file_info )
494 {
495 libcerror_error_t *error = NULL;
496 static char *function = "mount_fuse_release";
497 int result = 0;
498
499 #if defined( HAVE_DEBUG_OUTPUT )
500 if( libcnotify_verbose != 0 )
501 {
502 libcnotify_printf(
503 "%s: %s\n",
504 function,
505 path );
506 }
507 #endif
508 if( path == NULL )
509 {
510 libcerror_error_set(
511 &error,
512 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
513 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
514 "%s: invalid path.",
515 function );
516
517 result = -EINVAL;
518
519 goto on_error;
520 }
521 if( file_info == NULL )
522 {
523 libcerror_error_set(
524 &error,
525 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
526 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
527 "%s: invalid file information.",
528 function );
529
530 result = -EINVAL;
531
532 goto on_error;
533 }
534 if( file_info->fh != (uint64_t) NULL )
535 {
536 if( mount_file_entry_free(
537 (mount_file_entry_t **) &( file_info->fh ),
538 &error ) != 1 )
539 {
540 libcerror_error_set(
541 &error,
542 LIBCERROR_ERROR_DOMAIN_RUNTIME,
543 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
544 "%s: unable to free file entry.",
545 function );
546
547 result = -ENOENT;
548
549 goto on_error;
550 }
551 }
552 return( 0 );
553
554 on_error:
555 if( error != NULL )
556 {
557 libcnotify_print_error_backtrace(
558 error );
559 libcerror_error_free(
560 &error );
561 }
562 return( result );
563 }
564
565 /* Opens a directory
566 * Returns 0 if successful or a negative errno value otherwise
567 */
mount_fuse_opendir(const char * path,struct fuse_file_info * file_info)568 int mount_fuse_opendir(
569 const char *path,
570 struct fuse_file_info *file_info )
571 {
572 libcerror_error_t *error = NULL;
573 static char *function = "mount_fuse_opendir";
574 int result = 0;
575
576 #if defined( HAVE_DEBUG_OUTPUT )
577 if( libcnotify_verbose != 0 )
578 {
579 libcnotify_printf(
580 "%s: %s\n",
581 function,
582 path );
583 }
584 #endif
585 if( path == NULL )
586 {
587 libcerror_error_set(
588 &error,
589 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
590 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
591 "%s: invalid path.",
592 function );
593
594 result = -EINVAL;
595
596 goto on_error;
597 }
598 if( file_info == NULL )
599 {
600 libcerror_error_set(
601 &error,
602 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
603 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
604 "%s: invalid file information.",
605 function );
606
607 result = -EINVAL;
608
609 goto on_error;
610 }
611 if( file_info->fh != (uint64_t) NULL )
612 {
613 libcerror_error_set(
614 &error,
615 LIBCERROR_ERROR_DOMAIN_RUNTIME,
616 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
617 "%s: invalid file information - file handle already set.",
618 function );
619
620 result = -EINVAL;
621
622 goto on_error;
623 }
624 if( mount_handle_get_file_entry_by_path(
625 regfmount_mount_handle,
626 path,
627 (mount_file_entry_t **) &( file_info->fh ),
628 &error ) != 1 )
629 {
630 libcerror_error_set(
631 &error,
632 LIBCERROR_ERROR_DOMAIN_RUNTIME,
633 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
634 "%s: unable to retrieve file entry for path: %s.",
635 function,
636 path );
637
638 result = -ENOENT;
639
640 goto on_error;
641 }
642 return( 0 );
643
644 on_error:
645 if( error != NULL )
646 {
647 libcnotify_print_error_backtrace(
648 error );
649 libcerror_error_free(
650 &error );
651 }
652 return( result );
653 }
654
655 /* Reads a directory
656 * Returns 0 if successful or a negative errno value otherwise
657 */
mount_fuse_readdir(const char * path,void * buffer,fuse_fill_dir_t filler,off_t offset REGFTOOLS_ATTRIBUTE_UNUSED,struct fuse_file_info * file_info REGFTOOLS_ATTRIBUTE_UNUSED)658 int mount_fuse_readdir(
659 const char *path,
660 void *buffer,
661 fuse_fill_dir_t filler,
662 off_t offset REGFTOOLS_ATTRIBUTE_UNUSED,
663 struct fuse_file_info *file_info REGFTOOLS_ATTRIBUTE_UNUSED )
664 {
665 struct stat *stat_info = NULL;
666 libcerror_error_t *error = NULL;
667 mount_file_entry_t *parent_file_entry = NULL;
668 mount_file_entry_t *sub_file_entry = NULL;
669 static char *function = "mount_fuse_readdir";
670 char *name = NULL;
671 size_t name_size = 0;
672 int number_of_sub_file_entries = 0;
673 int result = 0;
674 int sub_file_entry_index = 0;
675
676 REGFTOOLS_UNREFERENCED_PARAMETER( offset )
677
678 #if defined( HAVE_DEBUG_OUTPUT )
679 if( libcnotify_verbose != 0 )
680 {
681 libcnotify_printf(
682 "%s: %s\n",
683 function,
684 path );
685 }
686 #endif
687 if( path == NULL )
688 {
689 libcerror_error_set(
690 &error,
691 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
692 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
693 "%s: invalid path.",
694 function );
695
696 result = -EINVAL;
697
698 goto on_error;
699 }
700 if( file_info == NULL )
701 {
702 libcerror_error_set(
703 &error,
704 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
705 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
706 "%s: invalid file information.",
707 function );
708
709 result = -EINVAL;
710
711 goto on_error;
712 }
713 if( file_info->fh == (uint64_t) NULL )
714 {
715 libcerror_error_set(
716 &error,
717 LIBCERROR_ERROR_DOMAIN_RUNTIME,
718 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
719 "%s: invalid file information - missing file handle.",
720 function );
721
722 result = -EINVAL;
723
724 goto on_error;
725 }
726 stat_info = memory_allocate_structure(
727 struct stat );
728
729 if( stat_info == NULL )
730 {
731 libcerror_error_set(
732 &error,
733 LIBCERROR_ERROR_DOMAIN_MEMORY,
734 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
735 "%s: unable to create stat info.",
736 function );
737
738 result = errno;
739
740 goto on_error;
741 }
742 if( mount_fuse_filldir(
743 buffer,
744 filler,
745 ".",
746 stat_info,
747 (mount_file_entry_t *) file_info->fh,
748 &error ) != 1 )
749 {
750 libcerror_error_set(
751 &error,
752 LIBCERROR_ERROR_DOMAIN_RUNTIME,
753 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
754 "%s: unable to set self directory entry.",
755 function );
756
757 result = -EIO;
758
759 goto on_error;
760 }
761 result = mount_file_entry_get_parent_file_entry(
762 (mount_file_entry_t *) file_info->fh,
763 &parent_file_entry,
764 &error );
765
766 if( result == -1 )
767 {
768 libcerror_error_set(
769 &error,
770 LIBCERROR_ERROR_DOMAIN_RUNTIME,
771 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
772 "%s: unable to retrieve parent file entry.",
773 function );
774
775 result = -EIO;
776
777 goto on_error;
778 }
779 if( mount_fuse_filldir(
780 buffer,
781 filler,
782 "..",
783 stat_info,
784 parent_file_entry,
785 &error ) != 1 )
786 {
787 libcerror_error_set(
788 &error,
789 LIBCERROR_ERROR_DOMAIN_RUNTIME,
790 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
791 "%s: unable to set parent directory entry.",
792 function );
793
794 result = -EIO;
795
796 goto on_error;
797 }
798 if( mount_file_entry_free(
799 &parent_file_entry,
800 &error ) != 1 )
801 {
802 libcerror_error_set(
803 &error,
804 LIBCERROR_ERROR_DOMAIN_RUNTIME,
805 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
806 "%s: unable to free parent file entry.",
807 function );
808
809 result = -EIO;
810
811 goto on_error;
812 }
813 if( mount_file_entry_get_number_of_sub_file_entries(
814 (mount_file_entry_t *) file_info->fh,
815 &number_of_sub_file_entries,
816 &error ) != 1 )
817 {
818 libcerror_error_set(
819 &error,
820 LIBCERROR_ERROR_DOMAIN_RUNTIME,
821 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
822 "%s: unable to retrieve number of sub file entries.",
823 function );
824
825 result = -EIO;
826
827 goto on_error;
828 }
829 for( sub_file_entry_index = 0;
830 sub_file_entry_index < number_of_sub_file_entries;
831 sub_file_entry_index++ )
832 {
833 if( mount_file_entry_get_sub_file_entry_by_index(
834 (mount_file_entry_t *) file_info->fh,
835 sub_file_entry_index,
836 &sub_file_entry,
837 &error ) != 1 )
838 {
839 libcerror_error_set(
840 &error,
841 LIBCERROR_ERROR_DOMAIN_RUNTIME,
842 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
843 "%s: unable to retrieve sub file entry: %d.",
844 function,
845 sub_file_entry_index );
846
847 result = -EIO;
848
849 goto on_error;
850 }
851 if( mount_file_entry_get_name_size(
852 sub_file_entry,
853 &name_size,
854 &error ) != 1 )
855 {
856 libcerror_error_set(
857 &error,
858 LIBCERROR_ERROR_DOMAIN_RUNTIME,
859 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
860 "%s: unable to retrieve sub file entry: %d name size.",
861 function,
862 sub_file_entry_index );
863
864 result = -EIO;
865
866 goto on_error;
867 }
868 name = narrow_string_allocate(
869 name_size );
870
871 if( name == NULL )
872 {
873 libcerror_error_set(
874 &error,
875 LIBCERROR_ERROR_DOMAIN_MEMORY,
876 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
877 "%s: unable to create sub file entry: %d name.",
878 function );
879
880 result = -EIO;
881
882 goto on_error;
883 }
884 if( mount_file_entry_get_name(
885 sub_file_entry,
886 name,
887 name_size,
888 &error ) != 1 )
889 {
890 libcerror_error_set(
891 &error,
892 LIBCERROR_ERROR_DOMAIN_RUNTIME,
893 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
894 "%s: unable to retrieve sub file entry: %d name.",
895 function,
896 sub_file_entry_index );
897
898 result = -EIO;
899
900 goto on_error;
901 }
902 if( mount_fuse_filldir(
903 buffer,
904 filler,
905 name,
906 stat_info,
907 sub_file_entry,
908 &error ) != 1 )
909 {
910 libcerror_error_set(
911 &error,
912 LIBCERROR_ERROR_DOMAIN_RUNTIME,
913 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
914 "%s: unable to set directory entry.",
915 function );
916
917 result = -EIO;
918
919 goto on_error;
920 }
921 memory_free(
922 name );
923
924 name = NULL;
925
926 if( mount_file_entry_free(
927 &sub_file_entry,
928 &error ) != 1 )
929 {
930 libcerror_error_set(
931 &error,
932 LIBCERROR_ERROR_DOMAIN_RUNTIME,
933 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
934 "%s: unable to free sub file entry: %d.",
935 function,
936 sub_file_entry_index );
937
938 result = -EIO;
939
940 goto on_error;
941 }
942 }
943 memory_free(
944 stat_info );
945
946 return( 0 );
947
948 on_error:
949 if( error != NULL )
950 {
951 libcnotify_print_error_backtrace(
952 error );
953 libcerror_error_free(
954 &error );
955 }
956 if( name != NULL )
957 {
958 memory_free(
959 name );
960 }
961 if( sub_file_entry != NULL )
962 {
963 mount_file_entry_free(
964 &sub_file_entry,
965 NULL );
966 }
967 if( parent_file_entry != NULL )
968 {
969 mount_file_entry_free(
970 &parent_file_entry,
971 NULL );
972 }
973 if( stat_info != NULL )
974 {
975 memory_free(
976 stat_info );
977 }
978 return( result );
979 }
980
981 /* Releases a directory entry
982 * Returns 0 if successful or a negative errno value otherwise
983 */
mount_fuse_releasedir(const char * path,struct fuse_file_info * file_info)984 int mount_fuse_releasedir(
985 const char *path,
986 struct fuse_file_info *file_info )
987 {
988 libcerror_error_t *error = NULL;
989 static char *function = "mount_fuse_releasedir";
990 int result = 0;
991
992 #if defined( HAVE_DEBUG_OUTPUT )
993 if( libcnotify_verbose != 0 )
994 {
995 libcnotify_printf(
996 "%s: %s\n",
997 function,
998 path );
999 }
1000 #endif
1001 if( path == NULL )
1002 {
1003 libcerror_error_set(
1004 &error,
1005 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1006 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1007 "%s: invalid path.",
1008 function );
1009
1010 result = -EINVAL;
1011
1012 goto on_error;
1013 }
1014 if( file_info == NULL )
1015 {
1016 libcerror_error_set(
1017 &error,
1018 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1019 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1020 "%s: invalid file information.",
1021 function );
1022
1023 result = -EINVAL;
1024
1025 goto on_error;
1026 }
1027 if( file_info->fh != (uint64_t) NULL )
1028 {
1029 file_info->fh = (uint64_t) NULL;
1030 }
1031 return( 0 );
1032
1033 on_error:
1034 if( error != NULL )
1035 {
1036 libcnotify_print_error_backtrace(
1037 error );
1038 libcerror_error_free(
1039 &error );
1040 }
1041 return( result );
1042 }
1043
1044 /* Retrieves the file stat info
1045 * Returns 0 if successful or a negative errno value otherwise
1046 */
mount_fuse_getattr(const char * path,struct stat * stat_info)1047 int mount_fuse_getattr(
1048 const char *path,
1049 struct stat *stat_info )
1050 {
1051 libcerror_error_t *error = NULL;
1052 mount_file_entry_t *file_entry = NULL;
1053 static char *function = "mount_fuse_getattr";
1054 size64_t file_size = 0;
1055 uint64_t access_time = 0;
1056 uint64_t inode_change_time = 0;
1057 uint64_t modification_time = 0;
1058 uint16_t file_mode = 0;
1059 int result = 0;
1060
1061 #if defined( HAVE_DEBUG_OUTPUT )
1062 if( libcnotify_verbose != 0 )
1063 {
1064 libcnotify_printf(
1065 "%s: %s\n",
1066 function,
1067 path );
1068 }
1069 #endif
1070 if( path == NULL )
1071 {
1072 libcerror_error_set(
1073 &error,
1074 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1075 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1076 "%s: invalid path.",
1077 function );
1078
1079 result = -EINVAL;
1080
1081 goto on_error;
1082 }
1083 if( stat_info == NULL )
1084 {
1085 libcerror_error_set(
1086 &error,
1087 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1088 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1089 "%s: invalid stat info.",
1090 function );
1091
1092 result = -EINVAL;
1093
1094 goto on_error;
1095 }
1096 if( memory_set(
1097 stat_info,
1098 0,
1099 sizeof( struct stat ) ) == NULL )
1100 {
1101 libcerror_error_set(
1102 &error,
1103 LIBCERROR_ERROR_DOMAIN_MEMORY,
1104 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1105 "%s: unable to clear stat info.",
1106 function );
1107
1108 result = errno;
1109
1110 goto on_error;
1111 }
1112 result = mount_handle_get_file_entry_by_path(
1113 regfmount_mount_handle,
1114 path,
1115 &file_entry,
1116 &error );
1117
1118 if( result == -1 )
1119 {
1120 libcerror_error_set(
1121 &error,
1122 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1123 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1124 "%s: unable to retrieve value for: %s.",
1125 function,
1126 path );
1127
1128 result = -ENOENT;
1129
1130 goto on_error;
1131 }
1132 else if( result == 0 )
1133 {
1134 return( -ENOENT );
1135 }
1136 if( mount_file_entry_get_size(
1137 file_entry,
1138 &file_size,
1139 &error ) != 1 )
1140 {
1141 libcerror_error_set(
1142 &error,
1143 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1144 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1145 "%s: unable to retrieve file entry size.",
1146 function );
1147
1148 result = -EIO;
1149
1150 goto on_error;
1151 }
1152 if( mount_file_entry_get_file_mode(
1153 file_entry,
1154 &file_mode,
1155 &error ) != 1 )
1156 {
1157 libcerror_error_set(
1158 &error,
1159 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1160 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1161 "%s: unable to retrieve file mode.",
1162 function );
1163
1164 result = -EIO;
1165
1166 goto on_error;
1167 }
1168 if( mount_file_entry_get_access_time(
1169 file_entry,
1170 &access_time,
1171 &error ) != 1 )
1172 {
1173 libcerror_error_set(
1174 &error,
1175 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1176 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1177 "%s: unable to retrieve access time.",
1178 function );
1179
1180 result = -EIO;
1181
1182 goto on_error;
1183 }
1184 if( mount_file_entry_get_modification_time(
1185 file_entry,
1186 &modification_time,
1187 &error ) != 1 )
1188 {
1189 libcerror_error_set(
1190 &error,
1191 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1192 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1193 "%s: unable to retrieve modification time.",
1194 function );
1195
1196 result = -EIO;
1197
1198 goto on_error;
1199 }
1200 if( mount_file_entry_get_inode_change_time(
1201 file_entry,
1202 &inode_change_time,
1203 &error ) != 1 )
1204 {
1205 libcerror_error_set(
1206 &error,
1207 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1208 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1209 "%s: unable to retrieve inode change time.",
1210 function );
1211
1212 result = -EIO;
1213
1214 goto on_error;
1215 }
1216 if( mount_fuse_set_stat_info(
1217 stat_info,
1218 file_size,
1219 file_mode,
1220 (int64_t) access_time,
1221 (int64_t) inode_change_time,
1222 (int64_t) modification_time,
1223 &error ) != 1 )
1224 {
1225 libcerror_error_set(
1226 &error,
1227 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1228 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1229 "%s: unable to set stat info.",
1230 function );
1231
1232 result = -EIO;
1233
1234 goto on_error;
1235 }
1236 if( mount_file_entry_free(
1237 &file_entry,
1238 &error ) != 1 )
1239 {
1240 libcerror_error_set(
1241 &error,
1242 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1243 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1244 "%s: unable to free file entry.",
1245 function );
1246
1247 result = -EIO;
1248
1249 goto on_error;
1250 }
1251 return( 0 );
1252
1253 on_error:
1254 if( error != NULL )
1255 {
1256 libcnotify_print_error_backtrace(
1257 error );
1258 libcerror_error_free(
1259 &error );
1260 }
1261 if( file_entry != NULL )
1262 {
1263 mount_file_entry_free(
1264 &file_entry,
1265 NULL );
1266 }
1267 return( result );
1268 }
1269
1270 /* Cleans up when fuse is done
1271 */
mount_fuse_destroy(void * private_data REGFTOOLS_ATTRIBUTE_UNUSED)1272 void mount_fuse_destroy(
1273 void *private_data REGFTOOLS_ATTRIBUTE_UNUSED )
1274 {
1275 libcerror_error_t *error = NULL;
1276 static char *function = "mount_fuse_destroy";
1277
1278 REGFTOOLS_UNREFERENCED_PARAMETER( private_data )
1279
1280 #if defined( HAVE_DEBUG_OUTPUT )
1281 if( libcnotify_verbose != 0 )
1282 {
1283 libcnotify_printf(
1284 "%s\n",
1285 function );
1286 }
1287 #endif
1288 if( regfmount_mount_handle != NULL )
1289 {
1290 if( mount_handle_free(
1291 ®fmount_mount_handle,
1292 &error ) != 1 )
1293 {
1294 libcerror_error_set(
1295 &error,
1296 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1297 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1298 "%s: unable to free mount handle.",
1299 function );
1300
1301 goto on_error;
1302 }
1303 }
1304 return;
1305
1306 on_error:
1307 if( error != NULL )
1308 {
1309 libcnotify_print_error_backtrace(
1310 error );
1311 libcerror_error_free(
1312 &error );
1313 }
1314 return;
1315 }
1316
1317 #endif /* defined( HAVE_LIBFUSE ) || defined( HAVE_LIBOSXFUSE ) */
1318
1319