Coverage Report

Created: 2026-05-30 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libnk2/libnk2/libnk2_file.c
Line
Count
Source
1
/*
2
 * libnk2 file
3
 *
4
 * Copyright (C) 2009-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <narrow_string.h>
25
#include <types.h>
26
#include <wide_string.h>
27
28
#include "libnk2_codepage.h"
29
#include "libnk2_debug.h"
30
#include "libnk2_definitions.h"
31
#include "libnk2_io_handle.h"
32
#include "libnk2_item.h"
33
#include "libnk2_file.h"
34
#include "libnk2_file_footer.h"
35
#include "libnk2_file_header.h"
36
#include "libnk2_libbfio.h"
37
#include "libnk2_libcdata.h"
38
#include "libnk2_libcerror.h"
39
#include "libnk2_libcnotify.h"
40
41
/* Creates a file
42
 * Make sure the value file is referencing, is set to NULL
43
 * Returns 1 if successful or -1 on error
44
 */
45
int libnk2_file_initialize(
46
     libnk2_file_t **file,
47
     libcerror_error_t **error )
48
582
{
49
582
  libnk2_internal_file_t *internal_file = NULL;
50
582
  static char *function                 = "libnk2_file_initialize";
51
52
582
  if( file == NULL )
53
0
  {
54
0
    libcerror_error_set(
55
0
     error,
56
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
57
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
58
0
     "%s: invalid file.",
59
0
     function );
60
61
0
    return( -1 );
62
0
  }
63
582
  if( *file != NULL )
64
0
  {
65
0
    libcerror_error_set(
66
0
     error,
67
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
68
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
69
0
     "%s: invalid file value already set.",
70
0
     function );
71
72
0
    return( -1 );
73
0
  }
74
582
  internal_file = memory_allocate_structure(
75
582
                   libnk2_internal_file_t );
76
77
582
  if( internal_file == NULL )
78
0
  {
79
0
    libcerror_error_set(
80
0
     error,
81
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
82
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
83
0
     "%s: unable to create file.",
84
0
     function );
85
86
0
    goto on_error;
87
0
  }
88
582
  if( memory_set(
89
582
       internal_file,
90
582
       0,
91
582
       sizeof( libnk2_internal_file_t ) ) == NULL )
92
0
  {
93
0
    libcerror_error_set(
94
0
     error,
95
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
96
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
97
0
     "%s: unable to clear file.",
98
0
     function );
99
100
0
    memory_free(
101
0
     internal_file );
102
103
0
    return( -1 );
104
0
  }
105
582
  if( libcdata_array_initialize(
106
582
       &( internal_file->items_array ),
107
582
       0,
108
582
       error ) != 1 )
109
0
  {
110
0
    libcerror_error_set(
111
0
     error,
112
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
113
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
114
0
     "%s: unable to create items array.",
115
0
     function );
116
117
0
    goto on_error;
118
0
  }
119
582
  if( libnk2_io_handle_initialize(
120
582
       &( internal_file->io_handle ),
121
582
       error ) != 1 )
122
0
  {
123
0
    libcerror_error_set(
124
0
     error,
125
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
126
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
127
0
     "%s: unable to create IO handle.",
128
0
     function );
129
130
0
    goto on_error;
131
0
  }
132
582
  *file = (libnk2_file_t *) internal_file;
133
134
582
  return( 1 );
135
136
0
on_error:
137
0
  if( internal_file != NULL )
138
0
  {
139
0
    if( internal_file->items_array != NULL )
140
0
    {
141
0
      libcdata_array_free(
142
0
       &( internal_file->items_array ),
143
0
       NULL,
144
0
       NULL );
145
0
    }
146
0
    memory_free(
147
0
     internal_file );
148
0
  }
149
0
  return( -1 );
150
582
}
151
152
/* Frees a file
153
 * Returns 1 if successful or -1 on error
154
 */
155
int libnk2_file_free(
156
     libnk2_file_t **file,
157
     libcerror_error_t **error )
158
582
{
159
582
  libnk2_internal_file_t *internal_file = NULL;
160
582
  static char *function                 = "libnk2_file_free";
161
582
  int result                            = 1;
162
163
582
  if( file == NULL )
164
0
  {
165
0
    libcerror_error_set(
166
0
     error,
167
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
168
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
169
0
     "%s: invalid file.",
170
0
     function );
171
172
0
    return( -1 );
173
0
  }
174
582
  if( *file != NULL )
175
582
  {
176
582
    internal_file = (libnk2_internal_file_t *) *file;
177
178
582
    if( internal_file->file_io_handle != NULL )
179
0
    {
180
0
      if( libnk2_file_close(
181
0
           *file,
182
0
           error ) != 0 )
183
0
      {
184
0
        libcerror_error_set(
185
0
         error,
186
0
         LIBCERROR_ERROR_DOMAIN_IO,
187
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
188
0
         "%s: unable to close file.",
189
0
         function );
190
191
0
        result = -1;
192
0
      }
193
0
    }
194
582
    *file = NULL;
195
196
582
    if( libcdata_array_free(
197
582
         &( internal_file->items_array ),
198
582
         (int (*)(intptr_t **, libcerror_error_t **)) &libnk2_internal_item_free,
199
582
         error ) != 1 )
200
0
    {
201
0
      libcerror_error_set(
202
0
       error,
203
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
204
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
205
0
       "%s: unable to free items array.",
206
0
       function );
207
208
0
      result = -1;
209
0
    }
210
582
    if( libnk2_io_handle_free(
211
582
         &( internal_file->io_handle ),
212
582
         error ) != 1 )
213
0
    {
214
0
      libcerror_error_set(
215
0
       error,
216
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
217
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
218
0
       "%s: unable to free IO handle.",
219
0
       function );
220
221
0
      result = -1;
222
0
    }
223
582
    memory_free(
224
582
     internal_file );
225
582
  }
226
582
  return( result );
227
582
}
228
229
/* Signals the file to abort its current activity
230
 * Returns 1 if successful or -1 on error
231
 */
