Coverage Report

Created: 2024-02-25 07:19

/src/libvsbsdl/libvsbsdl/libvsbsdl_volume.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The volume functions
3
 *
4
 * Copyright (C) 2023, 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 <narrow_string.h>
25
#include <types.h>
26
#include <wide_string.h>
27
28
#include "libvsbsdl_debug.h"
29
#include "libvsbsdl_definitions.h"
30
#include "libvsbsdl_volume.h"
31
#include "libvsbsdl_io_handle.h"
32
#include "libvsbsdl_libbfio.h"
33
#include "libvsbsdl_libcerror.h"
34
#include "libvsbsdl_libcnotify.h"
35
#include "libvsbsdl_partition.h"
36
#include "libvsbsdl_types.h"
37
38
/* Creates a volume
39
 * Make sure the value volume is referencing, is set to NULL
40
 * Returns 1 if successful or -1 on error
41
 */
42
int libvsbsdl_volume_initialize(
43
     libvsbsdl_volume_t **volume,
44
     libcerror_error_t **error )
45
160
{
46
160
  libvsbsdl_internal_volume_t *internal_volume = NULL;
47
160
  static char *function                        = "libvsbsdl_volume_initialize";
48
49
160
  if( volume == NULL )
50
0
  {
51
0
    libcerror_error_set(
52
0
     error,
53
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
54
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
55
0
     "%s: invalid volume.",
56
0
     function );
57
58
0
    return( -1 );
59
0
  }
60
160
  if( *volume != NULL )
61
0
  {
62
0
    libcerror_error_set(
63
0
     error,
64
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
65
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
66
0
     "%s: invalid volume value already set.",
67
0
     function );
68
69
0
    return( -1 );
70
0
  }
71
160
  internal_volume = memory_allocate_structure(
72
160
                     libvsbsdl_internal_volume_t );
73
74
160
  if( internal_volume == NULL )
75
0
  {
76
0
    libcerror_error_set(
77
0
     error,
78
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
79
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
80
0
     "%s: unable to create volume.",
81
0
     function );
82
83
0
    goto on_error;
84
0
  }
85
160
  if( memory_set(
86
160
       internal_volume,
87
160
       0,
88
160
       sizeof( libvsbsdl_internal_volume_t ) ) == NULL )
89
0
  {
90
0
    libcerror_error_set(
91
0
     error,
92
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
93
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
94
0
     "%s: unable to clear volume.",
95
0
     function );
96
97
0
    memory_free(
98
0
     internal_volume );
99
100
0
    return( -1 );
101
0
  }
102
160
  if( libvsbsdl_io_handle_initialize(
103
160
       &( internal_volume->io_handle ),
104
160
       error ) != 1 )
105
0
  {
106
0
    libcerror_error_set(
107
0
     error,
108
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
109
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
110
0
     "%s: unable to create IO handle.",
111
0
     function );
112
113
0
    goto on_error;
114
0
  }
115
160
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
116
160
  if( libcthreads_read_write_lock_initialize(
117
160
       &( internal_volume->read_write_lock ),
118
160
       error ) != 1 )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
123
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
124
0
     "%s: unable to initialize read/write lock.",
125
0
     function );
126
127
0
    goto on_error;
128
0
  }
129
160
#endif
130
160
  *volume = (libvsbsdl_volume_t *) internal_volume;
131
132
160
  return( 1 );
133
134
0
on_error:
135
0
  if( internal_volume != NULL )
136
0
  {
137
0
    memory_free(
138
0
     internal_volume );
139
0
  }
140
0
  return( -1 );
141
160
}
142
143
/* Frees a volume
144
 * Returns 1 if successful or -1 on error
145
 */
146
int libvsbsdl_volume_free(
147
     libvsbsdl_volume_t **volume,
148
     libcerror_error_t **error )
