Coverage Report

Created: 2023-06-07 06:53

/src/libcreg/libcreg/libcreg_file.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * File functions
3
 *
4
 * Copyright (C) 2013-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 "libcreg_codepage.h"
29
#include "libcreg_data_block.h"
30
#include "libcreg_debug.h"
31
#include "libcreg_definitions.h"
32
#include "libcreg_file.h"
33
#include "libcreg_io_handle.h"
34
#include "libcreg_key.h"
35
#include "libcreg_key_item.h"
36
#include "libcreg_key_navigation.h"
37
#include "libcreg_key_tree.h"
38
#include "libcreg_libbfio.h"
39
#include "libcreg_libcerror.h"
40
#include "libcreg_libcnotify.h"
41
#include "libcreg_libcthreads.h"
42
#include "libcreg_libfcache.h"
43
#include "libcreg_libuna.h"
44
45
#include "creg_file_header.h"
46
#include "creg_key_navigation.h"
47
48
/* Creates a file
49
 * Make sure the value file is referencing, is set to NULL
50
 * Returns 1 if successful or -1 on error
51
 */
52
int libcreg_file_initialize(
53
     libcreg_file_t **file,
54
     libcerror_error_t **error )
55
1.41k
{
56
1.41k
  libcreg_internal_file_t *internal_file = NULL;
57
1.41k
  static char *function                  = "libcreg_file_initialize";
58
59
1.41k
  if( file == NULL )
60
0
  {
61
0
    libcerror_error_set(
62
0
     error,
63
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
64
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
65
0
     "%s: invalid file.",
66
0
     function );
67
68
0
    return( -1 );
69
0
  }
70
1.41k
  if( *file != NULL )
71
0
  {
72
0
    libcerror_error_set(
73
0
     error,
74
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
75
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
76
0
     "%s: invalid file value already set.",
77
0
     function );
78
79
0
    return( -1 );
80
0
  }
81
1.41k
  internal_file = memory_allocate_structure(
82
1.41k
                   libcreg_internal_file_t );
83
84
1.41k
  if( internal_file == NULL )
85
0
  {
86
0
    libcerror_error_set(
87
0
     error,
88
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
89
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
90
0
     "%s: unable to create file.",
91
0
     function );
92
93
0
    goto on_error;
94
0
  }
95
1.41k
  if( memory_set(
96
1.41k
       internal_file,
97
1.41k
       0,
98
1.41k
       sizeof( libcreg_internal_file_t ) ) == NULL )
99
0
  {
100
0
    libcerror_error_set(
101
0
     error,
102
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
103
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
104
0
     "%s: unable to clear file.",
105
0
     function );
106
107
0
    goto on_error;
108
0
  }
109
1.41k
  if( libcreg_io_handle_initialize(
110
1.41k
       &( internal_file->io_handle ),
111
1.41k
       error ) != 1 )
112
0
  {
113
0
    libcerror_error_set(
114
0
     error,
115
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
116
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
117
0
     "%s: unable to create IO handle.",
118
0
     function );
119
120
0
    goto on_error;
121
0
  }
122
1.41k
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
123
1.41k
  if( libcthreads_read_write_lock_initialize(
124
1.41k
       &( internal_file->read_write_lock ),
125
1.41k
       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 initialize read/write lock.",
132
0
     function );
133
134
0
    goto on_error;
135
0
  }
136
1.41k
#endif
137
1.41k
  *file = (libcreg_file_t *) internal_file;
138
139
1.41k
  return( 1 );
140
141
0
on_error:
142
0
  if( internal_file != NULL )
143
0
  {
144
0
    memory_free(
145
0
     internal_file );
146
0
  }
147
0
  return( -1 );
148
1.41k
}
149
150
/* Frees a file
151
 * Returns 1 if successful or -1 on error
152
 */
153
int libcreg_file_free(
154
     libcreg_file_t **file,
155
     libcerror_error_t **error )
156
1.41k
{
157
1.41k
  libcreg_internal_file_t *internal_file = NULL;
158
1.41k
  static char *function                  = "libcreg_file_free";
159
1.41k
  int result                             = 1;
160
161
1.41k
  if( file == NULL )
162
0
  {
163
0
    libcerror_error_set(
164
0
     error,
165
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
166
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
167
0
     "%s: invalid file.",
168
0
     function );
169
170
0
    return( -1 );
171
0
  }
172
1.41k
  if( *file != NULL )
173
1.41k
  {
174
1.41k
    internal_file = (libcreg_internal_file_t *) *file;
175
176
1.41k
    if( internal_file->file_io_handle != NULL )
177
0
    {
178
0
      if( libcreg_file_close(
179
0
           *file,
180
0
           error ) != 0 )
181
0
      {
182
0
        libcerror_error_set(
183
0
         error,
184
0
         LIBCERROR_ERROR_DOMAIN_IO,
185
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
186
0
         "%s: unable to close file.",
187
0
         function );
188
189
0
        result = -1;
190
0
      }
191
0
    }
192
1.41k
    *file = NULL;
193
194
1.41k
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
195
1.41k
    if( libcthreads_read_write_lock_free(
196
1.41k
         &( internal_file->read_write_lock ),
197
1.41k
         error ) != 1 )
198
0
    {
199
0
      libcerror_error_set(
200
0
       error,
201
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
202
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
203
0
       "%s: unable to free read/write lock.",
204
0
       function );
205
206
0
      result = -1;
207
0
    }
208
1.41k
#endif
209
1.41k
    if( libcreg_io_handle_free(
210
1.41k
         &( internal_file->io_handle ),
211
1.41k
         error ) != 1 )
212
0
    {
213
0
      libcerror_error_set(
214
0
       error,
215
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
216
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
217
0
       "%s: unable to free IO handle.",
218
0
       function );
219
220
0
      result = -1;
221
0
    }
222
1.41k
    memory_free(
223
1.41k
     internal_file );
224
1.41k
  }
225
1.41k
  return( result );
226
1.41k
}
227
228
/* Signals the libcreg file to abort its current activity
229
 * Returns 1 if successful or -1 on error
230
 */
231
int libcreg_file_signal_abort(
232
     libcreg_file_t *file,
233
     libcerror_error_t **error )
234
0
{
235
0
  static char *function = "libcreg_file_signal_abort";
236
237
0
  if( file == NULL )
238
0
  {
239
0
    libcerror_error_set(
240
0
     error,
241
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
242
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
243
0
     "%s: invalid file.",
244
0
     function );
245
246
0
    return( -1 );
247
0
  }
248
0
  ( (libcreg_internal_file_t *) file )->abort = 1;
249
250
0
  return( 1 );
251
0
}
252
253
/* Opens a file
254
 * Returns 1 if successful or -1 on error
255
 */
256
int libcreg_file_open(
257
     libcreg_file_t *file,
258
     const char *filename,
259
     int access_flags,
260
     libcerror_error_t **error )