232
int libnk2_file_signal_abort(
233
     libnk2_file_t *file,
234
     libcerror_error_t **error )
235
0
{
236
0
  libnk2_internal_file_t *internal_file = NULL;
237
0
  static char *function                 = "libnk2_file_signal_abort";
238
239
0
  if( file == NULL )
240
0
  {
241
0
    libcerror_error_set(
242
0
     error,
243
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
244
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
245
0
     "%s: invalid file.",
246
0
     function );
247
248
0
    return( -1 );
249
0
  }
250
0
  internal_file = (libnk2_internal_file_t *) file;
251
252
0
  if( internal_file->io_handle == NULL )
253
0
  {
254
0
    libcerror_error_set(
255
0
     error,
256
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
257
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
258
0
     "%s: invalid internal file - missing IO handle.",
259
0
     function );
260
261
0
    return( -1 );
262
0
  }
263
0
  internal_file->io_handle->abort = 1;
264
265
0
  return( 1 );
266
0
}
267
268
/* Opens a file
269
 * Returns 1 if successful or -1 on error
270
 */
271
int libnk2_file_open(
272
     libnk2_file_t *file,
273
     const char *filename,
274
     int access_flags,
275
     libcerror_error_t **error )
276
0
{
277
0
  libbfio_handle_t *file_io_handle      = NULL;
278
0
  libnk2_internal_file_t *internal_file = NULL;
279
0
  static char *function                 = "libnk2_file_open";
280
0
  size_t filename_length                = 0;
281
282
0
  if( file == NULL )
283
0
  {
284
0
    libcerror_error_set(
285
0
     error,
286
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
287
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
288
0
     "%s: invalid file.",
289
0
     function );
290
291
0
    return( -1 );
292
0
  }
293
0
  internal_file = (libnk2_internal_file_t *) file;
294
295
0
  if( filename == NULL )
296
0
  {
297
0
    libcerror_error_set(
298
0
     error,
299
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
300
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
301
0
     "%s: invalid filename.",
302
0
     function );
303
304
0
    return( -1 );
305
0
  }
306
0
  if( ( ( access_flags & LIBNK2_ACCESS_FLAG_READ ) == 0 )
307
0
   && ( ( access_flags & LIBNK2_ACCESS_FLAG_WRITE ) == 0 ) )
308
0
  {
309
0
    libcerror_error_set(
310
0
     error,
311
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
312
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
313
0
     "%s: unsupported access flags.",
314
0
     function );
315
316
0
    return( -1 );
317
0
  }
318
0
  if( ( access_flags & LIBNK2_ACCESS_FLAG_WRITE ) != 0 )
319
0
  {
320
0
    libcerror_error_set(
321
0
     error,
322
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
323
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
324
0
     "%s: write access currently not supported.",
325
0
     function );
326
327
0
    return( -1 );
328
0
  }
329
0
  if( libbfio_file_initialize(
330
0
       &file_io_handle,
331
0
       error ) != 1 )
332
0
  {
333
0
    libcerror_error_set(
334
0
     error,
335
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
336
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
337
0
     "%s: unable to create file IO handle.",
338
0
     function );
339
340
0
    goto on_error;
341
0
  }
342
#if defined( HAVE_DEBUG_OUTPUT )
343
  if( libbfio_handle_set_track_offsets_read(
344
       file_io_handle,
345
       1,
346
       error ) != 1 )
347
  {
348
                libcerror_error_set(
349
                 error,
350
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
351
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
352
                 "%s: unable to set track offsets read in file IO handle.",
353
                 function );
354
355
    goto on_error;
356
  }
357
#endif
358
0
  filename_length = narrow_string_length(
359
0
                     filename );
360
361
0
  if( libbfio_file_set_name(
362
0
       file_io_handle,
363
0
       filename,
364
0
       filename_length + 1,
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_SET_FAILED,
371
0
                 "%s: unable to set filename in file IO handle.",
372
0
                 function );
373
374
0
    goto on_error;
375
0
  }
376
0
  if( libnk2_file_open_file_io_handle(
377
0
       file,
378
0
       file_io_handle,
379
0
       access_flags,
380
0
       error ) != 1 )
381
0
  {
382
0
    libcerror_error_set(
383
0
     error,
384
0
     LIBCERROR_ERROR_DOMAIN_IO,
385
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
386
0
     "%s: unable to open file: %s.",
387
0
     function,
388
0
     filename );
389
390
0
    goto on_error;
391
0
  }
392
0
  internal_file->file_io_handle_created_in_library = 1;
393
394
0
  return( 1 );
395
396
0
on_error:
397
0
  if( file_io_handle != NULL )
398
0
  {
399
0
    libbfio_handle_free(
400
0
     &file_io_handle,
401
0
     NULL );
402
0
  }
403
0
  return( -1 );
404
0
}
405
406
#if defined( HAVE_WIDE_CHARACTER_TYPE )
407
408
/* Opens a file
409
 * Returns 1 if successful or -1 on error
410
 */
