Coverage Report

Created: 2024-02-25 07:19

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