261
0
{
262
0
  libbfio_handle_t *file_io_handle       = NULL;
263
0
  libcreg_internal_file_t *internal_file = NULL;
264
0
  static char *function                  = "libcreg_file_open";
265
0
  size_t filename_length                 = 0;
266
267
0
  if( file == NULL )
268
0
  {
269
0
    libcerror_error_set(
270
0
     error,
271
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
272
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
273
0
     "%s: invalid file.",
274
0
     function );
275
276
0
    return( -1 );
277
0
  }
278
0
  if( filename == NULL )
279
0
  {
280
0
    libcerror_error_set(
281
0
     error,
282
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
283
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
284
0
     "%s: invalid filename.",
285
0
     function );
286
287
0
    return( -1 );
288
0
  }
289
0
  if( ( ( access_flags & LIBCREG_ACCESS_FLAG_READ ) == 0 )
290
0
   && ( ( access_flags & LIBCREG_ACCESS_FLAG_WRITE ) == 0 ) )
291
0
  {
292
0
    libcerror_error_set(
293
0
     error,
294
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
295
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
296
0
     "%s: unsupported access flags.",
297
0
     function );
298
299
0
    return( -1 );
300
0
  }
301
0
  if( ( access_flags & LIBCREG_ACCESS_FLAG_WRITE ) != 0 )
302
0
  {
303
0
    libcerror_error_set(
304
0
     error,
305
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
306
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
307
0
     "%s: write access currently not supported.",
308
0
     function );
309
310
0
    return( -1 );
311
0
  }
312
0
  internal_file = (libcreg_internal_file_t *) file;
313
314
0
  if( libbfio_file_initialize(
315
0
       &file_io_handle,
316
0
       error ) != 1 )
317
0
  {
318
0
    libcerror_error_set(
319
0
     error,
320
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
321
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
322
0
     "%s: unable to create file IO handle.",
323
0
     function );
324
325
0
    goto on_error;
326
0
  }
327
#if defined( HAVE_DEBUG_OUTPUT )
328
  if( libbfio_handle_set_track_offsets_read(
329
       file_io_handle,
330
       1,
331
       error ) != 1 )
332
  {
333
    libcerror_error_set(
334
     error,
335
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
336
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
337
     "%s: unable to set track offsets read in file IO handle.",
338
     function );
339
340
    goto on_error;
341
  }
342
#endif
343
0
  filename_length = narrow_string_length(
344
0
                     filename );
345
346
0
  if( libbfio_file_set_name(
347
0
       file_io_handle,
348
0
       filename,
349
0
       filename_length + 1,
350
0
       error ) != 1 )
351
0
  {
352
0
    libcerror_error_set(
353
0
     error,
354
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
355
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
356
0
     "%s: unable to set filename in file IO handle.",
357
0
     function );
358
359
0
    goto on_error;
360
0
  }
361
0
  if( libcreg_file_open_file_io_handle(
362
0
       file,
363
0
       file_io_handle,
364
0
       access_flags,
365
0
       error ) != 1 )
366
0
  {
367
0
    libcerror_error_set(
368
0
     error,
369
0
     LIBCERROR_ERROR_DOMAIN_IO,
370
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
371
0
     "%s: unable to open file: %s.",
372
0
     function,
373
0
     filename );
374
375
0
    goto on_error;
376
0
  }
377
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
378
0
  if( libcthreads_read_write_lock_grab_for_write(
379
0
       internal_file->read_write_lock,
380
0
       error ) != 1 )
381
0
  {
382
0
    libcerror_error_set(
383
0
     error,
384
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
385
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
386
0
     "%s: unable to grab read/write lock for writing.",
387
0
     function );
388
389
0
    goto on_error;
390
0
  }
391
0
#endif
392
0
  internal_file->file_io_handle_created_in_library = 1;
393
394
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
395
0
  if( libcthreads_read_write_lock_release_for_write(
396
0
       internal_file->read_write_lock,
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 release read/write lock for writing.",
404
0
     function );
405
406
0
    internal_file->file_io_handle_created_in_library = 0;
407
408
0
    goto on_error;
409
0
  }
410
0
#endif
411
0
  return( 1 );
412
413
0
on_error:
414
0
  if( file_io_handle != NULL )
415
0
  {
416
0
    libbfio_handle_free(
417
0
     &file_io_handle,
418
0
     NULL );
419
0
  }
420
0
  return( -1 );
421
0
}
422
423
#if defined( HAVE_WIDE_CHARACTER_TYPE )
424
425
/* Opens a file
426
 * Returns 1 if successful or -1 on error
427
 */
428
int libcreg_file_open_wide(
429
     libcreg_file_t *file,
430
     const wchar_t *filename,
431
     int access_flags,
432
     libcerror_error_t **error )
433
{
434
  libbfio_handle_t *file_io_handle       = NULL;
435
  libcreg_internal_file_t *internal_file = NULL;
436
  static char *function                  = "libcreg_file_open_wide";
437
  size_t filename_length                 = 0;
438
439
  if( file == NULL )
440
  {
441
    libcerror_error_set(
442
     error,
443
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
444
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
445
     "%s: invalid file.",
446
     function );
447
448
    return( -1 );
449
  }
450
  if( filename == NULL )
451
  {
452
    libcerror_error_set(
453
     error,
454
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
455
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
456
     "%s: invalid filename.",
457
     function );
458
459
    return( -1 );
460
  }
461
  if( ( ( access_flags & LIBCREG_ACCESS_FLAG_READ ) == 0 )
462
   && ( ( access_flags & LIBCREG_ACCESS_FLAG_WRITE ) == 0 ) )
463
  {
464
    libcerror_error_set(
465
     error,
466
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
467
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
468
     "%s: unsupported access flags.",
469
     function );
470
471
    return( -1 );
472
  }
473
  if( ( access_flags & LIBCREG_ACCESS_FLAG_WRITE ) != 0 )
474
  {
475
    libcerror_error_set(
476
     error,
477
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
478
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
479
     "%s: write access currently not supported.",
480
     function );
481
482
    return( -1 );
483
  }
484
  internal_file = (libcreg_internal_file_t *) file;
485
486
  if( libbfio_file_initialize(
487
       &file_io_handle,
488
       error ) != 1 )
489
  {
490
    libcerror_error_set(
491
     error,
492
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
493
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
494
     "%s: unable to create file IO handle.",
495
     function );
496
497
    goto on_error;
498
  }
499
#if defined( HAVE_DEBUG_OUTPUT )
500
  if( libbfio_handle_set_track_offsets_read(
501
       file_io_handle,
502
       1,
503
       error ) != 1 )
504
  {
505
    libcerror_error_set(
506
     error,
507
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
508
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
509
     "%s: unable to set track offsets read in file IO handle.",
510
     function );
511
512
    goto on_error;
513
  }
514
#endif
515
  filename_length = wide_string_length(
516
                     filename );
517
518
  if( libbfio_file_set_name_wide(
519
       file_io_handle,
520
       filename,
521
       filename_length + 1,
522
       error ) != 1 )
523
  {
524
    libcerror_error_set(
525
     error,
526
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
527
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
528
     "%s: unable to set filename in file IO handle.",
529
     function );
530
531
    goto on_error;
532
  }
533
  if( libcreg_file_open_file_io_handle(
534
       file,
535
       file_io_handle,
536
       access_flags,
537
       error ) != 1 )
538
  {
539
    libcerror_error_set(
540
     error,
541
     LIBCERROR_ERROR_DOMAIN_IO,
542
     LIBCERROR_IO_ERROR_OPEN_FAILED,
543
     "%s: unable to open file: %ls.",
544
     function,
545
     filename );
546
547
    goto on_error;
548
  }
549
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
550
  if( libcthreads_read_write_lock_grab_for_write(
551
       internal_file->read_write_lock,
552
       error ) != 1 )
553
  {
554
    libcerror_error_set(
555
     error,
556
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
557
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
558
     "%s: unable to grab read/write lock for writing.",
559
     function );
560
561
    goto on_error;
562
  }
563
#endif
564
  internal_file->file_io_handle_created_in_library = 1;
565
566
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
567
  if( libcthreads_read_write_lock_release_for_write(
568
       internal_file->read_write_lock,
569
       error ) != 1 )
570
  {
571
    libcerror_error_set(
572
     error,
573
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
574
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
575
     "%s: unable to release read/write lock for writing.",
576
     function );
577
578
    internal_file->file_io_handle_created_in_library = 0;
579
580
    goto on_error;
581
  }
582
#endif
583
  return( 1 );
584
585
on_error:
586
  if( file_io_handle != NULL )
587
  {
588
    libbfio_handle_free(
589
     &file_io_handle,
590
     NULL );
591
  }
592
  return( -1 );
593
}
594
595
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
596
597
/* Opens a file using a Basic File IO (bfio) handle
598
 * Returns 1 if successful or -1 on error
599
 */