411
int libnk2_file_open_wide(
412
     libnk2_file_t *file,
413
     const wchar_t *filename,
414
     int access_flags,
415
     libcerror_error_t **error )
416
{
417
  libbfio_handle_t *file_io_handle      = NULL;
418
  libnk2_internal_file_t *internal_file = NULL;
419
  static char *function                 = "libnk2_file_open_wide";
420
  size_t filename_length                = 0;
421
422
  if( file == NULL )
423
  {
424
    libcerror_error_set(
425
     error,
426
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
427
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
428
     "%s: invalid file.",
429
     function );
430
431
    return( -1 );
432
  }
433
  internal_file = (libnk2_internal_file_t *) file;
434
435
  if( filename == NULL )
436
  {
437
    libcerror_error_set(
438
     error,
439
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
440
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
441
     "%s: invalid filename.",
442
     function );
443
444
    return( -1 );
445
  }
446
  if( ( ( access_flags & LIBNK2_ACCESS_FLAG_READ ) == 0 )
447
   && ( ( access_flags & LIBNK2_ACCESS_FLAG_WRITE ) == 0 ) )
448
  {
449
    libcerror_error_set(
450
     error,
451
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
452
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
453
     "%s: unsupported access flags.",
454
     function );
455
456
    return( -1 );
457
  }
458
  if( ( access_flags & LIBNK2_ACCESS_FLAG_WRITE ) != 0 )
459
  {
460
    libcerror_error_set(
461
     error,
462
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
463
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
464
     "%s: write access currently not supported.",
465
     function );
466
467
    return( -1 );
468
  }
469
  if( libbfio_file_initialize(
470
       &file_io_handle,
471
       error ) != 1 )
472
  {
473
    libcerror_error_set(
474
     error,
475
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
476
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
477
     "%s: unable to create file IO handle.",
478
     function );
479
480
    goto on_error;
481
  }
482
#if defined( HAVE_DEBUG_OUTPUT )
483
  if( libbfio_handle_set_track_offsets_read(
484
       file_io_handle,
485
       1,
486
       error ) != 1 )
487
  {
488
                libcerror_error_set(
489
                 error,
490
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
491
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
492
                 "%s: unable to set track offsets read in file IO handle.",
493
                 function );
494
495
    goto on_error;
496
  }
497
#endif
498
  filename_length = wide_string_length(
499
                     filename );
500
501
  if( libbfio_file_set_name_wide(
502
       file_io_handle,
503
       filename,
504
       filename_length + 1,
505
       error ) != 1 )
506
  {
507
                libcerror_error_set(
508
                 error,
509
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
510
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
511
                 "%s: unable to set filename in file IO handle.",
512
                 function );
513
514
    goto on_error;
515
  }
516
  if( libnk2_file_open_file_io_handle(
517
       file,
518
       file_io_handle,
519
       access_flags,
520
       error ) != 1 )
521
  {
522
    libcerror_error_set(
523
     error,
524
     LIBCERROR_ERROR_DOMAIN_IO,
525
     LIBCERROR_IO_ERROR_OPEN_FAILED,
526
     "%s: unable to open file: %ls.",
527
     function,
528
     filename );
529
530
    goto on_error;
531
  }
532
  internal_file->file_io_handle_created_in_library = 1;
533
534
  return( 1 );
535
536
on_error:
537
  if( file_io_handle != NULL )
538
  {
539
    libbfio_handle_free(
540
     &file_io_handle,
541
     NULL );
542
  }
543
  return( -1 );
544
}
545
546
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
547
548
/* Opens a file using a Basic File IO (bfio) handle
549
 * Returns 1 if successful or -1 on error
550
 */
551
int libnk2_file_open_file_io_handle(
552
     libnk2_file_t *file,
553
     libbfio_handle_t *file_io_handle,
554
     int access_flags,
555
     libcerror_error_t **error )
