Coverage Report

Created: 2024-02-25 07:20

/src/libqcow/libqcow/libqcow_file.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * File functions
3
 *
4
 * Copyright (C) 2010-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 "libqcow_cluster_block.h"
29
#include "libqcow_cluster_table.h"
30
#include "libqcow_codepage.h"
31
#include "libqcow_compression.h"
32
#include "libqcow_debug.h"
33
#include "libqcow_definitions.h"
34
#include "libqcow_encryption.h"
35
#include "libqcow_file_header.h"
36
#include "libqcow_i18n.h"
37
#include "libqcow_io_handle.h"
38
#include "libqcow_file.h"
39
#include "libqcow_libbfio.h"
40
#include "libqcow_libcerror.h"
41
#include "libqcow_libcnotify.h"
42
#include "libqcow_libcthreads.h"
43
#include "libqcow_libfcache.h"
44
#include "libqcow_libfdata.h"
45
#include "libqcow_libuna.h"
46
47
/* Creates a file
48
 * Make sure the value file is referencing, is set to NULL
49
 * Returns 1 if successful or -1 on error
50
 */
51
int libqcow_file_initialize(
52
     libqcow_file_t **file,
53
     libcerror_error_t **error )
54
845
{
55
845
  libqcow_internal_file_t *internal_file = NULL;
56
845
  static char *function                  = "libqcow_file_initialize";
57
58
845
  if( file == NULL )
59
0
  {
60
0
    libcerror_error_set(
61
0
     error,
62
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
63
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
64
0
     "%s: invalid file.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
845
  if( *file != NULL )
70
0
  {
71
0
    libcerror_error_set(
72
0
     error,
73
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
74
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
75
0
     "%s: invalid file value already set.",
76
0
     function );
77
78
0
    return( -1 );
79
0
  }
80
845
  internal_file = memory_allocate_structure(
81
845
                   libqcow_internal_file_t );
82
83
845
  if( internal_file == NULL )
84
0
  {
85
0
    libcerror_error_set(
86
0
     error,
87
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
88
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
89
0
     "%s: unable to create file.",
90
0
     function );
91
92
0
    goto on_error;
93
0
  }
94
845
  if( memory_set(
95
845
       internal_file,
96
845
       0,
97
845
       sizeof( libqcow_internal_file_t ) ) == NULL )
98
0
  {
99
0
    libcerror_error_set(
100
0
     error,
101
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
102
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
103
0
     "%s: unable to clear file.",
104
0
     function );
105
106
0
    memory_free(
107
0
     internal_file );
108
109
0
    return( -1 );
110
0
  }
111
845
  if( libqcow_io_handle_initialize(
112
845
       &( internal_file->io_handle ),
113
845
       error ) != 1 )
114
0
  {
115
0
    libcerror_error_set(
116
0
     error,
117
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
118
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
119
0
     "%s: unable to create IO handle.",
120
0
     function );
121
122
0
    goto on_error;
123
0
  }
124
845
  if( libqcow_i18n_initialize(
125
845
       error ) != 1 )
126
0
  {
127
0
    libcerror_error_set(
128
0
     error,
129
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
130
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
131
0
     "%s: unable to initalize internationalization (i18n).",
132
0
     function );
133
134
0
    goto on_error;
135
0
  }
136
845
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
137
845
  if( libcthreads_read_write_lock_initialize(
138
845
       &( internal_file->read_write_lock ),
139
845
       error ) != 1 )
140
0
  {
141
0
    libcerror_error_set(
142
0
     error,
143
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
144
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
145
0
     "%s: unable to initialize read/write lock.",
146
0
     function );
147
148
0
    goto on_error;
149
0
  }
150
845
#endif
151
845
  internal_file->is_locked = 1;
152
153
845
  *file = (libqcow_file_t *) internal_file;
154
155
845
  return( 1 );
156
157
0
on_error:
158
0
  if( internal_file != NULL )
159
0
  {
160
0
    if( internal_file->io_handle != NULL )
161
0
    {
162
0
      libqcow_io_handle_free(
163
0
       &( internal_file->io_handle ),
164
0
       NULL );
165
0
    }
166
0
    memory_free(
167
0
     internal_file );
168
0
  }
169
0
  return( -1 );
170
845
}
171
172
/* Frees a file
173
 * Returns 1 if successful or -1 on error
174
 */
175
int libqcow_file_free(
176
     libqcow_file_t **file,
177
     libcerror_error_t **error )
178
845
{
179
845
  libqcow_internal_file_t *internal_file = NULL;
180
845
  static char *function                  = "libqcow_file_free";
181
845
  int result                             = 1;
182
183
845
  if( file == NULL )
184
0
  {
185
0
    libcerror_error_set(
186
0
     error,
187
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
188
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
189
0
     "%s: invalid file.",
190
0
     function );
191
192
0
    return( -1 );
193
0
  }
194
845
  if( *file != NULL )
195
845
  {
196
845
    internal_file = (libqcow_internal_file_t *) *file;
197
198
845
    if( internal_file->file_io_handle != NULL )
199
0
    {
200
0
      if( libqcow_file_close(
201
0
           *file,
202
0
           error ) != 0 )
203
0
      {
204
0
        libcerror_error_set(
205
0
         error,
206
0
         LIBCERROR_ERROR_DOMAIN_IO,
207
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
208
0
         "%s: unable to close file.",
209
0
         function );
210
211
0
        result = -1;
212
0
      }
213
0
    }
214
845
    *file = NULL;
215
216
845
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
217
845
    if( libcthreads_read_write_lock_free(
218
845
         &( internal_file->read_write_lock ),
219
845
         error ) != 1 )
220
0
    {
221
0
      libcerror_error_set(
222
0
       error,
223
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
224
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
225
0
       "%s: unable to free read/write lock.",
226
0
       function );
227
228
0
      result = -1;
229
0
    }
230
845
#endif
231
845
    if( libqcow_io_handle_free(
232
845
         &( internal_file->io_handle ),
233
845
         error ) != 1 )
234
0
    {
235
0
      libcerror_error_set(
236
0
       error,
237
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
238
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
239
0
       "%s: unable to free IO handle.",
240
0
       function );
241
242
0
      result = -1;
243
0
    }
244
845
    if( memory_set(
245
845
         internal_file->key_data,
246
845
         0,
247
845
         16 ) == NULL )
248
0
    {
249
0
      libcerror_error_set(
250
0
       error,
251
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
252
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
253
0
       "%s: unable to clear key data.",
254
0
       function );
255
256
0
      result = -1;
257
0
    }
258
845
    memory_free(
259
845
     internal_file );
260
845
  }
261
845
  return( result );
262
845
}
263
264
/* Signals a file to abort its current activity
265
 * Returns 1 if successful or -1 on error
266
 */
267
int libqcow_file_signal_abort(
268
     libqcow_file_t *file,
269
     libcerror_error_t **error )
270
0
{
271
0
  libqcow_internal_file_t *internal_file = NULL;
272
0
  static char *function                  = "libqcow_file_signal_abort";
273
274
0
  if( file == 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 file.",
281
0
     function );
282
283
0
    return( -1 );
284
0
  }
285
0
  internal_file = (libqcow_internal_file_t *) file;
286
287
0
  if( internal_file->io_handle == NULL )
288
0
  {
289
0
    libcerror_error_set(
290
0
     error,
291
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
292
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
293
0
     "%s: invalid file - missing IO handle.",
294
0
     function );
295
296
0
    return( -1 );
297
0
  }
298
0
  internal_file->io_handle->abort = 1;
299
300
0
  return( 1 );
301
0
}
302
303
/* Opens a file
304
 * Returns 1 if successful or -1 on error
305
 */
306
int libqcow_file_open(
307
     libqcow_file_t *file,
308
     const char *filename,
309
     int access_flags,
310
     libcerror_error_t **error )
311
0
{
312
0
  libbfio_handle_t *file_io_handle       = NULL;
313
0
  libqcow_internal_file_t *internal_file = NULL;
314
0
  static char *function                  = "libqcow_file_open";
315
316
0
  if( file == NULL )
317
0
  {
318
0
    libcerror_error_set(
319
0
     error,
320
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
321
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
322
0
     "%s: invalid file.",
323
0
     function );
324
325
0
    return( -1 );
326
0
  }
327
0
  if( filename == NULL )
328
0
  {
329
0
    libcerror_error_set(
330
0
     error,
331
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
332
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
333
0
     "%s: invalid filename.",
334
0
     function );
335
336
0
    return( -1 );
337
0
  }
338
0
  if( ( ( access_flags & LIBQCOW_ACCESS_FLAG_READ ) == 0 )
339
0
   && ( ( access_flags & LIBQCOW_ACCESS_FLAG_WRITE ) == 0 ) )
340
0
  {
341
0
    libcerror_error_set(
342
0
     error,
343
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
344
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
345
0
     "%s: unsupported access flags.",
346
0
     function );
347
348
0
    return( -1 );
349
0
  }
350
0
  if( ( access_flags & LIBQCOW_ACCESS_FLAG_WRITE ) != 0 )
351
0
  {
352
0
    libcerror_error_set(
353
0
     error,
354
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
355
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
356
0
     "%s: write access currently not supported.",
357
0
     function );
358
359
0
    return( -1 );
360
0
  }
361
0
  internal_file = (libqcow_internal_file_t *) file;
362
363
0
  if( libbfio_file_initialize(
364
0
       &file_io_handle,
365
0
       error ) != 1 )
366
0
  {
367
0
    libcerror_error_set(
368
0
     error,
369
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
370
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
371
0
     "%s: unable to create file IO handle.",
372
0
     function );
373
374
0
    goto on_error;
375
0
  }
376
#if defined( HAVE_DEBUG_OUTPUT )
377
  if( libbfio_handle_set_track_offsets_read(
378
       file_io_handle,
379
       1,
380
       error ) != 1 )
381
  {
382
                libcerror_error_set(
383
                 error,
384
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
385
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
386
                 "%s: unable to set track offsets read in file IO handle.",
387
                 function );
388
389
    goto on_error;
390
  }
391
#endif
392
0
  if( libbfio_file_set_name(
393
0
       file_io_handle,
394
0
       filename,
395
0
       narrow_string_length(
396
0
        filename ) + 1,
397
0
       error ) != 1 )
398
0
  {
399
0
                libcerror_error_set(
400
0
                 error,
401
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
402
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
403
0
                 "%s: unable to set filename in file IO handle.",
404
0
                 function );
405
406
0
    goto on_error;
407
0
  }
408
0
  if( libqcow_file_open_file_io_handle(
409
0
       file,
410
0
       file_io_handle,
411
0
       access_flags,
412
0
       error ) != 1 )
413
0
  {
414
0
    libcerror_error_set(
415
0
     error,
416
0
     LIBCERROR_ERROR_DOMAIN_IO,
417
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
418
0
     "%s: unable to open file: %s.",
419
0
     function,
420
0
     filename );
421
422
0
    goto on_error;
423
0
  }
424
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
425
0
  if( libcthreads_read_write_lock_grab_for_write(
426
0
       internal_file->read_write_lock,
427
0
       error ) != 1 )
428
0
  {
429
0
    libcerror_error_set(
430
0
     error,
431
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
432
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
433
0
     "%s: unable to grab read/write lock for writing.",
434
0
     function );
435
436
0
    return( -1 );
437
0
  }
438
0
#endif
439
0
  internal_file->file_io_handle_created_in_library = 1;
440
441
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
442
0
  if( libcthreads_read_write_lock_release_for_write(
443
0
       internal_file->read_write_lock,
444
0
       error ) != 1 )
445
0
  {
446
0
    libcerror_error_set(
447
0
     error,
448
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
449
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
450
0
     "%s: unable to release read/write lock for writing.",
451
0
     function );
452
453
0
    return( -1 );
454
0
  }
455
0
#endif
456
0
  return( 1 );
457
458
0
on_error:
459
0
  if( file_io_handle != NULL )
460
0
  {
461
0
    libbfio_handle_free(
462
0
     &file_io_handle,
463
0
     NULL );
464
0
  }
465
0
  return( -1 );
466
0
}
467
468
#if defined( HAVE_WIDE_CHARACTER_TYPE )
469
470
/* Opens a file
471
 * Returns 1 if successful or -1 on error
472
 */
473
int libqcow_file_open_wide(
474
     libqcow_file_t *file,
475
     const wchar_t *filename,
476
     int access_flags,
477
     libcerror_error_t **error )
478
{
479
  libbfio_handle_t *file_io_handle       = NULL;
480
  libqcow_internal_file_t *internal_file = NULL;
481
  static char *function                  = "libqcow_file_open_wide";
482
483
  if( file == NULL )
484
  {
485
    libcerror_error_set(
486
     error,
487
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
488
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
489
     "%s: invalid file.",
490
     function );
491
492
    return( -1 );
493
  }
494
  if( filename == NULL )
495
  {
496
    libcerror_error_set(
497
     error,
498
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
499
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
500
     "%s: invalid filename.",
501
     function );
502
503
    return( -1 );
504
  }
505
  if( ( ( access_flags & LIBQCOW_ACCESS_FLAG_READ ) == 0 )
506
   && ( ( access_flags & LIBQCOW_ACCESS_FLAG_WRITE ) == 0 ) )
507
  {
508
    libcerror_error_set(
509
     error,
510
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
511
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
512
     "%s: unsupported access flags.",
513
     function );
514
515
    return( -1 );
516
  }
517
  if( ( access_flags & LIBQCOW_ACCESS_FLAG_WRITE ) != 0 )
518
  {
519
    libcerror_error_set(
520
     error,
521
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
522
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
523
     "%s: write access currently not supported.",
524
     function );
525
526
    return( -1 );
527
  }
528
  internal_file = (libqcow_internal_file_t *) file;
529
530
  if( libbfio_file_initialize(
531
       &file_io_handle,
532
       error ) != 1 )
533
  {
534
    libcerror_error_set(
535
     error,
536
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
537
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
538
     "%s: unable to create file IO handle.",
539
     function );
540
541
    goto on_error;
542
  }
543
#if defined( HAVE_DEBUG_OUTPUT )
544
  if( libbfio_handle_set_track_offsets_read(
545
       file_io_handle,
546
       1,
547
       error ) != 1 )
548
  {
549
                libcerror_error_set(
550
                 error,
551
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
552
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
553
                 "%s: unable to set track offsets read in file IO handle.",
554
                 function );
555
556
    goto on_error;
557
  }
558
#endif
559
  if( libbfio_file_set_name_wide(
560
       file_io_handle,
561
       filename,
562
       wide_string_length(
563
        filename ) + 1,
564
       error ) != 1 )
565
  {
566
                libcerror_error_set(
567
                 error,
568
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
569
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
570
                 "%s: unable to set filename in file IO handle.",
571
                 function );
572
573
    goto on_error;
574
  }
575
  if( libqcow_file_open_file_io_handle(
576
       file,
577
       file_io_handle,
578
       access_flags,
579
       error ) != 1 )
580
  {
581
    libcerror_error_set(
582
     error,
583
     LIBCERROR_ERROR_DOMAIN_IO,
584
     LIBCERROR_IO_ERROR_OPEN_FAILED,
585
     "%s: unable to open file: %ls.",
586
     function,
587
     filename );
588
589
    goto on_error;
590
  }
591
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
592
  if( libcthreads_read_write_lock_grab_for_write(
593
       internal_file->read_write_lock,
594
       error ) != 1 )
595
  {
596
    libcerror_error_set(
597
     error,
598
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
599
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
600
     "%s: unable to grab read/write lock for writing.",
601
     function );
602
603
    return( -1 );
604
  }
605
#endif
606
  internal_file->file_io_handle_created_in_library = 1;
607
608
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
609
  if( libcthreads_read_write_lock_release_for_write(
610
       internal_file->read_write_lock,
611
       error ) != 1 )
612
  {
613
    libcerror_error_set(
614
     error,
615
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
616
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
617
     "%s: unable to release read/write lock for writing.",
618
     function );
619
620
    return( -1 );
621
  }
622
#endif
623
  return( 1 );
624
625
on_error:
626
  if( file_io_handle != NULL )
627
  {
628
    libbfio_handle_free(
629
     &file_io_handle,
630
     NULL );
631
  }
632
  return( -1 );
633
}
634
635
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
636
637
/* Opens a file using a Basic File IO (bfio) handle
638
 * Returns 1 if successful or -1 on error
639
 */
640
int libqcow_file_open_file_io_handle(
641
     libqcow_file_t *file,
642
     libbfio_handle_t *file_io_handle,
643
     int access_flags,
644
     libcerror_error_t **error )
645
845
{
646
845
  libqcow_internal_file_t *internal_file   = NULL;
647
845
  static char *function                    = "libqcow_file_open_file_io_handle";
648
845
  uint8_t file_io_handle_opened_in_library = 0;
649
845
  int bfio_access_flags                    = 0;
650
845
  int file_io_handle_is_open               = 0;
651
845
  int result                               = 0;
652
653
845
  if( file == NULL )
654
0
  {
655
0
    libcerror_error_set(
656
0
     error,
657
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
658
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
659
0
     "%s: invalid file.",
660
0
     function );
661
662
0
    return( -1 );
663
0
  }
664
845
  internal_file = (libqcow_internal_file_t *) file;
665
666
845
  if( internal_file->file_io_handle != NULL )
667
0
  {
668
0
    libcerror_error_set(
669
0
     error,
670
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
671
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
672
0
     "%s: invalid file - file IO handle already set.",
673
0
     function );
674
675
0
    return( -1 );
676
0
  }
677
845
  if( file_io_handle == NULL )
678
0
  {
679
0
    libcerror_error_set(
680
0
     error,
681
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
682
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
683
0
     "%s: invalid file IO handle.",
684
0
     function );
685
686
0
    return( -1 );
687
0
  }
688
845
  if( ( ( access_flags & LIBQCOW_ACCESS_FLAG_READ ) == 0 )
689
845
   && ( ( access_flags & LIBQCOW_ACCESS_FLAG_WRITE ) == 0 ) )
690
0
  {
691
0
    libcerror_error_set(
692
0
     error,
693
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
694
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
695
0
     "%s: unsupported access flags.",
696
0
     function );
697
698
0
    return( -1 );
699
0
  }
700
845
  if( ( access_flags & LIBQCOW_ACCESS_FLAG_WRITE ) != 0 )
701
0
  {
702
0
    libcerror_error_set(
703
0
     error,
704
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
705
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
706
0
     "%s: write access currently not supported.",
707
0
     function );
708
709
0
    return( -1 );
710
0
  }
711
845
  if( ( access_flags & LIBQCOW_ACCESS_FLAG_READ ) != 0 )
712
845
  {
713
845
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
714
845
  }
715
845
  file_io_handle_is_open = libbfio_handle_is_open(
716
845
                            file_io_handle,
717
845
                            error );
718
719
845
  if( file_io_handle_is_open == -1 )
720
0
  {
721
0
    libcerror_error_set(
722
0
     error,
723
0
     LIBCERROR_ERROR_DOMAIN_IO,
724
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
725
0
     "%s: unable to determine if file IO handle is open.",
726
0
     function );
727
728
0
    goto on_error;
729
0
  }
730
845
  else if( file_io_handle_is_open == 0 )
731
845
  {
732
845
    if( libbfio_handle_open(
733
845
         file_io_handle,
734
845
         bfio_access_flags,
735
845
         error ) != 1 )
736
0
    {
737
0
      libcerror_error_set(
738
0
       error,
739
0
       LIBCERROR_ERROR_DOMAIN_IO,
740
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
741
0
       "%s: unable to open file IO handle.",
742
0
       function );
743
744
0
      goto on_error;
745
0
    }
746
845
    file_io_handle_opened_in_library = 1;
747
845
  }
748
845
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
749
845
  if( libcthreads_read_write_lock_grab_for_write(
750
845
       internal_file->read_write_lock,
751
845
       error ) != 1 )
752
0
  {
753
0
    libcerror_error_set(
754
0
     error,
755
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
756
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
757
0
     "%s: unable to grab read/write lock for writing.",
758
0
     function );
759
760
0
    return( -1 );
761
0
  }
762
845
#endif
763
845
  result = libqcow_internal_file_open_read(
764
845
            internal_file,
765
845
            file_io_handle,
766
845
            error );
767
768
845
  if( result != 1 )
769
800
  {
770
800
    libcerror_error_set(
771
800
     error,
772
800
     LIBCERROR_ERROR_DOMAIN_IO,
773
800
     LIBCERROR_IO_ERROR_READ_FAILED,
774
800
     "%s: unable to read from file IO handle.",
775
800
     function );
776
800
  }
777
45
  else
778
45
  {
779
45
    internal_file->file_io_handle                   = file_io_handle;
780
45
    internal_file->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
781
45
  }
782
845
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
783
845
  if( libcthreads_read_write_lock_release_for_write(
784
845
       internal_file->read_write_lock,
785
845
       error ) != 1 )
786
0
  {
787
0
    libcerror_error_set(
788
0
     error,
789
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
790
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
791
0
     "%s: unable to release read/write lock for writing.",
792
0
     function );
793
794
0
    return( -1 );
795
0
  }
796
845
#endif
797
845
  return( result );
798
799
0
on_error:
800
0
  if( file_io_handle_opened_in_library != 0 )
801
0
  {
802
0
    libbfio_handle_close(
803
0
     file_io_handle,
804
0
     error );
805
0
  }
806
0
  return( -1 );
807
845
}
808
809
/* Closes a file
810
 * Returns 0 if successful or -1 on error
811
 */
812
int libqcow_file_close(
813
     libqcow_file_t *file,
814
     libcerror_error_t **error )
815
45
{
816
45
  libqcow_internal_file_t *internal_file = NULL;
817
45
  static char *function                  = "libqcow_file_close";
818
45
  int result                             = 0;
819
820
45
  if( file == NULL )
821
0
  {
822
0
    libcerror_error_set(
823
0
     error,
824
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
825
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
826
0
     "%s: invalid file.",
827
0
     function );
828
829
0
    return( -1 );
830
0
  }
831
45
  internal_file = (libqcow_internal_file_t *) file;
832
833
45
  if( internal_file->file_io_handle == NULL )
834
0
  {
835
0
    libcerror_error_set(
836
0
     error,
837
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
838
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
839
0
     "%s: invalid file - missing file IO handle.",
840
0
     function );
841
842
0
    return( -1 );
843
0
  }
844
45
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
845
45
  if( libcthreads_read_write_lock_grab_for_write(
846
45
       internal_file->read_write_lock,
847
45
       error ) != 1 )
848
0
  {
849
0
    libcerror_error_set(
850
0
     error,
851
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
852
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
853
0
     "%s: unable to grab read/write lock for writing.",
854
0
     function );
855
856
0
    return( -1 );
857
0
  }
858
45
#endif
859
#if defined( HAVE_DEBUG_OUTPUT )
860
  if( libcnotify_verbose != 0 )
861
  {
862
    if( internal_file->file_io_handle_created_in_library != 0 )
863
    {
864
      if( libqcow_debug_print_read_offsets(
865
           internal_file->file_io_handle,
866
           error ) != 1 )
867
      {
868
        libcerror_error_set(
869
         error,
870
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
871
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
872
         "%s: unable to print the read offsets.",
873
         function );
874
875
        result = -1;
876
      }
877
    }
878
  }
879
#endif
880
45
  if( internal_file->file_io_handle_opened_in_library != 0 )
881
45
  {
882
45
    if( libbfio_handle_close(
883
45
         internal_file->file_io_handle,
884
45
         error ) != 0 )
885
0
    {
886
0
      libcerror_error_set(
887
0
       error,
888
0
       LIBCERROR_ERROR_DOMAIN_IO,
889
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
890
0
       "%s: unable to close file IO handle.",
891
0
       function );
892
893
0
      result = -1;
894
0
    }
895
45
    internal_file->file_io_handle_opened_in_library = 0;
896
45
  }
897
45
  if( internal_file->file_io_handle_created_in_library != 0 )
898
0
  {
899
0
    if( libbfio_handle_free(
900
0
         &( internal_file->file_io_handle ),
901
0
         error ) != 1 )
902
0
    {
903
0
      libcerror_error_set(
904
0
       error,
905
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
906
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
907
0
       "%s: unable to free file IO handle.",
908
0
       function );
909
910
0
      result = -1;
911
0
    }
912
0
    internal_file->file_io_handle_created_in_library = 0;
913
0
  }
914
45
  internal_file->file_io_handle = NULL;
915
45
  internal_file->current_offset = 0;
916
45
  internal_file->is_locked      = 1;
917
918
45
  if( libqcow_io_handle_clear(
919
45
       internal_file->io_handle,
920
45
       error ) != 1 )
921
0
  {
922
0
    libcerror_error_set(
923
0
     error,
924
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
925
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
926
0
     "%s: unable to clear IO handle.",
927
0
     function );
928
929
0
    result = -1;
930
0
  }
931
45
  if( libqcow_file_header_free(
932
45
       &( internal_file->file_header ),
933
45
       error ) != 1 )
934
0
  {
935
0
    libcerror_error_set(
936
0
     error,
937
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
938
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
939
0
     "%s: unable to free file header.",
940
0
     function );
941
942
0
    result = -1;
943
0
  }
944
45
  if( internal_file->backing_filename != NULL )
945
18
  {
946
18
    memory_free(
947
18
     internal_file->backing_filename );
948
949
18
    internal_file->backing_filename      = NULL;
950
18
    internal_file->backing_filename_size = 0;
951
18
  }
952
45
  if( libqcow_cluster_table_free(
953
45
       &( internal_file->level1_table ),
954
45
       error ) != 1 )
955
0
  {
956
0
    libcerror_error_set(
957
0
     error,
958
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
959
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
960
0
     "%s: unable to free level 1 table.",
961
0
     function );
962
963
0
    result = -1;
964
0
  }
965
45
  if( libfdata_vector_free(
966
45
       &( internal_file->level2_table_vector ),
967
45
       error ) != 1 )
968
0
  {
969
0
    libcerror_error_set(
970
0
     error,
971
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
972
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
973
0
     "%s: unable to free level2 table vector.",
974
0
     function );
975
976
0
    result = -1;
977
0
  }
978
45
  if( libfcache_cache_free(
979
45
       &( internal_file->level2_table_cache ),
980
45
       error ) != 1 )
981
0
  {
982
0
    libcerror_error_set(
983
0
     error,
984
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
985
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
986
0
     "%s: unable to free level2 table cache.",
987
0
     function );
988
989
0
    result = -1;
990
0
  }
991
45
  if( libfdata_vector_free(
992
45
       &( internal_file->cluster_block_vector ),
993
45
       error ) != 1 )
994
0
  {
995
0
    libcerror_error_set(
996
0
     error,
997
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
998
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
999
0
     "%s: unable to free cluster block vector.",
1000
0
     function );
1001
1002
0
    result = -1;
1003
0
  }
1004
45
  if( libfcache_cache_free(
1005
45
       &( internal_file->cluster_block_cache ),
1006
45
       error ) != 1 )
1007
0
  {
1008
0
    libcerror_error_set(
1009
0
     error,
1010
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1011
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1012
0
     "%s: unable to free cluster block cache.",
1013
0
     function );
1014
1015
0
    result = -1;
1016
0
  }
1017
45
  if( libfcache_cache_free(
1018
45
       &( internal_file->compressed_cluster_block_cache ),
1019
45
       error ) != 1 )
1020
0
  {
1021
0
    libcerror_error_set(
1022
0
     error,
1023
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1024
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1025
0
     "%s: unable to free compressed cluster block cache.",
1026
0
     function );
1027
1028
0
    result = -1;
1029
0
  }
1030
45
  if( internal_file->encryption_context != NULL )
1031
31
  {
1032
31
    if( libqcow_encryption_free(
1033
31
         &( internal_file->encryption_context ),
1034
31
         error ) != 1 )
1035
0
    {
1036
0
      libcerror_error_set(
1037
0
       error,
1038
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1039
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1040
0
       "%s: unable to free encryption context.",
1041
0
       function );
1042
1043
0
      result = -1;
1044
0
    }
1045
31
  }
1046
45
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
1047
45
  if( libcthreads_read_write_lock_release_for_write(
1048
45
       internal_file->read_write_lock,
1049
45
       error ) != 1 )
1050
0
  {
1051
0
    libcerror_error_set(
1052
0
     error,
1053
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1054
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1055
0
     "%s: unable to release read/write lock for writing.",
1056
0
     function );
1057
1058
0
    return( -1 );
1059
0
  }
1060
45
#endif
1061
45
  return( result );
1062
45
}
1063
1064
/* Opens a file for reading
1065
 * Returns 1 if successful or -1 on error
1066
 */
1067
int libqcow_internal_file_open_read(
1068
     libqcow_internal_file_t *internal_file,
1069
     libbfio_handle_t *file_io_handle,
1070
     libcerror_error_t **error )
1071
845
{
1072
845
  static char *function                      = "libqcow_internal_file_open_read";
1073
845
  size_t level1_table_size                   = 0;
1074
845
  size_t level2_table_size                   = 0;
1075
845
  uint32_t number_of_level1_table_references = 0;
1076
845
  uint32_t number_of_level2_table_bits       = 0;
1077
845
  int entry_index                            = 0;
1078
1079
845
  if( internal_file == NULL )
1080
0
  {
1081
0
    libcerror_error_set(
1082
0
     error,
1083
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1084
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1085
0
     "%s: invalid file.",
1086
0
     function );
1087
1088
0
    return( -1 );
1089
0
  }
1090
845
  if( internal_file->io_handle == NULL )
1091
0
  {
1092
0
    libcerror_error_set(
1093
0
     error,
1094
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1095
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1096
0
     "%s: invalid file - missing IO handle.",
1097
0
     function );
1098
1099
0
    return( -1 );
1100
0
  }
1101
845
  if( internal_file->file_header != NULL )
1102
0
  {
1103
0
    libcerror_error_set(
1104
0
     error,
1105
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1106
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1107
0
     "%s: invalid file - file header value already set.",
1108
0
     function );
1109
1110
0
    return( -1 );
1111
0
  }
1112
845
  if( internal_file->backing_filename != NULL )
1113
0
  {
1114
0
    libcerror_error_set(
1115
0
     error,
1116
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1117
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1118
0
     "%s: invalid file - backing filename value already set.",
1119
0
     function );
1120
1121
0
    return( -1 );
1122
0
  }
1123
845
  if( internal_file->level1_table != NULL )
1124
0
  {
1125
0
    libcerror_error_set(
1126
0
     error,
1127
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1128
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1129
0
     "%s: invalid file - level 1 table already set.",
1130
0
     function );
1131
1132
0
    return( -1 );
1133
0
  }
1134
845
  if( internal_file->level2_table_vector != NULL )
1135
0
  {
1136
0
    libcerror_error_set(
1137
0
     error,
1138
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1139
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1140
0
     "%s: invalid file - level2 table vector already set.",
1141
0
     function );
1142
1143
0
    return( -1 );
1144
0
  }
1145
845
  if( internal_file->level2_table_cache != NULL )
1146
0
  {
1147
0
    libcerror_error_set(
1148
0
     error,
1149
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1150
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1151
0
     "%s: invalid file - level2 table cache already set.",
1152
0
     function );
1153
1154
0
    return( -1 );
1155
0
  }
1156
845
  if( internal_file->cluster_block_vector != NULL )
1157
0
  {
1158
0
    libcerror_error_set(
1159
0
     error,
1160
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1161
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1162
0
     "%s: invalid file - cluster block vector already set.",
1163
0
     function );
1164
1165
0
    return( -1 );
1166
0
  }
1167
845
  if( internal_file->cluster_block_cache != NULL )
1168
0
  {
1169
0
    libcerror_error_set(
1170
0
     error,
1171
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1172
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1173
0
     "%s: invalid file - cluster block cache already set.",
1174
0
     function );
1175
1176
0
    return( -1 );
1177
0
  }
1178
845
  if( internal_file->compressed_cluster_block_cache != NULL )
1179
0
  {
1180
0
    libcerror_error_set(
1181
0
     error,
1182
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1183
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1184
0
     "%s: invalid file - compressed cluster block cache already set.",
1185
0
     function );
1186
1187
0
    return( -1 );
1188
0
  }
1189
845
  if( libbfio_handle_get_size(
1190
845
       file_io_handle,
1191
845
       &( internal_file->size ),
1192
845
       error ) != 1 )
1193
0
  {
1194
0
    libcerror_error_set(
1195
0
     error,
1196
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1197
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1198
0
     "%s: unable to retrieve file size.",
1199
0
     function );
1200
1201
0
    goto on_error;
1202
0
  }
1203
845
  if( internal_file->size == 0 )
1204
0
  {
1205
0
    libcerror_error_set(
1206
0
     error,
1207
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1208
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1209
0
     "%s: invalid file size.",
1210
0
     function );
1211
1212
0
    goto on_error;
1213
0
  }
1214
#if defined( HAVE_DEBUG_OUTPUT )
1215
  if( libcnotify_verbose != 0 )
1216
  {
1217
    libcnotify_printf(
1218
     "Reading file header:\n" );
1219
  }
1220
#endif
1221
845
  if( libqcow_file_header_initialize(
1222
845
       &( internal_file->file_header ),
1223
845
       error ) != 1 )
1224
0
  {
1225
0
    libcerror_error_set(
1226
0
     error,
1227
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1228
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1229
0
     "%s: unable to create file header.",
1230
0
     function );
1231
1232
0
    goto on_error;
1233
0
  }
1234
845
  if( libqcow_file_header_read_file_io_handle(
1235
845
       internal_file->file_header,
1236
845
       file_io_handle,
1237
845
       error ) != 1 )
1238
330
  {
1239
330
    libcerror_error_set(
1240
330
     error,
1241
330
     LIBCERROR_ERROR_DOMAIN_IO,
1242
330
     LIBCERROR_IO_ERROR_READ_FAILED,
1243
330
     "%s: unable to read file header.",
1244
330
     function );
1245
1246
330
    goto on_error;
1247
330
  }
1248
1249
515
  internal_file->encryption_method  = internal_file->file_header->encryption_method;
1250
1251
515
  number_of_level1_table_references = internal_file->file_header->number_of_level1_table_references;
1252
1253
515
  if( internal_file->file_header->format_version == 1 )
1254
452
  {
1255
452
    if( internal_file->file_header->number_of_cluster_block_bits > 63 )
1256
2
    {
1257
2
      libcerror_error_set(
1258
2
       error,
1259
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1260
2
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1261
2
       "%s: invalid number of cluster block bits value out of bounds.",
1262
2
       function );
1263
1264
2
      goto on_error;
1265
2
    }
1266
450
    if( internal_file->file_header->number_of_level2_table_bits > 63 )
1267
2
    {
1268
2
      libcerror_error_set(
1269
2
       error,
1270
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1271
2
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1272
2
       "%s: invalid number of cluster block bits value out of bounds.",
1273
2
       function );
1274
1275
2
      goto on_error;
1276
2
    }
1277
448
    number_of_level2_table_bits = internal_file->file_header->number_of_level2_table_bits;
1278
1279
448
    internal_file->offset_bit_mask           = 0x7fffffffffffffffULL;
1280
448
    internal_file->compression_flag_bit_mask = (uint64_t) 1UL << 63;
1281
448
    internal_file->compression_bit_shift     = 63 - internal_file->file_header->number_of_cluster_block_bits;
1282
448
  }
1283
63
  else if( ( internal_file->file_header->format_version == 2 )
1284
63
        || ( internal_file->file_header->format_version == 3 ) )
1285
63
  {
1286
63
    if( ( internal_file->file_header->number_of_cluster_block_bits <= 8 )
1287
63
     || ( internal_file->file_header->number_of_cluster_block_bits > 63 ) )
1288
45
    {
1289
45
      libcerror_error_set(
1290
45
       error,
1291
45
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1292
45
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1293
45
       "%s: invalid number of cluster block bits value out of bounds.",
1294
45
       function );
1295
1296
45
      goto on_error;
1297
45
    }
1298
18
    number_of_level2_table_bits = internal_file->file_header->number_of_cluster_block_bits - 3;
1299
1300
18
    internal_file->offset_bit_mask           = 0x3fffffffffffffffULL;
1301
18
    internal_file->compression_flag_bit_mask = (uint64_t) 1UL << 62;
1302
18
    internal_file->compression_bit_shift     = 62 - ( internal_file->file_header->number_of_cluster_block_bits - 8 );
1303
18
  }
1304
466
  internal_file->level1_index_bit_shift = internal_file->file_header->number_of_cluster_block_bits + number_of_level2_table_bits;
1305
1306
466
  if( internal_file->level1_index_bit_shift > 63 )
1307
5
  {
1308
5
    libcerror_error_set(
1309
5
     error,
1310
5
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1311
5
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1312
5
     "%s: invalid level1 index bit shift value out of bounds.",
1313
5
     function );
1314
1315
5
    goto on_error;
1316
5
  }
1317
461
  internal_file->level2_index_bit_mask  = ~( (uint64_t) -1 << number_of_level2_table_bits );
1318
461
  internal_file->cluster_block_bit_mask = ~( (uint64_t) -1 << internal_file->file_header->number_of_cluster_block_bits );
1319
461
  internal_file->compression_bit_mask   = ~( (uint64_t) -1 << internal_file->compression_bit_shift );
1320
461
  internal_file->cluster_block_size     = (size64_t) 1 << internal_file->file_header->number_of_cluster_block_bits;
1321
1322
461
  level2_table_size = (size_t) 1 << number_of_level2_table_bits;
1323
1324
461
  if( internal_file->file_header->format_version == 1 )
1325
446
  {
1326
446
    if( internal_file->cluster_block_size > ( (size64_t) MEMORY_MAXIMUM_ALLOCATION_SIZE / level2_table_size ) )
1327
63
    {
1328
63
      libcerror_error_set(
1329
63
       error,
1330
63
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1331
63
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1332
63
       "%s: invalid cluster block size value out of bounds.",
1333
63
       function );
1334
1335
63
      goto on_error;
1336
63
    }
1337
383
    level1_table_size = (size_t) ( internal_file->cluster_block_size * level2_table_size );
1338
1339
383
    if( ( internal_file->file_header->media_size / level1_table_size ) > ( (size64_t) UINT32_MAX - 1 ) )
1340
39
    {
1341
39
      libcerror_error_set(
1342
39
       error,
1343
39
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1344
39
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1345
39
       "%s: invalid level1 table size value out of bounds: %zd.",
1346
39
       function, level1_table_size );
1347
1348
39
      goto on_error;
1349
39
    }
1350
344
    number_of_level1_table_references = (uint32_t) ( internal_file->file_header->media_size / level1_table_size );
1351
1352
344
    if( ( internal_file->file_header->media_size % level1_table_size ) != 0 )
1353
110
    {
1354
110
      number_of_level1_table_references += 1;
1355
110
    }
1356
344
    level1_table_size = (size_t) number_of_level1_table_references;
1357
344
  }
1358
15
  else if( ( internal_file->file_header->format_version == 2 )
1359
15
        || ( internal_file->file_header->format_version == 3 ) )
1360
15
  {
1361
15
    if( internal_file->cluster_block_size > (size64_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
1362
2
    {
1363
2
      libcerror_error_set(
1364
2
       error,
1365
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1366
2
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1367
2
       "%s: invalid cluster block size value out of bounds.",
1368
2
       function );
1369
1370
2
      goto on_error;
1371
2
    }
1372
13
    level1_table_size = (size_t) number_of_level1_table_references;
1373
13
  }
1374
357
  if( ( level1_table_size == 0 )
1375
357
   || ( level1_table_size > ( (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE / 8 ) ) )
1376
39
  {
1377
39
    libcerror_error_set(
1378
39
     error,
1379
39
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1380
39
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1381
39
     "%s: invalid level1 table size value out of bounds.",
1382
39
     function );
1383
1384
39
    goto on_error;
1385
39
  }
1386
318
  if( ( level2_table_size == 0 )
1387
318
   || ( level2_table_size > ( (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE / 8 ) ) )
1388
1
  {
1389
1
    libcerror_error_set(
1390
1
     error,
1391
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1392
1
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1393
1
     "%s: invalid level2 table size value out of bounds.",
1394
1
     function );
1395
1396
1
    goto on_error;
1397
1
  }
1398
317
  level1_table_size *= 8;
1399
317
  level2_table_size *= 8;
1400
1401
#if defined( HAVE_DEBUG_OUTPUT )
1402
  if( libcnotify_verbose != 0 )
1403
  {
1404
    libcnotify_printf(
1405
     "%s: level 1 table size\t\t\t: %" PRIzd "\n",
1406
     function,
1407
     level1_table_size );
1408
1409
    libcnotify_printf(
1410
     "%s: level 2 table size\t\t\t: %" PRIzd "\n",
1411
     function,
1412
     level2_table_size );
1413
1414
    libcnotify_printf(
1415
     "%s: cluster block size\t\t\t: %" PRIu64 "\n",
1416
     function,
1417
     internal_file->cluster_block_size );
1418
1419
    libcnotify_printf(
1420
     "\n" );
1421
  }
1422
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1423
1424
317
  if( ( internal_file->file_header->backing_filename_offset > 0 )
1425
317
   && ( internal_file->file_header->backing_filename_size > 0 ) )
1426
204
  {
1427
204
    if( libqcow_internal_file_open_read_backing_filename(
1428
204
         internal_file,
1429
204
         file_io_handle,
1430
204
         internal_file->file_header->backing_filename_offset,
1431
204
         internal_file->file_header->backing_filename_size,
1432
204
         error ) != 1 )
1433
140
    {
1434
140
      libcerror_error_set(
1435
140
       error,
1436
140
       LIBCERROR_ERROR_DOMAIN_IO,
1437
140
       LIBCERROR_IO_ERROR_READ_FAILED,
1438
140
       "%s: unable to read backing filename.",
1439
140
       function );
1440
1441
140
      goto on_error;
1442
140
    }
1443
204
  }
1444
177
  if( internal_file->encryption_method != LIBQCOW_ENCRYPTION_METHOD_NONE )
1445
139
  {
1446
139
    if( libqcow_encryption_initialize(
1447
139
         &( internal_file->encryption_context ),
1448
139
         internal_file->encryption_method,
1449
139
         error ) != 1 )
1450
0
    {
1451
0
      libcerror_error_set(
1452
0
       error,
1453
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1454
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1455
0
       "%s: unable to create encryption context.",
1456
0
       function );
1457
1458
0
      goto on_error;
1459
0
    }
1460
#if defined( HAVE_DEBUG_OUTPUT )
1461
    if( libcnotify_verbose != 0 )
1462
    {
1463
      libcnotify_printf(
1464
       "%s: key:\n",
1465
       function );
1466
      libcnotify_print_data(
1467
       internal_file->key_data,
1468
       16,
1469
       0 );
1470
    }
1471
#endif
1472
139
    if( libqcow_encryption_set_keys(
1473
139
         internal_file->encryption_context,
1474
139
         internal_file->key_data,
1475
139
         16,
1476
139
         error ) != 1 )
1477
0
    {
1478
0
      libcerror_error_set(
1479
0
       error,
1480
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1481
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1482
0
       "%s: unable to set key data in encryption context.",
1483
0
       function );
1484
1485
0
      goto on_error;
1486
0
    }
1487
139
  }
1488
#if defined( HAVE_DEBUG_OUTPUT )
1489
  if( libcnotify_verbose != 0 )
1490
  {
1491
    libcnotify_printf(
1492
     "Reading level 1 table:\n" );
1493
  }
1494
#endif
1495
177
  if( libqcow_cluster_table_initialize(
1496
177
       &( internal_file->level1_table ),
1497
177
       error ) != 1 )
1498
0
  {
1499
0
    libcerror_error_set(
1500
0
     error,
1501
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1502
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1503
0
     "%s: unable to create level 1 table.",
1504
0
     function );
1505
1506
0
    goto on_error;
1507
0
  }
1508
177
  if( libqcow_cluster_table_read(
1509
177
       internal_file->level1_table,
1510
177
       file_io_handle,
1511
177
       internal_file->file_header->level1_table_offset,
1512
177
       level1_table_size,
1513
177
       error ) != 1 )
1514
132
  {
1515
132
    libcerror_error_set(
1516
132
     error,
1517
132
     LIBCERROR_ERROR_DOMAIN_IO,
1518
132
     LIBCERROR_IO_ERROR_READ_FAILED,
1519
132
     "%s: unable to read level 1 table.",
1520
132
     function );
1521
1522
132
    goto on_error;
1523
132
  }
1524
/* TODO clone function ? */
1525
45
  if( libfdata_vector_initialize(
1526
45
       &( internal_file->level2_table_vector ),
1527
45
       (size64_t) level2_table_size,
1528
45
       (intptr_t *) internal_file->io_handle,
1529
45
       NULL,
1530
45
       NULL,
1531
45
       (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libqcow_io_handle_read_level2_table,
1532
45
       NULL,
1533
45
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
1534
45
       error ) != 1 )
1535
0
  {
1536
0
    libcerror_error_set(
1537
0
     error,
1538
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1539
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1540
0
     "%s: unable to create level2 table vector.",
1541
0
     function );
1542
1543
0
    goto on_error;
1544
0
  }
1545
45
  if( libfdata_vector_append_segment(
1546
45
       internal_file->level2_table_vector,
1547
45
       &entry_index,
1548
45
       0,
1549
45
       0,
1550
45
       internal_file->size,
1551
45
       0,
1552
45
       error ) != 1 )
1553
0
  {
1554
0
    libcerror_error_set(
1555
0
     error,
1556
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1557
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1558
0
     "%s: unable to append segment to level2 table vector.",
1559
0
     function );
1560
1561
0
    goto on_error;
1562
0
  }
1563
45
  if( libfcache_cache_initialize(
1564
45
       &( internal_file->level2_table_cache ),
1565
45
       LIBQCOW_MAXIMUM_CACHE_ENTRIES_LEVEL2_TABLES,
1566
45
       error ) != 1 )
1567
0
  {
1568
0
    libcerror_error_set(
1569
0
     error,
1570
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1571
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1572
0
     "%s: unable to create level2 table cache.",
1573
0
     function );
1574
1575
0
    goto on_error;
1576
0
  }
1577
/* TODO clone function ? */
1578
45
  if( libfdata_vector_initialize(
1579
45
       &( internal_file->cluster_block_vector ),
1580
45
       internal_file->cluster_block_size,
1581
45
       (intptr_t *) internal_file->io_handle,
1582
45
       NULL,
1583
45
       NULL,
1584
45
       (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libqcow_io_handle_read_cluster_block,
1585
45
       NULL,
1586
45
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
1587
45
       error ) != 1 )
1588
0
  {
1589
0
    libcerror_error_set(
1590
0
     error,
1591
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1592
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1593
0
     "%s: unable to create cluster block vector.",
1594
0
     function );
1595
1596
0
    goto on_error;
1597
0
  }
1598
45
  if( libfdata_vector_append_segment(
1599
45
       internal_file->cluster_block_vector,
1600
45
       &entry_index,
1601
45
       0,
1602
45
       0,
1603
45
       internal_file->size,
1604
45
       0,
1605
45
       error ) != 1 )
1606
0
  {
1607
0
    libcerror_error_set(
1608
0
     error,
1609
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1610
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1611
0
     "%s: unable to append segment to cluster block vector.",
1612
0
     function );
1613
1614
0
    goto on_error;
1615
0
  }
1616
45
  if( libfcache_cache_initialize(
1617
45
       &( internal_file->cluster_block_cache ),
1618
45
       LIBQCOW_MAXIMUM_CACHE_ENTRIES_CLUSTER_BLOCKS,
1619
45
       error ) != 1 )
1620
0
  {
1621
0
    libcerror_error_set(
1622
0
     error,
1623
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1624
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1625
0
     "%s: unable to create cluster block cache.",
1626
0
     function );
1627
1628
0
    goto on_error;
1629
0
  }
1630
45
  if( libfcache_cache_initialize(
1631
45
       &( internal_file->compressed_cluster_block_cache ),
1632
45
       LIBQCOW_MAXIMUM_CACHE_ENTRIES_CLUSTER_BLOCKS,
1633
45
       error ) != 1 )
1634
0
  {
1635
0
    libcerror_error_set(
1636
0
     error,
1637
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1638
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1639
0
     "%s: unable to create compressed cluster block cache.",
1640
0
     function );
1641
1642
0
    goto on_error;
1643
0
  }
1644
45
  internal_file->is_locked = 0;
1645
1646
45
  return( 1 );
1647
1648
800
on_error:
1649
800
  if( internal_file->cluster_block_cache != NULL )
1650
0
  {
1651
0
    libfcache_cache_free(
1652
0
     &( internal_file->cluster_block_cache ),
1653
0
     NULL );
1654
0
  }
1655
800
  if( internal_file->cluster_block_vector != NULL )
1656
0
  {
1657
0
    libfdata_vector_free(
1658
0
     &( internal_file->cluster_block_vector ),
1659
0
     NULL );
1660
0
  }
1661
800
  if( internal_file->level2_table_cache != NULL )
1662
0
  {
1663
0
    libfcache_cache_free(
1664
0
     &( internal_file->level2_table_cache ),
1665
0
     NULL );
1666
0
  }
1667
800
  if( internal_file->level2_table_vector != NULL )
1668
0
  {
1669
0
    libfdata_vector_free(
1670
0
     &( internal_file->level2_table_vector ),
1671
0
     NULL );
1672
0
  }
1673
800
  if( internal_file->level1_table != NULL )
1674
132
  {
1675
132
    libqcow_cluster_table_free(
1676
132
     &( internal_file->level1_table ),
1677
132
     NULL );
1678
132
  }
1679
800
  if( internal_file->encryption_context != NULL )
1680
108
  {
1681
108
    libqcow_encryption_free(
1682
108
     &( internal_file->encryption_context ),
1683
108
     NULL );
1684
108
  }
1685
800
  if( internal_file->backing_filename != NULL )
1686
46
  {
1687
46
    memory_free(
1688
46
     internal_file->backing_filename );
1689
1690
46
    internal_file->backing_filename = NULL;
1691
46
  }
1692
800
  internal_file->backing_filename_size = 0;
1693
1694
800
  if( internal_file->file_header != NULL )
1695
800
  {
1696
800
    libqcow_file_header_free(
1697
800
     &( internal_file->file_header ),
1698
800
     NULL );
1699
800
  }
1700
800
  return( -1 );
1701
45
}
1702
1703
/* Reads the backing filename
1704
 * Returns 1 if successful or -1 on error
1705
 */
1706
int libqcow_internal_file_open_read_backing_filename(
1707
     libqcow_internal_file_t *internal_file,
1708
     libbfio_handle_t *file_io_handle,
1709
     off64_t backing_filename_offset,
1710
     uint32_t backing_filename_size,
1711
     libcerror_error_t **error )
1712
204
{
1713
204
  static char *function = "libqcow_internal_file_open_read_backing_filename";
1714
204
  ssize_t read_count    = 0;
1715
1716
204
  if( internal_file == NULL )
1717
0
  {
1718
0
    libcerror_error_set(
1719
0
     error,
1720
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1721
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1722
0
     "%s: invalid file.",
1723
0
     function );
1724
1725
0
    return( -1 );
1726
0
  }
1727
204
  if( internal_file->backing_filename != NULL )
1728
0
  {
1729
0
    libcerror_error_set(
1730
0
     error,
1731
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1732
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1733
0
     "%s: invalid file - backing filename value already set.",
1734
0
     function );
1735
1736
0
    return( -1 );
1737
0
  }
1738
204
  if( ( backing_filename_size == 0 )
1739
204
   || ( backing_filename_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
1740
35
  {
1741
35
    libcerror_error_set(
1742
35
     error,
1743
35
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1744
35
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1745
35
     "%s: invalid backing filename size value out of bounds.",
1746
35
     function );
1747
1748
35
    goto on_error;
1749
35
  }
1750
169
  internal_file->backing_filename = (uint8_t *) memory_allocate(
1751
169
                                                 sizeof( uint8_t ) * backing_filename_size );
1752
1753
169
  if( internal_file->backing_filename == NULL )
1754
0
  {
1755
0
    libcerror_error_set(
1756
0
     error,
1757
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1758
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1759
0
     "%s: unable to create backing filename.",
1760
0
     function );
1761
1762
0
    goto on_error;
1763
0
  }
1764
169
  internal_file->backing_filename_size = (size_t) backing_filename_size;
1765
1766
#if defined( HAVE_DEBUG_OUTPUT )
1767
  if( libcnotify_verbose != 0 )
1768
  {
1769
    libcnotify_printf(
1770
     "%s: reading backing filename at offset: %" PRIu64 " (0x%08" PRIx64 ")\n",
1771
     function,
1772
     backing_filename_offset,
1773
     backing_filename_offset );
1774
  }
1775
#endif
1776
169
  read_count = libbfio_handle_read_buffer_at_offset(
1777
169
          file_io_handle,
1778
169
          internal_file->backing_filename,
1779
169
          (size_t) backing_filename_size,
1780
169
          backing_filename_offset,
1781
169
          error );
1782
1783
169
  if( read_count != (ssize_t) backing_filename_size )
1784
105
  {
1785
105
    libcerror_error_set(
1786
105
     error,
1787
105
     LIBCERROR_ERROR_DOMAIN_IO,
1788
105
     LIBCERROR_IO_ERROR_READ_FAILED,
1789
105
     "%s: unable to read backing filename data at offset: %" PRIu64 " (0x%08" PRIx64 ").",
1790
105
     function,
1791
105
     backing_filename_offset,
1792
105
     backing_filename_offset );
1793
1794
105
    goto on_error;
1795
105
  }
1796
#if defined( HAVE_DEBUG_OUTPUT )
1797
  if( libcnotify_verbose != 0 )
1798
  {
1799
    libcnotify_printf(
1800
     "%s: backing filename data:\n",
1801
     function );
1802
    libcnotify_print_data(
1803
     internal_file->backing_filename,
1804
     (size_t) backing_filename_size,
1805
     0 );
1806
  }
1807
#endif
1808
64
  return( 1 );
1809
1810
140
on_error:
1811
140
  if( internal_file->backing_filename != NULL )
1812
105
  {
1813
105
    memory_free(
1814
105
     internal_file->backing_filename );
1815
1816
105
    internal_file->backing_filename = NULL;
1817
105
  }
1818
140
  internal_file->backing_filename_size = 0;
1819
1820
140
  return( -1 );
1821
169
}
1822
1823
/* Determines if the file is locked
1824
 * Returns 1 if locked, 0 if not or -1 on error
1825
 */
1826
int libqcow_file_is_locked(
1827
     libqcow_file_t *file,
1828
     libcerror_error_t **error )
1829
0
{
1830
0
  libqcow_internal_file_t *internal_file = NULL;
1831
0
  static char *function                  = "libqcow_file_is_locked";
1832
0
  uint8_t is_locked                      = 0;
1833
1834
0
  if( file == NULL )
1835
0
  {
1836
0
    libcerror_error_set(
1837
0
     error,
1838
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1839
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1840
0
     "%s: invalid file.",
1841
0
     function );
1842
1843
0
    return( -1 );
1844
0
  }
1845
0
  internal_file = (libqcow_internal_file_t *) file;
1846
1847
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
1848
0
  if( libcthreads_read_write_lock_grab_for_read(
1849
0
       internal_file->read_write_lock,
1850
0
       error ) != 1 )
1851
0
  {
1852
0
    libcerror_error_set(
1853
0
     error,
1854
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1855
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1856
0
     "%s: unable to grab read/write lock for reading.",
1857
0
     function );
1858
1859
0
    return( -1 );
1860
0
  }
1861
0
#endif
1862
0
  is_locked = internal_file->is_locked;
1863
1864
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
1865
0
  if( libcthreads_read_write_lock_release_for_read(
1866
0
       internal_file->read_write_lock,
1867
0
       error ) != 1 )
1868
0
  {
1869
0
    libcerror_error_set(
1870
0
     error,
1871
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1872
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1873
0
     "%s: unable to release read/write lock for reading.",
1874
0
     function );
1875
1876
0
    return( -1 );
1877
0
  }
1878
0
#endif
1879
0
  return( is_locked );
1880
0
}
1881
1882
/* Retrieves the cluster block offset for a specific offset
1883
 * Returns 1 if successful or -1 on error
1884
 */
1885
int libqcow_internal_file_get_cluster_block_offset(
1886
     libqcow_internal_file_t *internal_file,
1887
     libbfio_handle_t *file_io_handle,
1888
     off64_t offset,
1889
     uint64_t *cluster_block_offset,
1890
     uint64_t *cluster_block_data_offset,
1891
     uint8_t *cluster_block_is_compressed,
1892
     libcerror_error_t **error )
1893
0
{
1894
0
  libqcow_cluster_table_t *level2_table = NULL;
1895
0
  static char *function                 = "libqcow_internal_file_get_cluster_block_offset";
1896
0
  off64_t element_data_offset           = 0;
1897
0
  uint64_t level1_table_index           = 0;
1898
0
  uint64_t level2_table_index           = 0;
1899
0
  uint64_t level2_table_offset          = 0;
1900
0
  uint64_t safe_cluster_block_offset    = 0;
1901
0
  uint8_t is_compressed                 = 0;
1902
1903
0
  if( internal_file == NULL )
1904
0
  {
1905
0
    libcerror_error_set(
1906
0
     error,
1907
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1908
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1909
0
     "%s: invalid file.",
1910
0
     function );
1911
1912
0
    return( -1 );
1913
0
  }
1914
0
  if( internal_file->file_header == NULL )
1915
0
  {
1916
0
    libcerror_error_set(
1917
0
     error,
1918
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1919
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1920
0
     "%s: invalid file - missing file header.",
1921
0
     function );
1922
1923
0
    return( -1 );
1924
0
  }
1925
0
  if( offset < 0 )
1926
0
  {
1927
0
    libcerror_error_set(
1928
0
     error,
1929
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1930
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1931
0
     "%s: invalid offset value out of bounds.",
1932
0
     function );
1933
1934
0
    return( -1 );
1935
0
  }
1936
0
  if( cluster_block_offset == NULL )
1937
0
  {
1938
0
    libcerror_error_set(
1939
0
     error,
1940
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1941
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1942
0
     "%s: invalid cluster block offset.",
1943
0
     function );
1944
1945
0
    return( -1 );
1946
0
  }
1947
0
  if( cluster_block_data_offset == NULL )
1948
0
  {
1949
0
    libcerror_error_set(
1950
0
     error,
1951
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1952
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1953
0
     "%s: invalid cluster block data offset.",
1954
0
     function );
1955
1956
0
    return( -1 );
1957
0
  }
1958
0
  if( cluster_block_is_compressed == NULL )
1959
0
  {
1960
0
    libcerror_error_set(
1961
0
     error,
1962
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1963
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1964
0
     "%s: invalid cluster block is compressed.",
1965
0
     function );
1966
1967
0
    return( -1 );
1968
0
  }
1969
0
  level1_table_index = offset >> internal_file->level1_index_bit_shift;
1970
1971
#if defined( HAVE_DEBUG_OUTPUT )
1972
  if( libcnotify_verbose != 0 )
1973
  {
1974
    libcnotify_printf(
1975
     "%s: level 1 table index\t: %" PRIu64 "\n",
1976
     function,
1977
     level1_table_index );
1978
  }
1979
#endif
1980
0
  if( level1_table_index > (uint64_t) INT_MAX )
1981
0
  {
1982
0
    libcerror_error_set(
1983
0
     error,
1984
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1985
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1986
0
     "%s: invalid level 1 table index value out of bounds.",
1987
0
     function );
1988
1989
0
    return( -1 );
1990
0
  }
1991
0
  if( libqcow_cluster_table_get_reference_by_index(
1992
0
       internal_file->level1_table,
1993
0
       (int) level1_table_index,
1994
0
       &level2_table_offset,
1995
0
       error ) != 1 )
1996
0
  {
1997
0
    libcerror_error_set(
1998
0
     error,
1999
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2000
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2001
0
     "%s: unable to retrieve level 2 table offset: %" PRIi64 " from level 1 table.",
2002
0
     function,
2003
0
     level1_table_index );
2004
2005
0
    return( -1 );
2006
0
  }
2007
#if defined( HAVE_DEBUG_OUTPUT )
2008
  if( libcnotify_verbose != 0 )
2009
  {
2010
    libcnotify_printf(
2011
     "%s: level 2 table offset\t: 0x%08" PRIx64 "\n",
2012
     function,
2013
     level2_table_offset );
2014
2015
    libcnotify_printf(
2016
     "\n" );
2017
  }
2018
#endif
2019
0
  level2_table_offset &= internal_file->offset_bit_mask;
2020
2021
  /* If level2_table_offset is 0 the level 2 table is sparse
2022
   */
2023
0
  if( level2_table_offset > 0 )
2024
0
  {
2025
0
    if( libfdata_vector_get_element_value_at_offset(
2026
0
         internal_file->level2_table_vector,
2027
0
         (intptr_t *) file_io_handle,
2028
0
         (libfdata_cache_t *) internal_file->level2_table_cache,
2029
0
         (off64_t) level2_table_offset,
2030
0
         &element_data_offset,
2031
0
         (intptr_t **) &level2_table,
2032
0
         0,
2033
0
         error ) != 1 )
2034
0
    {
2035
0
      libcerror_error_set(
2036
0
       error,
2037
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2038
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2039
0
       "%s: unable to retrieve level2 table at offset: 0x%08" PRIx64 ".",
2040
0
       function,
2041
0
       level2_table_offset );
2042
2043
0
      return( -1 );
2044
0
    }
2045
0
    level2_table_index = ( internal_file->current_offset >> internal_file->file_header->number_of_cluster_block_bits ) & internal_file->level2_index_bit_mask;
2046
2047
#if defined( HAVE_DEBUG_OUTPUT )
2048
    if( libcnotify_verbose != 0 )
2049
    {
2050
      libcnotify_printf(
2051
       "%s: level 2 table index\t: %" PRIu64 "\n",
2052
       function,
2053
       level2_table_index );
2054
    }
2055
#endif
2056
0
    if( level2_table_index > (uint64_t) INT_MAX )
2057
0
    {
2058
0
      libcerror_error_set(
2059
0
       error,
2060
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2061
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2062
0
       "%s: invalid level 2 table index value out of bounds.",
2063
0
       function );
2064
2065
0
      return( -1 );
2066
0
    }
2067
0
    if( libqcow_cluster_table_get_reference_by_index(
2068
0
         level2_table,
2069
0
         (int) level2_table_index,
2070
0
         &safe_cluster_block_offset,
2071
0
         error ) != 1 )
2072
0
    {
2073
0
      libcerror_error_set(
2074
0
       error,
2075
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2076
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2077
0
       "%s: unable to retrieve level 2 table entry: %" PRIu64 ".",
2078
0
       function,
2079
0
       level2_table_index );
2080
2081
0
      return( -1 );
2082
0
    }
2083
0
  }
2084
#if defined( HAVE_DEBUG_OUTPUT )
2085
  if( libcnotify_verbose != 0 )
2086
  {
2087
    libcnotify_printf(
2088
     "%s: table2 entry: %" PRIu64 "\t\t: 0x%08" PRIx64 "\n",
2089
     function,
2090
     level2_table_index,
2091
     safe_cluster_block_offset );
2092
2093
    libcnotify_printf(
2094
     "%s: cluster block offset\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
2095
     function,
2096
     safe_cluster_block_offset & internal_file->offset_bit_mask,
2097
     safe_cluster_block_offset & internal_file->offset_bit_mask );
2098
  }
2099
#endif
2100
0
  if( ( safe_cluster_block_offset & internal_file->compression_flag_bit_mask ) != 0 )
2101
0
  {
2102
0
    if( internal_file->encryption_method != LIBQCOW_ENCRYPTION_METHOD_NONE )
2103
0
    {
2104
0
      libcerror_error_set(
2105
0
       error,
2106
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2107
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2108
0
       "%s: simultaneous encryption and compression not supported.",
2109
0
       function );
2110
2111
0
      return( -1 );
2112
0
    }
2113
#if defined( HAVE_DEBUG_OUTPUT )
2114
    if( libcnotify_verbose != 0 )
2115
    {
2116
      libcnotify_printf(
2117
       "%s: is compressed\n",
2118
       function );
2119
    }
2120
#endif
2121
0
    is_compressed = 1;
2122
0
  }
2123
#if defined( HAVE_DEBUG_OUTPUT )
2124
  if( libcnotify_verbose != 0 )
2125
  {
2126
    libcnotify_printf(
2127
     "\n" );
2128
  }
2129
#endif
2130
0
  *cluster_block_offset        = safe_cluster_block_offset & internal_file->offset_bit_mask;
2131
0
  *cluster_block_data_offset   = offset & internal_file->cluster_block_bit_mask;
2132
0
  *cluster_block_is_compressed = is_compressed;
2133
2134
0
  return( 1 );
2135
0
}
2136
2137
/* Reads a cluster block
2138
 * Returns 1 if successful or -1 on error
2139
 */
2140
int libqcow_internal_file_read_cluster_block(
2141
     libqcow_internal_file_t *internal_file,
2142
     libbfio_handle_t *file_io_handle,
2143
     uint64_t cluster_block_offset,
2144
     uint64_t cluster_block_data_offset,
2145
     uint8_t cluster_block_is_compressed,
2146
     libqcow_cluster_block_t **cluster_block,
2147
     libcerror_error_t **error )
2148
0
{
2149
0
  libfcache_cache_t *cluster_block_cache       = NULL;
2150
0
  libqcow_cluster_block_t *safe_cluster_block  = NULL;
2151
0
  static char *function                        = "libqcow_internal_file_read_cluster_block";
2152
0
  size_t cluster_block_size                    = 0;
2153
0
  size_t safe_cluster_block_data_size          = 0;
2154
0
  off64_t element_data_offset                  = 0;
2155
0
  uint64_t block_key                           = 0;
2156
0
  uint64_t compressed_cluster_block_end_offset = 0;
2157
0
  int cache_entry_index                        = 0;
2158
2159
0
  if( internal_file == NULL )
2160
0
  {
2161
0
    libcerror_error_set(
2162
0
     error,
2163
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2164
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2165
0
     "%s: invalid file.",
2166
0
     function );
2167
2168
0
    return( -1 );
2169
0
  }
2170
0
  if( internal_file->file_header == NULL )
2171
0
  {
2172
0
    libcerror_error_set(
2173
0
     error,
2174
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2175
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2176
0
     "%s: invalid file - missing file header.",
2177
0
     function );
2178
2179
0
    return( -1 );
2180
0
  }
2181
0
  if( internal_file->cluster_block_size == 0 )
2182
0
  {
2183
0
    libcerror_error_set(
2184
0
     error,
2185
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2186
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2187
0
     "%s: invalid file - cluster block size value out of bounds.",
2188
0
     function );
2189
2190
0
    return( -1 );
2191
0
  }
2192
0
  if( cluster_block == NULL )
2193
0
  {
2194
0
    libcerror_error_set(
2195
0
     error,
2196
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2197
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2198
0
     "%s: invalid cluster block.",
2199
0
     function );
2200
2201
0
    return( -1 );
2202
0
  }
2203
0
  if( cluster_block_is_compressed != 0 )
2204
0
  {
2205
    /* Handle compressed cluster block
2206
     */
2207
0
    cluster_block_size    = (size_t) ( cluster_block_offset >> internal_file->compression_bit_shift );
2208
0
    cluster_block_offset &= internal_file->compression_bit_mask;
2209
2210
0
    if( ( internal_file->file_header->format_version == 2 )
2211
0
     || ( internal_file->file_header->format_version == 3 ) )
2212
0
    {
2213
0
      cluster_block_size += 1;
2214
0
      cluster_block_size *= 512;
2215
2216
      /* Make sure the compressed block size stays within the bounds
2217
       * of the cluster block size and the size of the file
2218
       */
2219
0
      compressed_cluster_block_end_offset = cluster_block_offset / internal_file->cluster_block_size;
2220
2221
0
      if( ( cluster_block_offset % internal_file->cluster_block_size ) != 0 )
2222
0
      {
2223
0
        compressed_cluster_block_end_offset += 1;
2224
0
      }
2225
0
      compressed_cluster_block_end_offset += 1;
2226
0
      compressed_cluster_block_end_offset *= internal_file->cluster_block_size;
2227
2228
0
      if( compressed_cluster_block_end_offset > internal_file->size )
2229
0
      {
2230
0
        compressed_cluster_block_end_offset = internal_file->size;
2231
0
      }
2232
0
      if( ( cluster_block_offset + cluster_block_size ) > compressed_cluster_block_end_offset )
2233
0
      {
2234
0
        cluster_block_size = (size_t) ( compressed_cluster_block_end_offset - cluster_block_offset );
2235
0
      }
2236
0
    }
2237
#if defined( HAVE_DEBUG_OUTPUT )
2238
    if( libcnotify_verbose != 0 )
2239
    {
2240
      libcnotify_printf(
2241
       "%s: compressed cluster block offset\t\t: 0x%08" PRIx64 "\n",
2242
       function,
2243
       cluster_block_offset );
2244
2245
      libcnotify_printf(
2246
       "%s: compressed cluster block size\t\t: %" PRIzd "\n",
2247
       function,
2248
       cluster_block_size );
2249
    }
2250
#endif
2251
0
    cluster_block_cache = internal_file->compressed_cluster_block_cache;
2252
0
  }
2253
0
  else
2254
0
  {
2255
    /* For version 2 and 3 make sure the sure the last cluster block size
2256
     * stays within the bounds of the size of the file
2257
     */
2258
0
    if( ( ( internal_file->file_header->format_version == 2 )
2259
0
      ||  ( internal_file->file_header->format_version == 3 ) )
2260
0
     && ( ( cluster_block_offset + internal_file->cluster_block_size ) > internal_file->size ) )
2261
0
    {
2262
0
      cluster_block_size = (size_t) ( internal_file->size - cluster_block_offset );
2263
2264
#if defined( HAVE_DEBUG_OUTPUT )
2265
      if( libcnotify_verbose != 0 )
2266
      {
2267
        libcnotify_printf(
2268
         "%s: last cluster block offset\t\t: 0x%08" PRIx64 "\n",
2269
         function,
2270
         cluster_block_offset );
2271
2272
        libcnotify_printf(
2273
         "%s: last cluster block size\t\t\t: %" PRIzd "\n",
2274
         function,
2275
         cluster_block_size );
2276
      }
2277
#endif
2278
0
    }
2279
0
    cluster_block_cache = internal_file->cluster_block_cache;
2280
0
  }
2281
0
  if( cluster_block_size != 0 )
2282
0
  {
2283
/* TODO check cache  */
2284
0
    if( libqcow_cluster_block_initialize(
2285
0
         &safe_cluster_block,
2286
0
         cluster_block_size,
2287
0
         error ) != 1 )
2288
0
    {
2289
0
      libcerror_error_set(
2290
0
       error,
2291
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2292
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2293
0
       "%s: unable to create cluster block.",
2294
0
       function );
2295
2296
0
      goto on_error;
2297
0
    }
2298
0
    if( libqcow_cluster_block_read(
2299
0
         safe_cluster_block,
2300
0
         file_io_handle,
2301
0
         cluster_block_offset,
2302
0
         error ) != 1 )
2303
0
    {
2304
0
      libcerror_error_set(
2305
0
       error,
2306
0
       LIBCERROR_ERROR_DOMAIN_IO,
2307
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2308
0
       "%s: unable to read cluster block at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2309
0
       function,
2310
0
       cluster_block_offset,
2311
0
       cluster_block_offset );
2312
2313
0
      goto on_error;
2314
0
    }
2315
0
  }
2316
0
  else
2317
0
  {
2318
0
    if( libfdata_vector_get_element_value_at_offset(
2319
0
         internal_file->cluster_block_vector,
2320
0
         (intptr_t *) file_io_handle,
2321
0
         (libfdata_cache_t *) cluster_block_cache,
2322
0
         (off64_t) cluster_block_offset,
2323
0
         &element_data_offset,
2324
0
         (intptr_t **) cluster_block,
2325
0
         0,
2326
0
         error ) != 1 )
2327
0
    {
2328
0
      libcerror_error_set(
2329
0
       error,
2330
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2331
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2332
0
       "%s: unable to retrieve cluster block at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2333
0
       function,
2334
0
       cluster_block_offset,
2335
0
       cluster_block_offset );
2336
2337
0
      goto on_error;
2338
0
    }
2339
0
  }
2340
0
  if( cluster_block_is_compressed != 0 )
2341
0
  {
2342
0
    safe_cluster_block->compressed_data = safe_cluster_block->data;
2343
2344
0
    safe_cluster_block->data = (uint8_t *) memory_allocate(
2345
0
                                            sizeof( uint8_t ) * internal_file->cluster_block_size );
2346
2347
0
    if( safe_cluster_block->data == NULL )
2348
0
    {
2349
0
      libcerror_error_set(
2350
0
       error,
2351
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2352
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2353
0
       "%s: unable to create cluster block data.",
2354
0
       function );
2355
2356
0
      goto on_error;
2357
0
    }
2358
0
    safe_cluster_block->data_size = internal_file->cluster_block_size;
2359
2360
0
    safe_cluster_block_data_size = safe_cluster_block->data_size;
2361
2362
0
    if( libqcow_decompress_data(
2363
0
         safe_cluster_block->compressed_data,
2364
0
         cluster_block_size,
2365
0
         LIBQCOW_COMPRESSION_METHOD_DEFLATE,
2366
0
         safe_cluster_block->data,
2367
0
         &safe_cluster_block_data_size,
2368
0
         error ) != 1 )
2369
0
    {
2370
0
      libcerror_error_set(
2371
0
       error,
2372
0
       LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
2373
0
       LIBCERROR_ENCRYPTION_ERROR_GENERIC,
2374
0
       "%s: unable to decompress cluster block data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2375
0
       function,
2376
0
       cluster_block_offset,
2377
0
       cluster_block_offset );
2378
2379
0
      goto on_error;
2380
0
    }
2381
/* TODO check safe_cluster_block_data_size
2382
    if( safe_cluster_block_data_size != safe_cluster_block->data_size )
2383
    {
2384
      libcerror_error_set(
2385
       error,
2386
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2387
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
2388
       "%s: invalid cluster block size value out of bounds.",
2389
       function );
2390
2391
      goto on_error;
2392
    }
2393
*/
2394
0
  }
2395
0
  if( safe_cluster_block != NULL )
2396
0
  {
2397
0
    cache_entry_index = ( cluster_block_offset & internal_file->cluster_block_bit_mask ) % LIBQCOW_MAXIMUM_CACHE_ENTRIES_CLUSTER_BLOCKS;
2398
2399
0
    if( libfcache_cache_set_value_by_index(
2400
0
         cluster_block_cache,
2401
0
         cache_entry_index,
2402
0
         0,
2403
0
         cluster_block_offset,
2404
0
         0,
2405
0
         (intptr_t *) safe_cluster_block,
2406
0
         (int (*)(intptr_t **, libcerror_error_t **)) &libqcow_cluster_block_free,
2407
0
         LIBFCACHE_CACHE_VALUE_FLAG_MANAGED,
2408
0
         error ) != 1 )
2409
0
    {
2410
0
      libcerror_error_set(
2411
0
       error,
2412
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2413
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2414
0
       "%s: unable to set value in cache entry: %d.",
2415
0
       function,
2416
0
       cache_entry_index );
2417
2418
0
      goto on_error;
2419
0
    }
2420
0
    *cluster_block = safe_cluster_block;
2421
0
  }
2422
0
  if( internal_file->encryption_method != LIBQCOW_ENCRYPTION_METHOD_NONE )
2423
0
  {
2424
0
    if( *cluster_block == NULL )
2425
0
    {
2426
0
      libcerror_error_set(
2427
0
       error,
2428
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2429
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2430
0
       "%s: missing cluster block.",
2431
0
       function );
2432
2433
0
      goto on_error;
2434
0
    }
2435
0
    if( ( *cluster_block )->encrypted_data == NULL )
2436
0
    {
2437
0
      ( *cluster_block )->encrypted_data = ( *cluster_block )->data;
2438
2439
0
      ( *cluster_block )->data = (uint8_t *) memory_allocate(
2440
0
                                              sizeof( uint8_t ) * ( *cluster_block )->data_size );
2441
2442
0
      if( ( *cluster_block )->data == NULL )
2443
0
      {
2444
0
        libcerror_error_set(
2445
0
         error,
2446
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
2447
0
         LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2448
0
         "%s: unable to create cluster block data.",
2449
0
         function );
2450
2451
0
        goto on_error;
2452
0
      }
2453
0
      block_key = (uint64_t) ( internal_file->current_offset - cluster_block_data_offset ) / 512;
2454
2455
0
      if( libqcow_encryption_crypt(
2456
0
           internal_file->encryption_context,
2457
0
           LIBQCOW_ENCYPTION_CRYPT_MODE_DECRYPT,
2458
0
           ( *cluster_block )->encrypted_data,
2459
0
           ( *cluster_block )->data_size,
2460
0
           ( *cluster_block )->data,
2461
0
           ( *cluster_block )->data_size,
2462
0
           block_key,
2463
0
           error ) != 1 )
2464
0
      {
2465
0
        libcerror_error_set(
2466
0
         error,
2467
0
         LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
2468
0
         LIBCERROR_ENCRYPTION_ERROR_GENERIC,
2469
0
         "%s: unable to decrypt cluster block data.",
2470
0
         function );
2471
2472
0
        goto on_error;
2473
0
      }
2474
0
    }
2475
0
  }
2476
0
  return( 1 );
2477
2478
0
on_error:
2479
0
  if( safe_cluster_block != NULL )
2480
0
  {
2481
0
    libqcow_cluster_block_free(
2482
0
     &safe_cluster_block,
2483
0
     NULL );
2484
0
  }
2485
0
  return( -1 );
2486
0
}
2487
2488
/* Reads (media) data from the current offset into a buffer using a Basic File IO (bfio) handle
2489
 * This function is not multi-thread safe acquire write lock before call
2490
 * Returns the number of bytes read or -1 on error
2491
 */
2492
ssize_t libqcow_internal_file_read_buffer_from_file_io_handle(
2493
         libqcow_internal_file_t *internal_file,
2494
         libbfio_handle_t *file_io_handle,
2495
         void *buffer,
2496
         size_t buffer_size,
2497
         libcerror_error_t **error )
2498
0
{
2499
0
  libqcow_cluster_block_t *cluster_block = NULL;
2500
0
  static char *function                  = "libqcow_internal_file_read_buffer_from_file_io_handle";
2501
0
  size_t buffer_offset                   = 0;
2502
0
  size_t read_size                       = 0;
2503
0
  ssize_t read_count                     = 0;
2504
0
  uint64_t cluster_block_data_offset     = 0;
2505
0
  uint64_t cluster_block_file_offset     = 0;
2506
0
  uint8_t cluster_block_is_compressed    = 0;
2507
2508
0
  if( internal_file == NULL )
2509
0
  {
2510
0
    libcerror_error_set(
2511
0
     error,
2512
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2513
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2514
0
     "%s: invalid file.",
2515
0
     function );
2516
2517
0
    return( -1 );
2518
0
  }
2519
0
  if( internal_file->file_header == NULL )
2520
0
  {
2521
0
    libcerror_error_set(
2522
0
     error,
2523
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2524
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2525
0
     "%s: invalid file - missing file header.",
2526
0
     function );
2527
2528
0
    return( -1 );
2529
0
  }
2530
0
  if( internal_file->current_offset < 0 )
2531
0
  {
2532
0
    libcerror_error_set(
2533
0
     error,
2534
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2535
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2536
0
     "%s: invalid file - current offset value out of bounds.",
2537
0
     function );
2538
2539
0
    return( -1 );
2540
0
  }
2541
0
  if( internal_file->cluster_block_size == 0 )
2542
0
  {
2543
0
    libcerror_error_set(
2544
0
     error,
2545
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2546
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2547
0
     "%s: invalid file - cluster block size value out of bounds.",
2548
0
     function );
2549
2550
0
    return( -1 );
2551
0
  }
2552
0
  if( internal_file->backing_filename != NULL )
2553
0
  {
2554
0
    if( internal_file->parent_file == NULL )
2555
0
    {
2556
0
      libcerror_error_set(
2557
0
       error,
2558
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2559
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2560
0
       "%s: invalid file - missing parent file.",
2561
0
       function );
2562
2563
0
      return( -1 );
2564
0
    }
2565
0
  }
2566
0
  if( buffer == NULL )
2567
0
  {
2568
0
    libcerror_error_set(
2569
0
     error,
2570
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2571
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2572
0
     "%s: invalid buffer.",
2573
0
     function );
2574
2575
0
    return( -1 );
2576
0
  }
2577
0
  if( buffer_size > (size_t) SSIZE_MAX )
2578
0
  {
2579
0
    libcerror_error_set(
2580
0
     error,
2581
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2582
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2583
0
     "%s: invalid buffer size value exceeds maximum.",
2584
0
     function );
2585
2586
0
    return( -1 );
2587
0
  }
2588
0
  internal_file->io_handle->abort = 0;
2589
2590
0
  if( (size64_t) internal_file->current_offset >= internal_file->file_header->media_size )
2591
0
  {
2592
0
    return( 0 );
2593
0
  }
2594
0
  while( buffer_offset < buffer_size )
2595
0
  {
2596
#if defined( HAVE_DEBUG_OUTPUT )
2597
    if( libcnotify_verbose != 0 )
2598
    {
2599
      libcnotify_printf(
2600
       "%s: current offset\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
2601
       function,
2602
       internal_file->current_offset,
2603
       internal_file->current_offset );
2604
    }
2605
#endif
2606
0
    if( libqcow_internal_file_get_cluster_block_offset(
2607
0
         internal_file,
2608
0
         file_io_handle,
2609
0
         internal_file->current_offset,
2610
0
         &cluster_block_file_offset,
2611
0
         &cluster_block_data_offset,
2612
0
         &cluster_block_is_compressed,
2613
0
         error ) != 1 )
2614
0
    {
2615
0
      libcerror_error_set(
2616
0
       error,
2617
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2618
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2619
0
       "%s: unable to retrieve cluster block offset for offset: %" PRIi64 " (0x%08" PRIx64 ").",
2620
0
       function,
2621
0
       internal_file->current_offset,
2622
0
       internal_file->current_offset );
2623
2624
0
      return( -1 );
2625
0
    }
2626
0
    read_size = internal_file->cluster_block_size - (size_t) cluster_block_data_offset;
2627
2628
0
    if( ( (size64_t) internal_file->current_offset + read_size ) > internal_file->file_header->media_size )
2629
0
    {
2630
0
      read_size = (size_t) ( internal_file->file_header->media_size - internal_file->current_offset );
2631
0
    }
2632
0
    if( ( buffer_offset + read_size ) > buffer_size )
2633
0
    {
2634
0
      read_size = buffer_size - buffer_offset;
2635
0
    }
2636
0
    if( cluster_block_file_offset > 0 )
2637
0
    {
2638
0
      if( libqcow_internal_file_read_cluster_block(
2639
0
           internal_file,
2640
0
           file_io_handle,
2641
0
           cluster_block_file_offset,
2642
0
           cluster_block_data_offset,
2643
0
           cluster_block_is_compressed,
2644
0
           &cluster_block,
2645
0
           error ) != 1 )
2646
0
      {
2647
0
        libcerror_error_set(
2648
0
         error,
2649
0
         LIBCERROR_ERROR_DOMAIN_IO,
2650
0
         LIBCERROR_IO_ERROR_READ_FAILED,
2651
0
         "%s: unable to read cluster block.",
2652
0
         function );
2653
2654
0
        return( -1 );
2655
0
      }
2656
0
      if( cluster_block == NULL )
2657
0
      {
2658
0
        libcerror_error_set(
2659
0
         error,
2660
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2661
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2662
0
         "%s: invalid cluster block.",
2663
0
         function );
2664
2665
0
        return( -1 );
2666
0
      }
2667
0
      if( cluster_block->data == NULL )
2668
0
      {
2669
0
        libcerror_error_set(
2670
0
         error,
2671
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2672
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2673
0
         "%s: invalid cluster block - missing data.",
2674
0
         function );
2675
2676
0
        return( -1 );
2677
0
      }
2678
0
      if( memory_copy(
2679
0
           &( ( (uint8_t *) buffer )[ buffer_offset ] ),
2680
0
           &( cluster_block->data[ cluster_block_data_offset ] ),
2681
0
           read_size ) == NULL )
2682
0
      {
2683
0
        libcerror_error_set(
2684
0
         error,
2685
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
2686
0
         LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2687
0
         "%s: unable to copy cluster block data to buffer.",
2688
0
         function );
2689
2690
0
        return( -1 );
2691
0
      }
2692
0
    }
2693
0
    else if( internal_file->parent_file != NULL )
2694
0
    {
2695
0
      read_count = libqcow_file_read_buffer_at_offset(
2696
0
              internal_file->parent_file,
2697
0
              &( ( (uint8_t *) buffer )[ buffer_offset ] ),
2698
0
              buffer_size - buffer_offset,
2699
0
              internal_file->current_offset,
2700
0
              error );
2701
2702
0
      if( read_count == -1 )
2703
0
      {
2704
0
        libcerror_error_set(
2705
0
         error,
2706
0
         LIBCERROR_ERROR_DOMAIN_IO,
2707
0
         LIBCERROR_IO_ERROR_READ_FAILED,
2708
0
         "%s: unable to read buffer from parent file.",
2709
0
         function );
2710
2711
0
        return( -1 );
2712
0
      }
2713
0
      read_size = (size_t) read_count;
2714
0
    }
2715
0
    else
2716
0
    {
2717
      /* Handle sparse cluster block
2718
       */
2719
0
      if( memory_set(
2720
0
           &( ( (uint8_t *) buffer )[ buffer_offset ] ),
2721
0
           0,
2722
0
           read_size ) == NULL )
2723
0
      {
2724
0
        libcerror_error_set(
2725
0
         error,
2726
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
2727
0
         LIBCERROR_MEMORY_ERROR_SET_FAILED,
2728
0
         "%s: unable to set sparse data in buffer.",
2729
0
         function );
2730
2731
0
        return( -1 );
2732
0
      }
2733
0
    }
2734
0
    internal_file->current_offset += read_size;
2735
0
    buffer_offset                 += read_size;
2736
2737
#if defined( HAVE_DEBUG_OUTPUT )
2738
    if( libcnotify_verbose != 0 )
2739
    {
2740
      libcnotify_printf(
2741
       "\n" );
2742
    }
2743
#endif
2744
0
    if( (size64_t) internal_file->current_offset >= internal_file->file_header->media_size )
2745
0
    {
2746
0
      break;
2747
0
    }
2748
0
  }
2749
0
  return( (ssize_t) buffer_offset );
2750
0
}
2751
2752
/* Reads (media) data from the current offset into a buffer
2753
 * Returns the number of bytes read or -1 on error
2754
 */
2755
ssize_t libqcow_file_read_buffer(
2756
         libqcow_file_t *file,
2757
         void *buffer,
2758
         size_t buffer_size,
2759
         libcerror_error_t **error )
2760
0
{
2761
0
  libqcow_internal_file_t *internal_file = NULL;
2762
0
  static char *function                  = "libqcow_file_read_buffer";
2763
0
  ssize_t read_count                     = 0;
2764
2765
0
  if( file == NULL )
2766
0
  {
2767
0
    libcerror_error_set(
2768
0
     error,
2769
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2770
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2771
0
     "%s: invalid file.",
2772
0
     function );
2773
2774
0
    return( -1 );
2775
0
  }
2776
0
  internal_file = (libqcow_internal_file_t *) file;
2777
2778
0
  if( internal_file->file_io_handle == NULL )
2779
0
  {
2780
0
    libcerror_error_set(
2781
0
     error,
2782
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2783
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2784
0
     "%s: invalid file - missing file IO handle.",
2785
0
     function );
2786
2787
0
    return( -1 );
2788
0
  }
2789
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
2790
0
  if( libcthreads_read_write_lock_grab_for_write(
2791
0
       internal_file->read_write_lock,
2792
0
       error ) != 1 )
2793
0
  {
2794
0
    libcerror_error_set(
2795
0
     error,
2796
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2797
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2798
0
     "%s: unable to grab read/write lock for writing.",
2799
0
     function );
2800
2801
0
    return( -1 );
2802
0
  }
2803
0
#endif
2804
0
  read_count = libqcow_internal_file_read_buffer_from_file_io_handle(
2805
0
          internal_file,
2806
0
          internal_file->file_io_handle,
2807
0
          buffer,
2808
0
          buffer_size,
2809
0
          error );
2810
2811
0
  if( read_count == -1 )
2812
0
  {
2813
0
    libcerror_error_set(
2814
0
     error,
2815
0
     LIBCERROR_ERROR_DOMAIN_IO,
2816
0
     LIBCERROR_IO_ERROR_READ_FAILED,
2817
0
     "%s: unable to read buffer.",
2818
0
     function );
2819
2820
0
    read_count = -1;
2821
0
  }
2822
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
2823
0
  if( libcthreads_read_write_lock_release_for_write(
2824
0
       internal_file->read_write_lock,
2825
0
       error ) != 1 )
2826
0
  {
2827
0
    libcerror_error_set(
2828
0
     error,
2829
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2830
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2831
0
     "%s: unable to release read/write lock for writing.",
2832
0
     function );
2833
2834
0
    return( -1 );
2835
0
  }
2836
0
#endif
2837
0
  return( read_count );
2838
0
}
2839
2840
/* Reads (media) data at a specific offset
2841
 * Returns the number of bytes read or -1 on error
2842
 */
2843
ssize_t libqcow_file_read_buffer_at_offset(
2844
         libqcow_file_t *file,
2845
         void *buffer,
2846
         size_t buffer_size,
2847
         off64_t offset,
2848
         libcerror_error_t **error )
2849
0
{
2850
0
  libqcow_internal_file_t *internal_file = NULL;
2851
0
  static char *function                  = "libqcow_file_read_buffer_at_offset";
2852
0
  ssize_t read_count                     = 0;
2853
2854
0
  if( file == NULL )
2855
0
  {
2856
0
    libcerror_error_set(
2857
0
     error,
2858
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2859
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2860
0
     "%s: invalid file.",
2861
0
     function );
2862
2863
0
    return( -1 );
2864
0
  }
2865
0
  internal_file = (libqcow_internal_file_t *) file;
2866
2867
0
  if( internal_file->file_io_handle == NULL )
2868
0
  {
2869
0
    libcerror_error_set(
2870
0
     error,
2871
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2872
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2873
0
     "%s: invalid file - missing file IO handle.",
2874
0
     function );
2875
2876
0
    return( -1 );
2877
0
  }
2878
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
2879
0
  if( libcthreads_read_write_lock_grab_for_write(
2880
0
       internal_file->read_write_lock,
2881
0
       error ) != 1 )
2882
0
  {
2883
0
    libcerror_error_set(
2884
0
     error,
2885
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2886
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2887
0
     "%s: unable to grab read/write lock for writing.",
2888
0
     function );
2889
2890
0
    return( -1 );
2891
0
  }
2892
0
#endif
2893
0
  if( libqcow_internal_file_seek_offset(
2894
0
       internal_file,
2895
0
       offset,
2896
0
       SEEK_SET,
2897
0
       error ) == -1 )
2898
0
  {
2899
0
    libcerror_error_set(
2900
0
     error,
2901
0
     LIBCERROR_ERROR_DOMAIN_IO,
2902
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
2903
0
     "%s: unable to seek offset.",
2904
0
     function );
2905
2906
0
    read_count = -1;
2907
0
  }
2908
0
  else
2909
0
  {
2910
0
    read_count = libqcow_internal_file_read_buffer_from_file_io_handle(
2911
0
            internal_file,
2912
0
            internal_file->file_io_handle,
2913
0
            buffer,
2914
0
            buffer_size,
2915
0
            error );
2916
2917
0
    if( read_count == -1 )
2918
0
    {
2919
0
      libcerror_error_set(
2920
0
       error,
2921
0
       LIBCERROR_ERROR_DOMAIN_IO,
2922
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2923
0
       "%s: unable to read buffer.",
2924
0
       function );
2925
2926
0
      read_count = -1;
2927
0
    }
2928
0
  }
2929
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
2930
0
  if( libcthreads_read_write_lock_release_for_write(
2931
0
       internal_file->read_write_lock,
2932
0
       error ) != 1 )
2933
0
  {
2934
0
    libcerror_error_set(
2935
0
     error,
2936
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2937
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2938
0
     "%s: unable to release read/write lock for writing.",
2939
0
     function );
2940
2941
0
    return( -1 );
2942
0
  }
2943
0
#endif
2944
0
  return( read_count );
2945
0
}
2946
2947
/* Seeks a certain offset of the (media) data
2948
 * This function is not multi-thread safe acquire write lock before call
2949
 * Returns the offset if seek is successful or -1 on error
2950
 */
2951
off64_t libqcow_internal_file_seek_offset(
2952
         libqcow_internal_file_t *internal_file,
2953
         off64_t offset,
2954
         int whence,
2955
         libcerror_error_t **error )
2956
0
{
2957
0
  static char *function = "libqcow_internal_file_seek_offset";
2958
2959
0
  if( internal_file == NULL )
2960
0
  {
2961
0
    libcerror_error_set(
2962
0
     error,
2963
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2964
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2965
0
     "%s: invalid file.",
2966
0
     function );
2967
2968
0
    return( -1 );
2969
0
  }
2970
0
  if( internal_file->file_header == NULL )
2971
0
  {
2972
0
    libcerror_error_set(
2973
0
     error,
2974
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2975
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2976
0
     "%s: invalid file - missing file header.",
2977
0
     function );
2978
2979
0
    return( -1 );
2980
0
  }
2981
0
  if( internal_file->backing_filename != NULL )
2982
0
  {
2983
0
    if( internal_file->parent_file == NULL )
2984
0
    {
2985
0
      libcerror_error_set(
2986
0
       error,
2987
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2988
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2989
0
       "%s: invalid file - missing parent file.",
2990
0
       function );
2991
2992
0
      return( -1 );
2993
0
    }
2994
0
  }
2995
0
  if( ( whence != SEEK_CUR )
2996
0
   && ( whence != SEEK_END )
2997
0
   && ( whence != SEEK_SET ) )
2998
0
  {
2999
0
    libcerror_error_set(
3000
0
     error,
3001
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3002
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3003
0
     "%s: unsupported whence.",
3004
0
     function );
3005
3006
0
    return( -1 );
3007
0
  }
3008
0
  if( whence == SEEK_CUR )
3009
0
  {
3010
0
    offset += internal_file->current_offset;
3011
0
  }
3012
0
  else if( whence == SEEK_END )
3013
0
  {
3014
0
    offset += (off64_t) internal_file->file_header->media_size;
3015
0
  }
3016
0
  if( offset < 0 )
3017
0
  {
3018
0
    libcerror_error_set(
3019
0
     error,
3020
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3021
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
3022
0
     "%s: invalid offset value out of bounds.",
3023
0
     function );
3024
3025
0
    return( -1 );
3026
0
  }
3027
0
  internal_file->current_offset = offset;
3028
3029
0
  return( offset );
3030
0
}
3031
3032
/* Seeks a certain offset of the (media) data
3033
 * Returns the offset if seek is successful or -1 on error
3034
 */
3035
off64_t libqcow_file_seek_offset(
3036
         libqcow_file_t *file,
3037
         off64_t offset,
3038
         int whence,
3039
         libcerror_error_t **error )
3040
0
{
3041
0
  libqcow_internal_file_t *internal_file = NULL;
3042
0
  static char *function                  = "libqcow_file_seek_offset";
3043
3044
0
  if( file == NULL )
3045
0
  {
3046
0
    libcerror_error_set(
3047
0
     error,
3048
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3049
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3050
0
     "%s: invalid file.",
3051
0
     function );
3052
3053
0
    return( -1 );
3054
0
  }
3055
0
  internal_file = (libqcow_internal_file_t *) file;
3056
3057
0
  if( internal_file->file_io_handle == NULL )
3058
0
  {
3059
0
    libcerror_error_set(
3060
0
     error,
3061
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3062
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3063
0
     "%s: invalid file - missing file IO handle.",
3064
0
     function );
3065
3066
0
    return( -1 );
3067
0
  }
3068
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3069
0
  if( libcthreads_read_write_lock_grab_for_write(
3070
0
       internal_file->read_write_lock,
3071
0
       error ) != 1 )
3072
0
  {
3073
0
    libcerror_error_set(
3074
0
     error,
3075
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3076
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3077
0
     "%s: unable to grab read/write lock for writing.",
3078
0
     function );
3079
3080
0
    return( -1 );
3081
0
  }
3082
0
#endif
3083
0
  offset = libqcow_internal_file_seek_offset(
3084
0
            internal_file,
3085
0
            offset,
3086
0
            whence,
3087
0
            error );
3088
3089
0
  if( offset == -1 )
3090
0
  {
3091
0
    libcerror_error_set(
3092
0
     error,
3093
0
     LIBCERROR_ERROR_DOMAIN_IO,
3094
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
3095
0
     "%s: unable to seek offset.",
3096
0
     function );
3097
3098
0
    offset = -1;
3099
0
  }
3100
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3101
0
  if( libcthreads_read_write_lock_release_for_write(
3102
0
       internal_file->read_write_lock,
3103
0
       error ) != 1 )
3104
0
  {
3105
0
    libcerror_error_set(
3106
0
     error,
3107
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3108
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3109
0
     "%s: unable to release read/write lock for writing.",
3110
0
     function );
3111
3112
0
    return( -1 );
3113
0
  }
3114
0
#endif
3115
0
  return( offset );
3116
0
}
3117
3118
/* Retrieves the current offset of the (media) data
3119
 * Returns 1 if successful or -1 on error
3120
 */
3121
int libqcow_file_get_offset(
3122
     libqcow_file_t *file,
3123
     off64_t *offset,
3124
     libcerror_error_t **error )
3125
0
{
3126
0
  libqcow_internal_file_t *internal_file = NULL;
3127
0
  static char *function                  = "libqcow_file_get_offset";
3128
3129
0
  if( file == NULL )
3130
0
  {
3131
0
    libcerror_error_set(
3132
0
     error,
3133
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3134
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3135
0
     "%s: invalid file.",
3136
0
     function );
3137
3138
0
    return( -1 );
3139
0
  }
3140
0
  internal_file = (libqcow_internal_file_t *) file;
3141
3142
0
  if( internal_file->file_io_handle == NULL )
3143
0
  {
3144
0
    libcerror_error_set(
3145
0
     error,
3146
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3147
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3148
0
     "%s: invalid file - missing file IO handle.",
3149
0
     function );
3150
3151
0
    return( -1 );
3152
0
  }
3153
0
  if( offset == NULL )
3154
0
  {
3155
0
    libcerror_error_set(
3156
0
     error,
3157
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3158
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3159
0
     "%s: invalid offset.",
3160
0
     function );
3161
3162
0
    return( -1 );
3163
0
  }
3164
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3165
0
  if( libcthreads_read_write_lock_grab_for_read(
3166
0
       internal_file->read_write_lock,
3167
0
       error ) != 1 )
3168
0
  {
3169
0
    libcerror_error_set(
3170
0
     error,
3171
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3172
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3173
0
     "%s: unable to grab read/write lock for reading.",
3174
0
     function );
3175
3176
0
    return( -1 );
3177
0
  }
3178
0
#endif
3179
0
  *offset = internal_file->current_offset;
3180
3181
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3182
0
  if( libcthreads_read_write_lock_release_for_read(
3183
0
       internal_file->read_write_lock,
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_SET_FAILED,
3190
0
     "%s: unable to release read/write lock for reading.",
3191
0
     function );
3192
3193
0
    return( -1 );
3194
0
  }
3195
0
#endif
3196
0
  return( 1 );
3197
0
}
3198
3199
/* Sets the parent (backing) file of a differential image
3200
 * Returns 1 if successful or -1 on error
3201
 */
3202
int libqcow_file_set_parent_file(
3203
     libqcow_file_t *file,
3204
     libqcow_file_t *parent_file,
3205
     libcerror_error_t **error )
3206
0
{
3207
0
  libqcow_internal_file_t *internal_file = NULL;
3208
0
  static char *function                  = "libqcow_file_set_parent_file";
3209
3210
0
  if( file == NULL )
3211
0
  {
3212
0
    libcerror_error_set(
3213
0
     error,
3214
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3215
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3216
0
     "%s: invalid file.",
3217
0
     function );
3218
3219
0
    return( -1 );
3220
0
  }
3221
0
  internal_file = (libqcow_internal_file_t *) file;
3222
3223
0
  if( internal_file->backing_filename == NULL )
3224
0
  {
3225
0
    libcerror_error_set(
3226
0
     error,
3227
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3228
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3229
0
     "%s: invalid file - missing backing filename.",
3230
0
     function );
3231
3232
0
    return( -1 );
3233
0
  }
3234
0
  if( internal_file->parent_file != NULL )
3235
0
  {
3236
0
    libcerror_error_set(
3237
0
     error,
3238
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3239
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3240
0
     "%s: invalid file - parent file already set.",
3241
0
     function );
3242
3243
0
    return( -1 );
3244
0
  }
3245
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3246
0
  if( libcthreads_read_write_lock_grab_for_write(
3247
0
       internal_file->read_write_lock,
3248
0
       error ) != 1 )
3249
0
  {
3250
0
    libcerror_error_set(
3251
0
     error,
3252
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3253
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3254
0
     "%s: unable to grab read/write lock for writing.",
3255
0
     function );
3256
3257
0
    return( -1 );
3258
0
  }
3259
0
#endif
3260
0
  internal_file->parent_file = parent_file;
3261
3262
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3263
0
  if( libcthreads_read_write_lock_release_for_write(
3264
0
       internal_file->read_write_lock,
3265
0
       error ) != 1 )
3266
0
  {
3267
0
    libcerror_error_set(
3268
0
     error,
3269
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3270
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3271
0
     "%s: unable to release read/write lock for writing.",
3272
0
     function );
3273
3274
0
    return( -1 );
3275
0
  }
3276
0
#endif
3277
0
  return( 1 );
3278
0
}
3279
3280
/* Set the keys
3281
 * This function needs to be used before one of the open functions
3282
 * Returns 1 if successful or -1 on error
3283
 */
3284
int libqcow_file_set_keys(
3285
     libqcow_file_t *file,
3286
     const uint8_t *key,
3287
     size_t key_size,
3288
     libcerror_error_t **error )
3289
0
{
3290
0
  libqcow_internal_file_t *internal_file = NULL;
3291
0
  static char *function                  = "libqcow_file_set_keys";
3292
3293
0
  if( file == NULL )
3294
0
  {
3295
0
    libcerror_error_set(
3296
0
     error,
3297
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3298
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3299
0
     "%s: invalid file.",
3300
0
     function );
3301
3302
0
    return( -1 );
3303
0
  }
3304
0
  internal_file = (libqcow_internal_file_t *) file;
3305
3306
0
  if( internal_file->file_io_handle != NULL )
3307
0
  {
3308
0
    libcerror_error_set(
3309
0
     error,
3310
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3311
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3312
0
     "%s: invalid file - file IO handle already set.",
3313
0
     function );
3314
3315
0
    return( -1 );
3316
0
  }
3317
0
  if( key == NULL )
3318
0
  {
3319
0
    libcerror_error_set(
3320
0
     error,
3321
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3322
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3323
0
     "%s: invalid key.",
3324
0
     function );
3325
3326
0
    return( -1 );
3327
0
  }
3328
0
  if( key_size != 16 )
3329
0
  {
3330
0
    libcerror_error_set(
3331
0
     error,
3332
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3333
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3334
0
     "%s: unsupported key size.",
3335
0
     function );
3336
3337
0
    return( -1 );
3338
0
  }
3339
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3340
0
  if( libcthreads_read_write_lock_grab_for_write(
3341
0
       internal_file->read_write_lock,
3342
0
       error ) != 1 )
3343
0
  {
3344
0
    libcerror_error_set(
3345
0
     error,
3346
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3347
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3348
0
     "%s: unable to grab read/write lock for writing.",
3349
0
     function );
3350
3351
0
    return( -1 );
3352
0
  }
3353
0
#endif
3354
0
  if( memory_copy(
3355
0
       internal_file->key_data,
3356
0
       key,
3357
0
       key_size ) == NULL )
3358
0
  {
3359
0
    libcerror_error_set(
3360
0
     error,
3361
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
3362
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
3363
0
     "%s: unable to copy key.",
3364
0
     function );
3365
3366
0
    goto on_error;
3367
0
  }
3368
0
  internal_file->key_data_is_set = 1;
3369
3370
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3371
0
  if( libcthreads_read_write_lock_release_for_write(
3372
0
       internal_file->read_write_lock,
3373
0
       error ) != 1 )
3374
0
  {
3375
0
    libcerror_error_set(
3376
0
     error,
3377
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3378
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3379
0
     "%s: unable to release read/write lock for writing.",
3380
0
     function );
3381
3382
0
    return( -1 );
3383
0
  }
3384
0
#endif
3385
0
  return( 1 );
3386
3387
0
on_error:
3388
0
  memory_set(
3389
0
   internal_file->key_data,
3390
0
   0,
3391
0
   16 );
3392
3393
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3394
0
  libcthreads_read_write_lock_release_for_write(
3395
0
   internal_file->read_write_lock,
3396
0
   NULL );
3397
0
#endif
3398
0
  return( -1 );
3399
0
}
3400
3401
/* Sets an UTF-8 formatted password
3402
 * This function needs to be used before one of the open functions
3403
 * Returns 1 if successful, 0 if password is invalid or -1 on error
3404
 */
3405
int libqcow_file_set_utf8_password(
3406
     libqcow_file_t *file,
3407
     const uint8_t *utf8_string,
3408
     size_t utf8_string_length,
3409
     libcerror_error_t **error )
3410
0
{
3411
0
  libqcow_internal_file_t *internal_file = NULL;
3412
0
  static char *function                  = "libqcow_file_set_utf8_password";
3413
3414
0
  if( file == NULL )
3415
0
  {
3416
0
    libcerror_error_set(
3417
0
     error,
3418
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3419
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3420
0
     "%s: invalid file.",
3421
0
     function );
3422
3423
0
    return( -1 );
3424
0
  }
3425
0
  internal_file = (libqcow_internal_file_t *) file;
3426
3427
0
  if( internal_file->file_io_handle != NULL )
3428
0
  {
3429
0
    libcerror_error_set(
3430
0
     error,
3431
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3432
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3433
0
     "%s: invalid file - file IO handle already set.",
3434
0
     function );
3435
3436
0
    return( -1 );
3437
0
  }
3438
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3439
0
  if( libcthreads_read_write_lock_grab_for_write(
3440
0
       internal_file->read_write_lock,
3441
0
       error ) != 1 )
3442
0
  {
3443
0
    libcerror_error_set(
3444
0
     error,
3445
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3446
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3447
0
     "%s: unable to grab read/write lock for writing.",
3448
0
     function );
3449
3450
0
    return( -1 );
3451
0
  }
3452
0
#endif
3453
0
  if( memory_set(
3454
0
       internal_file->key_data,
3455
0
       0,
3456
0
       16 ) == NULL )
3457
0
  {
3458
0
    libcerror_error_set(
3459
0
     error,
3460
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
3461
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
3462
0
     "%s: unable to clear key data.",
3463
0
     function );
3464
3465
0
    goto on_error;
3466
0
  }
3467
0
  if( libuna_byte_stream_copy_from_utf8(
3468
0
       internal_file->key_data,
3469
0
       16,
3470
0
       LIBQCOW_CODEPAGE_US_ASCII,
3471
0
       utf8_string,
3472
0
       utf8_string_length,
3473
0
       error ) != 1 )
3474
0
  {
3475
0
    libcerror_error_set(
3476
0
     error,
3477
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3478
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3479
0
     "%s: unable to copy password.",
3480
0
     function );
3481
3482
0
    goto on_error;
3483
0
  }
3484
0
  internal_file->key_data_is_set = 1;
3485
3486
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3487
0
  if( libcthreads_read_write_lock_release_for_write(
3488
0
       internal_file->read_write_lock,
3489
0
       error ) != 1 )
3490
0
  {
3491
0
    libcerror_error_set(
3492
0
     error,
3493
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3494
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3495
0
     "%s: unable to release read/write lock for writing.",
3496
0
     function );
3497
3498
0
    return( -1 );
3499
0
  }
3500
0
#endif
3501
0
  return( 1 );
3502
3503
0
on_error:
3504
0
  memory_set(
3505
0
   internal_file->key_data,
3506
0
   0,
3507
0
   16 );
3508
3509
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3510
0
  libcthreads_read_write_lock_release_for_write(
3511
0
   internal_file->read_write_lock,
3512
0
   NULL );
3513
0
#endif
3514
0
  return( -1 );
3515
0
}
3516
3517
/* Sets an UTF-16 formatted password
3518
 * This function needs to be used before one of the open functions
3519
 * Returns 1 if successful, 0 if password is invalid or -1 on error
3520
 */
3521
int libqcow_file_set_utf16_password(
3522
     libqcow_file_t *file,
3523
     const uint16_t *utf16_string,
3524
     size_t utf16_string_length,
3525
     libcerror_error_t **error )
3526
0
{
3527
0
  libqcow_internal_file_t *internal_file = NULL;
3528
0
  static char *function                  = "libqcow_file_set_utf16_password";
3529
3530
0
  if( file == NULL )
3531
0
  {
3532
0
    libcerror_error_set(
3533
0
     error,
3534
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3535
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3536
0
     "%s: invalid file.",
3537
0
     function );
3538
3539
0
    return( -1 );
3540
0
  }
3541
0
  internal_file = (libqcow_internal_file_t *) file;
3542
3543
0
  if( internal_file->file_io_handle != NULL )
3544
0
  {
3545
0
    libcerror_error_set(
3546
0
     error,
3547
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3548
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3549
0
     "%s: invalid file - file IO handle already set.",
3550
0
     function );
3551
3552
0
    return( -1 );
3553
0
  }
3554
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3555
0
  if( libcthreads_read_write_lock_grab_for_write(
3556
0
       internal_file->read_write_lock,
3557
0
       error ) != 1 )
3558
0
  {
3559
0
    libcerror_error_set(
3560
0
     error,
3561
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3562
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3563
0
     "%s: unable to grab read/write lock for writing.",
3564
0
     function );
3565
3566
0
    return( -1 );
3567
0
  }
3568
0
#endif
3569
0
  if( memory_set(
3570
0
       internal_file->key_data,
3571
0
       0,
3572
0
       16 ) == NULL )
3573
0
  {
3574
0
    libcerror_error_set(
3575
0
     error,
3576
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
3577
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
3578
0
     "%s: unable to clear key data.",
3579
0
     function );
3580
3581
0
    goto on_error;
3582
0
  }
3583
0
  if( libuna_byte_stream_copy_from_utf16(
3584
0
       internal_file->key_data,
3585
0
       16,
3586
0
       LIBQCOW_CODEPAGE_US_ASCII,
3587
0
       utf16_string,
3588
0
       utf16_string_length,
3589
0
       error ) != 1 )
3590
0
  {
3591
0
    libcerror_error_set(
3592
0
     error,
3593
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3594
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3595
0
     "%s: unable to copy password.",
3596
0
     function );
3597
3598
0
    goto on_error;
3599
0
  }
3600
0
  internal_file->key_data_is_set = 1;
3601
3602
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3603
0
  if( libcthreads_read_write_lock_release_for_write(
3604
0
       internal_file->read_write_lock,
3605
0
       error ) != 1 )
3606
0
  {
3607
0
    libcerror_error_set(
3608
0
     error,
3609
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3610
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3611
0
     "%s: unable to release read/write lock for writing.",
3612
0
     function );
3613
3614
0
    return( -1 );
3615
0
  }
3616
0
#endif
3617
0
  return( 1 );
3618
3619
0
on_error:
3620
0
  memory_set(
3621
0
   internal_file->key_data,
3622
0
   0,
3623
0
   16 );
3624
3625
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3626
0
  libcthreads_read_write_lock_release_for_write(
3627
0
   internal_file->read_write_lock,
3628
0
   NULL );
3629
0
#endif
3630
0
  return( -1 );
3631
0
}
3632
3633
/* Retrieves the media size
3634
 * Returns 1 if successful or -1 on error
3635
 */
3636
int libqcow_file_get_media_size(
3637
     libqcow_file_t *file,
3638
     size64_t *media_size,
3639
     libcerror_error_t **error )
3640
0
{
3641
0
  libqcow_internal_file_t *internal_file = NULL;
3642
0
  static char *function                  = "libqcow_file_get_media_size";
3643
3644
0
  if( file == NULL )
3645
0
  {
3646
0
    libcerror_error_set(
3647
0
     error,
3648
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3649
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3650
0
     "%s: invalid file.",
3651
0
     function );
3652
3653
0
    return( -1 );
3654
0
  }
3655
0
  internal_file = (libqcow_internal_file_t *) file;
3656
3657
0
  if( internal_file->file_header == NULL )
3658
0
  {
3659
0
    libcerror_error_set(
3660
0
     error,
3661
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3662
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3663
0
     "%s: invalid file - missing file header.",
3664
0
     function );
3665
3666
0
    return( -1 );
3667
0
  }
3668
0
  if( media_size == NULL )
3669
0
  {
3670
0
    libcerror_error_set(
3671
0
     error,
3672
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3673
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3674
0
     "%s: invalid media size.",
3675
0
     function );
3676
3677
0
    return( -1 );
3678
0
  }
3679
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3680
0
  if( libcthreads_read_write_lock_grab_for_read(
3681
0
       internal_file->read_write_lock,
3682
0
       error ) != 1 )
3683
0
  {
3684
0
    libcerror_error_set(
3685
0
     error,
3686
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3687
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3688
0
     "%s: unable to grab read/write lock for reading.",
3689
0
     function );
3690
3691
0
    return( -1 );
3692
0
  }
3693
0
#endif
3694
0
  *media_size = internal_file->file_header->media_size;
3695
3696
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3697
0
  if( libcthreads_read_write_lock_release_for_read(
3698
0
       internal_file->read_write_lock,
3699
0
       error ) != 1 )
3700
0
  {
3701
0
    libcerror_error_set(
3702
0
     error,
3703
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3704
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3705
0
     "%s: unable to release read/write lock for reading.",
3706
0
     function );
3707
3708
0
    return( -1 );
3709
0
  }
3710
0
#endif
3711
0
  return( 1 );
3712
0
}
3713
3714
/* Retrieves the format version
3715
 * Returns 1 if successful or -1 on error
3716
 */
3717
int libqcow_file_get_format_version(
3718
     libqcow_file_t *file,
3719
     uint32_t *format_version,
3720
     libcerror_error_t **error )
3721
0
{
3722
0
  libqcow_internal_file_t *internal_file = NULL;
3723
0
  static char *function                  = "libqcow_file_get_format_version";
3724
3725
0
  if( file == NULL )
3726
0
  {
3727
0
    libcerror_error_set(
3728
0
     error,
3729
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3730
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3731
0
     "%s: invalid file.",
3732
0
     function );
3733
3734
0
    return( -1 );
3735
0
  }
3736
0
  internal_file = (libqcow_internal_file_t *) file;
3737
3738
0
  if( internal_file->file_header == NULL )
3739
0
  {
3740
0
    libcerror_error_set(
3741
0
     error,
3742
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3743
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3744
0
     "%s: invalid file - missing file header.",
3745
0
     function );
3746
3747
0
    return( -1 );
3748
0
  }
3749
0
  if( format_version == NULL )
3750
0
  {
3751
0
    libcerror_error_set(
3752
0
     error,
3753
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3754
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3755
0
     "%s: invalid format version.",
3756
0
     function );
3757
3758
0
    return( -1 );
3759
0
  }
3760
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3761
0
  if( libcthreads_read_write_lock_grab_for_read(
3762
0
       internal_file->read_write_lock,
3763
0
       error ) != 1 )
3764
0
  {
3765
0
    libcerror_error_set(
3766
0
     error,
3767
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3768
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3769
0
     "%s: unable to grab read/write lock for reading.",
3770
0
     function );
3771
3772
0
    return( -1 );
3773
0
  }
3774
0
#endif
3775
0
  *format_version = internal_file->file_header->format_version;
3776
3777
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3778
0
  if( libcthreads_read_write_lock_release_for_read(
3779
0
       internal_file->read_write_lock,
3780
0
       error ) != 1 )
3781
0
  {
3782
0
    libcerror_error_set(
3783
0
     error,
3784
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3785
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3786
0
     "%s: unable to release read/write lock for reading.",
3787
0
     function );
3788
3789
0
    return( -1 );
3790
0
  }
3791
0
#endif
3792
0
  return( 1 );
3793
0
}
3794
3795
/* Retrieves the encryption method
3796
 * Returns 1 if successful or -1 on error
3797
 */
3798
int libqcow_file_get_encryption_method(
3799
     libqcow_file_t *file,
3800
     uint32_t *encryption_method,
3801
     libcerror_error_t **error )
3802
0
{
3803
0
  libqcow_internal_file_t *internal_file = NULL;
3804
0
  static char *function                  = "libqcow_file_get_encryption_method";
3805
3806
0
  if( file == NULL )
3807
0
  {
3808
0
    libcerror_error_set(
3809
0
     error,
3810
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3811
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3812
0
     "%s: invalid file.",
3813
0
     function );
3814
3815
0
    return( -1 );
3816
0
  }
3817
0
  internal_file = (libqcow_internal_file_t *) file;
3818
3819
0
  if( internal_file->file_io_handle == NULL )
3820
0
  {
3821
0
    libcerror_error_set(
3822
0
     error,
3823
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3824
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3825
0
     "%s: invalid file - missing file IO handle.",
3826
0
     function );
3827
3828
0
    return( -1 );
3829
0
  }
3830
0
  if( encryption_method == NULL )
3831
0
  {
3832
0
    libcerror_error_set(
3833
0
     error,
3834
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3835
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3836
0
     "%s: invalid encryption method.",
3837
0
     function );
3838
3839
0
    return( -1 );
3840
0
  }
3841
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3842
0
  if( libcthreads_read_write_lock_grab_for_read(
3843
0
       internal_file->read_write_lock,
3844
0
       error ) != 1 )
3845
0
  {
3846
0
    libcerror_error_set(
3847
0
     error,
3848
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3849
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3850
0
     "%s: unable to grab read/write lock for reading.",
3851
0
     function );
3852
3853
0
    return( -1 );
3854
0
  }
3855
0
#endif
3856
0
  *encryption_method = internal_file->encryption_method;
3857
3858
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3859
0
  if( libcthreads_read_write_lock_release_for_read(
3860
0
       internal_file->read_write_lock,
3861
0
       error ) != 1 )
3862
0
  {
3863
0
    libcerror_error_set(
3864
0
     error,
3865
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3866
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3867
0
     "%s: unable to release read/write lock for reading.",
3868
0
     function );
3869
3870
0
    return( -1 );
3871
0
  }
3872
0
#endif
3873
0
  return( 1 );
3874
0
}
3875
3876
/* Retrieves the size of the UTF-8 encoded backing filename
3877
 * The returned size includes the end of string character
3878
 * Returns 1 if successful, 0 if not available or -1 on error
3879
 */
3880
int libqcow_file_get_utf8_backing_filename_size(
3881
     libqcow_file_t *file,
3882
     size_t *utf8_string_size,
3883
     libcerror_error_t **error )
3884
0
{
3885
0
  libqcow_internal_file_t *internal_file = NULL;
3886
0
  static char *function                  = "libqcow_file_get_utf8_backing_filename_size";
3887
0
  int result                             = 0;
3888
3889
0
  if( file == NULL )
3890
0
  {
3891
0
    libcerror_error_set(
3892
0
     error,
3893
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3894
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3895
0
     "%s: invalid file.",
3896
0
     function );
3897
3898
0
    return( -1 );
3899
0
  }
3900
0
  internal_file = (libqcow_internal_file_t *) file;
3901
3902
0
  if( internal_file->file_io_handle == NULL )
3903
0
  {
3904
0
    libcerror_error_set(
3905
0
     error,
3906
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3907
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3908
0
     "%s: invalid file - missing file IO handle.",
3909
0
     function );
3910
3911
0
    return( -1 );
3912
0
  }
3913
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3914
0
  if( libcthreads_read_write_lock_grab_for_read(
3915
0
       internal_file->read_write_lock,
3916
0
       error ) != 1 )
3917
0
  {
3918
0
    libcerror_error_set(
3919
0
     error,
3920
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3921
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3922
0
     "%s: unable to grab read/write lock for reading.",
3923
0
     function );
3924
3925
0
    return( -1 );
3926
0
  }
3927
0
#endif
3928
0
  if( internal_file->backing_filename != NULL )
3929
0
  {
3930
0
    result = libuna_utf8_string_size_from_utf8_stream(
3931
0
              internal_file->backing_filename,
3932
0
              internal_file->backing_filename_size,
3933
0
              utf8_string_size,
3934
0
              error );
3935
3936
0
    if( result != 1 )
3937
0
    {
3938
0
      libcerror_error_set(
3939
0
       error,
3940
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3941
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3942
0
       "%s: unable to retrieve UTF-8 string size of backing filename.",
3943
0
       function );
3944
3945
0
      result = -1;
3946
0
    }
3947
0
  }
3948
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
3949
0
  if( libcthreads_read_write_lock_release_for_read(
3950
0
       internal_file->read_write_lock,
3951
0
       error ) != 1 )
3952
0
  {
3953
0
    libcerror_error_set(
3954
0
     error,
3955
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3956
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3957
0
     "%s: unable to release read/write lock for reading.",
3958
0
     function );
3959
3960
0
    return( -1 );
3961
0
  }
3962
0
#endif
3963
0
  return( result );
3964
0
}
3965
3966
/* Retrieves the UTF-8 encoded backing filename
3967
 * The size should include the end of string character
3968
 * Returns 1 if successful, 0 if not available or -1 on error
3969
 */
3970
int libqcow_file_get_utf8_backing_filename(
3971
     libqcow_file_t *file,
3972
     uint8_t *utf8_string,
3973
     size_t utf8_string_size,
3974
     libcerror_error_t **error )
3975
0
{
3976
0
  libqcow_internal_file_t *internal_file = NULL;
3977
0
  static char *function                  = "libqcow_file_get_utf8_backing_filename";
3978
0
  int result                             = 0;
3979
3980
0
  if( file == NULL )
3981
0
  {
3982
0
    libcerror_error_set(
3983
0
     error,
3984
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3985
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3986
0
     "%s: invalid file.",
3987
0
     function );
3988
3989
0
    return( -1 );
3990
0
  }
3991
0
  internal_file = (libqcow_internal_file_t *) file;
3992
3993
0
  if( internal_file->file_io_handle == NULL )
3994
0
  {
3995
0
    libcerror_error_set(
3996
0
     error,
3997
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3998
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3999
0
     "%s: invalid file - missing file IO handle.",
4000
0
     function );
4001
4002
0
    return( -1 );
4003
0
  }
4004
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
4005
0
  if( libcthreads_read_write_lock_grab_for_read(
4006
0
       internal_file->read_write_lock,
4007
0
       error ) != 1 )
4008
0
  {
4009
0
    libcerror_error_set(
4010
0
     error,
4011
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4012
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4013
0
     "%s: unable to grab read/write lock for reading.",
4014
0
     function );
4015
4016
0
    return( -1 );
4017
0
  }
4018
0
#endif
4019
0
  if( internal_file->backing_filename != NULL )
4020
0
  {
4021
0
    result = libuna_utf8_string_copy_from_utf8_stream(
4022
0
              utf8_string,
4023
0
              utf8_string_size,
4024
0
              internal_file->backing_filename,
4025
0
              internal_file->backing_filename_size,
4026
0
              error );
4027
4028
0
    if( result != 1 )
4029
0
    {
4030
0
      libcerror_error_set(
4031
0
       error,
4032
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4033
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4034
0
       "%s: unable to retrieve UTF-8 string of backing filename.",
4035
0
       function );
4036
4037
0
      result = -1;
4038
0
    }
4039
0
  }
4040
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
4041
0
  if( libcthreads_read_write_lock_release_for_read(
4042
0
       internal_file->read_write_lock,
4043
0
       error ) != 1 )
4044
0
  {
4045
0
    libcerror_error_set(
4046
0
     error,
4047
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4048
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4049
0
     "%s: unable to release read/write lock for reading.",
4050
0
     function );
4051
4052
0
    return( -1 );
4053
0
  }
4054
0
#endif
4055
0
  return( result );
4056
0
}
4057
4058
/* Retrieves the size of the UTF-16 encoded backing filename
4059
 * The returned size includes the end of string character
4060
 * Returns 1 if successful, 0 if not available or -1 on error
4061
 */
4062
int libqcow_file_get_utf16_backing_filename_size(
4063
     libqcow_file_t *file,
4064
     size_t *utf16_string_size,
4065
     libcerror_error_t **error )
4066
0
{
4067
0
  libqcow_internal_file_t *internal_file = NULL;
4068
0
  static char *function                  = "libqcow_file_get_utf16_backing_filename_size";
4069
0
  int result                             = 0;
4070
4071
0
  if( file == NULL )
4072
0
  {
4073
0
    libcerror_error_set(
4074
0
     error,
4075
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4076
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4077
0
     "%s: invalid file.",
4078
0
     function );
4079
4080
0
    return( -1 );
4081
0
  }
4082
0
  internal_file = (libqcow_internal_file_t *) file;
4083
4084
0
  if( internal_file->file_io_handle == NULL )
4085
0
  {
4086
0
    libcerror_error_set(
4087
0
     error,
4088
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4089
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4090
0
     "%s: invalid file - missing file IO handle.",
4091
0
     function );
4092
4093
0
    return( -1 );
4094
0
  }
4095
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
4096
0
  if( libcthreads_read_write_lock_grab_for_read(
4097
0
       internal_file->read_write_lock,
4098
0
       error ) != 1 )
4099
0
  {
4100
0
    libcerror_error_set(
4101
0
     error,
4102
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4103
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4104
0
     "%s: unable to grab read/write lock for reading.",
4105
0
     function );
4106
4107
0
    return( -1 );
4108
0
  }
4109
0
#endif
4110
0
  if( internal_file->backing_filename != NULL )
4111
0
  {
4112
0
    result = libuna_utf16_string_size_from_utf8_stream(
4113
0
              internal_file->backing_filename,
4114
0
              internal_file->backing_filename_size,
4115
0
              utf16_string_size,
4116
0
              error );
4117
4118
0
    if( result != 1 )
4119
0
    {
4120
0
      libcerror_error_set(
4121
0
       error,
4122
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4123
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4124
0
       "%s: unable to retrieve UTF-16 string size of backing filename.",
4125
0
       function );
4126
4127
0
      result = -1;
4128
0
    }
4129
0
  }
4130
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
4131
0
  if( libcthreads_read_write_lock_release_for_read(
4132
0
       internal_file->read_write_lock,
4133
0
       error ) != 1 )
4134
0
  {
4135
0
    libcerror_error_set(
4136
0
     error,
4137
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4138
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4139
0
     "%s: unable to release read/write lock for reading.",
4140
0
     function );
4141
4142
0
    return( -1 );
4143
0
  }
4144
0
#endif
4145
0
  return( result );
4146
0
}
4147
4148
/* Retrieves the UTF-16 encoded backing filename
4149
 * The size should include the end of string character
4150
 * Returns 1 if successful, 0 if not available or -1 on error
4151
 */
4152
int libqcow_file_get_utf16_backing_filename(
4153
     libqcow_file_t *file,
4154
     uint16_t *utf16_string,
4155
     size_t utf16_string_size,
4156
     libcerror_error_t **error )
4157
0
{
4158
0
  libqcow_internal_file_t *internal_file = NULL;
4159
0
  static char *function                  = "libqcow_file_get_utf16_backing_filename";
4160
0
  int result                             = 0;
4161
4162
0
  if( file == NULL )
4163
0
  {
4164
0
    libcerror_error_set(
4165
0
     error,
4166
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4167
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4168
0
     "%s: invalid file.",
4169
0
     function );
4170
4171
0
    return( -1 );
4172
0
  }
4173
0
  internal_file = (libqcow_internal_file_t *) file;
4174
4175
0
  if( internal_file->file_io_handle == NULL )
4176
0
  {
4177
0
    libcerror_error_set(
4178
0
     error,
4179
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4180
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4181
0
     "%s: invalid file - missing file IO handle.",
4182
0
     function );
4183
4184
0
    return( -1 );
4185
0
  }
4186
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
4187
0
  if( libcthreads_read_write_lock_grab_for_read(
4188
0
       internal_file->read_write_lock,
4189
0
       error ) != 1 )
4190
0
  {
4191
0
    libcerror_error_set(
4192
0
     error,
4193
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4194
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4195
0
     "%s: unable to grab read/write lock for reading.",
4196
0
     function );
4197
4198
0
    return( -1 );
4199
0
  }
4200
0
#endif
4201
0
  if( internal_file->backing_filename != NULL )
4202
0
  {
4203
0
    result = libuna_utf16_string_copy_from_utf8_stream(
4204
0
              utf16_string,
4205
0
              utf16_string_size,
4206
0
              internal_file->backing_filename,
4207
0
              internal_file->backing_filename_size,
4208
0
              error );
4209
4210
0
    if( result != 1 )
4211
0
    {
4212
0
      libcerror_error_set(
4213
0
       error,
4214
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4215
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4216
0
       "%s: unable to retrieve UTF-16 string of backing filename.",
4217
0
       function );
4218
4219
0
      result = -1;
4220
0
    }
4221
0
  }
4222
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
4223
0
  if( libcthreads_read_write_lock_release_for_read(
4224
0
       internal_file->read_write_lock,
4225
0
       error ) != 1 )
4226
0
  {
4227
0
    libcerror_error_set(
4228
0
     error,
4229
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4230
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4231
0
     "%s: unable to release read/write lock for reading.",
4232
0
     function );
4233
4234
0
    return( -1 );
4235
0
  }
4236
0
#endif
4237
0
  return( result );
4238
0
}
4239
4240
/* Retrieves the number of snapshots
4241
 * Returns 1 if successful or -1 on error
4242
 */
4243
int libqcow_file_get_number_of_snapshots(
4244
     libqcow_file_t *file,
4245
     int *number_of_snapshots,
4246
     libcerror_error_t **error )
4247
0
{
4248
0
  libqcow_internal_file_t *internal_file = NULL;
4249
0
  static char *function                  = "libqcow_file_get_number_of_snapshots";
4250
4251
0
  if( file == NULL )
4252
0
  {
4253
0
    libcerror_error_set(
4254
0
     error,
4255
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4256
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4257
0
     "%s: invalid file.",
4258
0
     function );
4259
4260
0
    return( -1 );
4261
0
  }
4262
0
  internal_file = (libqcow_internal_file_t *) file;
4263
4264
0
  if( internal_file->file_header == NULL )
4265
0
  {
4266
0
    libcerror_error_set(
4267
0
     error,
4268
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4269
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4270
0
     "%s: invalid file - missing file header.",
4271
0
     function );
4272
4273
0
    return( -1 );
4274
0
  }
4275
0
  if( number_of_snapshots == NULL )
4276
0
  {
4277
0
    libcerror_error_set(
4278
0
     error,
4279
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4280
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4281
0
     "%s: invalid number of snapshots.",
4282
0
     function );
4283
4284
0
    return( -1 );
4285
0
  }
4286
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
4287
0
  if( libcthreads_read_write_lock_grab_for_read(
4288
0
       internal_file->read_write_lock,
4289
0
       error ) != 1 )
4290
0
  {
4291
0
    libcerror_error_set(
4292
0
     error,
4293
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4294
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4295
0
     "%s: unable to grab read/write lock for reading.",
4296
0
     function );
4297
4298
0
    return( -1 );
4299
0
  }
4300
0
#endif
4301
  /* TODO retrieve number of snapshots from array */
4302
0
  *number_of_snapshots = (int) internal_file->file_header->number_of_snapshots;
4303
4304
0
#if defined( HAVE_LIBQCOW_MULTI_THREAD_SUPPORT )
4305
0
  if( libcthreads_read_write_lock_release_for_read(
4306
0
       internal_file->read_write_lock,
4307
0
       error ) != 1 )
4308
0
  {
4309
0
    libcerror_error_set(
4310
0
     error,
4311
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4312
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4313
0
     "%s: unable to release read/write lock for reading.",
4314
0
     function );
4315
4316
0
    return( -1 );
4317
0
  }
4318
0
#endif
4319
0
  return( 1 );
4320
0
}
4321