600
int libcreg_file_open_file_io_handle(
601
     libcreg_file_t *file,
602
     libbfio_handle_t *file_io_handle,
603
     int access_flags,
604
     libcerror_error_t **error )
605
1.41k
{
606
1.41k
  libcreg_internal_file_t *internal_file   = NULL;
607
1.41k
  static char *function                    = "libcreg_file_open_file_io_handle";
608
1.41k
  uint8_t file_io_handle_opened_in_library = 0;
609
1.41k
  int bfio_access_flags                    = 0;
610
1.41k
  int file_io_handle_is_open               = 0;
611
612
1.41k
  if( file == NULL )
613
0
  {
614
0
    libcerror_error_set(
615
0
     error,
616
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
617
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
618
0
     "%s: invalid file.",
619
0
     function );
620
621
0
    return( -1 );
622
0
  }
623
1.41k
  internal_file = (libcreg_internal_file_t *) file;
624
625
1.41k
  if( internal_file->file_io_handle != NULL )
626
0
  {
627
0
    libcerror_error_set(
628
0
     error,
629
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
630
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
631
0
     "%s: invalid file - file IO handle already set.",
632
0
     function );
633
634
0
    return( -1 );
635
0
  }
636
1.41k
  if( file_io_handle == NULL )
637
0
  {
638
0
    libcerror_error_set(
639
0
     error,
640
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
641
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
642
0
     "%s: invalid file IO handle.",
643
0
     function );
644
645
0
    return( -1 );
646
0
  }
647
1.41k
  if( ( ( access_flags & LIBCREG_ACCESS_FLAG_READ ) == 0 )
648
1.41k
   && ( ( access_flags & LIBCREG_ACCESS_FLAG_WRITE ) == 0 ) )
649
0
  {
650
0
    libcerror_error_set(
651
0
     error,
652
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
653
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
654
0
     "%s: unsupported access flags.",
655
0
     function );
656
657
0
    return( -1 );
658
0
  }
659
1.41k
  if( ( access_flags & LIBCREG_ACCESS_FLAG_WRITE ) != 0 )
660
0
  {
661
0
    libcerror_error_set(
662
0
     error,
663
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
664
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
665
0
     "%s: write access currently not supported.",
666
0
     function );
667
668
0
    return( -1 );
669
0
  }
670
1.41k
  if( ( access_flags & LIBCREG_ACCESS_FLAG_READ ) != 0 )
671
1.41k
  {
672
1.41k
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
673
1.41k
  }
674
1.41k
  file_io_handle_is_open = libbfio_handle_is_open(
675
1.41k
                            file_io_handle,
676
1.41k
                            error );
677
678
1.41k
  if( file_io_handle_is_open == -1 )
679
0
  {
680
0
    libcerror_error_set(
681
0
     error,
682
0
     LIBCERROR_ERROR_DOMAIN_IO,
683
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
684
0
     "%s: unable to open file.",
685
0
     function );
686
687
0
    goto on_error;
688
0
  }
689
1.41k
  else if( file_io_handle_is_open == 0 )
690
1.41k
  {
691
1.41k
    if( libbfio_handle_open(
692
1.41k
         file_io_handle,
693
1.41k
         bfio_access_flags,
694
1.41k
         error ) != 1 )
695
0
    {
696
0
      libcerror_error_set(
697
0
       error,
698
0
       LIBCERROR_ERROR_DOMAIN_IO,
699
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
700
0
       "%s: unable to open file IO handle.",
701
0
       function );
702
703
0
      goto on_error;
704
0
    }
705
1.41k
    file_io_handle_opened_in_library = 1;
706
1.41k
  }
707
1.41k
  if( libcreg_internal_file_open_read(
708
1.41k
       internal_file,
709
1.41k
       file_io_handle,
710
1.41k
       error ) != 1 )
711
241
  {
712
241
    libcerror_error_set(
713
241
     error,
714
241
     LIBCERROR_ERROR_DOMAIN_IO,
715
241
     LIBCERROR_IO_ERROR_READ_FAILED,
716
241
     "%s: unable to read from file handle.",
717
241
     function );
718
719
241
    goto on_error;
720
241
  }
721
1.17k
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
722
1.17k
  if( libcthreads_read_write_lock_grab_for_write(
723
1.17k
       internal_file->read_write_lock,
724
1.17k
       error ) != 1 )
725
0
  {
726
0
    libcerror_error_set(
727
0
     error,
728
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
729
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
730
0
     "%s: unable to grab read/write lock for writing.",
731
0
     function );
732
733
0
    goto on_error;
734
0
  }
735
1.17k
#endif
736
1.17k
  internal_file->file_io_handle                   = file_io_handle;
737
1.17k
  internal_file->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
738
739
1.17k
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
740
1.17k
  if( libcthreads_read_write_lock_release_for_write(
741
1.17k
       internal_file->read_write_lock,
742
1.17k
       error ) != 1 )
743
0
  {
744
0
    libcerror_error_set(
745
0
     error,
746
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
747
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
748
0
     "%s: unable to release read/write lock for writing.",
749
0
     function );
750
751
0
    internal_file->file_io_handle                   = NULL;
752
0
    internal_file->file_io_handle_opened_in_library = 0;
753
754
0
    goto on_error;
755
0
  }
756
1.17k
#endif
757
1.17k
  return( 1 );
758
759
241
on_error:
760
241
  if( file_io_handle_opened_in_library != 0 )
761
241
  {
762
241
    libbfio_handle_close(
763
241
     file_io_handle,
764
241
     error );
765
241
  }
766
241
  return( -1 );
767
1.17k
}
768
769
/* Closes a file
770
 * Returns 0 if successful or -1 on error
771
 */
