Coverage Report

Created: 2024-02-25 07:20

/src/libphdi/libcdirectory/libcdirectory_directory.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Directory functions
3
 *
4
 * Copyright (C) 2008-2024, 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 <system_string.h>
26
#include <types.h>
27
#include <wide_string.h>
28
29
#if defined( HAVE_ERRNO_H ) || defined( WINAPI )
30
#include <errno.h>
31
#endif
32
33
#if defined( HAVE_SYS_STAT_H )
34
#include <sys/stat.h>
35
#endif
36
37
#if defined( WINAPI ) && !defined( __CYGWIN__ )
38
#include <direct.h>
39
#endif
40
41
#if defined( HAVE_DIRENT_H )
42
#include <dirent.h>
43
#endif
44
45
#if defined( HAVE_UNISTD_H )
46
#include <unistd.h>
47
#endif
48
49
#include "libcdirectory_definitions.h"
50
#include "libcdirectory_directory.h"
51
#include "libcdirectory_directory_entry.h"
52
#include "libcdirectory_libcerror.h"
53
#include "libcdirectory_system_string.h"
54
#include "libcdirectory_types.h"
55
#include "libcdirectory_wide_string.h"
56
57
/* Creates a directory
58
 * Make sure the value directory is referencing, is set to NULL
59
 * Returns 1 if successful or -1 on error
60
 */
61
int libcdirectory_directory_initialize(
62
     libcdirectory_directory_t **directory,
63
     libcerror_error_t **error )
64
0
{
65
0
  libcdirectory_internal_directory_t *internal_directory = NULL;
66
0
  static char *function                                  = "libcdirectory_directory_initialize";
67
68
0
  if( directory == NULL )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
73
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
74
0
     "%s: invalid directory.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
0
  if( *directory != NULL )
80
0
  {
81
0
    libcerror_error_set(
82
0
     error,
83
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
84
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
85
0
     "%s: invalid directory value already set.",
86
0
     function );
87
88
0
    return( -1 );
89
0
  }
90
0
  internal_directory = memory_allocate_structure(
91
0
                  libcdirectory_internal_directory_t );
92
93
0
  if( internal_directory == NULL )
94
0
  {
95
0
    libcerror_error_set(
96
0
     error,
97
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
98
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
99
0
     "%s: unable to create directory.",
100
0
     function );
101
102
0
    goto on_error;
103
0
  }
104
0
  if( memory_set(
105
0
       internal_directory,
106
0
       0,
107
0
       sizeof( libcdirectory_internal_directory_t ) ) == NULL )
108
0
  {
109
0
    libcerror_error_set(
110
0
     error,
111
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
112
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
113
0
     "%s: unable to clear directory.",
114
0
     function );
115
116
0
    goto on_error;
117
0
  }
118
#if defined( WINAPI )
119
  internal_directory->handle = INVALID_HANDLE_VALUE;
120
#endif
121
122
0
  *directory = (libcdirectory_directory_t *) internal_directory;
123
124
0
  return( 1 );
125
126
0
on_error:
127
0
  if( internal_directory != NULL )
128
0
  {
129
0
    memory_free(
130
0
     internal_directory );
131
0
  }
132
0
  return( -1 );
133
0
}
134
135
/* Frees a directory
136
 * Returns 1 if successful or -1 on error
137
 */
138
int libcdirectory_directory_free(
139
     libcdirectory_directory_t **directory,
140
     libcerror_error_t **error )
141
0
{
142
0
  libcdirectory_internal_directory_t *internal_directory = NULL;
143
0
  static char *function                                  = "libcdirectory_directory_free";
144
0
  int result                                             = 1;
145
146
0
  if( directory == NULL )
147
0
  {
148
0
    libcerror_error_set(
149
0
     error,
150
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
151
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
152
0
     "%s: invalid directory.",
153
0
     function );
154
155
0
    return( -1 );
156
0
  }
157
0
  if( *directory != NULL )
158
0
  {
159
0
    internal_directory = (libcdirectory_internal_directory_t *) *directory;
160
  
161
#if defined( WINAPI )
162
    if( internal_directory->handle != INVALID_HANDLE_VALUE )
163
#else
164
0
    if( internal_directory->stream != NULL )
165
0
#endif
166
0
    {
167
0
      if( libcdirectory_directory_close(
168
0
           *directory,
169
0
           error ) != 0 )
170
0
      {
171
0
        libcerror_error_set(
172
0
         error,
173
0
         LIBCERROR_ERROR_DOMAIN_IO,
174
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
175
0
         "%s: unable to close directory.",
176
0
         function );
177
178
0
        result = -1;
179
0
      }
180
0
    }
181
0
    *directory = NULL;
182
183
0
    memory_free(
184
0
     internal_directory );
185
0
  }
186
0
  return( result );
187
0
}
188
189
#if defined( WINAPI ) && ( WINVER >= 0x0400 )
190
191
/* Opens a directory
192
 * This function uses the WINAPI function for Windows XP or later
193
 * Returns 1 if successful or -1 on error
194
 */
195
int libcdirectory_directory_open(
196
     libcdirectory_directory_t *directory,
197
     const char *directory_name,
198
     libcerror_error_t **error )
