1 /*
2  * The cache functions
3  *
4  * Copyright (C) 2010-2020, 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 <memory.h>
24 #include <types.h>
25 
26 #include "libfcache_cache.h"
27 #include "libfcache_cache_value.h"
28 #include "libfcache_definitions.h"
29 #include "libfcache_libcdata.h"
30 #include "libfcache_libcerror.h"
31 #include "libfcache_types.h"
32 
33 /* Creates a cache
34  * Make sure the value cache is referencing, is set to NULL
35  * Returns 1 if successful or -1 on error
36  */
libfcache_cache_initialize(libfcache_cache_t ** cache,int maximum_cache_entries,libcerror_error_t ** error)37 int libfcache_cache_initialize(
38      libfcache_cache_t **cache,
39      int maximum_cache_entries,
40      libcerror_error_t **error )
41 {
42 	libfcache_internal_cache_t *internal_cache = NULL;
43 	static char *function                      = "libfcache_cache_initialize";
44 
45 	if( cache == NULL )
46 	{
47 		libcerror_error_set(
48 		 error,
49 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
50 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
51 		 "%s: invalid cache.",
52 		 function );
53 
54 		return( -1 );
55 	}
56 	if( *cache != NULL )
57 	{
58 		libcerror_error_set(
59 		 error,
60 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
61 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
62 		 "%s: invalid cache value already set.",
63 		 function );
64 
65 		return( -1 );
66 	}
67 	if( maximum_cache_entries <= 0 )
68 	{
69 		libcerror_error_set(
70 		 error,
71 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
72 		 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
73 		 "%s: invalid maximum cache entries value zero or less.",
74 		 function );
75 
76 		return( -1 );
77 	}
78 	internal_cache = memory_allocate_structure(
79 	                  libfcache_internal_cache_t );
80 
81 	if( internal_cache == NULL )
82 	{
83 		libcerror_error_set(
84 		 error,
85 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
86 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
87 		 "%s: unable to create cache.",
88 		 function );
89 
90 		goto on_error;
91 	}
92 	if( memory_set(
93 	     internal_cache,
94 	     0,
95 	     sizeof( libfcache_internal_cache_t ) ) == NULL )
96 	{
97 		libcerror_error_set(
98 		 error,
99 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
100 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
101 		 "%s: unable to clear cache.",
102 		 function );
103 
104 		memory_free(
105 		 internal_cache );
106 
107 		return( -1 );
108 	}
109 	if( libcdata_array_initialize(
110 	     &( internal_cache->entries_array ),
111 	     maximum_cache_entries,
112 	     error ) != 1 )
113 	{
114 		libcerror_error_set(
115 		 error,
116 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
117 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
118 		 "%s: unable to create entries array.",
119 		 function );
120 
121 		goto on_error;
122 	}
123 	if( libcdata_list_initialize(
124 	     &( internal_cache->entries_list ),
125 	     error ) != 1 )
126 	{
127 		libcerror_error_set(
128 		 error,
129 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
130 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
131 		 "%s: unable to create entries list.",
132 		 function );
133 
134 		goto on_error;
135 	}
136 	*cache = (libfcache_cache_t *) internal_cache;
137 
138 	return( 1 );
139 
140 on_error:
141 	if( internal_cache != NULL )
142 	{
143 		if( internal_cache->entries_array != NULL )
144 		{
145 			libcdata_array_free(
146 			 &( internal_cache->entries_array ),
147 			 NULL,
148 			 NULL );
149 		}
150 		memory_free(
151 		 internal_cache );
152 	}
153 	return( -1 );
154 }
155 
156 /* Frees a cache
157  * Returns 1 if successful or -1 on error
158  */
libfcache_cache_free(libfcache_cache_t ** cache,libcerror_error_t ** error)159 int libfcache_cache_free(
160      libfcache_cache_t **cache,
161      libcerror_error_t **error )
162 {
163 	libfcache_internal_cache_t *internal_cache = NULL;
164 	static char *function                      = "libfcache_cache_free";
165 	int result                                 = 1;
166 
167 	if( cache == NULL )
168 	{
169 		libcerror_error_set(
170 		 error,
171 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
172 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
173 		 "%s: invalid cache.",
174 		 function );
175 
176 		return( -1 );
177 	}
178 	if( *cache != NULL )
179 	{
180 		internal_cache = (libfcache_internal_cache_t *) *cache;
181 		*cache         = NULL;
182 
183 		if( libcdata_list_free(
184 		     &( internal_cache->entries_list ),
185 		     NULL,
186 		     error ) != 1 )
187 		{
188 			libcerror_error_set(
189 			 error,
190 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
191 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
192 			 "%s: unable to free the entries list.",
193 			 function );
194 
195 			result = -1;
196 		}
197 		if( libcdata_array_free(
198 		     &( internal_cache->entries_array ),
199 		     (int (*)(intptr_t **, libcerror_error_t **)) &libfcache_cache_value_free,
200 		     error ) != 1 )
201 		{
202 			libcerror_error_set(
203 			 error,
204 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
205 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
206 			 "%s: unable to free the entries array.",
207 			 function );
208 
209 			result = -1;
210 		}
211 		memory_free(
212 		 internal_cache );
213 	}
214 	return( result );
215 }
216 
217 /* Empties the cache
218  * Returns 1 if successful or -1 on error
219  */
libfcache_cache_empty(libfcache_cache_t * cache,libcerror_error_t ** error)220 int libfcache_cache_empty(
221      libfcache_cache_t *cache,
222      libcerror_error_t **error )
223 {
224 	libfcache_internal_cache_t *internal_cache = NULL;
225 	static char *function                      = "libfcache_cache_empty";
226 
227 	if( cache == NULL )
228 	{
229 		libcerror_error_set(
230 		 error,
231 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
232 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
233 		 "%s: invalid cache.",
234 		 function );
235 
236 		return( -1 );
237 	}
238 	internal_cache = (libfcache_internal_cache_t *) cache;
239 
240 	if( libcdata_list_empty(
241 	     internal_cache->entries_list,
242 	     NULL,
243 	     error ) != 1 )
244 	{
245 		libcerror_error_set(
246 		 error,
247 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
248 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
249 		 "%s: unable to empty entries list.",
250 		 function );
251 
252 		return( -1 );
253 	}
254 	if( libcdata_array_clear(
255 	     internal_cache->entries_array,
256 	     (int (*)(intptr_t **, libcerror_error_t **)) &libfcache_cache_value_free,
257 	     error ) != 1 )
258 	{
259 		libcerror_error_set(
260 		 error,
261 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
262 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
263 		 "%s: unable to clear entries array.",
264 		 function );
265 
266 		return( -1 );
267 	}
268 	internal_cache->number_of_cache_values = 0;
269 
270 	return( 1 );
271 }
272 
273 /* Clones (duplicates) the cache, not the cache values
274  * Returns 1 if successful or -1 on error
275  */
libfcache_cache_clone(libfcache_cache_t ** destination_cache,libfcache_cache_t * source_cache,libcerror_error_t ** error)276 int libfcache_cache_clone(
277      libfcache_cache_t **destination_cache,
278      libfcache_cache_t *source_cache,
279      libcerror_error_t **error )
280 {
281 	libfcache_internal_cache_t *internal_source_cache = NULL;
282 	static char *function                             = "libfcache_cache_clone";
283 	int number_of_cache_entries                       = 0;
284 
285 	if( destination_cache == NULL )
286 	{
287 		libcerror_error_set(
288 		 error,
289 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
290 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
291 		 "%s: invalid destination cache.",
292 		 function );
293 
294 		return( -1 );
295 	}
296 	if( *destination_cache != NULL )
297 	{
298 		libcerror_error_set(
299 		 error,
300 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
301 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
302 		 "%s: destination cache already set.",
303 		 function );
304 
305 		return( -1 );
306 	}
307 	if( source_cache == NULL )
308 	{
309 		*destination_cache = NULL;
310 
311 		return( 1 );
312 	}
313 	internal_source_cache = (libfcache_internal_cache_t *) source_cache;
314 
315 	if( libcdata_array_get_number_of_entries(
316 	     internal_source_cache->entries_array,
317 	     &number_of_cache_entries,
318 	     error ) != 1 )
319 	{
320 		libcerror_error_set(
321 		 error,
322 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
323 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
324 		 "%s: unable to retrieve number of cache entries from source entries array.",
325 		 function );
326 
327 		return( -1 );
328 	}
329 	if( libfcache_cache_initialize(
330 	     destination_cache,
331 	     number_of_cache_entries,
332 	     error ) != 1 )
333 	{
334 		libcerror_error_set(
335 		 error,
336 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
337 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
338 		 "%s: unable to create destination cache.",
339 		 function );
340 
341 		return( -1 );
342 	}
343 	return( 1 );
344 }
345 
346 /* Resizes the cache
347  * Returns 1 if successful or -1 on error
348  */
libfcache_cache_resize(libfcache_cache_t * cache,int maximum_cache_entries,libcerror_error_t ** error)349 int libfcache_cache_resize(
350      libfcache_cache_t *cache,
351      int maximum_cache_entries,
352      libcerror_error_t **error )
353 {
354 	libfcache_internal_cache_t *internal_cache = NULL;
355 	static char *function                      = "libfcache_cache_resize";
356 
357 	if( cache == NULL )
358 	{
359 		libcerror_error_set(
360 		 error,
361 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
362 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
363 		 "%s: invalid cache.",
364 		 function );
365 
366 		return( -1 );
367 	}
368 	internal_cache = (libfcache_internal_cache_t *) cache;
369 
370 	if( libcdata_array_resize(
371 	     internal_cache->entries_array,
372 	     maximum_cache_entries,
373 	     (int (*)(intptr_t **, libcerror_error_t **)) &libfcache_cache_value_free,
374 	     error ) != 1 )
375 	{
376 		libcerror_error_set(
377 		 error,
378 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
379 		 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
380 		 "%s: unable to resize entries array.",
381 		 function );
382 
383 		return( -1 );
384 	}
385 	return( 1 );
386 }
387 
388 /* Retrieves the number of entries of the cache
389  * Returns 1 if successful or -1 on error
390  */
libfcache_cache_get_number_of_entries(libfcache_cache_t * cache,int * number_of_entries,libcerror_error_t ** error)391 int libfcache_cache_get_number_of_entries(
392      libfcache_cache_t *cache,
393      int *number_of_entries,
394      libcerror_error_t **error )
395 {
396 	libfcache_internal_cache_t *internal_cache = NULL;
397 	static char *function                      = "libfcache_cache_get_number_of_entries";
398 
399 	if( cache == NULL )
400 	{
401 		libcerror_error_set(
402 		 error,
403 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
404 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
405 		 "%s: invalid cache.",
406 		 function );
407 
408 		return( -1 );
409 	}
410 	internal_cache = (libfcache_internal_cache_t *) cache;
411 
412 	if( libcdata_array_get_number_of_entries(
413 	     internal_cache->entries_array,
414 	     number_of_entries,
415 	     error ) != 1 )
416 	{
417 		libcerror_error_set(
418 		 error,
419 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
420 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
421 		 "%s: unable to retrieve number of entries from entries array.",
422 		 function );
423 
424 		return( -1 );
425 	}
426 	return( 1 );
427 }
428 
429 /* Retrieves the number of cache values
430  * Returns 1 if successful or -1 on error
431  */
libfcache_cache_get_number_of_cache_values(libfcache_cache_t * cache,int * number_of_cache_values,libcerror_error_t ** error)432 int libfcache_cache_get_number_of_cache_values(
433      libfcache_cache_t *cache,
434      int *number_of_cache_values,
435      libcerror_error_t **error )
436 {
437 	libfcache_internal_cache_t *internal_cache = NULL;
438 	static char *function                      = "libfcache_cache_get_number_of_cache_values";
439 
440 	if( cache == NULL )
441 	{
442 		libcerror_error_set(
443 		 error,
444 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
445 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
446 		 "%s: invalid cache.",
447 		 function );
448 
449 		return( -1 );
450 	}
451 	internal_cache = (libfcache_internal_cache_t *) cache;
452 
453 	if( libcdata_list_get_number_of_elements(
454 	     internal_cache->entries_list,
455 	     number_of_cache_values,
456 	     error ) != 1 )
457 	{
458 		libcerror_error_set(
459 		 error,
460 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
461 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
462 		 "%s: unable to retrieve number of elements from entries list.",
463 		 function );
464 
465 		return( -1 );
466 	}
467 	return( 1 );
468 }
469 
470 /* Clears the cache value for the specific index
471  * Returns 1 if successful or -1 on error
472  */
libfcache_cache_clear_value_by_index(libfcache_cache_t * cache,int cache_entry_index,libcerror_error_t ** error)473 int libfcache_cache_clear_value_by_index(
474      libfcache_cache_t *cache,
475      int cache_entry_index,
476      libcerror_error_t **error )
477 {
478 	libfcache_cache_value_t *cache_value       = NULL;
479 	libfcache_internal_cache_t *internal_cache = NULL;
480 	static char *function                      = "libfcache_cache_clear_value_by_index";
481 
482 	if( cache == NULL )
483 	{
484 		libcerror_error_set(
485 		 error,
486 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
487 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
488 		 "%s: invalid cache.",
489 		 function );
490 
491 		return( -1 );
492 	}
493 	internal_cache = (libfcache_internal_cache_t *) cache;
494 
495 	if( libcdata_array_get_entry_by_index(
496 	     internal_cache->entries_array,
497 	     cache_entry_index,
498 	     (intptr_t **) &cache_value,
499 	     error ) != 1 )
500 	{
501 		libcerror_error_set(
502 		 error,
503 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
504 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
505 		 "%s: unable to retrieve cache value: %d from entries array.",
506 		 function,
507 		 cache_entry_index );
508 
509 		return( -1 );
510 	}
511 	if( libfcache_cache_value_clear(
512 	     cache_value,
513 	     error ) != 1 )
514 	{
515 		libcerror_error_set(
516 		 error,
517 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
518 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
519 		 "%s: unable to clear cache value.",
520 		 function );
521 
522 		return( -1 );
523 	}
524 	return( 1 );
525 }
526 
527 /* Retrieves the cache value that matches the file index, offset and timestamp
528  * Returns 1 if successful, 0 if no such value or -1 on error
529  */
libfcache_cache_get_value_by_identifier(libfcache_cache_t * cache,int file_index,off64_t offset,int64_t timestamp,libfcache_cache_value_t ** cache_value,libcerror_error_t ** error)530 int libfcache_cache_get_value_by_identifier(
531      libfcache_cache_t *cache,
532      int file_index,
533      off64_t offset,
534      int64_t timestamp,
535      libfcache_cache_value_t **cache_value,
536      libcerror_error_t **error )
537 {
538 	libcdata_list_element_t *list_element      = NULL;
539 	libfcache_cache_value_t *safe_cache_value  = NULL;
540 	libfcache_internal_cache_t *internal_cache = NULL;
541 	static char *function                      = "libfcache_cache_get_value_by_identifier";
542 	off64_t cache_value_offset                 = 0;
543 	int64_t cache_value_timestamp              = 0;
544 	int cache_value_file_index                 = 0;
545 	int number_of_cache_values                 = 0;
546 	int result                                 = 0;
547 
548 	if( cache == NULL )
549 	{
550 		libcerror_error_set(
551 		 error,
552 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
553 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
554 		 "%s: invalid cache.",
555 		 function );
556 
557 		return( -1 );
558 	}
559 	internal_cache = (libfcache_internal_cache_t *) cache;
560 
561 	if( cache_value == NULL )
562 	{
563 		libcerror_error_set(
564 		 error,
565 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
566 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
567 		 "%s: invalid cache value.",
568 		 function );
569 
570 		return( -1 );
571 	}
572 	*cache_value = NULL;
573 
574 	if( libcdata_list_get_number_of_elements(
575 	     internal_cache->entries_list,
576 	     &number_of_cache_values,
577 	     error ) != 1 )
578 	{
579 		libcerror_error_set(
580 		 error,
581 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
582 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
583 		 "%s: unable to retrieve number of elements from entries list.",
584 		 function );
585 
586 		return( -1 );
587 	}
588 	if( libcdata_list_get_first_element(
589 	     internal_cache->entries_list,
590 	     &list_element,
591 	     error ) != 1 )
592 	{
593 		libcerror_error_set(
594 		 error,
595 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
596 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
597 		 "%s: unable to retrieve first list element.",
598 		 function );
599 
600 		return( -1 );
601 	}
602 	while( list_element != NULL )
603 	{
604 		if( libcdata_list_element_get_value(
605 		     list_element,
606 		     (intptr_t **) &safe_cache_value,
607 		     error ) != 1 )
608 		{
609 			libcerror_error_set(
610 			 error,
611 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
612 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
613 			 "%s: unable to retrieve cache value from list element.",
614 			 function );
615 
616 			return( -1 );
617 		}
618 		if( libfcache_cache_value_get_identifier(
619 		     safe_cache_value,
620 		     &cache_value_file_index,
621 		     &cache_value_offset,
622 		     &cache_value_timestamp,
623 		     error ) != 1 )
624 		{
625 			libcerror_error_set(
626 			 error,
627 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
628 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
629 			 "%s: unable to retrieve cache value identifier.",
630 			 function );
631 
632 			return( -1 );
633 		}
634 		if( ( cache_value_file_index == file_index )
635 		 && ( cache_value_offset == offset )
636 		 && ( cache_value_timestamp == timestamp ) )
637 		{
638 			result = 1;
639 
640 			break;
641 		}
642 		if( libcdata_list_element_get_next_element(
643 		     list_element,
644 		     &list_element,
645 		     error ) != 1 )
646 		{
647 			libcerror_error_set(
648 			 error,
649 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
650 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
651 			 "%s: unable to retrieve next list element.",
652 			 function );
653 
654 			return( -1 );
655 		}
656 	}
657 	if( ( result != 0 )
658 	 && ( number_of_cache_values > 0 ) )
659 	{
660 		if( libcdata_list_remove_element(
661 		     internal_cache->entries_list,
662 		     list_element,
663 		     error ) != 1 )
664 		{
665 			libcerror_error_set(
666 			 error,
667 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
668 			 LIBCERROR_RUNTIME_ERROR_REMOVE_FAILED,
669 			 "%s: unable to remove list element.",
670 			 function );
671 
672 			return( -1 );
673 		}
674 		if( libcdata_list_prepend_element(
675 		     internal_cache->entries_list,
676 		     list_element,
677 		     error ) != 1 )
678 		{
679 			libcerror_error_set(
680 			 error,
681 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
682 			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
683 			 "%s: unable to prepend list element.",
684 			 function );
685 
686 			return( -1 );
687 		}
688 		*cache_value = safe_cache_value;
689 	}
690 	return( result );
691 }
692 
693 /* Retrieves the cache value for the specific index
694  * Returns 1 if successful or -1 on error
695  */
libfcache_cache_get_value_by_index(libfcache_cache_t * cache,int cache_entry_index,libfcache_cache_value_t ** cache_value,libcerror_error_t ** error)696 int libfcache_cache_get_value_by_index(
697      libfcache_cache_t *cache,
698      int cache_entry_index,
699      libfcache_cache_value_t **cache_value,
700      libcerror_error_t **error )
701 {
702 	libfcache_internal_cache_t *internal_cache = NULL;
703 	static char *function                      = "libfcache_cache_get_value_by_index";
704 
705 	if( cache == NULL )
706 	{
707 		libcerror_error_set(
708 		 error,
709 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
710 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
711 		 "%s: invalid cache.",
712 		 function );
713 
714 		return( -1 );
715 	}
716 	internal_cache = (libfcache_internal_cache_t *) cache;
717 
718 	if( libcdata_array_get_entry_by_index(
719 	     internal_cache->entries_array,
720 	     cache_entry_index,
721 	     (intptr_t **) cache_value,
722 	     error ) != 1 )
723 	{
724 		libcerror_error_set(
725 		 error,
726 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
727 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
728 		 "%s: unable to retrieve cache value: %d from entries array.",
729 		 function,
730 		 cache_entry_index );
731 
732 		return( -1 );
733 	}
734 	return( 1 );
735 }
736 
737 /* Sets the cache value for the file index, offset and timestamp
738  * Returns 1 if successful or -1 on error
739  */
libfcache_cache_set_value_by_identifier(libfcache_cache_t * cache,int file_index,off64_t offset,int64_t timestamp,intptr_t * value,int (* value_free_function)(intptr_t ** value,libcerror_error_t ** error),uint8_t flags,libcerror_error_t ** error)740 int libfcache_cache_set_value_by_identifier(
741      libfcache_cache_t *cache,
742      int file_index,
743      off64_t offset,
744      int64_t timestamp,
745      intptr_t *value,
746      int (*value_free_function)(
747             intptr_t **value,
748             libcerror_error_t **error ),
749      uint8_t flags,
750      libcerror_error_t **error )
751 {
752 	libcdata_list_element_t *list_element      = NULL;
753 	libfcache_cache_value_t *cache_value       = NULL;
754 	libfcache_internal_cache_t *internal_cache = NULL;
755 	static char *function                      = "libfcache_cache_set_value_by_identifier";
756 	int cache_entry_index                      = 0;
757 	int number_of_cache_entries                = 0;
758 	int number_of_cache_values                 = 0;
759 
760 	if( cache == NULL )
761 	{
762 		libcerror_error_set(
763 		 error,
764 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
765 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
766 		 "%s: invalid cache.",
767 		 function );
768 
769 		return( -1 );
770 	}
771 	internal_cache = (libfcache_internal_cache_t *) cache;
772 
773 	if( libcdata_array_get_number_of_entries(
774 	     internal_cache->entries_array,
775 	     &number_of_cache_entries,
776 	     error ) != 1 )
777 	{
778 		libcerror_error_set(
779 		 error,
780 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
781 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
782 		 "%s: unable to retrieve number of cache entries from entries array.",
783 		 function );
784 
785 		return( -1 );
786 	}
787 	if( libcdata_list_get_number_of_elements(
788 	     internal_cache->entries_list,
789 	     &number_of_cache_values,
790 	     error ) != 1 )
791 	{
792 		libcerror_error_set(
793 		 error,
794 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
795 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
796 		 "%s: unable to retrieve number of elements from entries list.",
797 		 function );
798 
799 		return( -1 );
800 	}
801 	if( number_of_cache_values < number_of_cache_entries )
802 	{
803 		cache_entry_index = number_of_cache_values;
804 
805 		if( libfcache_cache_value_initialize(
806 		     &cache_value,
807 		     error ) != 1 )
808 		{
809 			libcerror_error_set(
810 			 error,
811 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
812 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
813 			 "%s: unable to create cache value.",
814 			 function );
815 
816 			return( -1 );
817 		}
818 		if( libfcache_cache_value_set_cache_index(
819 		     cache_value,
820 		     cache_entry_index,
821 		     error ) != 1 )
822 		{
823 			libcerror_error_set(
824 			 error,
825 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
826 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
827 			 "%s: unable to set cache index in cache value.",
828 			 function );
829 
830 			libfcache_cache_value_free(
831 			 &cache_value,
832 			 NULL );
833 
834 			return( -1 );
835 		}
836 		if( libcdata_array_set_entry_by_index(
837 		     internal_cache->entries_array,
838 		     cache_entry_index,
839 		     (intptr_t *) cache_value,
840 		     error ) != 1 )
841 		{
842 			libcerror_error_set(
843 			 error,
844 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
845 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
846 			 "%s: unable to set cache value: %d in entries array.",
847 			 function,
848 			 cache_entry_index );
849 
850 			libfcache_cache_value_free(
851 			 &cache_value,
852 			 NULL );
853 
854 			return( -1 );
855 		}
856 		if( libcdata_list_prepend_value(
857 		     internal_cache->entries_list,
858 		     (intptr_t *) cache_value,
859 		     error ) != 1 )
860 		{
861 			libcerror_error_set(
862 			 error,
863 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
864 			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
865 			 "%s: unable to prepend cache value: %d to entries list.",
866 			 function );
867 
868 			return( -1 );
869 		}
870 	}
871 	else
872 	{
873 		if( libcdata_list_get_last_element(
874 		     internal_cache->entries_list,
875 		     &list_element,
876 		     error ) != 1 )
877 		{
878 			libcerror_error_set(
879 			 error,
880 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
881 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
882 			 "%s: unable to retrieve last list element.",
883 			 function );
884 
885 			return( -1 );
886 		}
887 		if( libcdata_list_element_get_value(
888 		     list_element,
889 		     (intptr_t **) &cache_value,
890 		     error ) != 1 )
891 		{
892 			libcerror_error_set(
893 			 error,
894 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
895 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
896 			 "%s: unable to retrieve cache value from list element.",
897 			 function );
898 
899 			return( -1 );
900 		}
901 		if( libfcache_cache_value_get_cache_index(
902 		     cache_value,
903 		     &cache_entry_index,
904 		     error ) != 1 )
905 		{
906 			libcerror_error_set(
907 			 error,
908 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
909 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
910 			 "%s: unable to retrieve cache index from cache value.",
911 			 function );
912 
913 			return( -1 );
914 		}
915 		if( libcdata_array_get_entry_by_index(
916 		     internal_cache->entries_array,
917 		     cache_entry_index,
918 		     (intptr_t **) &cache_value,
919 		     error ) != 1 )
920 		{
921 			libcerror_error_set(
922 			 error,
923 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
924 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
925 			 "%s: unable to retrieve cache value: %d from entries array.",
926 			 function,
927 			 cache_entry_index );
928 
929 			return( -1 );
930 		}
931 	}
932 	if( libfcache_cache_value_set_identifier(
933 	     cache_value,
934 	     file_index,
935 	     offset,
936 	     timestamp,
937 	     error ) != 1 )
938 	{
939 		libcerror_error_set(
940 		 error,
941 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
942 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
943 		 "%s: unable to set identifier in cache value.",
944 		 function );
945 
946 		return( -1 );
947 	}
948 	if( libfcache_cache_value_set_value(
949 	     cache_value,
950 	     value,
951 	     value_free_function,
952 	     flags,
953 	     error ) != 1 )
954 	{
955 		libcerror_error_set(
956 		 error,
957 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
958 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
959 		 "%s: unable to set value in cache value.",
960 		 function );
961 
962 		return( -1 );
963 	}
964 	return( 1 );
965 }
966 
967 /* Sets the cache value for the specific index
968  * Returns 1 if successful or -1 on error
969  */
libfcache_cache_set_value_by_index(libfcache_cache_t * cache,int cache_entry_index,int file_index,off64_t offset,int64_t timestamp,intptr_t * value,int (* value_free_function)(intptr_t ** value,libcerror_error_t ** error),uint8_t flags,libcerror_error_t ** error)970 int libfcache_cache_set_value_by_index(
971      libfcache_cache_t *cache,
972      int cache_entry_index,
973      int file_index,
974      off64_t offset,
975      int64_t timestamp,
976      intptr_t *value,
977      int (*value_free_function)(
978             intptr_t **value,
979             libcerror_error_t **error ),
980      uint8_t flags,
981      libcerror_error_t **error )
982 {
983 	libfcache_cache_value_t *cache_value       = NULL;
984 	libfcache_internal_cache_t *internal_cache = NULL;
985 	static char *function                      = "libfcache_cache_set_value_by_index";
986 
987 	if( cache == NULL )
988 	{
989 		libcerror_error_set(
990 		 error,
991 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
992 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
993 		 "%s: invalid cache.",
994 		 function );
995 
996 		return( -1 );
997 	}
998 	internal_cache = (libfcache_internal_cache_t *) cache;
999 
1000 	if( libcdata_array_get_entry_by_index(
1001 	     internal_cache->entries_array,
1002 	     cache_entry_index,
1003 	     (intptr_t **) &cache_value,
1004 	     error ) != 1 )
1005 	{
1006 		libcerror_error_set(
1007 		 error,
1008 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1009 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1010 		 "%s: unable to retrieve cache value: %d from entries array.",
1011 		 function,
1012 		 cache_entry_index );
1013 
1014 		return( -1 );
1015 	}
1016 	if( cache_value == NULL )
1017 	{
1018 		if( libfcache_cache_value_initialize(
1019 		     &cache_value,
1020 		     error ) != 1 )
1021 		{
1022 			libcerror_error_set(
1023 			 error,
1024 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1025 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1026 			 "%s: unable to create cache value.",
1027 			 function );
1028 
1029 			return( -1 );
1030 		}
1031 		if( libfcache_cache_value_set_cache_index(
1032 		     cache_value,
1033 		     cache_entry_index,
1034 		     error ) != 1 )
1035 		{
1036 			libcerror_error_set(
1037 			 error,
1038 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1039 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1040 			 "%s: unable to set cache index in cache value.",
1041 			 function );
1042 
1043 			libfcache_cache_value_free(
1044 			 &cache_value,
1045 			 NULL );
1046 
1047 			return( -1 );
1048 		}
1049 		if( libcdata_array_set_entry_by_index(
1050 		     internal_cache->entries_array,
1051 		     cache_entry_index,
1052 		     (intptr_t *) cache_value,
1053 		     error ) != 1 )
1054 		{
1055 			libcerror_error_set(
1056 			 error,
1057 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1058 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1059 			 "%s: unable to set cache value: %d in entries array.",
1060 			 function,
1061 			 cache_entry_index );
1062 
1063 			libfcache_cache_value_free(
1064 			 &cache_value,
1065 			 NULL );
1066 
1067 			return( -1 );
1068 		}
1069 		if( libcdata_list_prepend_value(
1070 		     internal_cache->entries_list,
1071 		     (intptr_t *) cache_value,
1072 		     error ) != 1 )
1073 		{
1074 			libcerror_error_set(
1075 			 error,
1076 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1077 			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1078 			 "%s: unable to prepend cache value: %d to entries list.",
1079 			 function );
1080 
1081 			return( -1 );
1082 		}
1083 	}
1084 	if( libfcache_cache_value_set_value(
1085 	     cache_value,
1086 	     value,
1087 	     value_free_function,
1088 	     flags,
1089 	     error ) != 1 )
1090 	{
1091 		libcerror_error_set(
1092 		 error,
1093 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1094 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1095 		 "%s: unable to set value in cache value.",
1096 		 function );
1097 
1098 		return( -1 );
1099 	}
1100 	if( libfcache_cache_value_set_identifier(
1101 	     cache_value,
1102 	     file_index,
1103 	     offset,
1104 	     timestamp,
1105 	     error ) != 1 )
1106 	{
1107 		libcerror_error_set(
1108 		 error,
1109 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1110 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1111 		 "%s: unable to set identifier in cache value.",
1112 		 function );
1113 
1114 		return( -1 );
1115 	}
1116 	return( 1 );
1117 }
1118 
1119