772
int libcreg_file_close(
773
     libcreg_file_t *file,
774
     libcerror_error_t **error )
775
1.17k
{
776
1.17k
  libcreg_internal_file_t *internal_file = NULL;
777
1.17k
  static char *function                  = "libcreg_file_close";
778
1.17k
  int result                             = 0;
779
780
1.17k
  if( file == NULL )
781
0
  {
782
0
    libcerror_error_set(
783
0
     error,
784
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
785
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
786
0
     "%s: invalid file.",
787
0
     function );
788
789
0
    return( -1 );
790
0
  }
791
1.17k
  internal_file = (libcreg_internal_file_t *) file;
792
793
1.17k
  if( internal_file->file_io_handle == NULL )
794
0
  {
795
0
    libcerror_error_set(
796
0
     error,
797
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
798
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
799
0
     "%s: invalid file - missing file IO handle.",
800
0
     function );
801
802
0
    return( -1 );
803
0
  }
804
1.17k
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
805
1.17k
  if( libcthreads_read_write_lock_grab_for_write(
806
1.17k
       internal_file->read_write_lock,
807
1.17k
       error ) != 1 )
808
0
  {
809
0
    libcerror_error_set(
810
0
     error,
811
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
812
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
813
0
     "%s: unable to grab read/write lock for writing.",
814
0
     function );
815
816
0
    return( -1 );
817
0
  }
818
1.17k
#endif
819
#if defined( HAVE_DEBUG_OUTPUT )
820
  if( libcnotify_verbose != 0 )
821
  {
822
    if( internal_file->file_io_handle_created_in_library != 0 )
823
    {
824
      if( libcreg_debug_print_read_offsets(
825
           internal_file->file_io_handle,
826
           error ) != 1 )
827
      {
828
        libcerror_error_set(
829
         error,
830
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
831
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
832
         "%s: unable to print the read offsets.",
833
         function );
834
      }
835
    }
836
  }
837
#endif
838
1.17k
  if( internal_file->file_io_handle_opened_in_library != 0 )
839
1.17k
  {
840
1.17k
    if( libbfio_handle_close(
841
1.17k
         internal_file->file_io_handle,
842
1.17k
         error ) != 0 )
843
0
    {
844
0
      libcerror_error_set(
845
0
       error,
846
0
       LIBCERROR_ERROR_DOMAIN_IO,
847
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
848
0
       "%s: unable to close file IO handle.",
849
0
       function );
850
851
0
      result = -1;
852
0
    }
853
1.17k
    internal_file->file_io_handle_opened_in_library = 0;
854
1.17k
  }
855
1.17k
  if( internal_file->file_io_handle_created_in_library != 0 )
856
0
  {
857
0
    if( libbfio_handle_free(
858
0
         &( internal_file->file_io_handle ),
859
0
         error ) != 1 )
860
0
    {
861
0
      libcerror_error_set(
862
0
       error,
863
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
864
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
865
0
       "%s: unable to free file IO handle.",
866
0
       function );
867
868
0
      result = -1;
869
0
    }
870
0
    internal_file->file_io_handle_created_in_library = 0;
871
0
  }
872
1.17k
  internal_file->file_io_handle = NULL;
873
874
1.17k
  if( libcreg_io_handle_clear(
875
1.17k
       internal_file->io_handle,
876
1.17k
       error ) != 1 )
877
0
  {
878
0
    libcerror_error_set(
879
0
     error,
880
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
881
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
882
0
     "%s: unable to clear IO handle.",
883
0
     function );
884
885
0
    result = -1;
886
0
  }
887
1.17k
  if( internal_file->key_navigation != NULL )
888
1.16k
  {
889
1.16k
    if( libcreg_key_navigation_free(
890
1.16k
         &( internal_file->key_navigation ),
891
1.16k
         error ) != 1 )
892
0
    {
893
0
      libcerror_error_set(
894
0
       error,
895
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
896
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
897
0
       "%s: unable to free key navigation.",
898
0
       function );
899
900
0
      result = -1;
901
0
    }
902
1.16k
  }
903
1.17k
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
904
1.17k
  if( libcthreads_read_write_lock_release_for_write(
905
1.17k
       internal_file->read_write_lock,
906
1.17k
       error ) != 1 )
907
0
  {
908
0
    libcerror_error_set(
909
0
     error,
910
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
911
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
912
0
     "%s: unable to release read/write lock for writing.",
913
0
     function );
914
915
0
    return( -1 );
916
0
  }
917
1.17k
#endif
918
1.17k
  return( result );
919
1.17k
}
920
921
/* Opens a file for reading
922
 * Returns 1 if successful or -1 on error
923
 */
924
int libcreg_internal_file_open_read(
925
     libcreg_internal_file_t *internal_file,
926
     libbfio_handle_t *file_io_handle,
927
     libcerror_error_t **error )