199
{
200
  libcdirectory_internal_directory_t *internal_directory                   = NULL;
201
  libcdirectory_internal_directory_entry_t *internal_first_directory_entry = NULL;
202
  system_character_t *system_directory_name                                = NULL;
203
  static char *function                                                    = "libcdirectory_directory_open";
204
  size_t directory_name_length                                             = 0;
205
  size_t system_directory_name_size                                        = 0;
206
  DWORD error_code                                                         = 0;
207
208
  if( directory == NULL )
209
  {
210
    libcerror_error_set(
211
     error,
212
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
213
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
214
     "%s: invalid directory.",
215
     function );
216
217
    return( -1 );
218
  }
219
  internal_directory = (libcdirectory_internal_directory_t *) directory;
220
  
221
  if( directory_name == NULL )
222
  {
223
    libcerror_error_set(
224
     error,
225
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
226
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
227
     "%s: invalid directory name.",
228
     function );
229
230
    return( -1 );
231
  }
232
  if( internal_directory->handle != INVALID_HANDLE_VALUE )
233
  {
234
    libcerror_error_set(
235
     error,
236
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
237
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
238
     "%s: invalid directory - handle value already set.",
239
     function );
240
241
    return( -1 );
242
  }
243
  if( internal_directory->first_entry != NULL )
244
  {
245
    libcerror_error_set(
246
     error,
247
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
248
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
249
     "%s: invalid directory - first entry value already set.",
250
     function );
251
252
    return( -1 );
253
  }
254
  if( libcdirectory_directory_entry_initialize(
255
       &( internal_directory->first_entry ),
256
       error ) != 1 )
257
  {
258
    libcerror_error_set(
259
     error,
260
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
261
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
262
     "%s: unable to create first entry.",
263
     function );
264
265
    goto on_error;
266
  }
267
  if( internal_directory->first_entry == NULL )
268
  {
269
    libcerror_error_set(
270
     error,
271
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
272
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
273
     "%s: invalid directory - missing first entry.",
274
     function );
275
276
    goto on_error;
277
  }
278
  internal_first_directory_entry = (libcdirectory_internal_directory_entry_t *) internal_directory->first_entry;
279
280
  directory_name_length = narrow_string_length(
281
                           directory_name );
282
283
  if( libcdirectory_system_string_size_from_narrow_string(
284
       directory_name,
285
       directory_name_length + 1,
286
       &system_directory_name_size,
287
       error ) != 1 )
288
  {
289
    libcerror_error_set(
290
     error,
291
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
292
     LIBCERROR_CONVERSION_ERROR_GENERIC,
293
     "%s: unable to determine system character directory name size.",
294
     function );
295
296
    goto on_error;
297
  }
298
  /* Find files requires a search path, add a \ and * if necessary
299
   */
300
  if( ( directory_name_length < 2 )
301
   || ( directory_name[ directory_name_length - 1 ] != '\\' ) )
302
  {
303
    system_directory_name_size += 1;
304
  }
305
  system_directory_name_size += 1;
306
307
  system_directory_name = system_string_allocate(
308
                           system_directory_name_size );
309
310
  if( system_directory_name == NULL )
311
  {
312
    libcerror_error_set(
313
     error,
314
     LIBCERROR_ERROR_DOMAIN_MEMORY,
315
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
316
     "%s: unable to create system character directory name.",
317
     function );
318
319
    goto on_error;
320
  }
321
  if( libcdirectory_system_string_copy_from_narrow_string(
322
       system_directory_name,
323
       system_directory_name_size,
324
       directory_name,
325
       directory_name_length + 1,
326
       error ) != 1 )
327
  {
328
    libcerror_error_set(
329
     error,
330
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
331
     LIBCERROR_CONVERSION_ERROR_GENERIC,
332
     "%s: unable to set system character directory name.",
333
     function );
334
335
    goto on_error;
336
  }
337
  /* Find files requires a search path, add a \ and * if necessary
338
   */
339
  if( ( directory_name_length < 2 )
340
   || ( directory_name[ directory_name_length - 1 ] != '\\' ) )
341
  {
342
    system_directory_name[ system_directory_name_size - 3 ] = (system_character_t) '\\';
343
  }
344
  system_directory_name[ system_directory_name_size - 2 ] = (system_character_t) '*';
345
  system_directory_name[ system_directory_name_size - 1 ] = 0;
346
347
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
348
  /* Cannot use FindFirstFileA here because it requires a narrow version of WIN32_FIND_DATA
349
   */
350
  internal_directory->handle = FindFirstFileW(
351
                                (LPCWSTR) system_directory_name,
352
                                &( internal_first_directory_entry->find_data ) );
353
#else
354
  internal_directory->handle = FindFirstFileA(
355
                                (LPCSTR) system_directory_name,
356
                                &( internal_first_directory_entry->find_data ) );
357
#endif
358
  if( internal_directory->handle == INVALID_HANDLE_VALUE )
359
  {
360
    error_code = GetLastError();
361
362
    libcerror_system_set_error(
363
     error,
364
     LIBCERROR_ERROR_DOMAIN_IO,
365
     LIBCERROR_IO_ERROR_OPEN_FAILED,
366
     error_code,
367
     "%s: unable to open directory.",
368
     function );
369
370
    goto on_error;
371
  }
372
  memory_free(
373
   system_directory_name );
374
375
  return( 1 );
376
377
on_error:
378
  if( system_directory_name != NULL )
379
  {
380
    memory_free(
381
     system_directory_name );
382
  }
383
  if( internal_directory->first_entry != NULL )
384
  {
385
    libcdirectory_directory_entry_free(
386
     &( internal_directory->first_entry ),
387
     NULL );
388
  }
389
  return( -1 );
390
}
391
392
#elif defined( WINAPI )
393
394
/* TODO */
395
#error WINAPI open directory for Windows earlier than NT4 not implemented
396
397
#elif defined( HAVE_OPENDIR )
398
399
/* Opens a directory
400
 * This function uses the POSIX opendir function
401
 * Returns 1 if successful or -1 on error
402
 */
403
int libcdirectory_directory_open(
404
     libcdirectory_directory_t *directory,
405
     const char *directory_name,
406
     libcerror_error_t **error )
407
0
{
408
0
  libcdirectory_internal_directory_t *internal_directory = NULL;
409
0
  static char *function                                  = "libcdirectory_directory_open";
410
411
0
  if( directory == NULL )
412
0
  {
413
0
    libcerror_error_set(
414
0
     error,
415
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
416
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
417
0
     "%s: invalid directory.",
418
0
     function );
419
420
0
    return( -1 );
421
0
  }
422
0
  internal_directory = (libcdirectory_internal_directory_t *) directory;
423
  
424
0
  if( directory_name == NULL )
425
0
  {
426
0
    libcerror_error_set(
427
0
     error,
428
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
429
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
430
0
     "%s: invalid directory name.",
431
0
     function );
432
433
0
    return( -1 );
434
0
  }
435
0
  if( internal_directory->stream != NULL )
436
0
  {
437
0
    libcerror_error_set(
438
0
     error,
439
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
440
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
441
0
     "%s: invalid directory - stream value already set.",
442
0
     function );
443
444
0
    return( -1 );
445
0
  }
446
0
  internal_directory->stream = opendir(
447
0
                                directory_name );
448
449
0
  if( internal_directory->stream == NULL )
450
0
  {
451
0
    libcerror_system_set_error(
452
0
     error,
453
0
     LIBCERROR_ERROR_DOMAIN_IO,
454
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
455
0
     errno,
456
0
     "%s: unable to open directory.",
457
0
     function );
458
459
0
    return( -1 );
460
0
  }
461
0
  return( 1 );
462
0
}
463
464
#else
465
#error Missing open directory function
466
#endif
467
468
#if defined( HAVE_WIDE_CHARACTER_TYPE )
469
470
#if defined( WINAPI ) && ( WINVER >= 0x0400 )
471
472
/* Opens a directory
473
 * This function uses the WINAPI function for Windows XP or later
474
 * Returns 1 if successful or -1 on error
475
 */