149
160
{
150
160
  libvsbsdl_internal_volume_t *internal_volume = NULL;
151
160
  static char *function                        = "libvsbsdl_volume_free";
152
160
  int result                                   = 1;
153
154
160
  if( volume == NULL )
155
0
  {
156
0
    libcerror_error_set(
157
0
     error,
158
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
159
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
160
0
     "%s: invalid volume.",
161
0
     function );
162
163
0
    return( -1 );
164
0
  }
165
160
  if( *volume != NULL )
166
160
  {
167
160
    internal_volume = (libvsbsdl_internal_volume_t *) *volume;
168
169
160
    if( internal_volume->file_io_handle != NULL )
170
0
    {
171
0
      if( libvsbsdl_volume_close(
172
0
           *volume,
173
0
           error ) != 0 )
174
0
      {
175
0
        libcerror_error_set(
176
0
         error,
177
0
         LIBCERROR_ERROR_DOMAIN_IO,
178
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
179
0
         "%s: unable to close volume.",
180
0
         function );
181
182
0
        result = -1;
183
0
      }
184
0
    }
185
160
    *volume = NULL;
186
187
160
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
188
160
    if( libcthreads_read_write_lock_free(
189
160
         &( internal_volume->read_write_lock ),
190
160
         error ) != 1 )
191
0
    {
192
0
      libcerror_error_set(
193
0
       error,
194
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
195
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
196
0
       "%s: unable to free read/write lock.",
197
0
       function );
198
199
0
      result = -1;
200
0
    }
201
160
#endif
202
160
    if( libvsbsdl_io_handle_free(
203
160
         &( internal_volume->io_handle ),
204
160
         error ) != 1 )
205
0
    {
206
0
      libcerror_error_set(
207
0
       error,
208
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
209
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
210
0
       "%s: unable to free IO handle.",
211
0
       function );
212
213
0
      result = -1;
214
0
    }
215
160
    memory_free(
216
160
     internal_volume );
217
160
  }
218
160
  return( result );
219
160
}
220
221
/* Signals the volume to abort its current activity
222
 * Returns 1 if successful or -1 on error
223
 */
224
int libvsbsdl_volume_signal_abort(
225
     libvsbsdl_volume_t *volume,
226
     libcerror_error_t **error )
227
0
{
228
0
  libvsbsdl_internal_volume_t *internal_volume = NULL;
229
0
  static char *function                        = "libvsbsdl_volume_signal_abort";
230
231
0
  if( volume == NULL )
232
0
  {
233
0
    libcerror_error_set(
234
0
     error,
235
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
236
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
237
0
     "%s: invalid volume.",
238
0
     function );
239
240
0
    return( -1 );
241
0
  }
242
0
  internal_volume = (libvsbsdl_internal_volume_t *) volume;
243
244
0
  if( internal_volume->io_handle == NULL )
245
0
  {
246
0
    libcerror_error_set(
247
0
     error,
248
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
249
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
250
0
     "%s: invalid volume - missing IO handle.",
251
0
     function );
252
253
0
    return( -1 );
254
0
  }
255
0
  internal_volume->io_handle->abort = 1;
256
257
0
  return( 1 );
258
0
}
259
260
/* Opens a volume
261
 * Returns 1 if successful or -1 on error
262
 */
263
int libvsbsdl_volume_open(
264
     libvsbsdl_volume_t *volume,
265
     const char *filename,
266
     int access_flags,
267
     libcerror_error_t **error )
268
0
{
269
0
  libbfio_handle_t *file_io_handle             = NULL;
270
0
  libvsbsdl_internal_volume_t *internal_volume = NULL;
271
0
  static char *function                        = "libvsbsdl_volume_open";
272
0
  size_t filename_length                       = 0;
273
274
0
  if( volume == NULL )
275
0
  {
276
0
    libcerror_error_set(
277
0
     error,
278
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
279
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
280
0
     "%s: invalid volume.",
281
0
     function );
282
283
0
    return( -1 );
284
0
  }
285
0
  internal_volume = (libvsbsdl_internal_volume_t *) volume;
286
287
0
  if( filename == NULL )
288
0
  {
289
0
    libcerror_error_set(
290
0
     error,
291
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
292
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
293
0
     "%s: invalid filename.",
294
0
     function );
295
296
0
    return( -1 );
297
0
  }
298
0
  if( ( ( access_flags & LIBVSBSDL_ACCESS_FLAG_READ ) == 0 )
299
0
   && ( ( access_flags & LIBVSBSDL_ACCESS_FLAG_WRITE ) == 0 ) )
300
0
  {
301
0
    libcerror_error_set(
302
0
     error,
303
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
304
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
305
0
     "%s: unsupported access flags.",
306
0
     function );
307
308
0
    return( -1 );
309
0
  }
310
0
  if( ( access_flags & LIBVSBSDL_ACCESS_FLAG_WRITE ) != 0 )
311
0
  {
312
0
    libcerror_error_set(
313
0
     error,
314
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
315
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
316
0
     "%s: write access currently not supported.",
317
0
     function );
318
319
0
    return( -1 );
320
0
  }
321
0
  if( libbfio_file_initialize(
322
0
       &file_io_handle,
323
0
       error ) != 1 )
324
0
  {
325
0
    libcerror_error_set(
326
0
     error,
327
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
328
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
329
0
     "%s: unable to create file IO handle.",
330
0
     function );
331
332
0
    goto on_error;
333
0
  }
334
#if defined( HAVE_DEBUG_OUTPUT )
335
  if( libbfio_handle_set_track_offsets_read(
336
       file_io_handle,
337
       1,
338
       error ) != 1 )
339
  {
340
    libcerror_error_set(
341
     error,
342
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
343
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
344
     "%s: unable to set track offsets read in file IO handle.",
345
     function );
346
347
    goto on_error;
348
  }
349
#endif
350
0
  filename_length = narrow_string_length(
351
0
                     filename );
352
353
0
  if( libbfio_file_set_name(
354
0
       file_io_handle,
355
0
       filename,
356
0
       filename_length + 1,
357
0
       error ) != 1 )
358
0
  {
359
0
    libcerror_error_set(
360
0
     error,
361
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
362
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
363
0
     "%s: unable to set filename in file IO handle.",
364
0
     function );
365
366
0
    goto on_error;
367
0
  }
368
0
  if( libvsbsdl_volume_open_file_io_handle(
369
0
       volume,
370
0
       file_io_handle,
371
0
       access_flags,
372
0
       error ) != 1 )
373
0
  {
374
0
    libcerror_error_set(
375
0
     error,
376
0
     LIBCERROR_ERROR_DOMAIN_IO,
377
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
378
0
     "%s: unable to open volume: %s.",
379
0
     function,
380
0
     filename );
381
382
0
    goto on_error;
383
0
  }
384
0
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
385
0
  if( libcthreads_read_write_lock_grab_for_write(
386
0
       internal_volume->read_write_lock,
387
0
       error ) != 1 )
388
0
  {
389
0
    libcerror_error_set(
390
0
     error,
391
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
392
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
393
0
     "%s: unable to grab read/write lock for writing.",
394
0
     function );
395
396
0
    return( -1 );
397
0
  }
398
0
#endif
399
0
  internal_volume->file_io_handle_created_in_library = 1;
400
401
0
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
402
0
  if( libcthreads_read_write_lock_release_for_write(
403
0
       internal_volume->read_write_lock,
404
0
       error ) != 1 )
405
0
  {
406
0
    libcerror_error_set(
407
0
     error,
408
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
409
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
410
0
     "%s: unable to release read/write lock for writing.",
411
0
     function );
412
413
0
    return( -1 );
414
0
  }
415
0
#endif
416
0
  return( 1 );
417
418
0
on_error:
419
0
  if( file_io_handle != NULL )
420
0
  {
421
0
    libbfio_handle_free(
422
0
     &file_io_handle,
423
0
     NULL );
424
0
  }
425
0
  return( -1 );
426
0
}
427
428
#if defined( HAVE_WIDE_CHARACTER_TYPE )
429
430
/* Opens a volume
431
 * Returns 1 if successful or -1 on error
432
 */
