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