476
int libcdirectory_directory_open_wide(
477
     libcdirectory_directory_t *directory,
478
     const wchar_t *directory_name,
479
     libcerror_error_t **error )
480
{
481
  libcdirectory_internal_directory_t *internal_directory                   = NULL;
482
  libcdirectory_internal_directory_entry_t *internal_first_directory_entry = NULL;
483
  system_character_t *system_directory_name                                = NULL;
484
  static char *function                                                    = "libcdirectory_directory_open_wide";
485
  size_t directory_name_length                                             = 0;
486
  size_t system_directory_name_size                                        = 0;
487
  DWORD error_code                                                         = 0;
488
489
  if( directory == NULL )
490
  {
491
    libcerror_error_set(
492
     error,
493
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
494
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
495
     "%s: invalid directory.",
496
     function );
497
498
    return( -1 );
499
  }
500
  internal_directory = (libcdirectory_internal_directory_t *) directory;
501
  
502
  if( directory_name == NULL )
503
  {
504
    libcerror_error_set(
505
     error,
506
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
507
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
508
     "%s: invalid directory name.",
509
     function );
510
511
    return( -1 );
512
  }
513
  if( internal_directory->handle != INVALID_HANDLE_VALUE )
514
  {
515
    libcerror_error_set(
516
     error,
517
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
518
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
519
     "%s: invalid directory - handle value already set.",
520
     function );
521
522
    return( -1 );
523
  }
524
  if( internal_directory->first_entry != NULL )
525
  {
526
    libcerror_error_set(
527
     error,
528
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
529
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
530
     "%s: invalid directory - first entry value already set.",
531
     function );
532
533
    return( -1 );
534
  }
535
  if( libcdirectory_directory_entry_initialize(
536
       &( internal_directory->first_entry ),
537
       error ) != 1 )
538
  {
539
    libcerror_error_set(
540
     error,
541
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
542
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
543
     "%s: unable to create first entry.",
544
     function );
545
546
    goto on_error;
547
  }
548
  if( internal_directory->first_entry == NULL )
549
  {
550
    libcerror_error_set(
551
     error,
552
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
553
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
554
     "%s: invalid directory - missing first entry.",
555
     function );
556
557
    goto on_error;
558
  }
559
  internal_first_directory_entry = (libcdirectory_internal_directory_entry_t *) internal_directory->first_entry;
560
561
  directory_name_length = wide_string_length(
562
                           directory_name );
563
564
  if( libcdirectory_system_string_size_from_wide_string(
565
       directory_name,
566
       directory_name_length + 1,
567
       &system_directory_name_size,
568
       error ) != 1 )
569
  {
570
    libcerror_error_set(
571
     error,
572
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
573
     LIBCERROR_CONVERSION_ERROR_GENERIC,
574
     "%s: unable to determine system character directory name size.",
575
     function );
576
577
    goto on_error;
578
  }
579
  /* Find files requires a search path, add a \ and * if necessary
580
   */
581
  if( ( directory_name_length < 2 )
582
   || ( directory_name[ directory_name_length - 1 ] == (wchar_t) '\\' ) )
583
  {
584
    system_directory_name_size += 1;
585
  }
586
  system_directory_name_size += 1;
587
588
  system_directory_name = system_string_allocate(
589
                           system_directory_name_size );
590
591
  if( system_directory_name == NULL )
592
  {
593
    libcerror_error_set(
594
     error,
595
     LIBCERROR_ERROR_DOMAIN_MEMORY,
596
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
597
     "%s: unable to create system character directory name.",
598
     function );
599
600
    goto on_error;
601
  }
602
  if( libcdirectory_system_string_copy_from_wide_string(
603
       system_directory_name,
604
       system_directory_name_size,
605
       directory_name,
606
       directory_name_length + 1,
607
       error ) != 1 )
608
  {
609
    libcerror_error_set(
610
     error,
611
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
612
     LIBCERROR_CONVERSION_ERROR_GENERIC,
613
     "%s: unable to set system character directory name.",
614
     function );
615
616
    goto on_error;
617
  }
618
  /* Find files requires a search path, add a \ and * if necessary
619
   */
620
  if( ( directory_name_length < 2 )
621
   || ( directory_name[ directory_name_length - 1 ] == (wchar_t) '\\' ) )
622
  {
623
    system_directory_name[ system_directory_name_size - 3 ] = (system_character_t) '\\';
624
  }
625
  system_directory_name[ system_directory_name_size - 2 ] = (system_character_t) '*';
626
  system_directory_name[ system_directory_name_size - 1 ] = 0;
627
628
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
629
  internal_directory->handle = FindFirstFileW(
630
                                (LPCWSTR) system_directory_name,
631
                                &( internal_first_directory_entry->find_data ) );
632
#else
633
  /* Cannot use FindFirstFileW here because it requires a wide version of WIN32_FIND_DATA
634
   */
635
  internal_directory->handle = FindFirstFileA(
636
                                (LPCSTR) system_directory_name,
637
                                &( internal_first_directory_entry->find_data ) );
638
#endif
639
  if( internal_directory->handle == INVALID_HANDLE_VALUE )
640
  {
641
    error_code = GetLastError();
642
643
    libcerror_system_set_error(
644
     error,
645
     LIBCERROR_ERROR_DOMAIN_IO,
646
     LIBCERROR_IO_ERROR_OPEN_FAILED,
647
     error_code,
648
     "%s: unable to open directory.",
649
     function );
650
651
    goto on_error;
652
  }
653
  memory_free(
654
   system_directory_name );
655
656
  return( 1 );
657
658
on_error:
659
  if( system_directory_name != NULL )
660
  {
661
    memory_free(
662
     system_directory_name );
663
  }
664
  if( internal_directory->first_entry != NULL )
665
  {
666
    libcdirectory_directory_entry_free(
667
     &( internal_directory->first_entry ),
668
     NULL );
669
  }
670
  return( -1 );
671
}
672
673
#elif defined( WINAPI )
674
675
/* TODO */
676
#error WINAPI open directory for Windows earlier than NT4 not implemented
677
678
#elif defined( HAVE_OPENDIR )
679
680
/* Opens a directory
681
 * This function uses the POSIX opendir function
682
 * Returns 1 if successful or -1 on error
683
 */