433
int libvsbsdl_volume_open_wide(
434
     libvsbsdl_volume_t *volume,
435
     const wchar_t *filename,
436
     int access_flags,
437
     libcerror_error_t **error )
438
{
439
  libbfio_handle_t *file_io_handle             = NULL;
440
  libvsbsdl_internal_volume_t *internal_volume = NULL;
441
  static char *function                        = "libvsbsdl_volume_open_wide";
442
  size_t filename_length                       = 0;
443
444
  if( volume == NULL )
445
  {
446
    libcerror_error_set(
447
     error,
448
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
449
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
450
     "%s: invalid volume.",
451
     function );
452
453
    return( -1 );
454
  }
455
  internal_volume = (libvsbsdl_internal_volume_t *) volume;
456
457
  if( filename == NULL )
458
  {
459
    libcerror_error_set(
460
     error,
461
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
462
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
463
     "%s: invalid filename.",
464
     function );
465
466
    return( -1 );
467
  }
468
  if( ( ( access_flags & LIBVSBSDL_ACCESS_FLAG_READ ) == 0 )
469
   && ( ( access_flags & LIBVSBSDL_ACCESS_FLAG_WRITE ) == 0 ) )
470
  {
471
    libcerror_error_set(
472
     error,
473
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
474
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
475
     "%s: unsupported access flags.",
476
     function );
477
478
    return( -1 );
479
  }
480
  if( ( access_flags & LIBVSBSDL_ACCESS_FLAG_WRITE ) != 0 )
481
  {
482
    libcerror_error_set(
483
     error,
484
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
485
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
486
     "%s: write access currently not supported.",
487
     function );
488
489
    return( -1 );
490
  }
491
  if( libbfio_file_initialize(
492
       &file_io_handle,
493
       error ) != 1 )
494
  {
495
    libcerror_error_set(
496
     error,
497
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
498
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
499
     "%s: unable to create file IO handle.",
500
     function );
501
502
    goto on_error;
503
  }
504
#if defined( HAVE_DEBUG_OUTPUT )
505
  if( libbfio_handle_set_track_offsets_read(
506
       file_io_handle,
507
       1,
508
       error ) != 1 )
509
  {
510
    libcerror_error_set(
511
     error,
512
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
513
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
514
     "%s: unable to set track offsets read in file IO handle.",
515
     function );
516
517
    goto on_error;
518
  }
519
#endif
520
  filename_length = wide_string_length(
521
                     filename );
522
523
  if( libbfio_file_set_name_wide(
524
       file_io_handle,
525
       filename,
526
       filename_length + 1,
527
       error ) != 1 )
528
  {
529
    libcerror_error_set(
530
     error,
531
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
532
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
533
     "%s: unable to set filename in file IO handle.",
534
     function );
535
536
    goto on_error;
537
  }
538
  if( libvsbsdl_volume_open_file_io_handle(
539
       volume,
540
       file_io_handle,
541
       access_flags,
542
       error ) != 1 )
543
  {
544
    libcerror_error_set(
545
     error,
546
     LIBCERROR_ERROR_DOMAIN_IO,
547
     LIBCERROR_IO_ERROR_OPEN_FAILED,
548
     "%s: unable to open volume: %ls.",
549
     function,
550
     filename );
551
552
    goto on_error;
553
  }
554
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
555
  if( libcthreads_read_write_lock_grab_for_write(
556
       internal_volume->read_write_lock,
557
       error ) != 1 )
558
  {
559
    libcerror_error_set(
560
     error,
561
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
562
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
563
     "%s: unable to grab read/write lock for writing.",
564
     function );
565
566
    return( -1 );
567
  }
568
#endif
569
  internal_volume->file_io_handle_created_in_library = 1;
570
571
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
572
  if( libcthreads_read_write_lock_release_for_write(
573
       internal_volume->read_write_lock,
574
       error ) != 1 )
575
  {
576
    libcerror_error_set(
577
     error,
578
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
579
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
580
     "%s: unable to release read/write lock for writing.",
581
     function );
582
583
    return( -1 );
584
  }
585
#endif
586
  return( 1 );
587
588
on_error:
589
  if( file_io_handle != NULL )
590
  {
591
    libbfio_handle_free(
592
     &file_io_handle,
593
     NULL );
594
  }
595
  return( -1 );
596
}
597
598
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
599
600
/* Opens a volume using a Basic File IO (bfio) volume
601
 * Returns 1 if successful or -1 on error
602
 */