556
582
{
557
582
  libnk2_internal_file_t *internal_file = NULL;
558
582
  static char *function                 = "libnk2_file_open_file_io_handle";
559
582
  int bfio_access_flags                 = 0;
560
582
  int file_io_handle_is_open            = 0;
561
562
582
  if( file == NULL )
563
0
  {
564
0
    libcerror_error_set(
565
0
     error,
566
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
567
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
568
0
     "%s: invalid file.",
569
0
     function );
570
571
0
    return( -1 );
572
0
  }
573
582
  internal_file = (libnk2_internal_file_t *) file;
574
575
582
  if( internal_file->file_io_handle != NULL )
576
0
  {
577
0
    libcerror_error_set(
578
0
     error,
579
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
580
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
581
0
     "%s: invalid internal file - file IO handle already set.",
582
0
     function );
583
584
0
    return( -1 );
585
0
  }
586
582
  if( file_io_handle == NULL )
587
0
  {
588
0
    libcerror_error_set(
589
0
     error,
590
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
591
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
592
0
     "%s: invalid file IO handle.",
593
0
     function );
594
595
0
    return( -1 );
596
0
  }
597
582
  if( ( ( access_flags & LIBNK2_ACCESS_FLAG_READ ) == 0 )
598
0
   && ( ( access_flags & LIBNK2_ACCESS_FLAG_WRITE ) == 0 ) )
599
0
  {
600
0
    libcerror_error_set(
601
0
     error,
602
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
603
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
604
0
     "%s: unsupported access flags.",
605
0
     function );
606
607
0
    return( -1 );
608
0
  }
609
582
  if( ( access_flags & LIBNK2_ACCESS_FLAG_WRITE ) != 0 )
610
0
  {
611
0
    libcerror_error_set(
612
0
     error,
613
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
614
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
615
0
     "%s: write access currently not supported.",
616
0
     function );
617
618
0
    return( -1 );
619
0
  }
620
582
  if( ( access_flags & LIBNK2_ACCESS_FLAG_READ ) != 0 )
621
582
  {
622
582
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
623
582
  }
624
582
  internal_file->file_io_handle = file_io_handle;
625
626
582
  file_io_handle_is_open = libbfio_handle_is_open(
627
582
                            internal_file->file_io_handle,
628
582
                            error );
629
630
582
  if( file_io_handle_is_open == -1 )
631
0
  {
632
0
    libcerror_error_set(
633
0
     error,
634
0
     LIBCERROR_ERROR_DOMAIN_IO,
635
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
636
0
     "%s: unable to determine if file IO handle is open.",
637
0
     function );
638
639
0
    goto on_error;
640
0
  }
641
582
  else if( file_io_handle_is_open == 0 )
642
582
  {
643
582
    if( libbfio_handle_open(
644
582
         internal_file->file_io_handle,
645
582
         bfio_access_flags,
646
582
         error ) != 1 )
647
0
    {
648
0
      libcerror_error_set(
649
0
       error,
650
0
       LIBCERROR_ERROR_DOMAIN_IO,
651
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
652
0
       "%s: unable to open file IO handle.",
653
0
       function );
654
655
0
      goto on_error;
656
0
    }
657
582
    internal_file->file_io_handle_opened_in_library = 1;
658
582
  }
659
582
  if( libnk2_file_open_read(
660
582
       internal_file,
661
582
       file_io_handle,
662
582
       error ) != 1 )
663
578
  {
664
578
    libcerror_error_set(
665
578
     error,
666
578
     LIBCERROR_ERROR_DOMAIN_IO,
667
578
     LIBCERROR_IO_ERROR_READ_FAILED,
668
578
     "%s: unable to read from file handle.",
669
578
     function );
670
671
578
    goto on_error;
672
578
  }
673
4
  internal_file->file_io_handle = file_io_handle;
674
675
4
  return( 1 );
676
677
578
on_error:
678
578
  if( ( file_io_handle_is_open == 0 )
679
578
   && ( internal_file->file_io_handle_opened_in_library != 0 ) )
680
578
  {
681
578
    libbfio_handle_close(
682
578
     file_io_handle,
683
578
     error );
684
685
578
    internal_file->file_io_handle_opened_in_library = 0;
686
578
  }
687
578
  internal_file->file_io_handle = NULL;
688
689
578
  return( -1 );
690
582
}
691
692
/* Closes a file
693
 * Returns 0 if successful or -1 on error
694
 */
695
int libnk2_file_close(
696
     libnk2_file_t *file,
697
     libcerror_error_t **error )