684
int libcdirectory_directory_open_wide(
685
     libcdirectory_directory_t *directory,
686
     const wchar_t *directory_name,
687
     libcerror_error_t **error )
688
{
689
  libcdirectory_internal_directory_t *internal_directory = NULL;
690
  static char *function                                  = "libcdirectory_directory_open_wide";
691
  char *system_directory_name                            = NULL;
692
  size_t directory_name_length                           = 0;
693
  size_t system_directory_name_size                      = 0;
694
695
  if( directory == NULL )
696
  {
697
    libcerror_error_set(
698
     error,
699
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
700
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
701
     "%s: invalid directory.",
702
     function );
703
704
    return( -1 );
705
  }
706
  internal_directory = (libcdirectory_internal_directory_t *) directory;
707
  
708
  if( directory_name == NULL )
709
  {
710
    libcerror_error_set(
711
     error,
712
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
713
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
714
     "%s: invalid directory name.",
715
     function );
716
717
    return( -1 );
718
  }
719
  if( internal_directory->stream != NULL )
720
  {
721
    libcerror_error_set(
722
     error,
723
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
724
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
725
     "%s: invalid directory - stream value already set.",
726
     function );
727
728
    return( -1 );
729
  }
730
  directory_name_length = wide_string_length(
731
                           directory_name );
732
733
  if( libcdirectory_system_string_size_from_wide_string(
734
       directory_name,
735
       directory_name_length + 1,
736
       &system_directory_name_size,
737
       error ) != 1 )
738
  {
739
    libcerror_error_set(
740
     error,
741
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
742
     LIBCERROR_CONVERSION_ERROR_GENERIC,
743
     "%s: unable to determine system character directory name size.",
744
     function );
745
746
    goto on_error;
747
  }
748
  system_directory_name = system_string_allocate(
749
                           system_directory_name_size );
750
751
  if( system_directory_name == NULL )
752
  {
753
    libcerror_error_set(
754
     error,
755
     LIBCERROR_ERROR_DOMAIN_MEMORY,
756
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
757
     "%s: unable to create system character directory name.",
758
     function );
759
760
    goto on_error;
761
  }
762
  if( libcdirectory_system_string_copy_from_wide_string(
763
       system_directory_name,
764
       system_directory_name_size,
765
       directory_name,
766
       directory_name_length + 1,
767
       error ) != 1 )
768
  {
769
    libcerror_error_set(
770
     error,
771
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
772
     LIBCERROR_CONVERSION_ERROR_GENERIC,
773
     "%s: unable to set system character directory name.",
774
     function );
775
776
    goto on_error;
777
  }
778
  internal_directory->stream = opendir(
779
                                system_directory_name );
780
781
  if( internal_directory->stream == NULL )
782
  {
783
    libcerror_system_set_error(
784
     error,
785
     LIBCERROR_ERROR_DOMAIN_IO,
786
     LIBCERROR_IO_ERROR_OPEN_FAILED,
787
     errno,
788
     "%s: unable to open directory.",
789
     function );
790
791
    goto on_error;
792
  }
793
  memory_free(
794
   system_directory_name );
795
796
  system_directory_name = NULL;
797
798
  return( 1 );
799
800
on_error:
801
  if( system_directory_name != NULL )
802
  {
803
    memory_free(
804
     system_directory_name );
805
  }
806
  return( -1 );
807
}
808
809
#else
810
#error Missing wide open directory function
811
#endif
812
813
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
814
815
#if defined( WINAPI ) && ( WINVER >= 0x0400 )
816
817
/* Closes a directory
818
 * This function uses the WINAPI function for Windows XP or later
819
 * Returns 0 if successful or -1 on error
820
 */
821
int libcdirectory_directory_close(
822
     libcdirectory_directory_t *directory,
823
     libcerror_error_t **error )
824
{
825
  libcdirectory_internal_directory_t *internal_directory = NULL;
826
  static char *function                                  = "libcdirectory_directory_close";
827
  int result                                             = 0;
828
  DWORD error_code                                       = 0;
829
830
  if( directory == NULL )
831
  {
832
    libcerror_error_set(
833
     error,
834
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
835
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
836
     "%s: invalid directory.",
837
     function );
838
839
    return( -1 );
840
  }
841
  internal_directory = (libcdirectory_internal_directory_t *) directory;
842
  
843
  if( internal_directory->handle != INVALID_HANDLE_VALUE )
844
  {
845
    if( FindClose(
846
         internal_directory->handle ) == 0 )
847
    {
848
      error_code = GetLastError();
849
850
      libcerror_system_set_error(
851
       error,
852
       LIBCERROR_ERROR_DOMAIN_IO,
853
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
854
       error_code,
855
       "%s: unable to close directory.",
856
       function );
857
858
      result = -1;
859
    }
860
    internal_directory->handle = INVALID_HANDLE_VALUE;
861
  }
862
  if( internal_directory->first_entry != NULL )
863
  {
864
    if( libcdirectory_directory_entry_free(
865
         &( internal_directory->first_entry ),
866
         error ) != 1 )
867
    {
868
      libcerror_error_set(
869
       error,
870
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
871
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
872
       "%s: unable to free first entry.",
873
       function );
874
875
      result = -1;
876
    }
877
  }
878
  return( result );
879
}
880
881
#elif defined( WINAPI )
882
883
/* TODO */
884
#error WINAPI close directory for Windows earlier than NT4 not implemented
885
886
#elif defined( HAVE_CLOSEDIR )
887
888
/* Closes a directory
889
 * This function uses the POSIX closedir function
890
 * Returns 0 if successful or -1 on error
891
 */