603
int libvsbsdl_volume_open_file_io_handle(
604
     libvsbsdl_volume_t *volume,
605
     libbfio_handle_t *file_io_handle,
606
     int access_flags,
607
     libcerror_error_t **error )
608
160
{
609
160
  libvsbsdl_internal_volume_t *internal_volume = NULL;
610
160
  static char *function                        = "libvsbsdl_volume_open_file_io_handle";
611
160
  uint8_t file_io_handle_opened_in_library     = 0;
612
160
  int bfio_access_flags                        = 0;
613
160
  int file_io_handle_is_open                   = 0;
614
615
160
  if( volume == NULL )
616
0
  {
617
0
    libcerror_error_set(
618
0
     error,
619
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
620
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
621
0
     "%s: invalid volume.",
622
0
     function );
623
624
0
    return( -1 );
625
0
  }
626
160
  internal_volume = (libvsbsdl_internal_volume_t *) volume;
627
628
160
  if( internal_volume->file_io_handle != NULL )
629
0
  {
630
0
    libcerror_error_set(
631
0
     error,
632
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
633
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
634
0
     "%s: invalid volume - file IO handle value already set.",
635
0
     function );
636
637
0
    return( -1 );
638
0
  }
639
160
  if( file_io_handle == NULL )
640
0
  {
641
0
    libcerror_error_set(
642
0
     error,
643
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
644
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
645
0
     "%s: invalid file IO handle.",
646
0
     function );
647
648
0
    return( -1 );
649
0
  }
650
160
  if( ( ( access_flags & LIBVSBSDL_ACCESS_FLAG_READ ) == 0 )
651
160
   && ( ( access_flags & LIBVSBSDL_ACCESS_FLAG_WRITE ) == 0 ) )
652
0
  {
653
0
    libcerror_error_set(
654
0
     error,
655
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
656
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
657
0
     "%s: unsupported access flags.",
658
0
     function );
659
660
0
    return( -1 );
661
0
  }
662
160
  if( ( access_flags & LIBVSBSDL_ACCESS_FLAG_WRITE ) != 0 )
663
0
  {
664
0
    libcerror_error_set(
665
0
     error,
666
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
667
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
668
0
     "%s: write access currently not supported.",
669
0
     function );
670
671
0
    return( -1 );
672
0
  }
673
160
  if( ( access_flags & LIBVSBSDL_ACCESS_FLAG_READ ) != 0 )
674
160
  {
675
160
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
676
160
  }
677
160
  file_io_handle_is_open = libbfio_handle_is_open(
678
160
                            file_io_handle,
679
160
                            error );
680
681
160
  if( file_io_handle_is_open == -1 )
682
0
  {
683
0
    libcerror_error_set(
684
0
     error,
685
0
     LIBCERROR_ERROR_DOMAIN_IO,
686
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
687
0
     "%s: unable to open volume.",
688
0
     function );
689
690
0
    goto on_error;
691
0
  }
692
160
  else if( file_io_handle_is_open == 0 )
693
160
  {
694
160
    if( libbfio_handle_open(
695
160
         file_io_handle,
696
160
         bfio_access_flags,
697
160
         error ) != 1 )
698
0
    {
699
0
      libcerror_error_set(
700
0
       error,
701
0
       LIBCERROR_ERROR_DOMAIN_IO,
702
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
703
0
       "%s: unable to open file IO handle.",
704
0
       function );
705
706
0
      goto on_error;
707
0
    }
708
160
    file_io_handle_opened_in_library = 1;
709
160
  }
710
160
  if( libvsbsdl_internal_volume_open_read(
711
160
       internal_volume,
712
160
       file_io_handle,
713
160
       error ) != 1 )
714
139
  {
715
139
    libcerror_error_set(
716
139
     error,
717
139
     LIBCERROR_ERROR_DOMAIN_IO,
718
139
     LIBCERROR_IO_ERROR_READ_FAILED,
719
139
     "%s: unable to read from file IO handle.",
720
139
     function );
721
722
139
    goto on_error;
723
139
  }
724
21
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
725
21
  if( libcthreads_read_write_lock_grab_for_write(
726
21
       internal_volume->read_write_lock,
727
21
       error ) != 1 )
728
0
  {
729
0
    libcerror_error_set(
730
0
     error,
731
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
732
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
733
0
     "%s: unable to grab read/write lock for writing.",
734
0
     function );
735
736
0
    return( -1 );
737
0
  }
738
21
#endif
739
21
  internal_volume->file_io_handle                   = file_io_handle;
740
21
  internal_volume->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
741
742
21
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
743
21
  if( libcthreads_read_write_lock_release_for_write(
744
21
       internal_volume->read_write_lock,
745
21
       error ) != 1 )
746
0
  {
747
0
    libcerror_error_set(
748
0
     error,
749
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
750
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
751
0
     "%s: unable to release read/write lock for writing.",
752
0
     function );
753
754
0
    return( -1 );
755
0
  }
756
21
#endif
757
21
  return( 1 );
758
759
139
on_error:
760
139
  if( file_io_handle_opened_in_library != 0 )
761
139
  {
762
139
    libbfio_handle_close(
763
139
     file_io_handle,
764
139
     error );
765
139
  }
766
139
  return( -1 );
767
21
}
768
769
/* Closes a volume
770
 * Returns 0 if successful or -1 on error
771
 */