698
4
{
699
4
  libnk2_internal_file_t *internal_file = NULL;
700
4
  static char *function                 = "libnk2_file_close";
701
4
  int result                            = 0;
702
703
4
  if( file == NULL )
704
0
  {
705
0
    libcerror_error_set(
706
0
     error,
707
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
708
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
709
0
     "%s: invalid file.",
710
0
     function );
711
712
0
    return( -1 );
713
0
  }
714
4
  internal_file = (libnk2_internal_file_t *) file;
715
716
4
  if( internal_file->file_io_handle == NULL )
717
0
  {
718
0
    libcerror_error_set(
719
0
     error,
720
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
721
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
722
0
     "%s: invalid file - missing file IO handle.",
723
0
     function );
724
725
0
    return( -1 );
726
0
  }
727
#if defined( HAVE_DEBUG_OUTPUT )
728
  if( libcnotify_verbose != 0 )
729
  {
730
    if( internal_file->file_io_handle_created_in_library != 0 )
731
    {
732
      if( libnk2_debug_print_read_offsets(
733
           internal_file->file_io_handle,
734
           error ) != 1 )
735
      {
736
        libcerror_error_set(
737
         error,
738
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
739
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
740
         "%s: unable to print the read offsets.",
741
         function );
742
743
        result = -1;
744
      }
745
    }
746
  }
747
#endif
748
4
  if( internal_file->file_io_handle_opened_in_library != 0 )
749
4
  {
750
4
    if( libbfio_handle_close(
751
4
         internal_file->file_io_handle,
752
4
         error ) != 0 )
753
0
    {
754
0
      libcerror_error_set(
755
0
       error,
756
0
       LIBCERROR_ERROR_DOMAIN_IO,
757
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
758
0
       "%s: unable to close file IO handle.",
759
0
       function );
760
761
0
      result = -1;
762
0
    }
763
4
    internal_file->file_io_handle_opened_in_library = 0;
764
4
  }
765
4
  if( internal_file->file_io_handle_created_in_library != 0 )
766
0
  {
767
0
    if( libbfio_handle_free(
768
0
         &( internal_file->file_io_handle ),
769
0
         error ) != 1 )
770
0
    {
771
0
      libcerror_error_set(
772
0
       error,
773
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
774
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
775
0
       "%s: unable to free file IO handle.",
776
0
       function );
777
778
0
      result = -1;
779
0
    }
780
0
    internal_file->file_io_handle_created_in_library = 0;
781
0
  }
782
4
  internal_file->file_io_handle = NULL;
783
784
4
  if( libnk2_io_handle_clear(
785
4
       internal_file->io_handle,
786
4
       error ) != 1 )
787
0
  {
788
0
    libcerror_error_set(
789
0
     error,
790
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
791
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
792
0
     "%s: unable to clear IO handle.",
793
0
     function );
794
795
0
    result = -1;
796
0
  }
797
4
  if( libcdata_array_empty(
798
4
       internal_file->items_array,
799
4
       (int (*)(intptr_t **, libcerror_error_t **)) &libnk2_internal_item_free,
800
4
       error ) != 1 )
801
0
  {
802
0
    libcerror_error_set(
803
0
     error,
804
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
805
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
806
0
     "%s: unable to empty items array.",
807
0
     function );
808
809
0
    result = -1;
810
0
  }
811
4
  internal_file->modification_time = 0;
812
813
4
  return( result );
814
4
}
815
816
/* Opens a file for reading
817
 * Returns 1 if successful or -1 on error
818
 */
819
int libnk2_file_open_read(
820
     libnk2_internal_file_t *internal_file,
821
     libbfio_handle_t *file_io_handle,
822
     libcerror_error_t **error )
823
582
{
824
582
  libnk2_file_footer_t *file_footer = NULL;
825
582
  libnk2_file_header_t *file_header = NULL;
826
582
  static char *function             = "libnk2_file_open_read";
827
828
582
  if( internal_file == NULL )
829
0
  {
830
0
    libcerror_error_set(
831
0
     error,
832
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
833
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
834
0
     "%s: invalid internal file.",
835
0
     function );
836
837
0
    return( -1 );
838
0
  }
839
582
  if( internal_file->io_handle == NULL )
840
0
  {
841
0
    libcerror_error_set(
842
0
     error,
843
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
844
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
845
0
     "%s: invalid internal file - missing IO handle.",
846
0
     function );
847
848
0
    return( -1 );
849
0
  }
850
582
  internal_file->io_handle->abort = 0;
851
852
#if defined( HAVE_DEBUG_OUTPUT )
853
  if( libcnotify_verbose != 0 )
854
  {
855
    libcnotify_printf(
856
     "Reading file header:\n" );
857
  }
858
#endif
859
582
  if( libnk2_file_header_initialize(
860
582
       &file_header,
861
582
       error ) != 1 )
862
0
  {
863
0
    libcerror_error_set(
864
0
     error,
865
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
866
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
867
0
     "%s: unable to create file header.",
868
0
     function );
869
870
0
    goto on_error;
871
0
  }
872
582
  if( libnk2_file_header_read_file_io_handle(
873
582
       file_header,
874
582
       file_io_handle,
875
582
       error ) != 1 )
876
48
  {
877
48
    libcerror_error_set(
878
48
     error,
879
48
     LIBCERROR_ERROR_DOMAIN_IO,
880
48
     LIBCERROR_IO_ERROR_READ_FAILED,
881
48
     "%s: unable to read file header.",
882
48
     function );
883
884
48
    goto on_error;
885
48
  }
886
#if defined( HAVE_DEBUG_OUTPUT )
887
  if( libcnotify_verbose != 0 )
888
  {
889
    libcnotify_printf(
890
     "Reading items:\n" );
891
  }
892
#endif
893
534
  if( libnk2_file_read_items(
894
534
       internal_file,
895
534
       file_io_handle,
896
534
       file_header->number_of_items,
897
534
       error ) != 1 )
898
519
  {
899
519
    libcerror_error_set(
900
519
     error,
901
519
     LIBCERROR_ERROR_DOMAIN_IO,
902
519
     LIBCERROR_IO_ERROR_READ_FAILED,
903
519
     "%s: unable to read items.",
904
519
     function );
905
906
519
    goto on_error;
907
519
  }
908
15
  if( libnk2_file_header_free(
909
15
       &file_header,
910
15
       error ) != 1 )
911
0
  {
912
0
    libcerror_error_set(
913
0
     error,
914
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
915
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
916
0
     "%s: unable to free file header.",
917
0
     function );
918
919
0
    goto on_error;
920
0
  }
921
#if defined( HAVE_DEBUG_OUTPUT )
922
  if( libcnotify_verbose != 0 )
923
  {
924
    libcnotify_printf(
925
     "Reading file footer:\n" );
926
  }
927
#endif
928
15
  if( libnk2_file_footer_initialize(
929
15
       &file_footer,
930
15
       error ) != 1 )
931
0
  {
932
0
    libcerror_error_set(
933
0
     error,
934
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
935
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
936
0
     "%s: unable to create file footer.",
937
0
     function );
938
939
0
    goto on_error;
940
0
  }
941
15
  if( libnk2_file_footer_read_file_io_handle(
942
15
       file_footer,
943
15
       file_io_handle,
944
15
       error ) != 1 )
945
11
  {
946
11
    libcerror_error_set(
947
11
     error,
948
11
     LIBCERROR_ERROR_DOMAIN_IO,
949
11
     LIBCERROR_IO_ERROR_READ_FAILED,
950
11
     "%s: unable to read file footer.",
951
11
     function );
952
953
11
    goto on_error;
954
11
  }
955
4
  internal_file->modification_time = file_footer->modification_time;
956
957
4
  if( libnk2_file_footer_free(
958
4
       &file_footer,
959
4
       error ) != 1 )
960
0
  {
961
0
    libcerror_error_set(
962
0
     error,
963
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
964
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
965
0
     "%s: unable to free file footer.",
966
0
     function );
967
968
0
    goto on_error;
969
0
  }
970
4
  internal_file->io_handle->abort = 0;
971
972
4
  return( 1 );
973
974
578
on_error:
975
578
  if( file_footer != NULL )
976
11
  {
977
11
    libnk2_file_footer_free(
978
11
     &file_footer,
979
11
     NULL );
980
11
  }
981
578
  if( file_header != NULL )
982
567
  {
983
567
    libnk2_file_header_free(
984
567
     &file_header,
985
567
     NULL );
986
567
  }
987
578
  libcdata_array_empty(
988
578
   internal_file->items_array,
989
578
   (int (*)(intptr_t **, libcerror_error_t **)) &libnk2_internal_item_free,
990
578
   NULL );
991
992
578
  internal_file->io_handle->abort = 0;
993
994
578
  return( -1 );
995
4
}
996
997
/* Reads the items into the items array
998
 * Returns 1 if successful or -1 on error
999
 */