928
1.41k
{
929
1.41k
  static char *function                 = "libcreg_internal_file_open_read";
930
1.41k
  size64_t file_size                    = 0;
931
1.41k
  uint16_t header_number_of_data_blocks = 0;
932
1.41k
  int number_of_data_blocks             = 0;
933
1.41k
  int result                            = 0;
934
935
1.41k
  if( internal_file == NULL )
936
0
  {
937
0
    libcerror_error_set(
938
0
     error,
939
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
940
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
941
0
     "%s: invalid file.",
942
0
     function );
943
944
0
    return( -1 );
945
0
  }
946
1.41k
  if( internal_file->io_handle == NULL )
947
0
  {
948
0
    libcerror_error_set(
949
0
     error,
950
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
951
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
952
0
     "%s: invalid file - missing IO handle.",
953
0
     function );
954
955
0
    return( -1 );
956
0
  }
957
1.41k
  if( internal_file->key_navigation != NULL )
958
0
  {
959
0
    libcerror_error_set(
960
0
     error,
961
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
962
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
963
0
     "%s: invalid file - key navigation already set.",
964
0
     function );
965
966
0
    return( -1 );
967
0
  }
968
1.41k
  if( libbfio_handle_get_size(
969
1.41k
       file_io_handle,
970
1.41k
       &file_size,
971
1.41k
       error ) != 1 )
972
0
  {
973
0
    libcerror_error_set(
974
0
     error,
975
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
976
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
977
0
     "%s: unable to retrieve file size.",
978
0
     function );
979
980
0
    goto on_error;
981
0
  }
982
#if defined( HAVE_DEBUG_OUTPUT )
983
  if( libcnotify_verbose != 0 )
984
  {
985
    libcnotify_printf(
986
     "Reading file header:\n" );
987
  }
988
#endif
989
1.41k
  if( libcreg_io_handle_read_file_header(
990
1.41k
       internal_file->io_handle,
991
1.41k
       file_io_handle,
992
1.41k
       &header_number_of_data_blocks,
993
1.41k
       error ) != 1 )
994
50
  {
995
50
    libcerror_error_set(
996
50
     error,
997
50
     LIBCERROR_ERROR_DOMAIN_IO,
998
50
     LIBCERROR_IO_ERROR_READ_FAILED,
999
50
     "%s: unable to read file header.",
1000
50
     function );
1001
1002
50
    goto on_error;
1003
50
  }
1004
1.36k
  if( file_size > sizeof( creg_file_header_t ) )
1005
1.35k
  {
1006
#if defined( HAVE_DEBUG_OUTPUT )
1007
    if( libcnotify_verbose != 0 )
1008
    {
1009
      libcnotify_printf(
1010
       "Reading key navigation:\n" );
1011
    }
1012
#endif
1013
1.35k
    if( libcreg_key_navigation_initialize(
1014
1.35k
         &( internal_file->key_navigation ),
1015
1.35k
         internal_file->io_handle,
1016
1.35k
         error ) != 1 )
1017
0
    {
1018
0
      libcerror_error_set(
1019
0
       error,
1020
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1021
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1022
0
       "%s: unable to create key navigation.",
1023
0
       function );
1024
1025
0
      goto on_error;
1026
0
    }
1027
1.35k
    result = libcreg_key_navigation_read_file_io_handle(
1028
1.35k
              internal_file->key_navigation,
1029
1.35k
              file_io_handle,
1030
1.35k
              error );
1031
1032
1.35k
    if( result == -1 )
1033
14
    {
1034
14
      libcerror_error_set(
1035
14
       error,
1036
14
       LIBCERROR_ERROR_DOMAIN_IO,
1037
14
       LIBCERROR_IO_ERROR_READ_FAILED,
1038
14
       "%s: unable to read key navigation.",
1039
14
       function );
1040
1041
14
      goto on_error;
1042
14
    }
1043
#if defined( HAVE_DEBUG_OUTPUT )
1044
    if( libcnotify_verbose != 0 )
1045
    {
1046
      libcnotify_printf(
1047
       "Reading data blocks:\n" );
1048
    }
1049
#endif
1050
1.34k
    result = libcreg_key_navigation_read_data_blocks(
1051
1.34k
              internal_file->key_navigation,
1052
1.34k
              file_io_handle,
1053
1.34k
              (off64_t) internal_file->io_handle->data_blocks_list_offset,
1054
1.34k
              file_size,
1055
1.34k
              error );
1056
1057
1.34k
    if( result == -1 )
1058
97
    {
1059
97
      libcerror_error_set(
1060
97
       error,
1061
97
       LIBCERROR_ERROR_DOMAIN_IO,
1062
97
       LIBCERROR_IO_ERROR_READ_FAILED,
1063
97
       "%s: unable to read data blocks.",
1064
97
       function );
1065
1066
97
      goto on_error;
1067
97
    }
1068
1.24k
    else if( result != 0 )
1069
624
    {
1070
624
      if( libcreg_key_navigation_get_number_of_data_blocks(
1071
624
           internal_file->key_navigation,
1072
624
           &number_of_data_blocks,
1073
624
           error ) != 1 )
1074
0
      {
1075
0
        libcerror_error_set(
1076
0
         error,
1077
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1078
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1079
0
         "%s: unable to retrieve number of data blocks.",
1080
0
         function );
1081
1082
0
        goto on_error;
1083
0
      }
1084
624
      if( number_of_data_blocks != (int) header_number_of_data_blocks )
1085
80
      {
1086
80
        libcerror_error_set(
1087
80
         error,
1088
80
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1089
80
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1090
80
         "%s: invalid number of data blocks value out of bounds.",
1091
80
         function );
1092
1093
80
        goto on_error;
1094
80
      }
1095
/* TODO free & clone function */
1096
624
    }
1097
1.34k
  }
1098
1.17k
  return( 1 );
1099
1100
241
on_error:
1101
241
  if( internal_file->key_navigation != NULL )
1102
191
  {
1103
191
    libcreg_key_navigation_free(
1104
191
     &( internal_file->key_navigation ),
1105
191
     NULL );
1106
191
  }
1107
241
  return( -1 );
1108
1.36k
}
1109
1110
/* Determine if the file corrupted
1111
 * Returns 1 if corrupted, 0 if not or -1 on error
1112
 */
1113
int libcreg_file_is_corrupted(
1114
     libcreg_file_t *file,
1115
     libcerror_error_t **error )
1116
0
{
1117
0
  libcreg_internal_file_t *internal_file = NULL;
1118
0
  static char *function                  = "libcreg_file_is_corrupted";
1119
0
  int result                             = 0;
1120
1121
0
  if( file == NULL )
1122
0
  {
1123
0
    libcerror_error_set(
1124
0
     error,
1125
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1126
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1127
0
     "%s: invalid file.",
1128
0
     function );
1129
1130
0
    return( -1 );
1131
0
  }
1132
0
  internal_file = (libcreg_internal_file_t *) file;
1133
1134
0
  if( internal_file->io_handle == NULL )
1135
0
  {
1136
0
    libcerror_error_set(
1137
0
     error,
1138
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1139
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1140
0
     "%s: invalid file - missing IO handle.",
1141
0
     function );
1142
1143
0
    return( -1 );
1144
0
  }
1145
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1146
0
  if( libcthreads_read_write_lock_grab_for_read(
1147
0
       internal_file->read_write_lock,
1148
0
       error ) != 1 )
1149
0
  {
1150
0
    libcerror_error_set(
1151
0
     error,
1152
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1153
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1154
0
     "%s: unable to grab read/write lock for reading.",
1155
0
     function );
1156
1157
0
    return( -1 );
1158
0
  }
1159
0
#endif
1160
0
  if( ( internal_file->io_handle->flags & LIBCREG_IO_HANDLE_FLAG_IS_CORRUPTED ) != 0 )
1161
0
  {
1162
0
    result = 1;
1163
0
  }
1164
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1165
0
  if( libcthreads_read_write_lock_release_for_read(
1166
0
       internal_file->read_write_lock,
1167
0
       error ) != 1 )
1168
0
  {
1169
0
    libcerror_error_set(
1170
0
     error,
1171
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1172
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1173
0
     "%s: unable to release read/write lock for reading.",
1174
0
     function );
1175
1176
0
    return( -1 );
1177
0
  }
1178
0
#endif
1179
0
  return( result );
1180
0
}
1181
1182
/* Retrieves the file ASCII codepage
1183
 * Returns 1 if successful or -1 on error
1184
 */