772
int libvsbsdl_volume_close(
773
     libvsbsdl_volume_t *volume,
774
     libcerror_error_t **error )
775
21
{
776
21
  libvsbsdl_internal_volume_t *internal_volume = NULL;
777
21
  static char *function                        = "libvsbsdl_volume_close";
778
21
  int result                                   = 0;
779
780
21
  if( volume == NULL )
781
0
  {
782
0
    libcerror_error_set(
783
0
     error,
784
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
785
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
786
0
     "%s: invalid volume.",
787
0
     function );
788
789
0
    return( -1 );
790
0
  }
791
21
  internal_volume = (libvsbsdl_internal_volume_t *) volume;
792
793
21
  if( internal_volume->file_io_handle == NULL )
794
0
  {
795
0
    libcerror_error_set(
796
0
     error,
797
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
798
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
799
0
     "%s: invalid volume - missing file IO handle.",
800
0
     function );
801
802
0
    return( -1 );
803
0
  }
804
21
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
805
21
  if( libcthreads_read_write_lock_grab_for_write(
806
21
       internal_volume->read_write_lock,
807
21
       error ) != 1 )
808
0
  {
809
0
    libcerror_error_set(
810
0
     error,
811
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
812
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
813
0
     "%s: unable to grab read/write lock for writing.",
814
0
     function );
815
816
0
    return( -1 );
817
0
  }
818
21
#endif
819
#if defined( HAVE_DEBUG_OUTPUT )
820
  if( libcnotify_verbose != 0 )
821
  {
822
    if( internal_volume->file_io_handle_created_in_library != 0 )
823
    {
824
      if( libvsbsdl_debug_print_read_offsets(
825
           internal_volume->file_io_handle,
826
           error ) != 1 )
827
      {
828
        libcerror_error_set(
829
         error,
830
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
831
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
832
         "%s: unable to print the read offsets.",
833
         function );
834
835
        result = -1;
836
      }
837
    }
838
  }
839
#endif
840
21
  if( internal_volume->file_io_handle_opened_in_library != 0 )
841
21
  {
842
21
    if( libbfio_handle_close(
843
21
         internal_volume->file_io_handle,
844
21
         error ) != 0 )
845
0
    {
846
0
      libcerror_error_set(
847
0
       error,
848
0
       LIBCERROR_ERROR_DOMAIN_IO,
849
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
850
0
       "%s: unable to close file IO handle.",
851
0
       function );
852
853
0
      result = -1;
854
0
    }
855
21
    internal_volume->file_io_handle_opened_in_library = 0;
856
21
  }
857
21
  if( internal_volume->file_io_handle_created_in_library != 0 )
858
0
  {
859
0
    if( libbfio_handle_free(
860
0
         &( internal_volume->file_io_handle ),
861
0
         error ) != 1 )
862
0
    {
863
0
      libcerror_error_set(
864
0
       error,
865
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
866
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
867
0
       "%s: unable to free file IO handle.",
868
0
       function );
869
870
0
      result = -1;
871
0
    }
872
0
    internal_volume->file_io_handle_created_in_library = 0;
873
0
  }
874
21
  internal_volume->file_io_handle = NULL;
875
876
21
  if( libvsbsdl_io_handle_clear(
877
21
       internal_volume->io_handle,
878
21
       error ) != 1 )
879
0
  {
880
0
    libcerror_error_set(
881
0
     error,
882
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
883
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
884
0
     "%s: unable to clear the IO handle.",
885
0
     function );
886
887
0
    result = -1;
888
0
  }
889
21
  if( internal_volume->disklabel != NULL )
890
21
  {
891
21
    if( libvsbsdl_disklabel_free(
892
21
         &( internal_volume->disklabel ),
893
21
         error ) != 1 )
894
0
    {
895
0
      libcerror_error_set(
896
0
       error,
897
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
898
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
899
0
       "%s: unable to free disklabel.",
900
0
       function );
901
902
0
      result = -1;
903
0
    }
904
21
  }
905
21
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
906
21
  if( libcthreads_read_write_lock_release_for_write(
907
21
       internal_volume->read_write_lock,
908
21
       error ) != 1 )
909
0
  {
910
0
    libcerror_error_set(
911
0
     error,
912
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
913
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
914
0
     "%s: unable to release read/write lock for writing.",
915
0
     function );
916
917
0
    return( -1 );
918
0
  }
919
21
#endif
920
21
  return( result );
921
21
}
922
923
/* Opens a volume for reading
924
 * Returns 1 if successful or -1 on error
925
 */