1000
int libnk2_file_read_items(
1001
     libnk2_internal_file_t *internal_file,
1002
     libbfio_handle_t *file_io_handle,
1003
     uint32_t number_of_items,
1004
     libcerror_error_t **error )
1005
534
{
1006
534
  uint8_t number_of_record_entries_data[ 4 ];
1007
1008
534
  libnk2_item_t *item               = NULL;
1009
534
  static char *function             = "libnk2_file_read_items";
1010
534
  ssize_t read_count                = 0;
1011
534
  uint32_t item_index               = 0;
1012
534
  uint32_t number_of_record_entries = 0;
1013
534
  int entry_index                   = 0;
1014
1015
534
  if( internal_file == NULL )
1016
0
  {
1017
0
    libcerror_error_set(
1018
0
     error,
1019
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1020
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1021
0
     "%s: invalid internal file.",
1022
0
     function );
1023
1024
0
    return( -1 );
1025
0
  }
1026
534
  if( libcdata_array_empty(
1027
534
       internal_file->items_array,
1028
534
       (int (*)(intptr_t **, libcerror_error_t **)) &libnk2_internal_item_free,
1029
534
       error ) != 1 )
1030
0
  {
1031
0
    libcerror_error_set(
1032
0
     error,
1033
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1034
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1035
0
     "%s: unable to empty items array.",
1036
0
     function );
1037
1038
0
    goto on_error;
1039
0
  }
1040
534
  for( item_index = 0;
1041
2.21k
       item_index < number_of_items;
1042
1.68k
       item_index++ )
1043
2.20k
  {
1044
2.20k
    read_count = libbfio_handle_read_buffer(
1045
2.20k
            file_io_handle,
1046
2.20k
            number_of_record_entries_data,
1047
2.20k
            4,
1048
2.20k
            error );
1049
1050
2.20k
    if( read_count != (ssize_t) 4 )
1051
90
    {
1052
90
      libcerror_error_set(
1053
90
       error,
1054
90
       LIBCERROR_ERROR_DOMAIN_IO,
1055
90
       LIBCERROR_IO_ERROR_READ_FAILED,
1056
90
       "%s: unable to read item: %" PRIu32 " number of record entries data.",
1057
90
       function,
1058
90
       item_index );
1059
1060
90
      goto on_error;
1061
90
    }
1062
2.11k
    byte_stream_copy_to_uint32_little_endian(
1063
2.11k
     number_of_record_entries_data,
1064
2.11k
     number_of_record_entries );
1065
1066
2.11k
    if( number_of_record_entries == 0 )
1067
3
    {
1068
3
      break;
1069
3
    }
1070
#if defined( HAVE_DEBUG_OUTPUT )
1071
    if( libcnotify_verbose != 0 )
1072
    {
1073
      libcnotify_printf(
1074
       "%s: item: %03" PRIu32 " number of record entries\t\t: %" PRIu32 "\n",
1075
       function,
1076
       item_index,
1077
       number_of_record_entries );
1078
1079
      libcnotify_printf(
1080
       "\n" );
1081
    }
1082
#endif
1083
2.11k
    if( libnk2_item_initialize(
1084
2.11k
         &item,
1085
2.11k
         error ) != 1 )
1086
0
    {
1087
0
      libcerror_error_set(
1088
0
       error,
1089
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1090
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1091
0
       "%s: unable to create item.",
1092
0
       function );
1093
1094
0
      goto on_error;
1095
0
    }
1096
2.11k
    if( libnk2_item_read_record_entries(
1097
2.11k
         (libnk2_internal_item_t *) item,
1098
2.11k
         internal_file->io_handle,
1099
2.11k
         file_io_handle,
1100
2.11k
         item_index,
1101
2.11k
         number_of_record_entries,
1102
2.11k
         error ) != 1 )
1103
429
    {
1104
429
      libcerror_error_set(
1105
429
       error,
1106
429
       LIBCERROR_ERROR_DOMAIN_IO,
1107
429
       LIBCERROR_IO_ERROR_READ_FAILED,
1108
429
       "%s: unable to read record entries: %" PRIu32 ".",
1109
429
       function,
1110
429
       item_index );
1111
1112
429
      goto on_error;
1113
429
    }
1114
1.68k
    if( libcdata_array_append_entry(
1115
1.68k
         internal_file->items_array,
1116
1.68k
         &entry_index,
1117
1.68k
         (intptr_t *) item,
1118
1.68k
         error ) != 1 )
1119
0
    {
1120
0
      libcerror_error_set(
1121
0
       error,
1122
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1123
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1124
0
       "%s: unable to append record entries to items array.",
1125
0
       function );
1126
1127
0
      goto on_error;
1128
0
    }
1129
1.68k
    item = NULL;
1130
1.68k
  }
1131
15
  return( 1 );
1132
1133
519
on_error:
1134
519
  if( item != NULL )
1135
429
  {
1136
429
    libnk2_internal_item_free(
1137
429
     (libnk2_internal_item_t **) &item,
1138
429
     NULL );
1139
429
  }
1140
519
  libcdata_array_empty(
1141
519
   internal_file->items_array,
1142
519
   (int (*)(intptr_t **, libcerror_error_t **)) &libnk2_internal_item_free,
1143
519
   NULL );
1144
1145
519
  return( -1 );
1146
534
}
1147
1148
/* Retrieves the file ASCII codepage
1149
 * Returns 1 if successful or -1 on error
1150
 */