1185
int libcreg_file_get_ascii_codepage(
1186
     libcreg_file_t *file,
1187
     int *ascii_codepage,
1188
     libcerror_error_t **error )
1189
0
{
1190
0
  libcreg_internal_file_t *internal_file = NULL;
1191
0
  static char *function                  = "libcreg_file_get_ascii_codepage";
1192
1193
0
  if( file == NULL )
1194
0
  {
1195
0
    libcerror_error_set(
1196
0
     error,
1197
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1198
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1199
0
     "%s: invalid file.",
1200
0
     function );
1201
1202
0
    return( -1 );
1203
0
  }
1204
0
  internal_file = (libcreg_internal_file_t *) file;
1205
1206
0
  if( internal_file->io_handle == NULL )
1207
0
  {
1208
0
    libcerror_error_set(
1209
0
     error,
1210
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1211
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1212
0
     "%s: invalid file - missing IO handle.",
1213
0
     function );
1214
1215
0
    return( -1 );
1216
0
  }
1217
0
  if( ascii_codepage == NULL )
1218
0
  {
1219
0
    libcerror_error_set(
1220
0
     error,
1221
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1222
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1223
0
     "%s: invalid ASCII codepage.",
1224
0
     function );
1225
1226
0
    return( -1 );
1227
0
  }
1228
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1229
0
  if( libcthreads_read_write_lock_grab_for_read(
1230
0
       internal_file->read_write_lock,
1231
0
       error ) != 1 )
1232
0
  {
1233
0
    libcerror_error_set(
1234
0
     error,
1235
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1236
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1237
0
     "%s: unable to grab read/write lock for reading.",
1238
0
     function );
1239
1240
0
    return( -1 );
1241
0
  }
1242
0
#endif
1243
0
  *ascii_codepage = internal_file->io_handle->ascii_codepage;
1244
1245
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1246
0
  if( libcthreads_read_write_lock_release_for_read(
1247
0
       internal_file->read_write_lock,
1248
0
       error ) != 1 )
1249
0
  {
1250
0
    libcerror_error_set(
1251
0
     error,
1252
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1253
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1254
0
     "%s: unable to release read/write lock for reading.",
1255
0
     function );
1256
1257
0
    return( -1 );
1258
0
  }
1259
0
#endif
1260
0
  return( 1 );
1261
0
}
1262
1263
/* Sets the file ASCII codepage
1264
 * Returns 1 if successful or -1 on error
1265
 */
1266
int libcreg_file_set_ascii_codepage(
1267
     libcreg_file_t *file,
1268
     int ascii_codepage,
1269
     libcerror_error_t **error )
1270
0
{
1271
0
  libcreg_internal_file_t *internal_file = NULL;
1272
0
  static char *function                  = "libcreg_file_set_ascii_codepage";
1273
1274
0
  if( file == NULL )
1275
0
  {
1276
0
    libcerror_error_set(
1277
0
     error,
1278
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1279
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1280
0
     "%s: invalid file.",
1281
0
     function );
1282
1283
0
    return( -1 );
1284
0
  }
1285
0
  internal_file = (libcreg_internal_file_t *) file;
1286
1287
0
  if( internal_file->io_handle == NULL )
1288
0
  {
1289
0
    libcerror_error_set(
1290
0
     error,
1291
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1292
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1293
0
     "%s: invalid file - missing IO handle.",
1294
0
     function );
1295
1296
0
    return( -1 );
1297
0
  }
1298
0
  if( ( ascii_codepage != LIBCREG_CODEPAGE_ASCII )
1299
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_874 )
1300
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_932 )
1301
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_936 )
1302
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_949 )
1303
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_950 )
1304
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_1250 )
1305
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_1251 )
1306
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_1252 )
1307
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_1253 )
1308
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_1254 )
1309
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_1255 )
1310
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_1256 )
1311
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_1257 )
1312
0
   && ( ascii_codepage != LIBCREG_CODEPAGE_WINDOWS_1258 ) )
1313
0
  {
1314
0
    libcerror_error_set(
1315
0
     error,
1316
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1317
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1318
0
     "%s: unsupported ASCII codepage.",
1319
0
     function );
1320
1321
0
    return( -1 );
1322
0
  }
1323
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1324
0
  if( libcthreads_read_write_lock_grab_for_write(
1325
0
       internal_file->read_write_lock,
1326
0
       error ) != 1 )
1327
0
  {
1328
0
    libcerror_error_set(
1329
0
     error,
1330
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1331
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1332
0
     "%s: unable to grab read/write lock for writing.",
1333
0
     function );
1334
1335
0
    return( -1 );
1336
0
  }
1337
0
#endif
1338
0
  internal_file->io_handle->ascii_codepage = ascii_codepage;
1339
1340
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1341
0
  if( libcthreads_read_write_lock_release_for_write(
1342
0
       internal_file->read_write_lock,
1343
0
       error ) != 1 )
1344
0
  {
1345
0
    libcerror_error_set(
1346
0
     error,
1347
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1348
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1349
0
     "%s: unable to release read/write lock for writing.",
1350
0
     function );
1351
1352
0
    return( -1 );
1353
0
  }
1354
0
#endif
1355
0
  return( 1 );
1356
0
}
1357
1358
/* Retrieves the format version
1359
 * Returns 1 if successful or -1 on error
1360
 */
1361
int libcreg_file_get_format_version(
1362
     libcreg_file_t *file,
1363
     uint16_t *major_version,
1364
     uint16_t *minor_version,
1365
     libcerror_error_t **error )
1366
0
{
1367
0
  libcreg_internal_file_t *internal_file = NULL;
1368
0
  static char *function                  = "libcreg_file_get_format_version";
1369
1370
0
  if( file == NULL )
1371
0
  {
1372
0
    libcerror_error_set(
1373
0
     error,
1374
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1375
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1376
0
     "%s: invalid file.",
1377
0
     function );
1378
1379
0
    return( -1 );
1380
0
  }
1381
0
  internal_file = (libcreg_internal_file_t *) file;
1382
1383
0
  if( internal_file->io_handle == NULL )
1384
0
  {
1385
0
    libcerror_error_set(
1386
0
     error,
1387
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1388
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1389
0
     "%s: invalid file - missing IO handle.",
1390
0
     function );
1391
1392
0
    return( -1 );
1393
0
  }
1394
0
  if( major_version == NULL )
1395
0
  {
1396
0
    libcerror_error_set(
1397
0
     error,
1398
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1399
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1400
0
     "%s: invalid major version.",
1401
0
     function );
1402
1403
0
    return( -1 );
1404
0
  }
1405
0
  if( minor_version == NULL )
1406
0
  {
1407
0
    libcerror_error_set(
1408
0
     error,
1409
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1410
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1411
0
     "%s: invalid minor version.",
1412
0
     function );
1413
1414
0
    return( -1 );
1415
0
  }
1416
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1417
0
  if( libcthreads_read_write_lock_grab_for_read(
1418
0
       internal_file->read_write_lock,
1419
0
       error ) != 1 )
1420
0
  {
1421
0
    libcerror_error_set(
1422
0
     error,
1423
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1424
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1425
0
     "%s: unable to grab read/write lock for reading.",
1426
0
     function );
1427
1428
0
    return( -1 );
1429
0
  }
1430
0
#endif
1431
0
  *major_version = internal_file->io_handle->major_version;
1432
0
  *minor_version = internal_file->io_handle->minor_version;
1433
1434
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1435
0
  if( libcthreads_read_write_lock_release_for_read(
1436
0
       internal_file->read_write_lock,
1437
0
       error ) != 1 )
1438
0
  {
1439
0
    libcerror_error_set(
1440
0
     error,
1441
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1442
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1443
0
     "%s: unable to release read/write lock for reading.",
1444
0
     function );
1445
1446
0
    return( -1 );
1447
0
  }
1448
0
#endif
1449
0
  return( 1 );
1450
0
}
1451
1452
/* Retrieves the type
1453
 * Returns 1 if successful or -1 on error
1454
 */