926
int libvsbsdl_internal_volume_open_read(
927
     libvsbsdl_internal_volume_t *internal_volume,
928
     libbfio_handle_t *file_io_handle,
929
     libcerror_error_t **error )
930
160
{
931
160
  static char *function = "libvsbsdl_internal_volume_open_read";
932
933
160
  if( internal_volume == NULL )
934
0
  {
935
0
    libcerror_error_set(
936
0
     error,
937
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
938
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
939
0
     "%s: invalid internal volume.",
940
0
     function );
941
942
0
    return( -1 );
943
0
  }
944
160
  if( internal_volume->io_handle == NULL )
945
0
  {
946
0
    libcerror_error_set(
947
0
     error,
948
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
949
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
950
0
     "%s: invalid volume - missing IO handle.",
951
0
     function );
952
953
0
    return( -1 );
954
0
  }
955
160
  if( internal_volume->disklabel != NULL )
956
0
  {
957
0
    libcerror_error_set(
958
0
     error,
959
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
960
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
961
0
     "%s: invalid volume - disklabel value already set.",
962
0
     function );
963
964
0
    return( -1 );
965
0
  }
966
160
  if( libbfio_handle_get_size(
967
160
       file_io_handle,
968
160
       &( internal_volume->size ),
969
160
       error ) != 1 )
970
0
  {
971
0
    libcerror_error_set(
972
0
     error,
973
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
974
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
975
0
     "%s: unable to retrieve size from file IO handle.",
976
0
     function );
977
978
0
    goto on_error;
979
0
  }
980
#if defined( HAVE_DEBUG_OUTPUT )
981
  if( libcnotify_verbose != 0 )
982
  {
983
    libcnotify_printf(
984
     "%s: reading BSD disklabel.\n",
985
     function );
986
  }
987
#endif
988
160
  if( libvsbsdl_disklabel_initialize(
989
160
       &( internal_volume->disklabel ),
990
160
       error ) != 1 )
991
0
  {
992
0
    libcerror_error_set(
993
0
     error,
994
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
995
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
996
0
     "%s: unable to create disklabel.",
997
0
     function );
998
999
0
    goto on_error;
1000
0
  }
1001
160
  if( libvsbsdl_disklabel_read_file_io_handle(
1002
160
       internal_volume->disklabel,
1003
160
       file_io_handle,
1004
160
       512,
1005
160
       error ) != 1 )
1006
139
  {
1007
139
    libcerror_error_set(
1008
139
     error,
1009
139
     LIBCERROR_ERROR_DOMAIN_IO,
1010
139
     LIBCERROR_IO_ERROR_READ_FAILED,
1011
139
     "%s: unable to read disklabel from file IO handle.",
1012
139
     function );
1013
1014
139
    goto on_error;
1015
139
  }
1016
21
  if( libvsbsdl_disklabel_get_bytes_per_sector(
1017
21
       internal_volume->disklabel,
1018
21
       &( internal_volume->io_handle->bytes_per_sector ),
1019
21
       error ) != 1 )
1020
0
  {
1021
0
    libcerror_error_set(
1022
0
     error,
1023
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1024
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1025
0
     "%s: unable to retrieve bytes per sector from disklabel.",
1026
0
     function );
1027
1028
0
    goto on_error;
1029
0
  }
1030
21
  return( 1 );
1031
1032
139
on_error:
1033
139
  if( internal_volume->disklabel != NULL )
1034
139
  {
1035
139
    libvsbsdl_disklabel_free(
1036
139
     &( internal_volume->disklabel ),
1037
139
     NULL );
1038
139
  }
1039
139
  return( -1 );
1040
21
}
1041
1042
/* Retrieves the number of bytes per sector
1043
 * Returns 1 if successful or -1 on error
1044
 */
