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 		     &regfmount_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