1151
int libnk2_file_get_ascii_codepage(
1152
     libnk2_file_t *file,
1153
     int *ascii_codepage,
1154
     libcerror_error_t **error )
1155
0
{
1156
0
  libnk2_internal_file_t *internal_file = NULL;
1157
0
  static char *function                 = "libnk2_file_get_ascii_codepage";
1158
1159
0
  if( file == NULL )
1160
0
  {
1161
0
    libcerror_error_set(
1162
0
     error,
1163
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1164
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1165
0
     "%s: invalid file.",
1166
0
     function );
1167
1168
0
    return( -1 );
1169
0
  }
1170
0
  internal_file = (libnk2_internal_file_t *) file;
1171
1172
0
  if( internal_file->io_handle == NULL )
1173
0
  {
1174
0
    libcerror_error_set(
1175
0
     error,
1176
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1177
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1178
0
     "%s: invalid internal file - missing IO handle.",
1179
0
     function );
1180
1181
0
    return( -1 );
1182
0
  }
1183
0
  if( ascii_codepage == NULL )
1184
0
  {
1185
0
    libcerror_error_set(
1186
0
     error,
1187
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1188
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1189
0
     "%s: invalid ASCII codepage.",
1190
0
     function );
1191
1192
0
    return( -1 );
1193
0
  }
1194
0
  *ascii_codepage = internal_file->io_handle->ascii_codepage;
1195
1196
0
  return( 1 );
1197
0
}
1198
1199
/* Sets the file ASCII codepage
1200
 * Returns 1 if successful or -1 on error
1201
 */
1202
int libnk2_file_set_ascii_codepage(
1203
     libnk2_file_t *file,
1204
     int ascii_codepage,
1205
     libcerror_error_t **error )
1206
0
{
1207
0
  libnk2_internal_file_t *internal_file = NULL;
1208
0
  static char *function                 = "libnk2_file_set_ascii_codepage";
1209
1210
0
  if( file == NULL )
1211
0
  {
1212
0
    libcerror_error_set(
1213
0
     error,
1214
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1215
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1216
0
     "%s: invalid file.",
1217
0
     function );
1218
1219
0
    return( -1 );
1220
0
  }
1221
0
  internal_file = (libnk2_internal_file_t *) file;
1222
1223
0
  if( internal_file->io_handle == NULL )
1224
0
  {
1225
0
    libcerror_error_set(
1226
0
     error,
1227
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1228
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1229
0
     "%s: invalid internal file - missing IO handle.",
1230
0
     function );
1231
1232
0
    return( -1 );
1233
0
  }
1234
0
  if( ( ascii_codepage != LIBNK2_CODEPAGE_ASCII )
1235
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_874 )
1236
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_932 )
1237
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_936 )
1238
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_949 )
1239
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_950 )
1240
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_1250 )
1241
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_1251 )
1242
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_1252 )
1243
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_1253 )
1244
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_1254 )
1245
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_1255 )
1246
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_1256 )
1247
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_1257 )
1248
0
   && ( ascii_codepage != LIBNK2_CODEPAGE_WINDOWS_1258 ) )