892
int libcdirectory_directory_close(
893
     libcdirectory_directory_t *directory,
894
     libcerror_error_t **error )
895
0
{
896
0
  libcdirectory_internal_directory_t *internal_directory = NULL;
897
0
  static char *function                                  = "libcdirectory_directory_close";
898
0
  int result                                             = 0;
899
900
0
  if( directory == NULL )
901
0
  {
902
0
    libcerror_error_set(
903
0
     error,
904
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
905
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
906
0
     "%s: invalid directory.",
907
0
     function );
908
909
0
    return( -1 );
910
0
  }
911
0
  internal_directory = (libcdirectory_internal_directory_t *) directory;
912
  
913
0
  if( internal_directory->stream != NULL )
914
0
  {
915
0
    if( closedir(
916
0
         internal_directory->stream ) != 0 )
917
0
    {
918
0
      libcerror_system_set_error(
919
0
       error,
920
0
       LIBCERROR_ERROR_DOMAIN_IO,
921
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
922
0
       errno,
923
0
       "%s: unable to close directory.",
924
0
       function );
925
926
0
      result = -1;
927
0
    }
928
0
    internal_directory->stream = NULL;
929
0
  }
930
0
  return( result );
931
0
}
932
933
#else
934
#error Missing close directory function
935
#endif
936
937
#if defined( WINAPI ) && ( WINVER >= 0x0400 )
938
939
/* Reads a directory
940
 * This function uses the WINAPI function for Windows XP or later
941
 * Returns 1 if successful, 0 if no such entry or -1 on error
942
 */
943
int libcdirectory_directory_read_entry(
944
     libcdirectory_directory_t *directory,
945
     libcdirectory_directory_entry_t *directory_entry,
946
     libcerror_error_t **error )
947
{
948
  libcdirectory_internal_directory_t *internal_directory             = NULL;
949
  libcdirectory_internal_directory_entry_t *internal_directory_entry = NULL;
950
  static char *function                                              = "libcdirectory_directory_read_entry";
951
  DWORD error_code                                                   = 0;
952
953
  if( directory == NULL )
954
  {
955
    libcerror_error_set(
956
     error,
957
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
958
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
959
     "%s: invalid directory.",
960
     function );
961
962
    return( -1 );
963
  }
964
  internal_directory = (libcdirectory_internal_directory_t *) directory;
965
  
966
  if( directory_entry == NULL )
967
  {
968
    libcerror_error_set(
969
     error,
970
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
971
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
972
     "%s: invalid directory entry.",
973
     function );
974
975
    return( -1 );
976
  }
977
  internal_directory_entry = (libcdirectory_internal_directory_entry_t *) directory_entry;
978
979
  if( internal_directory->handle == INVALID_HANDLE_VALUE )
980
  {
981
    libcerror_error_set(
982
     error,
983
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
984
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
985
     "%s: invalid directory - missing handle.",
986
     function );
987
988
    return( -1 );
989
  }
990
  if( internal_directory->first_entry != NULL )
991
  {
992
    if( libcdirectory_directory_entry_copy(
993
         directory_entry,
994
         internal_directory->first_entry,
995
         error ) != 1 )
996
    {
997
      libcerror_error_set(
998
       error,
999
       LIBCERROR_ERROR_DOMAIN_MEMORY,
1000
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1001
       "%s: unable to copy first directory entry.",
1002
       function );
1003
1004
      return( -1 );
1005
    }
1006
    if( libcdirectory_directory_entry_free(
1007
         (libcdirectory_directory_t **) &( internal_directory->first_entry ),
1008
         error ) != 1 )
1009
    {
1010
      libcerror_error_set(
1011
       error,
1012
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1013
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1014
       "%s: unable to free first entry.",
1015
       function );
1016
1017
      return( -1 );
1018
    }
1019
  }
1020
  else
1021
  {
1022
#if defined( HAVE_WIDE_CHARACTER_TYPE ) && defined( HAVE_WIDE_SYSTEM_CHARACTER )
1023
    if( internal_directory_entry->narrow_name != NULL )
1024
    {
1025
      memory_free(
1026
       internal_directory_entry->narrow_name );
1027
1028
      internal_directory_entry->narrow_name = NULL;
1029
    }
1030
#else
1031
    if( internal_directory_entry->wide_name != NULL )
1032
    {
1033
      memory_free(
1034
       internal_directory_entry->wide_name );
1035
1036
      internal_directory_entry->wide_name = NULL;
1037
    }
1038
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) && defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
1039
1040
    if( FindNextFile(
1041
         internal_directory->handle,
1042
         &( internal_directory_entry->find_data ) ) == 0 )
1043
    {
1044
      error_code = GetLastError();
1045
1046
      if( error_code == ERROR_NO_MORE_FILES )
1047
      {
1048
        return( 0 );
1049
      }
1050
      else
1051
      {
1052
        libcerror_system_set_error(
1053
         error,
1054
         LIBCERROR_ERROR_DOMAIN_IO,
1055
         LIBCERROR_IO_ERROR_READ_FAILED,
1056
         error_code,
1057
         "%s: unable to read from directory.",
1058
         function );
1059
      }
1060
      return( -1 );
1061
    }
1062
  }
1063
  return( 1 );
1064
}
1065
1066
#elif defined( WINAPI )
1067
1068
/* TODO */
1069
#error WINAPI read directory entry for Windows earlier than NT4 not implemented
1070
1071
#elif defined( HAVE_READDIR_R )
1072
1073
/* Reads a directory
1074
 * This function uses the POSIX readdir_r function
1075
 * Returns 1 if successful, 0 if no such entry or -1 on error
1076
 */