1045
int libvsbsdl_volume_get_bytes_per_sector(
1046
     libvsbsdl_volume_t *volume,
1047
     uint32_t *bytes_per_sector,
1048
     libcerror_error_t **error )
1049
0
{
1050
0
  libvsbsdl_internal_volume_t *internal_volume = NULL;
1051
0
  static char *function                        = "libvsbsdl_volume_get_bytes_per_sector";
1052
1053
0
  if( volume == NULL )
1054
0
  {
1055
0
    libcerror_error_set(
1056
0
     error,
1057
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1058
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1059
0
     "%s: invalid volume.",
1060
0
     function );
1061
1062
0
    return( -1 );
1063
0
  }
1064
0
  internal_volume = (libvsbsdl_internal_volume_t *) volume;
1065
1066
0
  if( internal_volume->io_handle == NULL )
1067
0
  {
1068
0
    libcerror_error_set(
1069
0
     error,
1070
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1071
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1072
0
     "%s: invalid volume - missing IO handle.",
1073
0
     function );
1074
1075
0
    return( -1 );
1076
0
  }
1077
0
  if( bytes_per_sector == NULL )
1078
0
  {
1079
0
    libcerror_error_set(
1080
0
     error,
1081
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1082
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1083
0
     "%s: invalid bytes per sector.",
1084
0
     function );
1085
1086
0
    return( -1 );
1087
0
  }
1088
0
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
1089
0
  if( libcthreads_read_write_lock_grab_for_read(
1090
0
       internal_volume->read_write_lock,
1091
0
       error ) != 1 )
1092
0
  {
1093
0
    libcerror_error_set(
1094
0
     error,
1095
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1096
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1097
0
     "%s: unable to grab read/write lock for reading.",
1098
0
     function );
1099
1100
0
    return( -1 );
1101
0
  }
1102
0
#endif
1103
0
  *bytes_per_sector = internal_volume->io_handle->bytes_per_sector;
1104
1105
0
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
1106
0
  if( libcthreads_read_write_lock_release_for_read(
1107
0
       internal_volume->read_write_lock,
1108
0
       error ) != 1 )
1109
0
  {
1110
0
    libcerror_error_set(
1111
0
     error,
1112
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1113
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1114
0
     "%s: unable to release read/write lock for reading.",
1115
0
     function );
1116
1117
0
    return( -1 );
1118
0
  }
1119
0
#endif
1120
0
  return( 1 );
1121
0
}
1122
1123
/* Retrieves the number of partitions
1124
 * Returns 1 if successful or -1 on error
1125
 */
1126
int libvsbsdl_volume_get_number_of_partitions(
1127
     libvsbsdl_volume_t *volume,
1128
     int *number_of_partitions,
1129
     libcerror_error_t **error )
