1 /*
2  * The internal pool functions
3  *
4  * Copyright (C) 2009-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 #if defined( HAVE_UNISTD_H )
27 #include <unistd.h>
28 #endif
29 
30 #include "libbfio_definitions.h"
31 #include "libbfio_handle.h"
32 #include "libbfio_libcdata.h"
33 #include "libbfio_libcerror.h"
34 #include "libbfio_pool.h"
35 #include "libbfio_types.h"
36 
37 /* Creates a pool
38  * Make sure the value pool is referencing, is set to NULL
39  * Returns 1 if successful or -1 on error
40  */
libbfio_pool_initialize(libbfio_pool_t ** pool,int number_of_handles,int maximum_number_of_open_handles,libcerror_error_t ** error)41 int libbfio_pool_initialize(
42      libbfio_pool_t **pool,
43      int number_of_handles,
44      int maximum_number_of_open_handles,
45      libcerror_error_t **error )
46 {
47 	libbfio_internal_pool_t *internal_pool = NULL;
48 	static char *function                  = "libbfio_pool_initialize";
49 
50 	if( pool == NULL )
51 	{
52 		libcerror_error_set(
53 		 error,
54 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56 		 "%s: invalid pool.",
57 		 function );
58 
59 		return( -1 );
60 	}
61 	if( *pool != NULL )
62 	{
63 		libcerror_error_set(
64 		 error,
65 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
66 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
67 		 "%s: invalid pool value already set.",
68 		 function );
69 
70 		return( -1 );
71 	}
72 	if( number_of_handles < 0 )
73 	{
74 		libcerror_error_set(
75 		 error,
76 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
77 		 LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO,
78 		 "%s: invalid number of handles value less than zero.",
79 		 function );
80 
81 		return( -1 );
82 	}
83 	if( maximum_number_of_open_handles < 0 )
84 	{
85 		libcerror_error_set(
86 		 error,
87 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
88 		 LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO,
89 		 "%s: invalid maximum number of open handles value less than zero.",
90 		 function );
91 
92 		return( -1 );
93 	}
94 	internal_pool = memory_allocate_structure(
95 	                 libbfio_internal_pool_t );
96 
97 	if( internal_pool == NULL )
98 	{
99 		libcerror_error_set(
100 		 error,
101 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
102 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
103 		 "%s: unable to create pool.",
104 		 function );
105 
106 		goto on_error;
107 	}
108 	if( memory_set(
109 	     internal_pool,
110 	     0,
111 	     sizeof( libbfio_internal_pool_t ) ) == NULL )
112 	{
113 		libcerror_error_set(
114 		 error,
115 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
116 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
117 		 "%s: unable to clear pool.",
118 		 function );
119 
120 		memory_free(
121 		 internal_pool );
122 
123 		return( -1 );
124 	}
125 	if( libcdata_array_initialize(
126 	     &( internal_pool->handles_array ),
127 	     number_of_handles,
128 	     error ) != 1 )
129 	{
130 		libcerror_error_set(
131 		 error,
132 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
133 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
134 		 "%s: unable to create handles array.",
135 		 function );
136 
137 		goto on_error;
138 	}
139 	if( libcdata_list_initialize(
140 	     &( internal_pool->last_used_list ),
141 	     error ) != 1 )
142 	{
143 		libcerror_error_set(
144 		 error,
145 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
146 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
147 		 "%s: unable to create last used list.",
148 		 function );
149 
150 		goto on_error;
151 	}
152 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
153 	if( libcthreads_read_write_lock_initialize(
154 	     &( internal_pool->read_write_lock ),
155 	     error ) != 1 )
156 	{
157 		libcerror_error_set(
158 		 error,
159 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
160 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
161 		 "%s: unable to initialize read/write lock.",
162 		 function );
163 
164 		goto on_error;
165 	}
166 #endif
167 	internal_pool->maximum_number_of_open_handles = maximum_number_of_open_handles;
168 	internal_pool->current_entry                  = -1;
169 
170 	*pool = (libbfio_pool_t *) internal_pool;
171 
172 	return( 1 );
173 
174 on_error:
175 	if( internal_pool != NULL )
176 	{
177 		if( internal_pool->last_used_list != NULL )
178 		{
179 			libcdata_list_free(
180 			 &( internal_pool->last_used_list ),
181 			 NULL,
182 			 NULL );
183 		}
184 		if( internal_pool->handles_array != NULL )
185 		{
186 			libcdata_array_free(
187 			 &( internal_pool->handles_array ),
188 			 (int (*)(intptr_t **, libcerror_error_t **)) &libbfio_handle_free,
189 			 NULL );
190 		}
191 		memory_free(
192 		 internal_pool );
193 	}
194 	return( -1 );
195 }
196 
197 /* Frees a pool
198  * Returns 1 if successful or -1 on error
199  */
libbfio_pool_free(libbfio_pool_t ** pool,libcerror_error_t ** error)200 int libbfio_pool_free(
201      libbfio_pool_t **pool,
202      libcerror_error_t **error )
203 {
204 	libbfio_internal_pool_t *internal_pool = NULL;
205 	static char *function                  = "libbfio_pool_free";
206 	int result                             = 1;
207 
208 	if( pool == NULL )
209 	{
210 		libcerror_error_set(
211 		 error,
212 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
213 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
214 		 "%s: invalid pool.",
215 		 function );
216 
217 		return( -1 );
218 	}
219 	if( *pool != NULL )
220 	{
221 		internal_pool = (libbfio_internal_pool_t *) *pool;
222 		*pool         = NULL;
223 
224 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
225 		if( libcthreads_read_write_lock_free(
226 		     &( internal_pool->read_write_lock ),
227 		     error ) != 1 )
228 		{
229 			libcerror_error_set(
230 			 error,
231 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
232 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
233 			 "%s: unable to free read/write lock.",
234 			 function );
235 
236 			result = -1;
237 		}
238 #endif
239 		if( libcdata_array_free(
240 		     &( internal_pool->handles_array ),
241 		     (int (*)(intptr_t **, libcerror_error_t **)) &libbfio_handle_free,
242 		     error ) != 1 )
243 		{
244 			libcerror_error_set(
245 			 error,
246 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
247 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
248 			 "%s: unable to free handles array.",
249 			 function );
250 
251 			result = -1;
252 		}
253 		if( libcdata_list_free(
254 		     &( internal_pool->last_used_list ),
255 		     NULL,
256 		     error ) != 1 )
257 		{
258 			libcerror_error_set(
259 			 error,
260 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
261 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
262 			 "%s: unable to free last used list.",
263 			 function );
264 
265 			result = -1;
266 		}
267 		memory_free(
268 		 internal_pool );
269 	}
270 	return( result );
271 }
272 
273 /* Clones (duplicates) the pool
274  * The values in the offsets read list are not duplicated
275  * Returns 1 if successful or -1 on error
276  */
libbfio_pool_clone(libbfio_pool_t ** destination_pool,libbfio_pool_t * source_pool,libcerror_error_t ** error)277 int libbfio_pool_clone(
278      libbfio_pool_t **destination_pool,
279      libbfio_pool_t *source_pool,
280      libcerror_error_t **error )
281 {
282 	libbfio_internal_pool_t *internal_destination_pool = NULL;
283 	libbfio_internal_pool_t *internal_source_pool      = NULL;
284 	static char *function                              = "libbfio_pool_clone";
285 
286 	if( destination_pool == NULL )
287 	{
288 		libcerror_error_set(
289 		 error,
290 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
291 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
292 		 "%s: invalid destination pool.",
293 		 function );
294 
295 		return( -1 );
296 	}
297 	if( *destination_pool != NULL )
298 	{
299 		libcerror_error_set(
300 		 error,
301 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
302 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
303 		 "%s: destination pool already set.",
304 		 function );
305 
306 		return( -1 );
307 	}
308 	if( source_pool == NULL )
309 	{
310 		*destination_pool = NULL;
311 
312 		return( 1 );
313 	}
314 	internal_source_pool = (libbfio_internal_pool_t *) source_pool;
315 
316 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
317 	if( libcthreads_read_write_lock_grab_for_read(
318 	     internal_source_pool->read_write_lock,
319 	     error ) != 1 )
320 	{
321 		libcerror_error_set(
322 		 error,
323 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
324 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
325 		 "%s: unable to grab read/write lock for reading.",
326 		 function );
327 
328 		return( -1 );
329 	}
330 #endif
331 	internal_destination_pool = memory_allocate_structure(
332 	                             libbfio_internal_pool_t );
333 
334 	if( internal_destination_pool == NULL )
335 	{
336 		libcerror_error_set(
337 		 error,
338 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
339 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
340 		 "%s: unable to create destination pool.",
341 		 function );
342 
343 		goto on_error;
344 	}
345 	if( memory_set(
346 	     internal_destination_pool,
347 	     0,
348 	     sizeof( libbfio_internal_pool_t ) ) == NULL )
349 	{
350 		libcerror_error_set(
351 		 error,
352 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
353 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
354 		 "%s: unable to clear destination pool.",
355 		 function );
356 
357 		memory_free(
358 		 internal_destination_pool );
359 
360 		internal_destination_pool = NULL;
361 
362 		goto on_error;
363 	}
364 	internal_destination_pool->current_entry  = -1;
365 	internal_destination_pool->current_handle = NULL;
366 
367 	if( libcdata_array_clone(
368 	     &( internal_destination_pool->handles_array ),
369 	     internal_source_pool->handles_array,
370 	     (int (*)(intptr_t **, libcerror_error_t **)) &libbfio_handle_free,
371 	     (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libbfio_handle_clone,
372 	     error ) != 1 )
373 	{
374 		libcerror_error_set(
375 		 error,
376 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
377 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
378 		 "%s: unable to create handles array.",
379 		 function );
380 
381 		goto on_error;
382 	}
383 	if( libcdata_list_initialize(
384 	     &( internal_destination_pool->last_used_list ),
385 	     error ) != 1 )
386 	{
387 		libcerror_error_set(
388 		 error,
389 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
390 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
391 		 "%s: unable to create last used list.",
392 		 function );
393 
394 		goto on_error;
395 	}
396 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
397 	if( libcthreads_read_write_lock_initialize(
398 	     &( internal_destination_pool->read_write_lock ),
399 	     error ) != 1 )
400 	{
401 		libcerror_error_set(
402 		 error,
403 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
404 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
405 		 "%s: unable to initialize read/write lock.",
406 		 function );
407 
408 		goto on_error;
409 	}
410 #endif
411 	internal_destination_pool->maximum_number_of_open_handles = internal_source_pool->maximum_number_of_open_handles;
412 
413 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
414 	if( libcthreads_read_write_lock_release_for_read(
415 	     internal_source_pool->read_write_lock,
416 	     error ) != 1 )
417 	{
418 		libcerror_error_set(
419 		 error,
420 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
421 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
422 		 "%s: unable to release read/write lock for reading.",
423 		 function );
424 
425 		libbfio_pool_free(
426 		 (libbfio_pool_t **) &internal_destination_pool,
427 		 NULL );
428 
429 		return( -1 );
430 	}
431 #endif
432 	*destination_pool = (libbfio_pool_t *) internal_destination_pool;
433 
434 	return( 1 );
435 
436 on_error:
437 	if( internal_destination_pool != NULL )
438 	{
439 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
440 		if( internal_destination_pool->read_write_lock != NULL )
441 		{
442 			libcthreads_read_write_lock_free(
443 			 &( internal_destination_pool->read_write_lock ),
444 			 NULL );
445 		}
446 #endif
447 		if( internal_destination_pool->last_used_list != NULL )
448 		{
449 			libcdata_list_free(
450 			 &( internal_destination_pool->last_used_list ),
451 			 NULL,
452 			 NULL );
453 		}
454 		if( internal_destination_pool->handles_array != NULL )
455 		{
456 			libcdata_array_free(
457 			 &( internal_destination_pool->handles_array ),
458 			 (int (*)(intptr_t **, libcerror_error_t **)) &libbfio_handle_free,
459 			 NULL );
460 		}
461 		memory_free(
462 		 internal_destination_pool );
463 	}
464 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
465 	libcthreads_read_write_lock_release_for_read(
466 	 internal_source_pool->read_write_lock,
467 	 NULL );
468 #endif
469 	return( -1 );
470 }
471 
472 /* Resizes the pool
473  * Returns 1 if successful or -1 on error
474  */
libbfio_pool_resize(libbfio_pool_t * pool,int number_of_handles,libcerror_error_t ** error)475 int libbfio_pool_resize(
476      libbfio_pool_t *pool,
477      int number_of_handles,
478      libcerror_error_t **error )
479 {
480 	libbfio_internal_pool_t *internal_pool = NULL;
481 	static char *function                  = "libbfio_pool_resize";
482 	int result                             = 1;
483 
484 	if( pool == NULL )
485 	{
486 		libcerror_error_set(
487 		 error,
488 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
489 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
490 		 "%s: invalid pool.",
491 		 function );
492 
493 		return( -1 );
494 	}
495 	internal_pool = (libbfio_internal_pool_t *) pool;
496 
497 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
498 	if( libcthreads_read_write_lock_grab_for_write(
499 	     internal_pool->read_write_lock,
500 	     error ) != 1 )
501 	{
502 		libcerror_error_set(
503 		 error,
504 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
505 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
506 		 "%s: unable to grab read/write lock for writing.",
507 		 function );
508 
509 		return( -1 );
510 	}
511 #endif
512 	if( libcdata_array_resize(
513 	     internal_pool->handles_array,
514 	     number_of_handles,
515 	     (int (*)(intptr_t **, libcerror_error_t **)) &libbfio_handle_free,
516 	     error ) != 1 )
517 	{
518 		libcerror_error_set(
519 		 error,
520 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
521 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
522 		 "%s: unable to resize handles array.",
523 		 function );
524 
525 		result = -1;
526 	}
527 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
528 	if( libcthreads_read_write_lock_release_for_write(
529 	     internal_pool->read_write_lock,
530 	     error ) != 1 )
531 	{
532 		libcerror_error_set(
533 		 error,
534 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
535 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
536 		 "%s: unable to release read/write lock for writing.",
537 		 function );
538 
539 		return( -1 );
540 	}
541 #endif
542 	return( result );
543 }
544 
545 /* Opens the handle
546  * Returns 1 if successful or -1 on error
547  */
libbfio_internal_pool_open_handle(libbfio_internal_pool_t * internal_pool,libbfio_handle_t * handle,int access_flags,libcerror_error_t ** error)548 int libbfio_internal_pool_open_handle(
549      libbfio_internal_pool_t *internal_pool,
550      libbfio_handle_t *handle,
551      int access_flags,
552      libcerror_error_t **error )
553 {
554 	libbfio_internal_handle_t *internal_handle = NULL;
555 	static char *function                      = "libbfio_internal_pool_open_handle";
556 	int is_open                                = 0;
557 
558 	if( internal_pool == NULL )
559 	{
560 		libcerror_error_set(
561 		 error,
562 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
563 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
564 		 "%s: invalid pool.",
565 		 function );
566 
567 		return( -1 );
568 	}
569 	if( internal_pool->last_used_list == NULL )
570 	{
571 		libcerror_error_set(
572 		 error,
573 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
574 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
575 		 "%s: invalid pool - missing last used list.",
576 		 function );
577 
578 		return( -1 );
579 	}
580 	if( handle == NULL )
581 	{
582 		libcerror_error_set(
583 		 error,
584 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
585 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
586 		 "%s: invalid handle.",
587 		 function );
588 
589 		return( -1 );
590 	}
591 	is_open = libbfio_handle_is_open(
592 	           handle,
593 	           error );
594 
595 	if( is_open == -1 )
596 	{
597 		libcerror_error_set(
598 		 error,
599 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
600 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
601 		 "%s: unable to determine if handle is open.",
602 		 function );
603 
604 		return( -1 );
605 	}
606 	else if( is_open == 1 )
607 	{
608 		return( 1 );
609 	}
610 	if( internal_pool->maximum_number_of_open_handles != LIBBFIO_POOL_UNLIMITED_NUMBER_OF_OPEN_HANDLES )
611 	{
612 		if( libbfio_internal_pool_append_handle_to_last_used_list(
613 		     internal_pool,
614 		     handle,
615 		     error ) != 1 )
616 		{
617 			libcerror_error_set(
618 			 error,
619 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
620 			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
621 			 "%s: unable to append handle to last used list.",
622 			 function );
623 
624 			return( -1 );
625 		}
626 	}
627 	if( libbfio_handle_open(
628 	     handle,
629 	     access_flags,
630 	     error ) != 1 )
631 	{
632 		libcerror_error_set(
633 		 error,
634 		 LIBCERROR_ERROR_DOMAIN_IO,
635 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
636 		 "%s: unable to open handle.",
637 		 function );
638 
639 		return( -1 );
640 	}
641 	internal_handle = (libbfio_internal_handle_t *) handle;
642 
643 	if( libbfio_handle_seek_offset(
644 	     handle,
645 	     internal_handle->current_offset,
646 	     SEEK_SET,
647 	     error ) == -1 )
648 	{
649 		libcerror_error_set(
650 		 error,
651 		 LIBCERROR_ERROR_DOMAIN_IO,
652 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
653 		 "%s: unable to seek offset.",
654 		 function );
655 
656 		return( -1 );
657 	}
658 	return( 1 );
659 }
660 
661 /* Appends the handle to the last used list
662  * Closes the less frequently used handle if necessary
663  * Returns 1 if successful or -1 on error
664  */
libbfio_internal_pool_append_handle_to_last_used_list(libbfio_internal_pool_t * internal_pool,const libbfio_handle_t * handle,libcerror_error_t ** error)665 int libbfio_internal_pool_append_handle_to_last_used_list(
666      libbfio_internal_pool_t *internal_pool,
667      const libbfio_handle_t *handle,
668      libcerror_error_t **error )
669 {
670 	libbfio_internal_handle_t *internal_handle      = NULL;
671 	libcdata_list_element_t *last_used_list_element = NULL;
672 	static char *function                           = "libbfio_internal_pool_append_handle_to_last_used_list";
673 
674 	if( internal_pool == NULL )
675 	{
676 		libcerror_error_set(
677 		 error,
678 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
679 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
680 		 "%s: invalid pool.",
681 		 function );
682 
683 		return( -1 );
684 	}
685 	if( internal_pool->last_used_list == NULL )
686 	{
687 		libcerror_error_set(
688 		 error,
689 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
690 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
691 		 "%s: invalid pool - missing last used list.",
692 		 function );
693 
694 		return( -1 );
695 	}
696 	if( handle == NULL )
697 	{
698 		libcerror_error_set(
699 		 error,
700 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
701 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
702 		 "%s: invalid handle.",
703 		 function );
704 
705 		return( -1 );
706 	}
707 	/* Check if there is room in the pool for another open handle
708 	 */
709 	if( ( internal_pool->maximum_number_of_open_handles != LIBBFIO_POOL_UNLIMITED_NUMBER_OF_OPEN_HANDLES )
710 	 && ( ( internal_pool->number_of_open_handles + 1 ) >= internal_pool->maximum_number_of_open_handles ) )
711 	{
712 		if( libcdata_list_get_last_element(
713 		     internal_pool->last_used_list,
714 		     &last_used_list_element,
715 		     error ) != 1 )
716 		{
717 			libcerror_error_set(
718 			 error,
719 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
720 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
721 			 "%s: unable to retrieve last list element from last used list.",
722 			 function );
723 
724 			return( -1 );
725 		}
726 	}
727 	if( last_used_list_element == NULL )
728 	{
729 		if( libcdata_list_element_initialize(
730 		     &last_used_list_element,
731 		     error ) != 1 )
732 		{
733 			libcerror_error_set(
734 			 error,
735 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
736 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
737 			 "%s: unable to create last used list element.",
738 			 function );
739 
740 			return( -1 );
741 		}
742 		internal_pool->number_of_open_handles++;
743 	}
744 	else
745 	{
746 		/* The last used list element is reused to contain the new last used entry
747 		 */
748 		if( libcdata_list_element_get_value(
749 		     last_used_list_element,
750 		     (intptr_t **) &internal_handle,
751 		     error ) != 1 )
752 		{
753 			libcerror_error_set(
754 			 error,
755 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
756 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
757 			 "%s: unable to retrieve value from last used list element.",
758 			 function );
759 
760 			return( -1 );
761 		}
762 		if( libcdata_list_remove_element(
763 		     internal_pool->last_used_list,
764 		     last_used_list_element,
765 		     error ) != 1 )
766 		{
767 			libcerror_error_set(
768 			 error,
769 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
770 			 LIBCERROR_RUNTIME_ERROR_REMOVE_FAILED,
771 			 "%s: unable to remove last list element from last used list.",
772 			 function );
773 
774 			return( -1 );
775 		}
776 		if( internal_handle != NULL )
777 		{
778 			if( libbfio_handle_close(
779 			     (libbfio_handle_t *) internal_handle,
780 			     error ) != 0 )
781 			{
782 				libcerror_error_set(
783 				 error,
784 				 LIBCERROR_ERROR_DOMAIN_IO,
785 				 LIBCERROR_IO_ERROR_CLOSE_FAILED,
786 				 "%s: unable to close handle.",
787 				 function );
788 
789 				libcdata_list_element_free(
790 				 &last_used_list_element,
791 				 NULL,
792 				 NULL );
793 
794 				return( -1 );
795 			}
796 			internal_handle->pool_last_used_list_element = NULL;
797 
798 			/* Make sure the truncate flag is removed from the handle
799 			 */
800 			internal_handle->access_flags &= ~( LIBBFIO_ACCESS_FLAG_TRUNCATE );
801 		}
802 	}
803 	internal_handle = (libbfio_internal_handle_t *) handle;
804 
805 	if( libcdata_list_element_set_value(
806 	     last_used_list_element,
807 	     (intptr_t *) handle,
808 	     error ) != 1 )
809 	{
810 		libcerror_error_set(
811 		 error,
812 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
813 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
814 		 "%s: unable to set value int last used list element.",
815 		 function );
816 
817 		return( -1 );
818 	}
819 	internal_handle->pool_last_used_list_element = last_used_list_element;
820 
821 	if( libcdata_list_prepend_element(
822 	     internal_pool->last_used_list,
823 	     last_used_list_element,
824 	     error ) != 1 )
825 	{
826 		libcerror_error_set(
827 		 error,
828 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
829 		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
830 		 "%s: unable to prepend last used list element to list.",
831 		 function );
832 
833 		libcdata_list_element_free(
834 		 &last_used_list_element,
835 		 NULL,
836 		 NULL );
837 
838 		return( -1 );
839 	}
840 	return( 1 );
841 }
842 
843 /* Moves the handle to the front of the last used list
844  * Returns 1 if successful or -1 on error
845  */
libbfio_internal_pool_move_handle_to_front_of_last_used_list(libbfio_internal_pool_t * internal_pool,libbfio_handle_t * handle,libcerror_error_t ** error)846 int libbfio_internal_pool_move_handle_to_front_of_last_used_list(
847      libbfio_internal_pool_t *internal_pool,
848      libbfio_handle_t *handle,
849      libcerror_error_t **error )
850 {
851 	libbfio_internal_handle_t *internal_handle      = NULL;
852 	libcdata_list_element_t *first_list_element     = NULL;
853 	libcdata_list_element_t *last_used_list_element = NULL;
854 	static char *function                           = "libbfio_internal_pool_move_handle_to_front_of_last_used_list";
855 
856 	if( internal_pool == NULL )
857 	{
858 		libcerror_error_set(
859 		 error,
860 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
861 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
862 		 "%s: invalid pool.",
863 		 function );
864 
865 		return( -1 );
866 	}
867 	if( internal_pool->last_used_list == NULL )
868 	{
869 		libcerror_error_set(
870 		 error,
871 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
872 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
873 		 "%s: invalid pool - missing last used list.",
874 		 function );
875 
876 		return( -1 );
877 	}
878 	if( handle == NULL )
879 	{
880 		libcerror_error_set(
881 		 error,
882 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
883 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
884 		 "%s: invalid handle.",
885 		 function );
886 
887 		return( -1 );
888 	}
889 	internal_handle = (libbfio_internal_handle_t *) handle;
890 
891 	if( libcdata_list_get_first_element(
892 	     internal_pool->last_used_list,
893 	     &first_list_element,
894 	     error ) != 1 )
895 	{
896 		libcerror_error_set(
897 		 error,
898 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
899 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
900 		 "%s: unable to retrieve first list element from last used list.",
901 		 function );
902 
903 		return( -1 );
904 	}
905 	last_used_list_element = internal_handle->pool_last_used_list_element;
906 
907 	if( last_used_list_element == NULL )
908 	{
909 		libcerror_error_set(
910 		 error,
911 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
912 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
913 		 "%s: missing last used list element.",
914 		 function );
915 
916 		return( -1 );
917 	}
918 	if( last_used_list_element != first_list_element )
919 	{
920 		if( libcdata_list_remove_element(
921 		     internal_pool->last_used_list,
922 		     last_used_list_element,
923 		     error ) != 1 )
924 		{
925 			libcerror_error_set(
926 			 error,
927 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
928 			 LIBCERROR_RUNTIME_ERROR_REMOVE_FAILED,
929 			 "%s: unable to remove last used list element from list.",
930 			 function );
931 
932 			return( -1 );
933 		}
934 		if( libcdata_list_prepend_element(
935 		     internal_pool->last_used_list,
936 		     last_used_list_element,
937 		     error ) != 1 )
938 		{
939 			libcerror_error_set(
940 			 error,
941 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
942 			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
943 			 "%s: unable to prepend last used list element to list.",
944 			 function );
945 
946 			internal_handle->pool_last_used_list_element = NULL;
947 
948 			libcdata_list_element_free(
949 			 &last_used_list_element,
950 			 NULL,
951 			 NULL );
952 
953 			return( -1 );
954 		}
955 	}
956 	return( 1 );
957 }
958 
959 /* Removes a handle from the last used list
960  * Returns 1 if successful or -1 on error
961  */
libbfio_internal_pool_remove_handle_from_last_used_list(libbfio_internal_pool_t * internal_pool,const libbfio_handle_t * handle,libcerror_error_t ** error)962 int libbfio_internal_pool_remove_handle_from_last_used_list(
963      libbfio_internal_pool_t *internal_pool,
964      const libbfio_handle_t *handle,
965      libcerror_error_t **error )
966 {
967 	libbfio_handle_t *last_used_handle              = NULL;
968 	libcdata_list_element_t *last_used_list_element = NULL;
969 	static char *function                           = "libbfio_internal_pool_remove_handle_from_last_used_list";
970 
971 	if( internal_pool == NULL )
972 	{
973 		libcerror_error_set(
974 		 error,
975 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
976 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
977 		 "%s: invalid pool.",
978 		 function );
979 
980 		return( -1 );
981 	}
982 	if( handle == NULL )
983 	{
984 		libcerror_error_set(
985 		 error,
986 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
987 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
988 		 "%s: invalid handle.",
989 		 function );
990 
991 		return( -1 );
992 	}
993 	if( libcdata_list_get_first_element(
994 	     internal_pool->last_used_list,
995 	     &last_used_list_element,
996 	     error ) != 1 )
997 	{
998 		libcerror_error_set(
999 		 error,
1000 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1001 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1002 		 "%s: unable to retrieve first list element from last used list.",
1003 		 function );
1004 
1005 		return( -1 );
1006 	}
1007 	while( last_used_list_element != NULL )
1008 	{
1009 		if( libcdata_list_element_get_value(
1010 		     last_used_list_element,
1011 		     (intptr_t **) &last_used_handle,
1012 		     error ) != 1 )
1013 		{
1014 			libcerror_error_set(
1015 			 error,
1016 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1017 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1018 			 "%s: unable to retrieve last used handle.",
1019 			 function );
1020 
1021 			return( -1 );
1022 		}
1023 		if( last_used_handle == handle )
1024 		{
1025 			break;
1026 		}
1027 		if( libcdata_list_element_get_next_element(
1028 		     last_used_list_element,
1029 		     &last_used_list_element,
1030 		     error ) != 1 )
1031 		{
1032 			libcerror_error_set(
1033 			 error,
1034 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1035 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1036 			 "%s: unable to retrieve next last used list element.",
1037 			 function );
1038 
1039 			return( -1 );
1040 		}
1041 	}
1042 	if( last_used_list_element != NULL )
1043 	{
1044 		if( libcdata_list_remove_element(
1045 		     internal_pool->last_used_list,
1046 		     last_used_list_element,
1047 		     error ) != 1 )
1048 		{
1049 			libcerror_error_set(
1050 			 error,
1051 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1052 			 LIBCERROR_RUNTIME_ERROR_REMOVE_FAILED,
1053 			 "%s: unable to remove last list element from last used list.",
1054 			 function );
1055 
1056 			return( -1 );
1057 		}
1058 	}
1059 	return( 1 );
1060 }
1061 
1062 /* Retrieves the number of handles in the pool
1063  * Returns 1 if successful or -1 on error
1064  */
libbfio_pool_get_number_of_handles(libbfio_pool_t * pool,int * number_of_handles,libcerror_error_t ** error)1065 int libbfio_pool_get_number_of_handles(
1066      libbfio_pool_t *pool,
1067      int *number_of_handles,
1068      libcerror_error_t **error )
1069 {
1070 	libbfio_internal_pool_t *internal_pool = NULL;
1071 	static char *function                  = "libbfio_pool_get_number_of_handles";
1072 	int result                             = 1;
1073 
1074 	if( pool == NULL )
1075 	{
1076 		libcerror_error_set(
1077 		 error,
1078 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1079 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1080 		 "%s: invalid pool.",
1081 		 function );
1082 
1083 		return( -1 );
1084 	}
1085 	internal_pool = (libbfio_internal_pool_t *) pool;
1086 
1087 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1088 	if( libcthreads_read_write_lock_grab_for_read(
1089 	     internal_pool->read_write_lock,
1090 	     error ) != 1 )
1091 	{
1092 		libcerror_error_set(
1093 		 error,
1094 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1095 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1096 		 "%s: unable to grab read/write lock for reading.",
1097 		 function );
1098 
1099 		return( -1 );
1100 	}
1101 #endif
1102 	if( libcdata_array_get_number_of_entries(
1103 	     internal_pool->handles_array,
1104 	     number_of_handles,
1105 	     error ) != 1 )
1106 	{
1107 		libcerror_error_set(
1108 		 error,
1109 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1110 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1111 		 "%s: unable to retrieve number of handles.",
1112 		 function );
1113 
1114 		result = -1;
1115 	}
1116 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1117 	if( libcthreads_read_write_lock_release_for_read(
1118 	     internal_pool->read_write_lock,
1119 	     error ) != 1 )
1120 	{
1121 		libcerror_error_set(
1122 		 error,
1123 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1124 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1125 		 "%s: unable to release read/write lock for reading.",
1126 		 function );
1127 
1128 		return( -1 );
1129 	}
1130 #endif
1131 	return( result );
1132 }
1133 
1134 /* Retrieves a specific handle from the pool
1135  * Returns 1 if successful or -1 on error
1136  */
libbfio_pool_get_handle(libbfio_pool_t * pool,int entry,libbfio_handle_t ** handle,libcerror_error_t ** error)1137 int libbfio_pool_get_handle(
1138      libbfio_pool_t *pool,
1139      int entry,
1140      libbfio_handle_t **handle,
1141      libcerror_error_t **error )
1142 {
1143 	libbfio_internal_pool_t *internal_pool = NULL;
1144 	static char *function                  = "libbfio_pool_get_handle";
1145 	int result                             = 1;
1146 
1147 	if( pool == NULL )
1148 	{
1149 		libcerror_error_set(
1150 		 error,
1151 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1152 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1153 		 "%s: invalid pool.",
1154 		 function );
1155 
1156 		return( -1 );
1157 	}
1158 	internal_pool = (libbfio_internal_pool_t *) pool;
1159 
1160 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1161 	if( libcthreads_read_write_lock_grab_for_read(
1162 	     internal_pool->read_write_lock,
1163 	     error ) != 1 )
1164 	{
1165 		libcerror_error_set(
1166 		 error,
1167 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1168 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1169 		 "%s: unable to grab read/write lock for reading.",
1170 		 function );
1171 
1172 		return( -1 );
1173 	}
1174 #endif
1175 	if( libcdata_array_get_entry_by_index(
1176 	     internal_pool->handles_array,
1177 	     entry,
1178 	     (intptr_t **) handle,
1179 	     error ) != 1 )
1180 	{
1181 		libcerror_error_set(
1182 		 error,
1183 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1184 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1185 		 "%s: unable to retrieve handle: %d.",
1186 		 function,
1187 		 entry );
1188 
1189 		result = -1;
1190 	}
1191 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1192 	if( libcthreads_read_write_lock_release_for_read(
1193 	     internal_pool->read_write_lock,
1194 	     error ) != 1 )
1195 	{
1196 		libcerror_error_set(
1197 		 error,
1198 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1199 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1200 		 "%s: unable to release read/write lock for reading.",
1201 		 function );
1202 
1203 		return( -1 );
1204 	}
1205 #endif
1206 	return( result );
1207 }
1208 
1209 /* Appends a handle to the pool
1210  * Sets the entry
1211  * Returns 1 if successful or -1 on error
1212  */
libbfio_pool_append_handle(libbfio_pool_t * pool,int * entry,libbfio_handle_t * handle,int access_flags,libcerror_error_t ** error)1213 int libbfio_pool_append_handle(
1214      libbfio_pool_t *pool,
1215      int *entry,
1216      libbfio_handle_t *handle,
1217      int access_flags,
1218      libcerror_error_t **error )
1219 {
1220 	libbfio_internal_pool_t *internal_pool = NULL;
1221 	static char *function                  = "libbfio_pool_append_handle";
1222 	int is_open                            = 0;
1223 	int number_of_handles                  = 0;
1224 	int result                             = 1;
1225 	int safe_entry                         = -1;
1226 
1227 	if( pool == NULL )
1228 	{
1229 		libcerror_error_set(
1230 		 error,
1231 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1232 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1233 		 "%s: invalid pool.",
1234 		 function );
1235 
1236 		return( -1 );
1237 	}
1238 	internal_pool = (libbfio_internal_pool_t *) pool;
1239 
1240 	if( internal_pool->last_used_list == NULL )
1241 	{
1242 		libcerror_error_set(
1243 		 error,
1244 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1245 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1246 		 "%s: invalid pool - missing last used list.",
1247 		 function );
1248 
1249 		return( -1 );
1250 	}
1251 	if( entry == NULL )
1252 	{
1253 		libcerror_error_set(
1254 		 error,
1255 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1256 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1257 		 "%s: invalid entry.",
1258 		 function );
1259 
1260 		return( -1 );
1261 	}
1262 	/* Check if the handle is open
1263 	 */
1264 	is_open = libbfio_handle_is_open(
1265 	           handle,
1266 	           error );
1267 
1268 	if( is_open == -1 )
1269 	{
1270 		libcerror_error_set(
1271 		 error,
1272 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1273 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1274 		 "%s: unable to determine if handle is open.",
1275 		 function );
1276 
1277 		return( -1 );
1278 	}
1279 	else if( is_open == 0 )
1280 	{
1281 		/* Set the access flags is the handle is not open
1282 		 */
1283 		if( libbfio_handle_set_access_flags(
1284 		     handle,
1285 		     access_flags,
1286 		     error ) != 1 )
1287 		{
1288 			libcerror_error_set(
1289 			 error,
1290 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1291 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1292 			 "%s: unable to set access flags.",
1293 			 function );
1294 
1295 			return( -1 );
1296 		}
1297 	}
1298 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1299 	if( libcthreads_read_write_lock_grab_for_write(
1300 	     internal_pool->read_write_lock,
1301 	     error ) != 1 )
1302 	{
1303 		libcerror_error_set(
1304 		 error,
1305 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1306 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1307 		 "%s: unable to grab read/write lock for writing.",
1308 		 function );
1309 
1310 		return( -1 );
1311 	}
1312 #endif
1313 	if( libcdata_array_get_number_of_entries(
1314 	     internal_pool->handles_array,
1315 	     &number_of_handles,
1316 	     error ) != 1 )
1317 	{
1318 		libcerror_error_set(
1319 		 error,
1320 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1321 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1322 		 "%s: unable to retrieve number of handles.",
1323 		 function );
1324 
1325 		result = -1;
1326 	}
1327 	else if( ( internal_pool->number_of_used_handles + 1 ) >= number_of_handles )
1328 	{
1329 		if( libcdata_array_append_entry(
1330 		     internal_pool->handles_array,
1331 		     &safe_entry,
1332 		     (intptr_t *) handle,
1333 		     error ) != 1 )
1334 		{
1335 			libcerror_error_set(
1336 			 error,
1337 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1338 			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1339 			 "%s: unable to append handle.",
1340 			 function );
1341 
1342 			result = -1;
1343 		}
1344 	}
1345 	else
1346 	{
1347 		safe_entry = internal_pool->number_of_used_handles;
1348 
1349 		if( libcdata_array_set_entry_by_index(
1350 		     internal_pool->handles_array,
1351 		     safe_entry,
1352 		     (intptr_t *) handle,
1353 		     error ) != 1 )
1354 		{
1355 			libcerror_error_set(
1356 			 error,
1357 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1358 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1359 			 "%s: unable to set handle: %d.",
1360 			 function,
1361 			 safe_entry );
1362 
1363 			result = -1;
1364 		}
1365 	}
1366 	if( result == 1 )
1367 	{
1368 		internal_pool->number_of_used_handles += 1;
1369 
1370 		if( is_open != 0 )
1371 		{
1372 			if( internal_pool->maximum_number_of_open_handles != LIBBFIO_POOL_UNLIMITED_NUMBER_OF_OPEN_HANDLES )
1373 			{
1374 				if( libbfio_internal_pool_append_handle_to_last_used_list(
1375 				     internal_pool,
1376 				     handle,
1377 				     error ) != 1 )
1378 				{
1379 					libcerror_error_set(
1380 					 error,
1381 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1382 					 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1383 					 "%s: unable to append handle to last used list.",
1384 					 function );
1385 
1386 					result = -1;
1387 				}
1388 			}
1389 		}
1390 	}
1391 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1392 	if( libcthreads_read_write_lock_release_for_write(
1393 	     internal_pool->read_write_lock,
1394 	     error ) != 1 )
1395 	{
1396 		libcerror_error_set(
1397 		 error,
1398 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1399 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1400 		 "%s: unable to release read/write lock for writing.",
1401 		 function );
1402 
1403 		goto on_error;
1404 	}
1405 #endif
1406 	if( result != 1 )
1407 	{
1408 		goto on_error;
1409 	}
1410 	*entry = safe_entry;
1411 
1412 	return( 1 );
1413 
1414 on_error:
1415 	if( safe_entry >= 0 )
1416 	{
1417 		libcdata_array_set_entry_by_index(
1418 		 internal_pool->handles_array,
1419 		 safe_entry,
1420 		 NULL,
1421 		 NULL );
1422 
1423 		internal_pool->number_of_used_handles -= 1;
1424 	}
1425 	return( -1 );
1426 }
1427 
1428 /* Sets a specific handle in the pool
1429  * Returns 1 if successful or -1 on error
1430  */
libbfio_pool_set_handle(libbfio_pool_t * pool,int entry,libbfio_handle_t * handle,int access_flags,libcerror_error_t ** error)1431 int libbfio_pool_set_handle(
1432      libbfio_pool_t *pool,
1433      int entry,
1434      libbfio_handle_t *handle,
1435      int access_flags,
1436      libcerror_error_t **error )
1437 {
1438 	libbfio_internal_handle_t *backup_handle = NULL;
1439 	libbfio_internal_pool_t *internal_pool   = NULL;
1440 	static char *function                    = "libbfio_pool_set_handle";
1441 	int is_open                              = 0;
1442 	int result                               = 1;
1443 
1444 	if( pool == NULL )
1445 	{
1446 		libcerror_error_set(
1447 		 error,
1448 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1449 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1450 		 "%s: invalid pool.",
1451 		 function );
1452 
1453 		return( -1 );
1454 	}
1455 	internal_pool = (libbfio_internal_pool_t *) pool;
1456 
1457 	if( internal_pool->last_used_list == NULL )
1458 	{
1459 		libcerror_error_set(
1460 		 error,
1461 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1462 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1463 		 "%s: invalid pool - missing last used list.",
1464 		 function );
1465 
1466 		return( -1 );
1467 	}
1468 	/* Check if the handle is open
1469 	 */
1470 	is_open = libbfio_handle_is_open(
1471 	           handle,
1472 	           error );
1473 
1474 	if( is_open == -1 )
1475 	{
1476 		libcerror_error_set(
1477 		 error,
1478 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1479 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1480 		 "%s: unable to determine if handle is open.",
1481 		 function );
1482 
1483 		return( -1 );
1484 	}
1485 	else if( is_open == 0 )
1486 	{
1487 		/* Set the access flags is the handle is not open
1488 		 */
1489 		if( libbfio_handle_set_access_flags(
1490 		     handle,
1491 		     access_flags,
1492 		     error ) != 1 )
1493 		{
1494 			libcerror_error_set(
1495 			 error,
1496 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1497 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1498 			 "%s: unable to set access flags.",
1499 			 function );
1500 
1501 			return( -1 );
1502 		}
1503 	}
1504 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1505 	if( libcthreads_read_write_lock_grab_for_write(
1506 	     internal_pool->read_write_lock,
1507 	     error ) != 1 )
1508 	{
1509 		libcerror_error_set(
1510 		 error,
1511 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1512 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1513 		 "%s: unable to grab read/write lock for writing.",
1514 		 function );
1515 
1516 		return( -1 );
1517 	}
1518 #endif
1519 	if( libcdata_array_get_entry_by_index(
1520 	     internal_pool->handles_array,
1521 	     entry,
1522 	     (intptr_t **) &backup_handle,
1523 	     error ) != 1 )
1524 	{
1525 		libcerror_error_set(
1526 		 error,
1527 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1528 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1529 		 "%s: unable to retrieve handle: %d.",
1530 		 function,
1531 		 entry );
1532 
1533 		result = -1;
1534 	}
1535 /* TODO allow to re set handles, make sure all pool references are removed */
1536 	else if( backup_handle != NULL )
1537 	{
1538 		libcerror_error_set(
1539 		 error,
1540 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1541 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1542 		 "%s: invalid handle entry: %d value already set.",
1543 		 function,
1544 		 entry );
1545 
1546 		result = -1;
1547 	}
1548 	else if( libcdata_array_set_entry_by_index(
1549 	          internal_pool->handles_array,
1550 	          entry,
1551 	          (intptr_t *) handle,
1552 	          error ) != 1 )
1553 	{
1554 		libcerror_error_set(
1555 		 error,
1556 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1557 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1558 		 "%s: unable to set handle: %d.",
1559 		 function,
1560 		 entry );
1561 
1562 		result = -1;
1563 	}
1564 	if( result == 1 )
1565 	{
1566 		if( is_open != 0 )
1567 		{
1568 			if( internal_pool->maximum_number_of_open_handles != LIBBFIO_POOL_UNLIMITED_NUMBER_OF_OPEN_HANDLES )
1569 			{
1570 				if( libbfio_internal_pool_append_handle_to_last_used_list(
1571 				     internal_pool,
1572 				     handle,
1573 				     error ) != 1 )
1574 				{
1575 					libcerror_error_set(
1576 					 error,
1577 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1578 					 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1579 					 "%s: unable to append handle to last used list.",
1580 					 function );
1581 
1582 					result = -1;
1583 				}
1584 			}
1585 		}
1586 		if( entry == internal_pool->current_entry )
1587 		{
1588 			internal_pool->current_entry  = -1;
1589 			internal_pool->current_handle = NULL;
1590 		}
1591 	}
1592 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1593 	if( libcthreads_read_write_lock_release_for_write(
1594 	     internal_pool->read_write_lock,
1595 	     error ) != 1 )
1596 	{
1597 		libcerror_error_set(
1598 		 error,
1599 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1600 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1601 		 "%s: unable to release read/write lock for writing.",
1602 		 function );
1603 
1604 		goto on_error;
1605 	}
1606 #endif
1607 	if( result != 1 )
1608 	{
1609 		goto on_error;
1610 	}
1611 	return( result );
1612 
1613 on_error:
1614 	libcdata_array_set_entry_by_index(
1615 	 internal_pool->handles_array,
1616 	 entry,
1617 	 (intptr_t *) backup_handle,
1618 	 NULL );
1619 
1620 	return( -1 );
1621 }
1622 
1623 /* Removes a specific handle from the pool
1624  * Returns 1 if successful or -1 on error
1625  */
libbfio_pool_remove_handle(libbfio_pool_t * pool,int entry,libbfio_handle_t ** handle,libcerror_error_t ** error)1626 int libbfio_pool_remove_handle(
1627      libbfio_pool_t *pool,
1628      int entry,
1629      libbfio_handle_t **handle,
1630      libcerror_error_t **error )
1631 {
1632 	libbfio_handle_t *backup_handle        = NULL;
1633 	libbfio_internal_pool_t *internal_pool = NULL;
1634 	static char *function                  = "libbfio_pool_remove_handle";
1635 	int result                             = 1;
1636 
1637 	if( pool == NULL )
1638 	{
1639 		libcerror_error_set(
1640 		 error,
1641 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1642 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1643 		 "%s: invalid pool.",
1644 		 function );
1645 
1646 		return( -1 );
1647 	}
1648 	internal_pool = (libbfio_internal_pool_t *) pool;
1649 
1650 	if( internal_pool->last_used_list == NULL )
1651 	{
1652 		libcerror_error_set(
1653 		 error,
1654 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1655 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1656 		 "%s: invalid pool - missing last used list.",
1657 		 function );
1658 
1659 		return( -1 );
1660 	}
1661 	if( handle == NULL )
1662 	{
1663 		libcerror_error_set(
1664 		 error,
1665 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1666 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1667 		 "%s: invalid handle.",
1668 		 function );
1669 
1670 		return( -1 );
1671 	}
1672 	*handle = NULL;
1673 
1674 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1675 	if( libcthreads_read_write_lock_grab_for_write(
1676 	     internal_pool->read_write_lock,
1677 	     error ) != 1 )
1678 	{
1679 		libcerror_error_set(
1680 		 error,
1681 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1682 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1683 		 "%s: unable to grab read/write lock for writing.",
1684 		 function );
1685 
1686 		return( -1 );
1687 	}
1688 #endif
1689 	if( libcdata_array_get_entry_by_index(
1690 	     internal_pool->handles_array,
1691 	     entry,
1692 	     (intptr_t **) &backup_handle,
1693 	     error ) != 1 )
1694 	{
1695 		libcerror_error_set(
1696 		 error,
1697 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1698 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1699 		 "%s: unable to retrieve handle: %d.",
1700 		 function,
1701 		 entry );
1702 
1703 		result = -1;
1704 	}
1705 	if( result == 1 )
1706 	{
1707 		if( libbfio_internal_pool_remove_handle_from_last_used_list(
1708 		     internal_pool,
1709 		     backup_handle,
1710 		     error ) != 1 )
1711 		{
1712 			libcerror_error_set(
1713 			 error,
1714 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1715 			 LIBCERROR_RUNTIME_ERROR_REMOVE_FAILED,
1716 			 "%s: unable to remove handle: %d from last used list.",
1717 			 function,
1718 			 entry );
1719 
1720 			result = -1;
1721 		}
1722 	}
1723 	if( result == 1 )
1724 	{
1725 		if( entry == internal_pool->current_entry )
1726 		{
1727 			internal_pool->current_entry  = -1;
1728 			internal_pool->current_handle = NULL;
1729 		}
1730 		if( libcdata_array_set_entry_by_index(
1731 		     internal_pool->handles_array,
1732 		     entry,
1733 		     NULL,
1734 		     error ) != 1 )
1735 		{
1736 			libcerror_error_set(
1737 			 error,
1738 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1739 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1740 			 "%s: unable to set handle: %d.",
1741 			 function,
1742 			 entry );
1743 
1744 			libbfio_internal_pool_append_handle_to_last_used_list(
1745 			 internal_pool,
1746 			 backup_handle,
1747 			 NULL );
1748 
1749 			result = -1;
1750 		}
1751 	}
1752 	if( result == 1 )
1753 	{
1754 		internal_pool->number_of_used_handles -= 1;
1755 	}
1756 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1757 	if( libcthreads_read_write_lock_release_for_write(
1758 	     internal_pool->read_write_lock,
1759 	     error ) != 1 )
1760 	{
1761 		libcerror_error_set(
1762 		 error,
1763 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1764 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1765 		 "%s: unable to release read/write lock for writing.",
1766 		 function );
1767 
1768 		goto on_error;
1769 	}
1770 #endif
1771 	if( result == 1 )
1772 	{
1773 		*handle = backup_handle;
1774 	}
1775 	return( result );
1776 
1777 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1778 on_error:
1779 	if( result == 1 )
1780 	{
1781 		libcdata_array_set_entry_by_index(
1782 		 internal_pool->handles_array,
1783 		  entry,
1784 		  (intptr_t *) backup_handle,
1785 		  NULL );
1786 
1787 		libbfio_internal_pool_append_handle_to_last_used_list(
1788 		 internal_pool,
1789 		 backup_handle,
1790 		 NULL );
1791 
1792 		internal_pool->number_of_used_handles += 1;
1793 	}
1794 	return( -1 );
1795 #endif
1796 }
1797 
1798 /* Retrieves the maximum number of open handles in the pool
1799  * Returns 1 if successful or -1 on error
1800  */
libbfio_pool_get_maximum_number_of_open_handles(libbfio_pool_t * pool,int * maximum_number_of_open_handles,libcerror_error_t ** error)1801 int libbfio_pool_get_maximum_number_of_open_handles(
1802      libbfio_pool_t *pool,
1803      int *maximum_number_of_open_handles,
1804      libcerror_error_t **error )
1805 {
1806 	libbfio_internal_pool_t *internal_pool = NULL;
1807 	static char *function                  = "libbfio_pool_get_maximum_number_of_open_handles";
1808 
1809 	if( pool == NULL )
1810 	{
1811 		libcerror_error_set(
1812 		 error,
1813 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1814 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1815 		 "%s: invalid pool.",
1816 		 function );
1817 
1818 		return( -1 );
1819 	}
1820 	internal_pool = (libbfio_internal_pool_t *) pool;
1821 
1822 	if( maximum_number_of_open_handles == NULL )
1823 	{
1824 		libcerror_error_set(
1825 		 error,
1826 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1827 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1828 		 "%s: invalid maximum number of open handles.",
1829 		 function );
1830 
1831 		return( -1 );
1832 	}
1833 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1834 	if( libcthreads_read_write_lock_grab_for_read(
1835 	     internal_pool->read_write_lock,
1836 	     error ) != 1 )
1837 	{
1838 		libcerror_error_set(
1839 		 error,
1840 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1841 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1842 		 "%s: unable to grab read/write lock for reading.",
1843 		 function );
1844 
1845 		return( -1 );
1846 	}
1847 #endif
1848 	*maximum_number_of_open_handles = internal_pool->maximum_number_of_open_handles;
1849 
1850 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1851 	if( libcthreads_read_write_lock_release_for_read(
1852 	     internal_pool->read_write_lock,
1853 	     error ) != 1 )
1854 	{
1855 		libcerror_error_set(
1856 		 error,
1857 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1858 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1859 		 "%s: unable to release read/write lock for reading.",
1860 		 function );
1861 
1862 		return( -1 );
1863 	}
1864 #endif
1865 	return( 1 );
1866 }
1867 
1868 /* Sets the maximum number of open handles in the pool
1869  * Returns 1 if successful or -1 on error
1870  */
libbfio_pool_set_maximum_number_of_open_handles(libbfio_pool_t * pool,int maximum_number_of_open_handles,libcerror_error_t ** error)1871 int libbfio_pool_set_maximum_number_of_open_handles(
1872      libbfio_pool_t *pool,
1873      int maximum_number_of_open_handles,
1874      libcerror_error_t **error )
1875 {
1876 	libbfio_internal_handle_t *internal_handle      = NULL;
1877 	libbfio_internal_pool_t *internal_pool          = NULL;
1878 	libcdata_list_element_t *last_used_list_element = NULL;
1879 	static char *function                           = "libbfio_pool_set_maximum_number_of_open_handles";
1880 
1881 	if( pool == NULL )
1882 	{
1883 		libcerror_error_set(
1884 		 error,
1885 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1886 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1887 		 "%s: invalid pool.",
1888 		 function );
1889 
1890 		return( -1 );
1891 	}
1892 	internal_pool = (libbfio_internal_pool_t *) pool;
1893 
1894 	if( maximum_number_of_open_handles < 0 )
1895 	{
1896 		libcerror_error_set(
1897 		 error,
1898 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1899 		 LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO,
1900 		 "%s: invalid maximum number of open handles value less than zero.",
1901 		 function );
1902 
1903 		return( -1 );
1904 	}
1905 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
1906 	if( libcthreads_read_write_lock_grab_for_write(
1907 	     internal_pool->read_write_lock,
1908 	     error ) != 1 )
1909 	{
1910 		libcerror_error_set(
1911 		 error,
1912 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1913 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1914 		 "%s: unable to grab read/write lock for writing.",
1915 		 function );
1916 
1917 		return( -1 );
1918 	}
1919 #endif
1920 	internal_pool->maximum_number_of_open_handles = maximum_number_of_open_handles;
1921 
1922 	while( ( internal_pool->maximum_number_of_open_handles != LIBBFIO_POOL_UNLIMITED_NUMBER_OF_OPEN_HANDLES )
1923 	    && ( internal_pool->number_of_open_handles > internal_pool->maximum_number_of_open_handles ) )
1924 	{
1925 		if( libcdata_list_get_last_element(
1926 		     internal_pool->last_used_list,
1927 		     &last_used_list_element,
1928 		     error ) != 1 )
1929 		{
1930 			libcerror_error_set(
1931 			 error,
1932 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1933 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1934 			 "%s: unable to retrieve last list element from last used list.",
1935 			 function );
1936 
1937 			goto on_error;
1938 		}
1939 		if( libcdata_list_element_get_value(
1940 		     last_used_list_element,
1941 		     (intptr_t **) &internal_handle,
1942 		     error ) != 1 )
1943 		{
1944 			libcerror_error_set(
1945 			 error,
1946 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1947 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1948 			 "%s: unable to retrieve value from last used list element.",
1949 			 function );
1950 
1951 			goto on_error;
1952 		}
1953 		if( internal_handle == NULL )
1954 		{
1955 			libcerror_error_set(
1956 			 error,
1957 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1958 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1959 			 "%s: missing last used list element value.",
1960 			 function );
1961 
1962 			goto on_error;
1963 		}
1964 		if( libcdata_list_remove_element(
1965 		     internal_pool->last_used_list,
1966 		     last_used_list_element,
1967 		     error ) != 1 )
1968 		{
1969 			libcerror_error_set(
1970 			 error,
1971 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1972 			 LIBCERROR_RUNTIME_ERROR_REMOVE_FAILED,
1973 			 "%s: unable to remove last used list element from list.",
1974 			 function );
1975 
1976 			goto on_error;
1977 		}
1978 		if( libbfio_handle_close(
1979 		     (libbfio_handle_t *) internal_handle,
1980 		     error ) != 0 )
1981 		{
1982 			libcerror_error_set(
1983 			 error,
1984 			 LIBCERROR_ERROR_DOMAIN_IO,
1985 			 LIBCERROR_IO_ERROR_CLOSE_FAILED,
1986 			 "%s: unable to close handle.",
1987 			 function );
1988 
1989 			goto on_error;
1990 		}
1991 		internal_pool->number_of_open_handles--;
1992 
1993 		internal_handle->pool_last_used_list_element = NULL;
1994 
1995 		/* Make sure the truncate flag is removed from the handle
1996 		 */
1997 		internal_handle->access_flags &= ~( LIBBFIO_ACCESS_FLAG_TRUNCATE );
1998 
1999 		if( libcdata_list_element_free(
2000 		     &last_used_list_element,
2001 		     NULL,
2002 		     error ) != 1 )
2003 		{
2004 			libcerror_error_set(
2005 			 error,
2006 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2007 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2008 			 "%s: unable to free last used list element.",
2009 			 function );
2010 
2011 			goto on_error;
2012 		}
2013 	}
2014 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2015 	if( libcthreads_read_write_lock_release_for_write(
2016 	     internal_pool->read_write_lock,
2017 	     error ) != 1 )
2018 	{
2019 		libcerror_error_set(
2020 		 error,
2021 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2022 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2023 		 "%s: unable to release read/write lock for writing.",
2024 		 function );
2025 
2026 		return( -1 );
2027 	}
2028 #endif
2029 	return( 1 );
2030 
2031 on_error:
2032 	if( last_used_list_element != NULL )
2033 	{
2034 		libcdata_list_element_free(
2035 		 &last_used_list_element,
2036 		 NULL,
2037 		 NULL );
2038 	}
2039 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2040 	libcthreads_read_write_lock_release_for_write(
2041 	 internal_pool->read_write_lock,
2042 	 NULL );
2043 #endif
2044 	return( -1 );
2045 }
2046 
2047 /* Opens a handle in the pool
2048  * Returns 1 if successful or -1 on error
2049  */
libbfio_internal_pool_open(libbfio_internal_pool_t * internal_pool,int entry,int access_flags,libcerror_error_t ** error)2050 int libbfio_internal_pool_open(
2051      libbfio_internal_pool_t *internal_pool,
2052      int entry,
2053      int access_flags,
2054      libcerror_error_t **error )
2055 {
2056 	libbfio_handle_t *handle = NULL;
2057 	static char *function    = "libbfio_internal_pool_open";
2058 	int is_open              = 0;
2059 
2060 	if( internal_pool == NULL )
2061 	{
2062 		libcerror_error_set(
2063 		 error,
2064 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2065 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2066 		 "%s: invalid pool.",
2067 		 function );
2068 
2069 		return( -1 );
2070 	}
2071 	if( libcdata_array_get_entry_by_index(
2072 	     internal_pool->handles_array,
2073 	     entry,
2074 	     (intptr_t **) &handle,
2075 	     error ) != 1 )
2076 	{
2077 		libcerror_error_set(
2078 		 error,
2079 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2080 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2081 		 "%s: unable to retrieve handle: %d.",
2082 		 function,
2083 		 entry );
2084 
2085 		return( -1 );
2086 	}
2087 	/* Make sure the handle is not already open
2088 	 */
2089 	is_open = libbfio_handle_is_open(
2090 	           handle,
2091 	           error );
2092 
2093 	if( is_open == -1 )
2094 	{
2095 		libcerror_error_set(
2096 		 error,
2097 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2098 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2099 		 "%s: unable to determine if entry: %d is open.",
2100 		 function,
2101 	         entry );
2102 
2103 		return( -1 );
2104 	}
2105 	else if( is_open == 1 )
2106 	{
2107 		libcerror_error_set(
2108 		 error,
2109 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2110 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2111 		 "%s: entry: %d is already open.",
2112 		 function,
2113 	         entry );
2114 
2115 		return( -1 );
2116 	}
2117 	if( libbfio_internal_pool_open_handle(
2118 	     internal_pool,
2119 	     handle,
2120 	     access_flags,
2121 	     error ) != 1 )
2122 	{
2123 		libcerror_error_set(
2124 		 error,
2125 		 LIBCERROR_ERROR_DOMAIN_IO,
2126 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
2127 		 "%s: unable to open entry: %d.",
2128 		 function,
2129 		 entry );
2130 
2131 		return( -1 );
2132 	}
2133 	internal_pool->current_entry  = entry;
2134 	internal_pool->current_handle = handle;
2135 
2136 	return( 1 );
2137 }
2138 
2139 /* Opens a handle in the pool
2140  * Returns 1 if successful or -1 on error
2141  */
libbfio_pool_open(libbfio_pool_t * pool,int entry,int access_flags,libcerror_error_t ** error)2142 int libbfio_pool_open(
2143      libbfio_pool_t *pool,
2144      int entry,
2145      int access_flags,
2146      libcerror_error_t **error )
2147 {
2148 	libbfio_internal_pool_t *internal_pool = NULL;
2149 	static char *function                  = "libbfio_pool_open";
2150 	int result                             = 1;
2151 
2152 	if( pool == NULL )
2153 	{
2154 		libcerror_error_set(
2155 		 error,
2156 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2157 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2158 		 "%s: invalid pool.",
2159 		 function );
2160 
2161 		return( -1 );
2162 	}
2163 	internal_pool = (libbfio_internal_pool_t *) pool;
2164 
2165 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2166 	if( libcthreads_read_write_lock_grab_for_write(
2167 	     internal_pool->read_write_lock,
2168 	     error ) != 1 )
2169 	{
2170 		libcerror_error_set(
2171 		 error,
2172 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2173 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2174 		 "%s: unable to grab read/write lock for writing.",
2175 		 function );
2176 
2177 		return( -1 );
2178 	}
2179 #endif
2180 	if( libbfio_internal_pool_open(
2181 	     internal_pool,
2182 	     entry,
2183 	     access_flags,
2184 	     error ) != 1 )
2185 	{
2186 		libcerror_error_set(
2187 		 error,
2188 		 LIBCERROR_ERROR_DOMAIN_IO,
2189 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
2190 		 "%s: unable to open entry: %d.",
2191 		 function,
2192 		 entry );
2193 
2194 		result = -1;
2195 	}
2196 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2197 	if( libcthreads_read_write_lock_release_for_write(
2198 	     internal_pool->read_write_lock,
2199 	     error ) != 1 )
2200 	{
2201 		libcerror_error_set(
2202 		 error,
2203 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2204 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2205 		 "%s: unable to release read/write lock for writing.",
2206 		 function );
2207 
2208 		return( -1 );
2209 	}
2210 #endif
2211 	return( result );
2212 }
2213 
2214 /* Reopens a handle in the pool
2215  * Returns 1 if successful or -1 on error
2216  */
libbfio_pool_reopen(libbfio_pool_t * pool,int entry,int access_flags,libcerror_error_t ** error)2217 int libbfio_pool_reopen(
2218      libbfio_pool_t *pool,
2219      int entry,
2220      int access_flags,
2221      libcerror_error_t **error )
2222 {
2223 	libbfio_handle_t *handle               = NULL;
2224 	libbfio_internal_pool_t *internal_pool = NULL;
2225 	static char *function                  = "libbfio_pool_reopen";
2226 
2227 	if( pool == NULL )
2228 	{
2229 		libcerror_error_set(
2230 		 error,
2231 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2232 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2233 		 "%s: invalid pool.",
2234 		 function );
2235 
2236 		return( -1 );
2237 	}
2238 	internal_pool = (libbfio_internal_pool_t *) pool;
2239 
2240 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2241 	if( libcthreads_read_write_lock_grab_for_write(
2242 	     internal_pool->read_write_lock,
2243 	     error ) != 1 )
2244 	{
2245 		libcerror_error_set(
2246 		 error,
2247 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2248 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2249 		 "%s: unable to grab read/write lock for writing.",
2250 		 function );
2251 
2252 		return( -1 );
2253 	}
2254 #endif
2255 	if( libcdata_array_get_entry_by_index(
2256 	     internal_pool->handles_array,
2257 	     entry,
2258 	     (intptr_t **) &handle,
2259 	     error ) != 1 )
2260 	{
2261 		libcerror_error_set(
2262 		 error,
2263 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2264 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2265 		 "%s: unable to retrieve handle: %d.",
2266 		 function,
2267 		 entry );
2268 
2269 		goto on_error;
2270 	}
2271 	if( libbfio_handle_reopen(
2272 	     handle,
2273 	     access_flags,
2274 	     error ) != 1 )
2275 	{
2276 		libcerror_error_set(
2277 		 error,
2278 		 LIBCERROR_ERROR_DOMAIN_IO,
2279 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
2280 		 "%s: unable to reopen handle for entry: %d.",
2281 		 function,
2282 		 entry );
2283 
2284 		goto on_error;
2285 	}
2286 	internal_pool->current_entry  = entry;
2287 	internal_pool->current_handle = handle;
2288 
2289 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2290 	if( libcthreads_read_write_lock_release_for_write(
2291 	     internal_pool->read_write_lock,
2292 	     error ) != 1 )
2293 	{
2294 		libcerror_error_set(
2295 		 error,
2296 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2297 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2298 		 "%s: unable to release read/write lock for writing.",
2299 		 function );
2300 
2301 		return( -1 );
2302 	}
2303 #endif
2304 	return( 1 );
2305 
2306 on_error:
2307 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2308 	libcthreads_read_write_lock_release_for_write(
2309 	 internal_pool->read_write_lock,
2310 	 NULL );
2311 #endif
2312 	return( -1 );
2313 }
2314 
2315 /* Closes a handle in the pool
2316  * Returns 0 if successful or -1 on error
2317  */
libbfio_internal_pool_close(libbfio_internal_pool_t * internal_pool,int entry,libcerror_error_t ** error)2318 int libbfio_internal_pool_close(
2319      libbfio_internal_pool_t *internal_pool,
2320      int entry,
2321      libcerror_error_t **error )
2322 {
2323 	libbfio_handle_t *handle                        = NULL;
2324 	libbfio_internal_handle_t *internal_handle      = NULL;
2325 	libcdata_list_element_t *last_used_list_element = NULL;
2326 	static char *function                           = "libbfio_internal_pool_close";
2327 
2328 	if( internal_pool == NULL )
2329 	{
2330 		libcerror_error_set(
2331 		 error,
2332 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2333 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2334 		 "%s: invalid pool.",
2335 		 function );
2336 
2337 		return( -1 );
2338 	}
2339 	if( libcdata_array_get_entry_by_index(
2340 	     internal_pool->handles_array,
2341 	     entry,
2342 	     (intptr_t **) &handle,
2343 	     error ) != 1 )
2344 	{
2345 		libcerror_error_set(
2346 		 error,
2347 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2348 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2349 		 "%s: unable to retrieve handle: %d.",
2350 		 function,
2351 		 entry );
2352 
2353 		goto on_error;
2354 	}
2355 	if( handle == NULL )
2356 	{
2357 		libcerror_error_set(
2358 		 error,
2359 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2360 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2361 		 "%s: invalid pool - missing handle for entry: %d.",
2362 		 function,
2363 		 entry );
2364 
2365 		goto on_error;
2366 	}
2367 	if( internal_pool->maximum_number_of_open_handles != LIBBFIO_POOL_UNLIMITED_NUMBER_OF_OPEN_HANDLES )
2368 	{
2369 /* TODO move into get function */
2370 		internal_handle = (libbfio_internal_handle_t *) handle;
2371 
2372 		last_used_list_element = internal_handle->pool_last_used_list_element;
2373 
2374 		if( libcdata_list_element_get_value(
2375 		     last_used_list_element,
2376 		     (intptr_t **) &internal_handle,
2377 		     error ) != 1 )
2378 		{
2379 			libcerror_error_set(
2380 			 error,
2381 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2382 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2383 			 "%s: unable to retrieve value from last used list element.",
2384 			 function );
2385 
2386 			goto on_error;
2387 		}
2388 		if( internal_handle == NULL )
2389 		{
2390 			libcerror_error_set(
2391 			 error,
2392 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2393 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2394 			 "%s: missing last used list element value.",
2395 			 function );
2396 
2397 			goto on_error;
2398 		}
2399 		if( libcdata_list_remove_element(
2400 		     internal_pool->last_used_list,
2401 		     last_used_list_element,
2402 		     error ) != 1 )
2403 		{
2404 			libcerror_error_set(
2405 			 error,
2406 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2407 			 LIBCERROR_RUNTIME_ERROR_REMOVE_FAILED,
2408 			 "%s: unable to remove last used list element from list.",
2409 			 function );
2410 
2411 			goto on_error;
2412 		}
2413 		internal_handle->pool_last_used_list_element = NULL;
2414 
2415 		if( libcdata_list_element_free(
2416 		     &last_used_list_element,
2417 		     NULL,
2418 		     error ) != 1 )
2419 		{
2420 			libcerror_error_set(
2421 			 error,
2422 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2423 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2424 			 "%s: unable to free last used list element.",
2425 			 function );
2426 
2427 			goto on_error;
2428 		}
2429 	}
2430 	if( libbfio_handle_close(
2431 	     handle,
2432 	     error ) != 0 )
2433 	{
2434 		libcerror_error_set(
2435 		 error,
2436 		 LIBCERROR_ERROR_DOMAIN_IO,
2437 		 LIBCERROR_IO_ERROR_CLOSE_FAILED,
2438 		 "%s: unable to close handle for entry: %d.",
2439 		 function,
2440 		 entry );
2441 
2442 		goto on_error;
2443 	}
2444 	if( entry == internal_pool->current_entry )
2445 	{
2446 		internal_pool->current_entry  = -1;
2447 		internal_pool->current_handle = NULL;
2448 	}
2449 	return( 0 );
2450 
2451 on_error:
2452 	if( last_used_list_element != NULL )
2453 	{
2454 		libcdata_list_element_free(
2455 		 &last_used_list_element,
2456 		 NULL,
2457 		 NULL );
2458 	}
2459 	return( -1 );
2460 }
2461 
2462 /* Closes a handle in the pool
2463  * Returns 0 if successful or -1 on error
2464  */
libbfio_pool_close(libbfio_pool_t * pool,int entry,libcerror_error_t ** error)2465 int libbfio_pool_close(
2466      libbfio_pool_t *pool,
2467      int entry,
2468      libcerror_error_t **error )
2469 {
2470 	libbfio_internal_pool_t *internal_pool = NULL;
2471 	static char *function                  = "libbfio_pool_close";
2472 	int result                             = 0;
2473 
2474 	if( pool == NULL )
2475 	{
2476 		libcerror_error_set(
2477 		 error,
2478 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2479 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2480 		 "%s: invalid pool.",
2481 		 function );
2482 
2483 		return( -1 );
2484 	}
2485 	internal_pool = (libbfio_internal_pool_t *) pool;
2486 
2487 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2488 	if( libcthreads_read_write_lock_grab_for_write(
2489 	     internal_pool->read_write_lock,
2490 	     error ) != 1 )
2491 	{
2492 		libcerror_error_set(
2493 		 error,
2494 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2495 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2496 		 "%s: unable to grab read/write lock for writing.",
2497 		 function );
2498 
2499 		return( -1 );
2500 	}
2501 #endif
2502 	if( libbfio_internal_pool_close(
2503 	     internal_pool,
2504 	     entry,
2505 	     error ) != 0 )
2506 	{
2507 		libcerror_error_set(
2508 		 error,
2509 		 LIBCERROR_ERROR_DOMAIN_IO,
2510 		 LIBCERROR_IO_ERROR_CLOSE_FAILED,
2511 		 "%s: unable to close handle: %d.",
2512 		 function,
2513 		 entry );
2514 
2515 		result = -1;
2516 	}
2517 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2518 	if( libcthreads_read_write_lock_release_for_write(
2519 	     internal_pool->read_write_lock,
2520 	     error ) != 1 )
2521 	{
2522 		libcerror_error_set(
2523 		 error,
2524 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2525 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2526 		 "%s: unable to release read/write lock for writing.",
2527 		 function );
2528 
2529 		return( -1 );
2530 	}
2531 #endif
2532 	return( result );
2533 }
2534 
2535 /* Closes all the files in the pool
2536  * Returns 0 if successful or -1 on error
2537  */
libbfio_pool_close_all(libbfio_pool_t * pool,libcerror_error_t ** error)2538 int libbfio_pool_close_all(
2539      libbfio_pool_t *pool,
2540      libcerror_error_t **error )
2541 {
2542 	libbfio_handle_t *handle               = NULL;
2543 	libbfio_internal_pool_t *internal_pool = NULL;
2544 	static char *function                  = "libbfio_pool_close_all";
2545 	int entry                              = 0;
2546 	int is_open                            = 0;
2547 	int number_of_handles                  = 0;
2548 
2549 	if( pool == NULL )
2550 	{
2551 		libcerror_error_set(
2552 		 error,
2553 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2554 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2555 		 "%s: invalid pool.",
2556 		 function );
2557 
2558 		return( -1 );
2559 	}
2560 	internal_pool = (libbfio_internal_pool_t *) pool;
2561 
2562 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2563 	if( libcthreads_read_write_lock_grab_for_write(
2564 	     internal_pool->read_write_lock,
2565 	     error ) != 1 )
2566 	{
2567 		libcerror_error_set(
2568 		 error,
2569 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2570 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2571 		 "%s: unable to grab read/write lock for writing.",
2572 		 function );
2573 
2574 		return( -1 );
2575 	}
2576 #endif
2577 	if( libcdata_array_get_number_of_entries(
2578 	     internal_pool->handles_array,
2579 	     &number_of_handles,
2580 	     error ) != 1 )
2581 	{
2582 		libcerror_error_set(
2583 		 error,
2584 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2585 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2586 		 "%s: unable to retrieve number of handles.",
2587 		 function );
2588 
2589 		goto on_error;
2590 	}
2591 	for( entry = 0;
2592 	     entry < number_of_handles;
2593 	     entry++ )
2594 	{
2595 		if( libcdata_array_get_entry_by_index(
2596 		     internal_pool->handles_array,
2597 		     entry,
2598 		     (intptr_t **) &handle,
2599 		     error ) != 1 )
2600 		{
2601 			libcerror_error_set(
2602 			 error,
2603 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2604 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2605 			 "%s: unable to retrieve handle: %d.",
2606 			 function,
2607 			 entry );
2608 
2609 			goto on_error;
2610 		}
2611 		if( handle == NULL )
2612 		{
2613 			continue;
2614 		}
2615 		/* Make sure the handle is open
2616 		 */
2617 		is_open = libbfio_handle_is_open(
2618 			   handle,
2619 			   error );
2620 
2621 		if( is_open == -1 )
2622 		{
2623 			libcerror_error_set(
2624 			 error,
2625 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2626 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2627 			 "%s: unable to determine if handle: %d is open.",
2628 			 function,
2629 			 entry );
2630 
2631 			goto on_error;
2632 		}
2633 		else if( is_open == 0 )
2634 		{
2635 			continue;
2636 		}
2637 		if( libbfio_internal_pool_close(
2638 		     internal_pool,
2639 		     entry,
2640 		     error ) != 0 )
2641 		{
2642 			libcerror_error_set(
2643 			 error,
2644 			 LIBCERROR_ERROR_DOMAIN_IO,
2645 			 LIBCERROR_IO_ERROR_CLOSE_FAILED,
2646 			 "%s: unable to close handle: %d.",
2647 			 function,
2648 			 entry );
2649 
2650 			goto on_error;
2651 		}
2652 	}
2653 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2654 	if( libcthreads_read_write_lock_release_for_write(
2655 	     internal_pool->read_write_lock,
2656 	     error ) != 1 )
2657 	{
2658 		libcerror_error_set(
2659 		 error,
2660 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2661 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2662 		 "%s: unable to release read/write lock for writing.",
2663 		 function );
2664 
2665 		return( -1 );
2666 	}
2667 #endif
2668 	return( 0 );
2669 
2670 on_error:
2671 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2672 	libcthreads_read_write_lock_release_for_write(
2673 	 internal_pool->read_write_lock,
2674 	 NULL );
2675 #endif
2676 	return( -1 );
2677 }
2678 
2679 /* Retrieves a specific handle from the pool and opens it if needed
2680  * Returns 1 if successful or -1 on error
2681  */
libbfio_internal_pool_get_open_handle(libbfio_internal_pool_t * internal_pool,int entry,libbfio_handle_t ** handle,libcerror_error_t ** error)2682 int libbfio_internal_pool_get_open_handle(
2683      libbfio_internal_pool_t *internal_pool,
2684      int entry,
2685      libbfio_handle_t **handle,
2686      libcerror_error_t **error )
2687 {
2688 	libbfio_handle_t *safe_handle = NULL;
2689 	static char *function         = "libbfio_internal_pool_get_open_handle";
2690 	int access_flags              = 0;
2691 	int is_open                   = 0;
2692 
2693 	if( internal_pool == NULL )
2694 	{
2695 		libcerror_error_set(
2696 		 error,
2697 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2698 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2699 		 "%s: invalid pool.",
2700 		 function );
2701 
2702 		return( -1 );
2703 	}
2704 	if( handle == NULL )
2705 	{
2706 		libcerror_error_set(
2707 		 error,
2708 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2709 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2710 		 "%s: invalid handle.",
2711 		 function );
2712 
2713 		return( -1 );
2714 	}
2715 	if( entry != internal_pool->current_entry )
2716 	{
2717 		if( libcdata_array_get_entry_by_index(
2718 		     internal_pool->handles_array,
2719 		     entry,
2720 		     (intptr_t **) &safe_handle,
2721 		     error ) != 1 )
2722 		{
2723 			libcerror_error_set(
2724 			 error,
2725 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2726 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2727 			 "%s: unable to retrieve handle: %d.",
2728 			 function,
2729 			 entry );
2730 
2731 			return( -1 );
2732 		}
2733 		/* Make sure the handle is open
2734 		 */
2735 		is_open = libbfio_handle_is_open(
2736 		           safe_handle,
2737 		           error );
2738 
2739 		if( is_open == -1 )
2740 		{
2741 			libcerror_error_set(
2742 			 error,
2743 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2744 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2745 			 "%s: unable to determine if entry: %d is open.",
2746 			 function,
2747 			 entry );
2748 
2749 			return( -1 );
2750 		}
2751 		else if( is_open == 0 )
2752 		{
2753 			if( libbfio_handle_get_access_flags(
2754 			     safe_handle,
2755 			     &access_flags,
2756 			     error ) != 1 )
2757 			{
2758 				libcerror_error_set(
2759 				 error,
2760 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2761 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2762 				 "%s: unable to retrieve access flags.",
2763 				 function );
2764 
2765 				return( -1 );
2766 			}
2767 			if( libbfio_internal_pool_open_handle(
2768 			     internal_pool,
2769 			     safe_handle,
2770 			     access_flags,
2771 			     error ) != 1 )
2772 			{
2773 				libcerror_error_set(
2774 				 error,
2775 				 LIBCERROR_ERROR_DOMAIN_IO,
2776 				 LIBCERROR_IO_ERROR_OPEN_FAILED,
2777 				 "%s: unable to open entry: %d.",
2778 				 function,
2779 				 entry );
2780 
2781 				return( -1 );
2782 			}
2783 		}
2784 		if( internal_pool->maximum_number_of_open_handles != LIBBFIO_POOL_UNLIMITED_NUMBER_OF_OPEN_HANDLES )
2785 		{
2786 			if( libbfio_internal_pool_move_handle_to_front_of_last_used_list(
2787 			     internal_pool,
2788 			     safe_handle,
2789 			     error ) != 1 )
2790 			{
2791 				libcerror_error_set(
2792 				 error,
2793 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2794 				 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2795 				 "%s: unable to move handle to front of last used list.",
2796 				 function );
2797 
2798 				return( -1 );
2799 			}
2800 		}
2801 		internal_pool->current_entry  = entry;
2802 		internal_pool->current_handle = safe_handle;
2803 	}
2804 	*handle = internal_pool->current_handle;
2805 
2806 	return( 1 );
2807 }
2808 
2809 /* Reads data at the current offset into the buffer
2810  * Returns the number of bytes read or -1 on error
2811  */
libbfio_pool_read_buffer(libbfio_pool_t * pool,int entry,uint8_t * buffer,size_t size,libcerror_error_t ** error)2812 ssize_t libbfio_pool_read_buffer(
2813          libbfio_pool_t *pool,
2814          int entry,
2815          uint8_t *buffer,
2816          size_t size,
2817          libcerror_error_t **error )
2818 {
2819 	libbfio_handle_t *handle               = NULL;
2820 	libbfio_internal_pool_t *internal_pool = NULL;
2821 	static char *function                  = "libbfio_pool_read_buffer";
2822 	ssize_t read_count                     = 0;
2823 
2824 	if( pool == NULL )
2825 	{
2826 		libcerror_error_set(
2827 		 error,
2828 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2829 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2830 		 "%s: invalid pool.",
2831 		 function );
2832 
2833 		return( -1 );
2834 	}
2835 	internal_pool = (libbfio_internal_pool_t *) pool;
2836 
2837 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2838 	if( libcthreads_read_write_lock_grab_for_write(
2839 	     internal_pool->read_write_lock,
2840 	     error ) != 1 )
2841 	{
2842 		libcerror_error_set(
2843 		 error,
2844 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2845 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2846 		 "%s: unable to grab read/write lock for writing.",
2847 		 function );
2848 
2849 		return( -1 );
2850 	}
2851 #endif
2852 	if( libbfio_internal_pool_get_open_handle(
2853 	     internal_pool,
2854 	     entry,
2855 	     &handle,
2856 	     error ) != 1 )
2857 	{
2858 		libcerror_error_set(
2859 		 error,
2860 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2861 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2862 		 "%s: unable to retrieve handle: %d.",
2863 		 function,
2864 		 entry );
2865 
2866 		read_count = -1;
2867 	}
2868 	else
2869 	{
2870 		read_count = libbfio_handle_read_buffer(
2871 		              handle,
2872 		              buffer,
2873 		              size,
2874 		              error );
2875 
2876 		if( read_count < 0 )
2877 		{
2878 			libcerror_error_set(
2879 			 error,
2880 			 LIBCERROR_ERROR_DOMAIN_IO,
2881 			 LIBCERROR_IO_ERROR_READ_FAILED,
2882 			 "%s: unable to read from entry: %d.",
2883 			 function,
2884 			 entry );
2885 
2886 			read_count = -1;
2887 		}
2888 	}
2889 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2890 	if( libcthreads_read_write_lock_release_for_write(
2891 	     internal_pool->read_write_lock,
2892 	     error ) != 1 )
2893 	{
2894 		libcerror_error_set(
2895 		 error,
2896 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2897 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2898 		 "%s: unable to release read/write lock for writing.",
2899 		 function );
2900 
2901 		return( -1 );
2902 	}
2903 #endif
2904 	return( read_count );
2905 }
2906 
2907 /* Reads data at a specific offset into the buffer
2908  * Returns the number of bytes read or -1 on error
2909  */
libbfio_pool_read_buffer_at_offset(libbfio_pool_t * pool,int entry,uint8_t * buffer,size_t size,off64_t offset,libcerror_error_t ** error)2910 ssize_t libbfio_pool_read_buffer_at_offset(
2911          libbfio_pool_t *pool,
2912          int entry,
2913          uint8_t *buffer,
2914          size_t size,
2915          off64_t offset,
2916          libcerror_error_t **error )
2917 {
2918 	libbfio_handle_t *handle               = NULL;
2919 	libbfio_internal_pool_t *internal_pool = NULL;
2920 	static char *function                  = "libbfio_pool_read_buffer_at_offset";
2921 	ssize_t read_count                     = 0;
2922 
2923 	if( pool == NULL )
2924 	{
2925 		libcerror_error_set(
2926 		 error,
2927 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2928 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2929 		 "%s: invalid pool.",
2930 		 function );
2931 
2932 		return( -1 );
2933 	}
2934 	internal_pool = (libbfio_internal_pool_t *) pool;
2935 
2936 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2937 	if( libcthreads_read_write_lock_grab_for_write(
2938 	     internal_pool->read_write_lock,
2939 	     error ) != 1 )
2940 	{
2941 		libcerror_error_set(
2942 		 error,
2943 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2944 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2945 		 "%s: unable to grab read/write lock for writing.",
2946 		 function );
2947 
2948 		return( -1 );
2949 	}
2950 #endif
2951 	if( libbfio_internal_pool_get_open_handle(
2952 	     internal_pool,
2953 	     entry,
2954 	     &handle,
2955 	     error ) != 1 )
2956 	{
2957 		libcerror_error_set(
2958 		 error,
2959 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2960 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2961 		 "%s: unable to retrieve handle: %d.",
2962 		 function,
2963 		 entry );
2964 
2965 		read_count = -1;
2966 	}
2967 	else
2968 	{
2969 		read_count = libbfio_handle_read_buffer_at_offset(
2970 		              handle,
2971 		              buffer,
2972 		              size,
2973 		              offset,
2974 		              error );
2975 
2976 		if( read_count < 0 )
2977 		{
2978 			libcerror_error_set(
2979 			 error,
2980 			 LIBCERROR_ERROR_DOMAIN_IO,
2981 			 LIBCERROR_IO_ERROR_READ_FAILED,
2982 			 "%s: unable to read from entry: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2983 			 function,
2984 			 entry,
2985 			 offset,
2986 			 offset );
2987 
2988 			read_count = -1;
2989 		}
2990 	}
2991 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
2992 	if( libcthreads_read_write_lock_release_for_write(
2993 	     internal_pool->read_write_lock,
2994 	     error ) != 1 )
2995 	{
2996 		libcerror_error_set(
2997 		 error,
2998 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2999 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3000 		 "%s: unable to release read/write lock for writing.",
3001 		 function );
3002 
3003 		return( -1 );
3004 	}
3005 #endif
3006 	return( read_count );
3007 }
3008 
3009 /* Writes data at the current offset from the buffer
3010  * Returns the number of bytes written or -1 on error
3011  */
libbfio_pool_write_buffer(libbfio_pool_t * pool,int entry,const uint8_t * buffer,size_t size,libcerror_error_t ** error)3012 ssize_t libbfio_pool_write_buffer(
3013          libbfio_pool_t *pool,
3014          int entry,
3015          const uint8_t *buffer,
3016          size_t size,
3017          libcerror_error_t **error )
3018 {
3019 	libbfio_handle_t *handle               = NULL;
3020 	libbfio_internal_pool_t *internal_pool = NULL;
3021 	static char *function                  = "libbfio_pool_write_buffer";
3022 	ssize_t write_count                    = 0;
3023 
3024 	if( pool == NULL )
3025 	{
3026 		libcerror_error_set(
3027 		 error,
3028 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3029 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3030 		 "%s: invalid pool.",
3031 		 function );
3032 
3033 		return( -1 );
3034 	}
3035 	internal_pool = (libbfio_internal_pool_t *) pool;
3036 
3037 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
3038 	if( libcthreads_read_write_lock_grab_for_write(
3039 	     internal_pool->read_write_lock,
3040 	     error ) != 1 )
3041 	{
3042 		libcerror_error_set(
3043 		 error,
3044 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3045 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3046 		 "%s: unable to grab read/write lock for writing.",
3047 		 function );
3048 
3049 		return( -1 );
3050 	}
3051 #endif
3052 	if( libbfio_internal_pool_get_open_handle(
3053 	     internal_pool,
3054 	     entry,
3055 	     &handle,
3056 	     error ) != 1 )
3057 	{
3058 		libcerror_error_set(
3059 		 error,
3060 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3061 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3062 		 "%s: unable to retrieve handle: %d.",
3063 		 function,
3064 		 entry );
3065 
3066 		write_count = -1;
3067 	}
3068 	else
3069 	{
3070 		write_count = libbfio_handle_write_buffer(
3071 		               handle,
3072 		               buffer,
3073 		               size,
3074 		               error );
3075 
3076 		if( write_count < 0 )
3077 		{
3078 			libcerror_error_set(
3079 			 error,
3080 			 LIBCERROR_ERROR_DOMAIN_IO,
3081 			 LIBCERROR_IO_ERROR_WRITE_FAILED,
3082 			 "%s: unable to write to entry: %d.",
3083 			 function,
3084 			 entry );
3085 
3086 			write_count = -1;
3087 		}
3088 	}
3089 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
3090 	if( libcthreads_read_write_lock_release_for_write(
3091 	     internal_pool->read_write_lock,
3092 	     error ) != 1 )
3093 	{
3094 		libcerror_error_set(
3095 		 error,
3096 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3097 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3098 		 "%s: unable to release read/write lock for writing.",
3099 		 function );
3100 
3101 		return( -1 );
3102 	}
3103 #endif
3104 	return( write_count );
3105 }
3106 
3107 /* Writes data at a specific offset from the buffer
3108  * Returns the number of bytes written or -1 on error
3109  */
libbfio_pool_write_buffer_at_offset(libbfio_pool_t * pool,int entry,const uint8_t * buffer,size_t size,off64_t offset,libcerror_error_t ** error)3110 ssize_t libbfio_pool_write_buffer_at_offset(
3111          libbfio_pool_t *pool,
3112          int entry,
3113          const uint8_t *buffer,
3114          size_t size,
3115          off64_t offset,
3116          libcerror_error_t **error )
3117 {
3118 	libbfio_handle_t *handle               = NULL;
3119 	libbfio_internal_pool_t *internal_pool = NULL;
3120 	static char *function                  = "libbfio_pool_write_buffer_at_offset";
3121 	ssize_t write_count                    = 0;
3122 
3123 	if( pool == NULL )
3124 	{
3125 		libcerror_error_set(
3126 		 error,
3127 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3128 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3129 		 "%s: invalid pool.",
3130 		 function );
3131 
3132 		return( -1 );
3133 	}
3134 	internal_pool = (libbfio_internal_pool_t *) pool;
3135 
3136 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
3137 	if( libcthreads_read_write_lock_grab_for_write(
3138 	     internal_pool->read_write_lock,
3139 	     error ) != 1 )
3140 	{
3141 		libcerror_error_set(
3142 		 error,
3143 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3144 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3145 		 "%s: unable to grab read/write lock for writing.",
3146 		 function );
3147 
3148 		return( -1 );
3149 	}
3150 #endif
3151 	if( libbfio_internal_pool_get_open_handle(
3152 	     internal_pool,
3153 	     entry,
3154 	     &handle,
3155 	     error ) != 1 )
3156 	{
3157 		libcerror_error_set(
3158 		 error,
3159 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3160 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3161 		 "%s: unable to retrieve handle: %d.",
3162 		 function,
3163 		 entry );
3164 
3165 		write_count = -1;
3166 	}
3167 	else
3168 	{
3169 		write_count = libbfio_handle_write_buffer_at_offset(
3170 		               handle,
3171 		               buffer,
3172 		               size,
3173 		               offset,
3174 		               error );
3175 
3176 		if( write_count < 0 )
3177 		{
3178 			libcerror_error_set(
3179 			 error,
3180 			 LIBCERROR_ERROR_DOMAIN_IO,
3181 			 LIBCERROR_IO_ERROR_WRITE_FAILED,
3182 			 "%s: unable to write to entry: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
3183 			 function,
3184 			 entry,
3185 			 offset,
3186 			 offset );
3187 
3188 			write_count = -1;
3189 		}
3190 	}
3191 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
3192 	if( libcthreads_read_write_lock_release_for_write(
3193 	     internal_pool->read_write_lock,
3194 	     error ) != 1 )
3195 	{
3196 		libcerror_error_set(
3197 		 error,
3198 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3199 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3200 		 "%s: unable to release read/write lock for writing.",
3201 		 function );
3202 
3203 		return( -1 );
3204 	}
3205 #endif
3206 	return( write_count );
3207 }
3208 
3209 /* Seeks an offset in a handle in the pool
3210  * Returns the offset if successful or -1 on error
3211  */
libbfio_pool_seek_offset(libbfio_pool_t * pool,int entry,off64_t offset,int whence,libcerror_error_t ** error)3212 off64_t libbfio_pool_seek_offset(
3213          libbfio_pool_t *pool,
3214          int entry,
3215          off64_t offset,
3216          int whence,
3217          libcerror_error_t **error )
3218 {
3219 	libbfio_handle_t *handle               = NULL;
3220 	libbfio_internal_pool_t *internal_pool = NULL;
3221 	static char *function                  = "libbfio_pool_seek_offset";
3222 
3223 	if( pool == NULL )
3224 	{
3225 		libcerror_error_set(
3226 		 error,
3227 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3228 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3229 		 "%s: invalid pool.",
3230 		 function );
3231 
3232 		return( -1 );
3233 	}
3234 	internal_pool = (libbfio_internal_pool_t *) pool;
3235 
3236 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
3237 	if( libcthreads_read_write_lock_grab_for_write(
3238 	     internal_pool->read_write_lock,
3239 	     error ) != 1 )
3240 	{
3241 		libcerror_error_set(
3242 		 error,
3243 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3244 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3245 		 "%s: unable to grab read/write lock for writing.",
3246 		 function );
3247 
3248 		return( -1 );
3249 	}
3250 #endif
3251 	if( libbfio_internal_pool_get_open_handle(
3252 	     internal_pool,
3253 	     entry,
3254 	     &handle,
3255 	     error ) != 1 )
3256 	{
3257 		libcerror_error_set(
3258 		 error,
3259 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3260 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3261 		 "%s: unable to retrieve handle: %d.",
3262 		 function,
3263 		 entry );
3264 
3265 		offset = -1;
3266 	}
3267 	else
3268 	{
3269 		offset = libbfio_handle_seek_offset(
3270 		          handle,
3271 		          offset,
3272 		          whence,
3273 		          error );
3274 
3275 		if( offset == -1 )
3276 		{
3277 			libcerror_error_set(
3278 			 error,
3279 			 LIBCERROR_ERROR_DOMAIN_IO,
3280 			 LIBCERROR_IO_ERROR_SEEK_FAILED,
3281 			 "%s: unable to seek offset in entry: %d.",
3282 			 function,
3283 			 entry );
3284 
3285 			offset = -1;
3286 		}
3287 	}
3288 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
3289 	if( libcthreads_read_write_lock_release_for_write(
3290 	     internal_pool->read_write_lock,
3291 	     error ) != 1 )
3292 	{
3293 		libcerror_error_set(
3294 		 error,
3295 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3296 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3297 		 "%s: unable to release read/write lock for writing.",
3298 		 function );
3299 
3300 		return( -1 );
3301 	}
3302 #endif
3303 	return( offset );
3304 }
3305 
3306 /* Retrieves the current offset in a handle in the pool
3307  * Returns 1 if successful or -1 on error
3308  */
libbfio_pool_get_offset(libbfio_pool_t * pool,int entry,off64_t * offset,libcerror_error_t ** error)3309 int libbfio_pool_get_offset(
3310      libbfio_pool_t *pool,
3311      int entry,
3312      off64_t *offset,
3313      libcerror_error_t **error )
3314 {
3315 	libbfio_handle_t *handle               = NULL;
3316 	libbfio_internal_pool_t *internal_pool = NULL;
3317 	static char *function                  = "libbfio_pool_get_offset";
3318 	int result                             = 1;
3319 
3320 	if( pool == NULL )
3321 	{
3322 		libcerror_error_set(
3323 		 error,
3324 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3325 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3326 		 "%s: invalid pool.",
3327 		 function );
3328 
3329 		return( -1 );
3330 	}
3331 	internal_pool = (libbfio_internal_pool_t *) pool;
3332 
3333 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
3334 	if( libcthreads_read_write_lock_grab_for_write(
3335 	     internal_pool->read_write_lock,
3336 	     error ) != 1 )
3337 	{
3338 		libcerror_error_set(
3339 		 error,
3340 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3341 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3342 		 "%s: unable to grab read/write lock for writing.",
3343 		 function );
3344 
3345 		return( -1 );
3346 	}
3347 #endif
3348 	if( libbfio_internal_pool_get_open_handle(
3349 	     internal_pool,
3350 	     entry,
3351 	     &handle,
3352 	     error ) != 1 )
3353 	{
3354 		libcerror_error_set(
3355 		 error,
3356 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3357 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3358 		 "%s: unable to retrieve handle: %d.",
3359 		 function,
3360 		 entry );
3361 
3362 		result = -1;
3363 	}
3364 	else
3365 	{
3366 		if( libbfio_handle_get_offset(
3367 		     handle,
3368 		     offset,
3369 		     error ) != 1 )
3370 		{
3371 			libcerror_error_set(
3372 			 error,
3373 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3374 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3375 			 "%s: unable to retrieve offset.",
3376 			 function );
3377 
3378 			result = -1;
3379 		}
3380 	}
3381 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
3382 	if( libcthreads_read_write_lock_release_for_write(
3383 	     internal_pool->read_write_lock,
3384 	     error ) != 1 )
3385 	{
3386 		libcerror_error_set(
3387 		 error,
3388 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3389 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3390 		 "%s: unable to release read/write lock for writing.",
3391 		 function );
3392 
3393 		return( -1 );
3394 	}
3395 #endif
3396 	return( result );
3397 }
3398 
3399 /* Retrieves the size of a handle in the pool
3400  * Returns 1 if successful or -1 on error
3401  */
libbfio_pool_get_size(libbfio_pool_t * pool,int entry,size64_t * size,libcerror_error_t ** error)3402 int libbfio_pool_get_size(
3403      libbfio_pool_t *pool,
3404      int entry,
3405      size64_t *size,
3406      libcerror_error_t **error )
3407 {
3408 	libbfio_handle_t *handle               = NULL;
3409 	libbfio_internal_pool_t *internal_pool = NULL;
3410 	static char *function                  = "libbfio_pool_get_size";
3411 	int result                             = 1;
3412 
3413 	if( pool == NULL )
3414 	{
3415 		libcerror_error_set(
3416 		 error,
3417 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3418 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3419 		 "%s: invalid pool.",
3420 		 function );
3421 
3422 		return( -1 );
3423 	}
3424 	internal_pool = (libbfio_internal_pool_t *) pool;
3425 
3426 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
3427 	if( libcthreads_read_write_lock_grab_for_write(
3428 	     internal_pool->read_write_lock,
3429 	     error ) != 1 )
3430 	{
3431 		libcerror_error_set(
3432 		 error,
3433 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3434 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3435 		 "%s: unable to grab read/write lock for writing.",
3436 		 function );
3437 
3438 		return( -1 );
3439 	}
3440 #endif
3441 	if( libbfio_internal_pool_get_open_handle(
3442 	     internal_pool,
3443 	     entry,
3444 	     &handle,
3445 	     error ) != 1 )
3446 	{
3447 		libcerror_error_set(
3448 		 error,
3449 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3450 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3451 		 "%s: unable to retrieve handle: %d.",
3452 		 function,
3453 		 entry );
3454 
3455 		result = -1;
3456 	}
3457 	else
3458 	{
3459 		if( libbfio_handle_get_size(
3460 		     handle,
3461 		     size,
3462 		     error ) != 1 )
3463 		{
3464 			libcerror_error_set(
3465 			 error,
3466 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3467 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3468 			 "%s: unable to retrieve size of entry: %d.",
3469 			 function,
3470 			 entry );
3471 
3472 			result = -1;
3473 		}
3474 	}
3475 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO )
3476 	if( libcthreads_read_write_lock_release_for_write(
3477 	     internal_pool->read_write_lock,
3478 	     error ) != 1 )
3479 	{
3480 		libcerror_error_set(
3481 		 error,
3482 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3483 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3484 		 "%s: unable to release read/write lock for writing.",
3485 		 function );
3486 
3487 		return( -1 );
3488 	}
3489 #endif
3490 	return( result );
3491 }
3492 
3493