1077
int libcdirectory_directory_read_entry(
1078
     libcdirectory_directory_t *directory,
1079
     libcdirectory_directory_entry_t *directory_entry,
1080
     libcerror_error_t **error )
1081
0
{
1082
0
  libcdirectory_internal_directory_t *internal_directory             = NULL;
1083
0
  libcdirectory_internal_directory_entry_t *internal_directory_entry = NULL;
1084
0
  struct dirent *result_directory_entry                              = NULL;
1085
0
  static char *function                                              = "libcdirectory_directory_read_entry";
1086
0
  int result                                                         = 0;
1087
1088
0
  if( directory == NULL )
1089
0
  {
1090
0
    libcerror_error_set(
1091
0
     error,
1092
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1093
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1094
0
     "%s: invalid directory.",
1095
0
     function );
1096
1097
0
    return( -1 );
1098
0
  }
1099
0
  internal_directory = (libcdirectory_internal_directory_t *) directory;
1100
  
1101
0
  if( directory_entry == NULL )
1102
0
  {
1103
0
    libcerror_error_set(
1104
0
     error,
1105
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1106
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1107
0
     "%s: invalid directory entry.",
1108
0
     function );
1109
1110
0
    return( -1 );
1111
0
  }
1112
0
  internal_directory_entry = (libcdirectory_internal_directory_entry_t *) directory_entry;
1113
1114
0
  if( internal_directory->stream == NULL )
1115
0
  {
1116
0
    libcerror_error_set(
1117
0
     error,
1118
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1119
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1120
0
     "%s: invalid directory - missing stream.",
1121
0
     function );
1122
1123
0
    return( -1 );
1124
0
  }
1125
#if defined( HAVE_WIDE_CHARACTER_TYPE ) && defined( HAVE_WIDE_SYSTEM_CHARACTER )
1126
  if( internal_directory_entry->narrow_name != NULL )
1127
  {
1128
    memory_free(
1129
     internal_directory_entry->narrow_name );
1130
1131
    internal_directory_entry->narrow_name = NULL;
1132
  }
1133
#else
1134
0
  if( internal_directory_entry->wide_name != NULL )
1135
0
  {
1136
0
    memory_free(
1137
0
     internal_directory_entry->wide_name );
1138
1139
0
    internal_directory_entry->wide_name = NULL;
1140
0
  }
1141
0
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) && defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
1142
1143
0
  result = readdir_r(
1144
0
            internal_directory->stream,
1145
0
            &( internal_directory_entry->entry ),
1146
0
            &result_directory_entry );
1147
1148
0
  if( result != 0 )
1149
0
  {
1150
0
    libcerror_system_set_error(
1151
0
     error,
1152
0
     LIBCERROR_ERROR_DOMAIN_IO,
1153
0
     LIBCERROR_IO_ERROR_READ_FAILED,
1154
0
     errno,
1155
0
     "%s: unable to read from directory.",
1156
0
     function );
1157
1158
0
    return( -1 );
1159
0
  }
1160
0
  if( result_directory_entry == NULL )
1161
0
  {
1162
0
    return( 0 );
1163
0
  }
1164
0
  return( 1 );
1165
0
}
1166
1167
#else
1168
#error Missing read directory entry function
1169
#endif
1170
1171
/* Determines if a directory has a specific entry
1172
 * Returns 1 if the directory has the corresponding entry, 0 if not or -1 on error
1173
 */
1174
int libcdirectory_directory_has_entry(
1175
     libcdirectory_directory_t *directory,
1176
     libcdirectory_directory_entry_t *directory_entry,
1177
     const char *entry_name,
1178
     size_t entry_name_length,
1179
     uint8_t entry_type,
1180
     uint8_t compare_flags,
1181
     libcerror_error_t **error )
1182
0
{
1183
0
  libcdirectory_directory_entry_t *search_directory_entry = NULL;
1184
0
  char *search_directory_entry_name                       = NULL;
1185
0
  static char *function                                   = "libcdirectory_directory_read_entry";
1186
0
  size_t search_directory_entry_name_length               = 0;
1187
0
  uint8_t search_directory_entry_type                     = 0;
1188
0
  int entry_found                                         = 0;
1189
0
  int match                                               = 0;
1190
0
  int result                                              = 0;
1191
1192
0
  if( directory == NULL )
1193
0
  {
1194
0
    libcerror_error_set(
1195
0
     error,
1196
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1197
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1198
0
     "%s: invalid directory.",
1199
0
     function );
1200
1201
0
    return( -1 );
1202
0
  }
1203
0
  if( directory_entry == NULL )
1204
0
  {
1205
0
    libcerror_error_set(
1206
0
     error,
1207
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1208
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1209
0
     "%s: invalid directory entry.",
1210
0
     function );
1211
1212
0
    return( -1 );
1213
0
  }
1214
0
  if( entry_name == NULL )
1215
0
  {
1216
0
    libcerror_error_set(
1217
0
     error,
1218
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1219
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1220
0
     "%s: invalid entry name.",
1221
0
     function );
1222
1223
0
    return( -1 );
1224
0
  }
1225
0
  if( entry_name_length > (size_t) SSIZE_MAX )
1226
0
  {
1227
0
    libcerror_error_set(
1228
0
     error,
1229
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1230
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1231
0
     "%s: invalid entry name length value exceeds maximum.",
1232
0
     function );
1233
1234
0
    return( -1 );
1235
0
  }
1236
0
  if( ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_DEVICE )
1237
0
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_DIRECTORY )
1238
0
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_FILE )
1239
0
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_LINK )
1240
0
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_PIPE )
1241
0
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_SOCKET )
1242
0
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_UNDEFINED ) )
1243
0
  {
1244
0
    libcerror_error_set(
1245
0
     error,
1246
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1247
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1248
0
     "%s: unsupported entry type.",
1249
0
     function );
1250
1251
0
    return( -1 );
1252
0
  }
1253
0
  if( ( compare_flags & ~( LIBCDIRECTORY_COMPARE_FLAG_NO_CASE ) ) != 0 )
1254
0
  {
1255
0
    libcerror_error_set(
1256
0
     error,
1257
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1258
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1259
0
     "%s: unsupported compare flags.",
1260
0
     function );
1261
1262
0
    return( -1 );
1263
0
  }