1249
0
  {
1250
0
    libcerror_error_set(
1251
0
     error,
1252
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1253
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1254
0
     "%s: unsupported ASCII codepage.",
1255
0
     function );
1256
1257
0
    return( -1 );
1258
0
  }
1259
0
  internal_file->io_handle->ascii_codepage = ascii_codepage;
1260
1261
0
  return( 1 );
1262
0
}
1263
1264
/* Retrieves the modification time
1265
 * The returned time is a 64-bit version of a filetime value
1266
 * Returns 1 if successful, 0 if not set or -1 on error
1267
 */
1268
int libnk2_file_get_modification_time(
1269
     libnk2_file_t *file,
1270
     uint64_t *filetime,
1271
     libcerror_error_t **error )
1272
0
{
1273
0
  libnk2_internal_file_t *internal_file = NULL;
1274
0
  static char *function                 = "libnk2_file_get_modification_time";
1275
0
  int result                            = 0;
1276
1277
0
  if( file == NULL )
1278
0
  {
1279
0
    libcerror_error_set(
1280
0
     error,
1281
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1282
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1283
0
     "%s: invalid file.",
1284
0
     function );
1285
1286
0
    return( -1 );
1287
0
  }
1288
0
  internal_file = (libnk2_internal_file_t *) file;
1289
1290
0
  if( filetime == NULL )
1291
0
  {
1292
0
    libcerror_error_set(
1293
0
     error,
1294
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1295
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1296
0
     "%s: invalid filetime.",
1297
0
     function );
1298
1299
0
    return( -1 );
1300
0
  }
1301
0
  if( internal_file->file_io_handle != NULL )
1302
0
  {
1303
0
    *filetime = internal_file->modification_time;
1304
1305
0
    result = 1;
1306
0
  }
1307
0
  return( result );
1308
0
}
1309
1310
/* Retrieves the number of items
1311
 * Returns 1 if successful or -1 on error
1312
 */
1313
int libnk2_file_get_number_of_items(
1314
     libnk2_file_t *file,
1315
     int *number_of_items,
1316
     libcerror_error_t **error )
1317
0
{
1318
0
  libnk2_internal_file_t *internal_file = NULL;
1319
0
  static char *function                 = "libnk2_file_get_number_of_items";
1320
1321
0
  if( file == NULL )
1322
0
  {
1323
0
    libcerror_error_set(
1324
0
     error,
1325
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1326
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1327
0
     "%s: invalid file.",
1328
0
     function );
1329
1330
0
    return( -1 );
1331
0
  }
1332
0
  internal_file = (libnk2_internal_file_t *) file;
1333
1334
0
  if( libcdata_array_get_number_of_entries(
1335
0
       internal_file->items_array,
1336
0
       number_of_items,
1337
0
       error ) != 1 )
1338
0
  {
1339
0
    libcerror_error_set(
1340
0
     error,
1341
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1342
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1343
0
     "%s: unable to retrieve number of items.",
1344
0
     function );
1345
1346
0
    return( -1 );
1347
0
  }
1348
0
  return( 1 );
1349
0
}
1350
1351
/* Retrieves a specific item
1352
 * Returns 1 if successful or -1 on error
1353
 */
1354
int libnk2_file_get_item(
1355
     libnk2_file_t *file,
1356
     int item_index,
1357
     libnk2_item_t **item,
1358
     libcerror_error_t **error )
1359
0
{
1360
0
  libnk2_internal_file_t *internal_file = NULL;
1361
0
  static char *function                 = "libnk2_file_get_item";
1362
1363
0
  if( file == NULL )
1364
0
  {
1365
0
    libcerror_error_set(
1366
0
     error,
1367
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1368
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1369
0
     "%s: invalid file.",
1370
0
     function );
1371
1372
0
    return( -1 );
1373
0
  }
1374
0
  internal_file = (libnk2_internal_file_t *) file;
1375
1376
0
  if( internal_file->file_io_handle == NULL )
1377
0
  {
1378
0
    libcerror_error_set(
1379
0
     error,
1380
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1381
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1382
0
     "%s: invalid file - missing file IO handle.",
1383
0
     function );
1384
1385
0
    return( -1 );
1386
0
  }
1387
0
  if( item == NULL )
1388
0
  {
1389
0
    libcerror_error_set(
1390
0
     error,
1391
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1392
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1393
0
     "%s: invalid item.",
1394
0
     function );
1395
1396
0
    return( -1 );
1397
0
  }
1398
0
  if( *item != NULL )
1399
0
  {
1400
0
    libcerror_error_set(
1401
0
     error,
1402
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1403
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1404
0
     "%s: invalid item value already set.",
1405
0
     function );
1406
1407
0
    return( -1 );
1408
0
  }
1409
0
  if( libcdata_array_get_entry_by_index(
1410
0
       internal_file->items_array,
1411
0
       item_index,
1412
0
       (intptr_t **) item,
1413
0
       error ) != 1 )
1414
0
  {
1415
0
    libcerror_error_set(
1416
0
     error,
1417
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1418
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1419
0
     "%s: unable to retrieve item: %d.",
1420
0
     function,
1421
0
     item_index );
1422
1423
0
    return( -1 );
1424
0
  }
1425
0
  return( 1 );
1426
0
}
1427