Coverage Report

Created: 2026-07-10 07:32

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