1264
0
  if( libcdirectory_directory_entry_initialize(
1265
0
       &search_directory_entry,
1266
0
       error ) != 1 )
1267
0
  {
1268
0
    libcerror_error_set(
1269
0
     error,
1270
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1271
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1272
0
     "%s: unable to create search directory entry.",
1273
0
     function );
1274
1275
0
    goto on_error;
1276
0
  }
1277
0
  entry_found = 0;
1278
1279
0
  do
1280
0
  {
1281
0
    result = libcdirectory_directory_read_entry(
1282
0
        directory,
1283
0
        search_directory_entry,
1284
0
        error );
1285
1286
0
    if( result == -1 )
1287
0
    {
1288
0
      libcerror_error_set(
1289
0
       error,
1290
0
       LIBCERROR_ERROR_DOMAIN_IO,
1291
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1292
0
       "%s: unable to read directory entry.",
1293
0
       function );
1294
1295
0
      goto on_error;
1296
0
    }
1297
0
    else if( result == 0 )
1298
0
    {
1299
0
      break;
1300
0
    }
1301
0
    if( libcdirectory_directory_entry_get_type(
1302
0
         search_directory_entry,
1303
0
         &search_directory_entry_type,
1304
0
         error ) != 1 )
1305
0
    {
1306
0
      libcerror_error_set(
1307
0
       error,
1308
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1309
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1310
0
       "%s: unable to retrieve directory entry type.",
1311
0
       function );
1312
1313
0
      goto on_error;
1314
0
    }
1315
0
    if( search_directory_entry_type == entry_type )
1316
0
    {
1317
0
      if( libcdirectory_directory_entry_get_name(
1318
0
           search_directory_entry,
1319
0
           &search_directory_entry_name,
1320
0
           error ) != 1 )
1321
0
      {
1322
0
        libcerror_error_set(
1323
0
         error,
1324
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1325
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1326
0
         "%s: unable to retrieve directory entry name.",
1327
0
         function );
1328
1329
0
        goto on_error;
1330
0
      }
1331
0
      search_directory_entry_name_length = narrow_string_length(
1332
0
                                            search_directory_entry_name );
1333
1334
0
      if( search_directory_entry_name_length == entry_name_length )
1335
0
      {
1336
        /* If there is an exact match we're done searching
1337
         */
1338
0
        match = narrow_string_compare(
1339
0
           search_directory_entry_name,
1340
0
           entry_name,
1341
0
           entry_name_length );
1342
1343
0
        if( match == 0 )
1344
0
        {
1345
0
          if( libcdirectory_directory_entry_copy(
1346
0
               directory_entry,
1347
0
               search_directory_entry,
1348
0
               error ) != 1 )
1349
0
          {
1350
0
            libcerror_error_set(
1351
0
             error,
1352
0
             LIBCERROR_ERROR_DOMAIN_MEMORY,
1353
0
             LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1354
0
             "%s: unable to copy search directory entry.",
1355
0
             function );
1356
1357
0
            goto on_error;
1358
0
          }
1359
0
          entry_found = 1;
1360
1361
0
          break;
1362
0
        }
1363
        /* Ignore successive caseless matches
1364
         */
1365
0
        if( ( ( compare_flags & LIBCDIRECTORY_COMPARE_FLAG_NO_CASE ) != 0 )
1366
0
         && ( entry_found == 0 ) )
1367
0
        {
1368
0
          match = narrow_string_compare_no_case(
1369
0
             search_directory_entry_name,
1370
0
             entry_name,
1371
0
             entry_name_length );
1372
1373
0
          if( match == 0 )
1374
0
          {
1375
0
            if( libcdirectory_directory_entry_copy(
1376
0
                 directory_entry,
1377
0
                 search_directory_entry,
1378
0
                 error ) != 1 )
1379
0
            {
1380
0
              libcerror_error_set(
1381
0
               error,
1382
0
               LIBCERROR_ERROR_DOMAIN_MEMORY,
1383
0
               LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1384
0
               "%s: unable to copy search directory entry.",
1385
0
               function );
1386
1387
0
              goto on_error;
1388
0
            }
1389
0
            entry_found = 1;
1390
0
          }
1391
0
        }
1392
0
      }
1393
0
    }
1394
0
  }
1395
0
  while( result != 0 );
1396
1397
0
  if( libcdirectory_directory_entry_free(
1398
0
       &search_directory_entry,
1399
0
       error ) != 1 )
1400
0
  {
1401
0
    libcerror_error_set(
1402
0
     error,
1403
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1404
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1405
0
     "%s: unable to free search directory entry.",
1406
0
     function );
1407
1408
0
    goto on_error;
1409
0
  }
1410
0
  return( entry_found );
1411
1412
0
on_error:
1413
0
  if( search_directory_entry != NULL )
1414
0
  {
1415
0
    libcdirectory_directory_entry_free(
1416
0
     &search_directory_entry,
1417
0
     NULL );
1418
0
  }
1419
0
  return( -1 );
1420
0
}
1421
1422
#if defined( HAVE_WIDE_CHARACTER_TYPE )
1423
1424
/* Determines if a directory has a specific entry
1425
 * Returns 1 if the directory has the corresponding entry, 0 if not or -1 on error
1426
 */
1427
int libcdirectory_directory_has_entry_wide(
1428
     libcdirectory_directory_t *directory,
1429
     libcdirectory_directory_entry_t *directory_entry,
1430
     const wchar_t *entry_name,
1431
     size_t entry_name_length,
1432
     uint8_t entry_type,
1433
     uint8_t compare_flags,
1434
     libcerror_error_t **error )
