Coverage Report

Created: 2026-07-10 07:32

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