1130
0
{
1131
0
  libvsbsdl_internal_volume_t *internal_volume = NULL;
1132
0
  static char *function                        = "libvsbsdl_volume_get_number_of_partitions";
1133
0
  int result                                   = 1;
1134
1135
0
  if( volume == NULL )
1136
0
  {
1137
0
    libcerror_error_set(
1138
0
     error,
1139
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1140
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1141
0
     "%s: invalid volume.",
1142
0
     function );
1143
1144
0
    return( -1 );
1145
0
  }
1146
0
  internal_volume = (libvsbsdl_internal_volume_t *) volume;
1147
1148
0
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
1149
0
  if( libcthreads_read_write_lock_grab_for_read(
1150
0
       internal_volume->read_write_lock,
1151
0
       error ) != 1 )
1152
0
  {
1153
0
    libcerror_error_set(
1154
0
     error,
1155
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1156
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1157
0
     "%s: unable to grab read/write lock for reading.",
1158
0
     function );
1159
1160
0
    return( -1 );
1161
0
  }
1162
0
#endif
1163
0
  if( libvsbsdl_disklabel_get_number_of_partition_entries(
1164
0
       internal_volume->disklabel,
1165
0
       number_of_partitions,
1166
0
       error ) != 1 )
1167
0
  {
1168
0
    libcerror_error_set(
1169
0
     error,
1170
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1171
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1172
0
     "%s: unable to retrieve number of partition entries from disklabel.",
1173
0
     function );
1174
1175
0
    result = -1;
1176
0
  }
1177
0
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
1178
0
  if( libcthreads_read_write_lock_release_for_read(
1179
0
       internal_volume->read_write_lock,
1180
0
       error ) != 1 )
1181
0
  {
1182
0
    libcerror_error_set(
1183
0
     error,
1184
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1185
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1186
0
     "%s: unable to release read/write lock for reading.",
1187
0
     function );
1188
1189
0
    return( -1 );
1190
0
  }
1191
0
#endif
1192
0
  return( result );
1193
0
}
1194
1195
/* Retrieves a specific partition
1196
 * Returns 1 if successful or -1 on error
1197
 */
1198
int libvsbsdl_volume_get_partition_by_index(
1199
     libvsbsdl_volume_t *volume,
1200
     int partition_index,
1201
     libvsbsdl_partition_t **partition,
1202
     libcerror_error_t **error )
1203
0
{
1204
0
  libvsbsdl_internal_volume_t *internal_volume = NULL;
1205
0
  libvsbsdl_partition_entry_t *partition_entry = NULL;
1206
0
  static char *function                        = "libvsbsdl_volume_get_partition_by_index";
1207
0
  int result                                   = 1;
1208
1209
0
  if( volume == NULL )
1210
0
  {
1211
0
    libcerror_error_set(
1212
0
     error,
1213
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1214
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1215
0
     "%s: invalid volume.",
1216
0
     function );
1217
1218
0
    return( -1 );
1219
0
  }
1220
0
  internal_volume = (libvsbsdl_internal_volume_t *) volume;
1221
1222
0
  if( partition == NULL )
1223
0
  {
1224
0
    libcerror_error_set(
1225
0
     error,
1226
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1227
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1228
0
     "%s: invalid partition.",
1229
0
     function );
1230
1231
0
    return( -1 );
1232
0
  }
1233
0
  if( *partition != NULL )
1234
0
  {
1235
0
    libcerror_error_set(
1236
0
     error,
1237
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1238
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1239
0
     "%s: invalid partition value already set.",
1240
0
     function );
1241
1242
0
    return( -1 );
1243
0
  }
1244
0
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
1245
0
  if( libcthreads_read_write_lock_grab_for_read(
1246
0
       internal_volume->read_write_lock,
1247
0
       error ) != 1 )
1248
0
  {
1249
0
    libcerror_error_set(
1250
0
     error,
1251
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1252
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1253
0
     "%s: unable to grab read/write lock for reading.",
1254
0
     function );
1255
1256
0
    return( -1 );
1257
0
  }
1258
0
#endif
1259
0
  if( libvsbsdl_disklabel_get_partition_entry_by_index(
1260
0
       internal_volume->disklabel,
1261
0
       partition_index,
1262
0
       &partition_entry,
1263
0
       error ) != 1 )
1264
0
  {
1265
0
    libcerror_error_set(
1266
0
     error,
1267
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1268
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1269
0
     "%s: unable to retrieve partition entry: %d from disklabel.",
1270
0
     function,
1271
0
     partition_index );
1272
1273
0
    result = -1;
1274
0
  }
1275
0
  else
1276
0
  {
1277
0
    if( libvsbsdl_partition_initialize(
1278
0
         partition,
1279
0
         internal_volume->io_handle,
1280
0
         internal_volume->file_io_handle,
1281
0
         partition_entry,
1282
0
         error ) != 1 )
1283
0
    {
1284
0
      libcerror_error_set(
1285
0
       error,
1286
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1287
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1288
0
       "%s: unable to create partition: %d.",
1289
0
       function,
1290
0
       partition_index );
1291
1292
0
      result = -1;
1293
0
    }
1294
0
  }
1295
0
#if defined( HAVE_LIBVSBSDL_MULTI_THREAD_SUPPORT )
1296
0
  if( libcthreads_read_write_lock_release_for_read(
1297
0
       internal_volume->read_write_lock,
1298
0
       error ) != 1 )
1299
0
  {
1300
0
    libcerror_error_set(
1301
0
     error,
1302
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1303
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1304
0
     "%s: unable to release read/write lock for reading.",
1305
0
     function );
1306
1307
0
    return( -1 );
1308
0
  }
1309
0
#endif
1310
0
  return( result );
1311
0
}
1312