1435
{
1436
  libcdirectory_directory_entry_t *search_directory_entry = NULL;
1437
  wchar_t *search_directory_entry_name                    = NULL;
1438
  static char *function                                   = "libcdirectory_directory_read_entry_wide";
1439
  size_t search_directory_entry_name_length               = 0;
1440
  uint8_t search_directory_entry_type                     = 0;
1441
  int entry_found                                         = 0;
1442
  int match                                               = 0;
1443
  int result                                              = 0;
1444
1445
  if( directory == NULL )
1446
  {
1447
    libcerror_error_set(
1448
     error,
1449
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1450
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1451
     "%s: invalid directory.",
1452
     function );
1453
1454
    return( -1 );
1455
  }
1456
  if( directory_entry == NULL )
1457
  {
1458
    libcerror_error_set(
1459
     error,
1460
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1461
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1462
     "%s: invalid directory entry.",
1463
     function );
1464
1465
    return( -1 );
1466
  }
1467
  if( entry_name == NULL )
1468
  {
1469
    libcerror_error_set(
1470
     error,
1471
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1472
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1473
     "%s: invalid entry name.",
1474
     function );
1475
1476
    return( -1 );
1477
  }
1478
  if( entry_name_length > (size_t) SSIZE_MAX )
1479
  {
1480
    libcerror_error_set(
1481
     error,
1482
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1483
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1484
     "%s: invalid entry name length value exceeds maximum.",
1485
     function );
1486
1487
    return( -1 );
1488
  }
1489
  if( ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_DEVICE )
1490
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_DIRECTORY )
1491
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_FILE )
1492
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_LINK )
1493
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_PIPE )
1494
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_SOCKET )
1495
   && ( entry_type != LIBCDIRECTORY_ENTRY_TYPE_UNDEFINED ) )
1496
  {
1497
    libcerror_error_set(
1498
     error,
1499
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1500
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1501
     "%s: unsupported entry type.",
1502
     function );
1503
1504
    return( -1 );
1505
  }
1506
  if( ( compare_flags & ~( LIBCDIRECTORY_COMPARE_FLAG_NO_CASE ) ) != 0 )
1507
  {
1508
    libcerror_error_set(
1509
     error,
1510
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1511
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1512
     "%s: unsupported compare flags.",
1513
     function );
1514
1515
    return( -1 );
1516
  }
1517
  if( libcdirectory_directory_entry_initialize(
1518
       &search_directory_entry,
1519
       error ) != 1 )
1520
  {
1521
    libcerror_error_set(
1522
     error,
1523
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1524
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1525
     "%s: unable to create search directory entry.",
1526
     function );
1527
1528
    goto on_error;
1529
  }
1530
  entry_found = 0;
1531
1532
  do
1533
  {
1534
    result = libcdirectory_directory_read_entry(
1535
        directory,
1536
        search_directory_entry,
1537
        error );
1538
1539
    if( result == -1 )
1540
    {
1541
      libcerror_error_set(
1542
       error,
1543
       LIBCERROR_ERROR_DOMAIN_IO,
1544
       LIBCERROR_IO_ERROR_READ_FAILED,
1545
       "%s: unable to read directory entry.",
1546
       function );
1547
1548
      goto on_error;
1549
    }
1550
    else if( result == 0 )
1551
    {
1552
      break;
1553
    }
1554
    if( libcdirectory_directory_entry_get_type(
1555
         search_directory_entry,
1556
         &search_directory_entry_type,
1557
         error ) != 1 )
1558
    {
1559
      libcerror_error_set(
1560
       error,
1561
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1562
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1563
       "%s: unable to retrieve directory entry type.",
1564
       function );
1565
1566
      goto on_error;
1567
    }
1568
    if( search_directory_entry_type == entry_type )
1569
    {
1570
      if( libcdirectory_directory_entry_get_name_wide(
1571
           search_directory_entry,
1572
           &search_directory_entry_name,
1573
           error ) != 1 )
1574
      {
1575
        libcerror_error_set(
1576
         error,
1577
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1578
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1579
         "%s: unable to retrieve directory entry name.",
1580
         function );
1581
1582
        goto on_error;
1583
      }
1584
      search_directory_entry_name_length = wide_string_length(
1585
                                            search_directory_entry_name );
1586
1587
      if( search_directory_entry_name_length == entry_name_length )
1588
      {
1589
        /* If there is an exact match we're done searching
1590
         */
1591
        match = wide_string_compare(
1592
           search_directory_entry_name,
1593
           entry_name,
1594
           entry_name_length );
1595
1596
        if( match == 0 )
1597
        {
1598
          if( libcdirectory_directory_entry_copy(
1599
               directory_entry,
1600
               search_directory_entry,
1601
               error ) != 1 )
1602
          {
1603
            libcerror_error_set(
1604
             error,
1605
             LIBCERROR_ERROR_DOMAIN_MEMORY,
1606
             LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1607
             "%s: unable to copy search directory entry.",
1608
             function );
1609
1610
            goto on_error;
1611
          }
1612
          entry_found = 1;
1613
1614
          break;
1615
        }
1616
        /* Ignore successive caseless matches
1617
         */
1618
        if( ( ( compare_flags & LIBCDIRECTORY_COMPARE_FLAG_NO_CASE ) != 0 )
1619
         && ( entry_found == 0 ) )
1620
        {
1621
          match = wide_string_compare_no_case(
1622
             search_directory_entry_name,
1623
             entry_name,
1624
             entry_name_length );
1625
1626
          if( match == 0 )
1627
          {
1628
            if( libcdirectory_directory_entry_copy(
1629
                 directory_entry,
1630
                 search_directory_entry,
1631
                 error ) != 1 )
1632
            {
1633
              libcerror_error_set(
1634
               error,
1635
               LIBCERROR_ERROR_DOMAIN_MEMORY,
1636
               LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1637
               "%s: unable to copy search directory entry.",
1638
               function );
1639
1640
              goto on_error;
1641
            }
1642
            entry_found = 1;
1643
          }
1644
        }
1645
      }
1646
    }
1647
  }
1648
  while( result != 0 );
1649
1650
  if( libcdirectory_directory_entry_free(
1651
       &search_directory_entry,
1652
       error ) != 1 )
1653
  {
1654
    libcerror_error_set(
1655
     error,
1656
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1657
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1658
     "%s: unable to free search directory entry.",
1659
     function );
1660
1661
    goto on_error;
1662
  }
1663
  return( entry_found );
1664
1665
on_error:
1666
  if( search_directory_entry != NULL )
1667
  {
1668
    libcdirectory_directory_entry_free(
1669
     &search_directory_entry,
1670
     NULL );
1671
  }
1672
  return( -1 );
1673
}
1674
1675
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
1676