1455
int libcreg_file_get_type(
1456
     libcreg_file_t *file,
1457
     uint32_t *file_type,
1458
     libcerror_error_t **error )
1459
0
{
1460
0
  libcreg_internal_file_t *internal_file = NULL;
1461
0
  static char *function                  = "libcreg_file_get_type";
1462
1463
0
  if( file == NULL )
1464
0
  {
1465
0
    libcerror_error_set(
1466
0
     error,
1467
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1468
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1469
0
     "%s: invalid file.",
1470
0
     function );
1471
1472
0
    return( -1 );
1473
0
  }
1474
0
  internal_file = (libcreg_internal_file_t *) file;
1475
1476
0
  if( internal_file->io_handle == NULL )
1477
0
  {
1478
0
    libcerror_error_set(
1479
0
     error,
1480
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1481
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1482
0
     "%s: invalid file - missing IO handle.",
1483
0
     function );
1484
1485
0
    return( -1 );
1486
0
  }
1487
0
  if( file_type == NULL )
1488
0
  {
1489
0
    libcerror_error_set(
1490
0
     error,
1491
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1492
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1493
0
     "%s: invalid file type.",
1494
0
     function );
1495
1496
0
    return( -1 );
1497
0
  }
1498
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1499
0
  if( libcthreads_read_write_lock_grab_for_read(
1500
0
       internal_file->read_write_lock,
1501
0
       error ) != 1 )
1502
0
  {
1503
0
    libcerror_error_set(
1504
0
     error,
1505
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1506
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1507
0
     "%s: unable to grab read/write lock for reading.",
1508
0
     function );
1509
1510
0
    return( -1 );
1511
0
  }
1512
0
#endif
1513
0
  *file_type = internal_file->io_handle->file_type;
1514
1515
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1516
0
  if( libcthreads_read_write_lock_release_for_read(
1517
0
       internal_file->read_write_lock,
1518
0
       error ) != 1 )
1519
0
  {
1520
0
    libcerror_error_set(
1521
0
     error,
1522
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1523
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1524
0
     "%s: unable to release read/write lock for reading.",
1525
0
     function );
1526
1527
0
    return( -1 );
1528
0
  }
1529
0
#endif
1530
0
  return( 1 );
1531
0
}
1532
1533
/* Retrieves the root key
1534
 * Returns 1 if successful, if no such key or -1 on error
1535
 */
1536
int libcreg_file_get_root_key(
1537
     libcreg_file_t *file,
1538
     libcreg_key_t **root_key,
1539
     libcerror_error_t **error )
1540
1.17k
{
1541
1.17k
  libcreg_internal_file_t *internal_file = NULL;
1542
1.17k
  static char *function                  = "libcreg_file_get_root_key";
1543
1544
1.17k
  if( file == NULL )
1545
0
  {
1546
0
    libcerror_error_set(
1547
0
     error,
1548
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1549
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1550
0
     "%s: invalid file.",
1551
0
     function );
1552
1553
0
    return( -1 );
1554
0
  }
1555
1.17k
  internal_file = (libcreg_internal_file_t *) file;
1556
1557
1.17k
  if( root_key == NULL )
1558
0
  {
1559
0
    libcerror_error_set(
1560
0
     error,
1561
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1562
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1563
0
     "%s: invalid root key.",
1564
0
     function );
1565
1566
0
    return( -1 );
1567
0
  }
1568
1.17k
  if( *root_key != NULL )
1569
0
  {
1570
0
    libcerror_error_set(
1571
0
     error,
1572
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1573
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1574
0
     "%s: root key already set.",
1575
0
     function );
1576
1577
0
    return( -1 );
1578
0
  }
1579
/* TODO implement thread lock */
1580
1.17k
  if( libcreg_key_initialize(
1581
1.17k
       root_key,
1582
1.17k
       internal_file->io_handle,
1583
1.17k
       internal_file->file_io_handle,
1584
1.17k
       internal_file->key_navigation,
1585
1.17k
       LIBCREG_ROOT_KEY_OFFSET,
1586
1.17k
       error ) != 1 )
1587
936
  {
1588
936
    libcerror_error_set(
1589
936
     error,
1590
936
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1591
936
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1592
936
     "%s: unable to create root key.",
1593
936
     function );
1594
1595
936
    return( -1 );
1596
936
  }
1597
234
  return( 1 );
1598
1.17k
}
1599
1600
/* Retrieves the key for the specific UTF-8 encoded path
1601
 * The path separator is the \ character
1602
 * Returns 1 if successful, 0 if no such key or -1 on error
1603
 */
1604
int libcreg_file_get_key_by_utf8_path(
1605
     libcreg_file_t *file,
1606
     const uint8_t *utf8_string,
1607
     size_t utf8_string_length,
1608
     libcreg_key_t **key,
1609
     libcerror_error_t **error )
1610
0
{
1611
0
  libcreg_internal_file_t *internal_file = NULL;
1612
0
  static char *function                  = "libcreg_file_get_key_by_utf8_path";
1613
0
  int result                             = 0;
1614
1615
0
  if( file == NULL )
1616
0
  {
1617
0
    libcerror_error_set(
1618
0
     error,
1619
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1620
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1621
0
     "%s: invalid file.",
1622
0
     function );
1623
1624
0
    return( -1 );
1625
0
  }
1626
0
  internal_file = (libcreg_internal_file_t *) file;
1627
1628
0
  if( internal_file->io_handle == NULL )
1629
0
  {
1630
0
    libcerror_error_set(
1631
0
     error,
1632
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1633
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1634
0
     "%s: invalid file - missing IO handle.",
1635
0
     function );
1636
1637
0
    return( -1 );
1638
0
  }
1639
0
  if( utf8_string == NULL )
1640
0
  {
1641
0
    libcerror_error_set(
1642
0
     error,
1643
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1644
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1645
0
     "%s: invalid UTF-8 string.",
1646
0
     function );
1647
1648
0
    return( -1 );
1649
0
  }
1650
0
  if( utf8_string_length > (size_t) SSIZE_MAX )
1651
0
  {
1652
0
    libcerror_error_set(
1653
0
     error,
1654
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1655
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1656
0
     "%s: invalid UTF-8 string length value exceeds maximum.",
1657
0
     function );
1658
1659
0
    return( -1 );
1660
0
  }
1661
0
  if( key == NULL )
1662
0
  {
1663
0
    libcerror_error_set(
1664
0
     error,
1665
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1666
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1667
0
     "%s: invalid key.",
1668
0
     function );
1669
1670
0
    return( -1 );
1671
0
  }
1672
0
  if( *key != NULL )
1673
0
  {
1674
0
    libcerror_error_set(
1675
0
     error,
1676
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1677
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1678
0
     "%s: key already set.",
1679
0
     function );
1680
1681
0
    return( -1 );
1682
0
  }
1683
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1684
0
  if( libcthreads_read_write_lock_grab_for_write(
1685
0
       internal_file->read_write_lock,
1686
0
       error ) != 1 )
1687
0
  {
1688
0
    libcerror_error_set(
1689
0
     error,
1690
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1691
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1692
0
     "%s: unable to grab read/write lock for writing.",
1693
0
     function );
1694
1695
0
    return( -1 );
1696
0
  }
1697
0
#endif
1698
0
  result = libcreg_key_tree_get_sub_key_by_utf8_path(
1699
0
            internal_file->io_handle,
1700
0
            internal_file->file_io_handle,
1701
0
            internal_file->key_navigation,
1702
0
            (off64_t) LIBCREG_ROOT_KEY_OFFSET,
1703
0
            utf8_string,
1704
0
            utf8_string_length,
1705
0
            internal_file->io_handle->ascii_codepage,
1706
0
            key,
1707
0
      error );
1708
1709
0
  if( result == -1 )
1710
0
  {
1711
0
    libcerror_error_set(
1712
0
     error,
1713
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1714
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1715
0
     "%s: unable to retrieve key by UTF-8 path.",
1716
0
     function );
1717
1718
0
    result = -1;
1719
0
  }
1720
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1721
0
  if( libcthreads_read_write_lock_release_for_write(
1722
0
       internal_file->read_write_lock,
1723
0
       error ) != 1 )
1724
0
  {
1725
0
    libcerror_error_set(
1726
0
     error,
1727
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1728
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1729
0
     "%s: unable to release read/write lock for writing.",
1730
0
     function );
1731
1732
0
    return( -1 );
1733
0
  }
1734
0
#endif
1735
0
  return( result );
1736
0
}
1737
1738
/* Retrieves the key for the specific UTF-16 encoded path
1739
 * The path separator is the \ character
1740
 * Returns 1 if successful, 0 if no such key or -1 on error
1741
 */
1742
int libcreg_file_get_key_by_utf16_path(
1743
     libcreg_file_t *file,
1744
     const uint16_t *utf16_string,
1745
     size_t utf16_string_length,
1746
     libcreg_key_t **key,
1747
     libcerror_error_t **error )
1748
0
{
1749
0
  libcreg_internal_file_t *internal_file = NULL;
1750
0
  static char *function                  = "libcreg_file_get_key_by_utf16_path";
1751
0
  int result                             = 0;
1752
1753
0
  if( file == NULL )
1754
0
  {
1755
0
    libcerror_error_set(
1756
0
     error,
1757
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1758
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1759
0
     "%s: invalid file.",
1760
0
     function );
1761
1762
0
    return( -1 );
1763
0
  }
1764
0
  internal_file = (libcreg_internal_file_t *) file;
1765
1766
0
  if( internal_file->io_handle == NULL )
1767
0
  {
1768
0
    libcerror_error_set(
1769
0
     error,
1770
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1771
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1772
0
     "%s: invalid file - missing IO handle.",
1773
0
     function );
1774
1775
0
    return( -1 );
1776
0
  }
1777
0
  if( utf16_string == NULL )
1778
0
  {
1779
0
    libcerror_error_set(
1780
0
     error,
1781
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1782
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1783
0
     "%s: invalid UTF-16 string.",
1784
0
     function );
1785
1786
0
    return( -1 );
1787
0
  }
1788
0
  if( utf16_string_length > (size_t) SSIZE_MAX )
1789
0
  {
1790
0
    libcerror_error_set(
1791
0
     error,
1792
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1793
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1794
0
     "%s: invalid UTF-16 string length value exceeds maximum.",
1795
0
     function );
1796
1797
0
    return( -1 );
1798
0
  }
1799
0
  if( key == NULL )
1800
0
  {
1801
0
    libcerror_error_set(
1802
0
     error,
1803
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1804
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1805
0
     "%s: invalid key.",
1806
0
     function );
1807
1808
0
    return( -1 );
1809
0
  }
1810
0
  if( *key != NULL )
1811
0
  {
1812
0
    libcerror_error_set(
1813
0
     error,
1814
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1815
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1816
0
     "%s: key already set.",
1817
0
     function );
1818
1819
0
    return( -1 );
1820
0
  }
1821
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1822
0
  if( libcthreads_read_write_lock_grab_for_write(
1823
0
       internal_file->read_write_lock,
1824
0
       error ) != 1 )
1825
0
  {
1826
0
    libcerror_error_set(
1827
0
     error,
1828
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1829
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1830
0
     "%s: unable to grab read/write lock for writing.",
1831
0
     function );
1832
1833
0
    return( -1 );
1834
0
  }
1835
0
#endif
1836
0
  result = libcreg_key_tree_get_sub_key_by_utf16_path(
1837
0
            internal_file->io_handle,
1838
0
            internal_file->file_io_handle,
1839
0
            internal_file->key_navigation,
1840
0
            (off64_t) LIBCREG_ROOT_KEY_OFFSET,
1841
0
            utf16_string,
1842
0
            utf16_string_length,
1843
0
            internal_file->io_handle->ascii_codepage,
1844
0
            key,
1845
0
      error );
1846
1847
0
  if( result == -1 )
1848
0
  {
1849
0
    libcerror_error_set(
1850
0
     error,
1851
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1852
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1853
0
     "%s: unable to retrieve key by UTF-16 path.",
1854
0
     function );
1855
1856
0
    result = -1;
1857
0
  }
1858
0
#if defined( HAVE_LIBCREG_MULTI_THREAD_SUPPORT )
1859
0
  if( libcthreads_read_write_lock_release_for_write(
1860
0
       internal_file->read_write_lock,
1861
0
       error ) != 1 )
1862
0
  {
1863
0
    libcerror_error_set(
1864
0
     error,
1865
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1866
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1867
0
     "%s: unable to release read/write lock for writing.",
1868
0
     function );
1869
1870
0
    return( -1 );
1871
0
  }
1872
0
#endif
1873
0
  return( result );
1874
0
}
1875