Coverage Report

Created: 2026-05-24 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libqcow/libcpath/libcpath_path.c
Line
Count
Source
1
/*
2
 * Path 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 <types.h>
26
#include <wide_string.h>
27
28
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
29
#include <system_string.h>
30
#endif
31
32
#if defined( HAVE_ERRNO_H )
33
#include <errno.h>
34
#endif
35
36
#if defined( HAVE_SYS_STAT_H )
37
#include <sys/stat.h>
38
#endif
39
40
#if defined( HAVE_LIMITS_H ) || defined( WINAPI )
41
/* Include for PATH_MAX */
42
#include <limits.h>
43
#endif
44
45
#if defined( HAVE_UNISTD_H )
46
#include <unistd.h>
47
#endif
48
49
#include "libcpath_definitions.h"
50
#include "libcpath_libcerror.h"
51
#include "libcpath_libcsplit.h"
52
#include "libcpath_path.h"
53
#include "libcpath_system_string.h"
54
55
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
56
57
/* Cross Windows safe version of CloseHandle
58
 * Returns TRUE if successful or FALSE on error
59
 */
60
BOOL libcpath_CloseHandle(
61
      HANDLE file_handle )
62
{
63
  FARPROC function       = NULL;
64
  HMODULE library_handle = NULL;
65
  BOOL result            = FALSE;
66
67
  if( file_handle == NULL )
68
  {
69
    return( FALSE );
70
  }
71
  library_handle = LoadLibrary(
72
                    _SYSTEM_STRING( "kernel32.dll" ) );
73
74
  if( library_handle == NULL )
75
  {
76
    return( FALSE );
77
  }
78
  function = GetProcAddress(
79
        library_handle,
80
        (LPCSTR) "CloseHandle" );
81
82
  if( function != NULL )
83
  {
84
    result = function(
85
        file_handle );
86
  }
87
  /* This call should be after using the function
88
   * in most cases kernel32.dll will still be available after free
89
   */
90
  if( FreeLibrary(
91
       library_handle ) != TRUE )
92
  {
93
    result = FALSE;
94
  }
95
  return( result );
96
}
97
98
#endif /* defined( WINAPI ) && ( WINVER <= 0x0500 ) */
99
100
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
101
102
/* Cross Windows safe version of SetCurrentDirectoryA
103
 * Returns TRUE if successful or FALSE on error
104
 */
105
BOOL libcpath_SetCurrentDirectoryA(
106
      LPCSTR path )
107
{
108
  FARPROC function       = NULL;
109
  HMODULE library_handle = NULL;
110
  BOOL result            = FALSE;
111
112
  if( path == NULL )
113
  {
114
    return( FALSE );
115
  }
116
  library_handle = LoadLibrary(
117
                    _SYSTEM_STRING( "kernel32.dll" ) );
118
119
  if( library_handle == NULL )
120
  {
121
    return( FALSE );
122
  }
123
  function = GetProcAddress(
124
        library_handle,
125
        (LPCSTR) "SetCurrentDirectoryA" );
126
127
  if( function != NULL )
128
  {
129
    result = function(
130
        path );
131
  }
132
  /* This call should be after using the function
133
   * in most cases kernel32.dll will still be available after free
134
   */
135
  if( FreeLibrary(
136
       library_handle ) != TRUE )
137
  {
138
    libcpath_CloseHandle(
139
     library_handle );
140
141
    return( FALSE );
142
  }
143
  return( result );
144
}
145
146
#endif /* defined( WINAPI ) && ( WINVER <= 0x0500 ) */
147
148
#if defined( WINAPI )
149
150
/* Changes the directory
151
 * This function uses the WINAPI function for Windows XP (0x0501) or later
152
 * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
153
 * Returns 1 if successful or -1 on error
154
 */
155
int libcpath_path_change_directory(
156
     const char *directory_name,
157
     libcerror_error_t **error )
158
{
159
  static char *function = "libcpath_path_change_directory";
160
  DWORD error_code      = 0;
161
162
  if( directory_name == NULL )
163
  {
164
    libcerror_error_set(
165
     error,
166
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
167
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
168
     "%s: invalid directory name.",
169
     function );
170
171
    return( -1 );
172
  }
173
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
174
  if( libcpath_SetCurrentDirectoryA(
175
       directory_name ) == 0 )
176
#else
177
  if( SetCurrentDirectoryA(
178
       directory_name ) == 0 )
179
#endif
180
  {
181
    error_code = GetLastError();
182
183
    libcerror_system_set_error(
184
     error,
185
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
186
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
187
     error_code,
188
     "%s: unable to change directory.",
189
     function );
190
191
    return( -1 );
192
  }
193
  return( 1 );
194
}
195
196
#elif defined( HAVE_CHDIR )
197
198
/* Changes the directory
199
 * This function uses the POSIX chdir function or equivalent
200
 * Returns 1 if successful or -1 on error
201
 */
202
int libcpath_path_change_directory(
203
     const char *directory_name,
204
     libcerror_error_t **error )
205
0
{
206
0
  static char *function = "libcpath_path_change_directory";
207
208
0
  if( directory_name == NULL )
209
0
  {
210
0
    libcerror_error_set(
211
0
     error,
212
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
213
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
214
0
     "%s: invalid directory name.",
215
0
     function );
216
217
0
    return( -1 );
218
0
  }
219
0
  if( chdir(
220
0
       directory_name ) != 0 )
221
0
  {
222
0
    libcerror_system_set_error(
223
0
     error,
224
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
225
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
226
0
     errno,
227
0
     "%s: unable to change directory.",
228
0
     function );
229
230
0
    return( -1 );
231
0
  }
232
0
  return( 1 );
233
0
}
234
235
#else
236
#error Missing change directory function
237
#endif
238
239
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
240
241
/* Cross Windows safe version of GetCurrentDirectoryA
242
 * Returns the number of characters in the current directory string or 0 on error
243
 */
244
DWORD libcpath_GetCurrentDirectoryA(
245
       DWORD buffer_size,
246
       LPCSTR buffer )
247
{
248
  FARPROC function       = NULL;
249
  HMODULE library_handle = NULL;
250
  DWORD result           = 0;
251
252
  library_handle = LoadLibrary(
253
                    _SYSTEM_STRING( "kernel32.dll" ) );
254
255
  if( library_handle == NULL )
256
  {
257
    return( 0 );
258
  }
259
  function = GetProcAddress(
260
        library_handle,
261
        (LPCSTR) "GetCurrentDirectoryA" );
262
263
  if( function != NULL )
264
  {
265
    result = function(
266
        buffer_size,
267
        buffer );
268
  }
269
  /* This call should be after using the function
270
   * in most cases kernel32.dll will still be available after free
271
   */
272
  if( FreeLibrary(
273
       library_handle ) != TRUE )
274
  {
275
    libcpath_CloseHandle(
276
     library_handle );
277
278
    return( 0 );
279
  }
280
  return( result );
281
}
282
283
#endif /* defined( WINAPI ) && ( WINVER <= 0x0500 ) */
284
285
#if defined( WINAPI )
286
287
/* Retrieves the current working directory
288
 * This function uses the WINAPI function for Windows XP (0x0501) or later
289
 * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
290
 * Returns 1 if successful or -1 on error
291
 */
292
int libcpath_path_get_current_working_directory(
293
     char **current_working_directory,
294
     size_t *current_working_directory_size,
295
     libcerror_error_t **error )
296
{
297
  static char *function                     = "libcpath_path_get_current_working_directory";
298
  DWORD safe_current_working_directory_size = 0;
299
  DWORD error_code                          = 0;
300
301
  if( current_working_directory == NULL )
302
  {
303
    libcerror_error_set(
304
     error,
305
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
306
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
307
     "%s: invalid current working directory.",
308
     function );
309
310
    return( -1 );
311
  }
312
  if( *current_working_directory != NULL )
313
  {
314
    libcerror_error_set(
315
     error,
316
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
317
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
318
     "%s: invalid current working directory value already set.",
319
     function );
320
321
    return( -1 );
322
  }
323
  if( current_working_directory_size == NULL )
324
  {
325
    libcerror_error_set(
326
     error,
327
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
328
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
329
     "%s: invalid current working directory size.",
330
     function );
331
332
    return( -1 );
333
  }
334
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
335
  safe_current_working_directory_size = libcpath_GetCurrentDirectoryA(
336
                                         0,
337
                                         NULL );
338
#else
339
  safe_current_working_directory_size = GetCurrentDirectoryA(
340
                                         0,
341
                                         NULL );
342
#endif
343
  if( safe_current_working_directory_size == 0 )
344
  {
345
    libcerror_error_set(
346
     error,
347
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
348
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
349
     "%s: unable to retrieve current working directory size.",
350
     function );
351
352
    goto on_error;
353
  }
354
  if( (size_t) safe_current_working_directory_size > (size_t) SSIZE_MAX )
355
  {
356
    libcerror_error_set(
357
     error,
358
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
359
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
360
     "%s: current working directory size value out of bounds.",
361
     function );
362
363
    goto on_error;
364
  }
365
  *current_working_directory_size = (size_t) safe_current_working_directory_size;
366
367
  *current_working_directory = narrow_string_allocate(
368
                                *current_working_directory_size );
369
370
  if( *current_working_directory == NULL )
371
  {
372
    libcerror_error_set(
373
     error,
374
     LIBCERROR_ERROR_DOMAIN_MEMORY,
375
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
376
     "%s: unable to create current working directory.",
377
     function );
378
379
    goto on_error;
380
  }
381
  if( memory_set(
382
       *current_working_directory,
383
       0,
384
       sizeof( char ) * *current_working_directory_size ) == NULL )
385
  {
386
    libcerror_error_set(
387
     error,
388
     LIBCERROR_ERROR_DOMAIN_MEMORY,
389
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
390
     "%s: unable to clear current working directory.",
391
     function );
392
393
    goto on_error;
394
  }
395
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
396
  if( libcpath_GetCurrentDirectoryA(
397
       safe_current_working_directory_size,
398
       *current_working_directory ) != ( safe_current_working_directory_size - 1 ) )
399
#else
400
  if( GetCurrentDirectoryA(
401
       safe_current_working_directory_size,
402
       *current_working_directory ) != ( safe_current_working_directory_size - 1 ) )
403
#endif
404
  {
405
    error_code = GetLastError();
406
407
    libcerror_system_set_error(
408
     error,
409
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
410
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
411
     error_code,
412
     "%s: unable to retrieve current working directory.",
413
     function );
414
415
    goto on_error;
416
  }
417
  return( 1 );
418
419
on_error:
420
  if( *current_working_directory != NULL )
421
  {
422
    memory_free(
423
     *current_working_directory );
424
425
    *current_working_directory = NULL;
426
  }
427
  *current_working_directory_size = 0;
428
429
  return( -1 );
430
}
431
432
#elif defined( HAVE_GETCWD )
433
434
/* Retrieves the current working directory
435
 * This function uses the POSIX getcwd function or equivalent
436
 * Returns 1 if successful or -1 on error
437
 */
438
int libcpath_path_get_current_working_directory(
439
     char **current_working_directory,
440
     size_t *current_working_directory_size,
441
     libcerror_error_t **error )
442
0
{
443
0
  static char *function = "libcpath_path_get_current_working_directory";
444
445
0
  if( current_working_directory == NULL )
446
0
  {
447
0
    libcerror_error_set(
448
0
     error,
449
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
450
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
451
0
     "%s: invalid current working directory.",
452
0
     function );
453
454
0
    return( -1 );
455
0
  }
456
0
  if( *current_working_directory != NULL )
457
0
  {
458
0
    libcerror_error_set(
459
0
     error,
460
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
461
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
462
0
     "%s: invalid current working directory value already set.",
463
0
     function );
464
465
0
    return( -1 );
466
0
  }
467
0
  if( current_working_directory_size == NULL )
468
0
  {
469
0
    libcerror_error_set(
470
0
     error,
471
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
472
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
473
0
     "%s: invalid current working directory size.",
474
0
     function );
475
476
0
    return( -1 );
477
0
  }
478
0
  *current_working_directory_size = (size_t) PATH_MAX;
479
480
0
  *current_working_directory = narrow_string_allocate(
481
0
                                *current_working_directory_size );
482
483
0
  if( *current_working_directory == NULL )
484
0
  {
485
0
    libcerror_error_set(
486
0
     error,
487
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
488
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
489
0
     "%s: unable to create current working directory.",
490
0
     function );
491
492
0
    goto on_error;
493
0
  }
494
0
  if( memory_set(
495
0
       *current_working_directory,
496
0
       0,
497
0
       sizeof( char ) * *current_working_directory_size ) == NULL )
498
0
  {
499
0
    libcerror_error_set(
500
0
     error,
501
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
502
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
503
0
     "%s: unable to clear current working directory.",
504
0
     function );
505
506
0
    goto on_error;
507
0
  }
508
0
  if( getcwd(
509
0
       *current_working_directory,
510
0
       *current_working_directory_size ) == NULL )
511
0
  {
512
0
    libcerror_system_set_error(
513
0
     error,
514
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
515
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
516
0
     errno,
517
0
     "%s: unable to retrieve current working directory.",
518
0
     function );
519
520
0
    goto on_error;
521
0
  }
522
0
  return( 1 );
523
524
0
on_error:
525
0
  if( *current_working_directory != NULL )
526
0
  {
527
0
    memory_free(
528
0
     *current_working_directory );
529
530
0
    *current_working_directory = NULL;
531
0
  }
532
0
  *current_working_directory_size = 0;
533
534
0
  return( -1 );
535
0
}
536
537
#else
538
#error Missing get current working directory function
539
#endif
540
541
#if defined( WINAPI )
542
543
/* Determines the path type
544
 * Returns 1 if succesful or -1 on error
545
 */
546
int libcpath_path_get_path_type(
547
     const char *path,
548
     size_t path_length,
549
     uint8_t *path_type,
550
     libcerror_error_t **error )
551
{
552
  static char *function = "libcpath_path_get_path_type";
553
554
  if( path == NULL )
555
  {
556
    libcerror_error_set(
557
     error,
558
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
559
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
560
     "%s: invalid path.",
561
     function );
562
563
    return( -1 );
564
  }
565
  if( path_length == 0 )
566
  {
567
    libcerror_error_set(
568
     error,
569
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
570
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
571
     "%s: invalid path length is zero.",
572
     function );
573
574
    return( -1 );
575
  }
576
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
577
  {
578
    libcerror_error_set(
579
     error,
580
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
581
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
582
     "%s: invalid path length value exceeds maximum.",
583
     function );
584
585
    return( -1 );
586
  }
587
  if( path_type == NULL )
588
  {
589
    libcerror_error_set(
590
     error,
591
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
592
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
593
     "%s: invalid path type.",
594
     function );
595
596
    return( -1 );
597
  }
598
  *path_type = LIBCPATH_TYPE_RELATIVE;
599
600
  /* Determine if the path is a special path
601
   * device path prefix:          \\.\
602
   * extended-length path prefix: \\?\
603
   */
604
  if( ( path_length >= 4 )
605
   && ( path[ 0 ] == '\\' )
606
   && ( path[ 1 ] == '\\' )
607
   && ( ( path[ 2 ] == '.' )
608
    ||  ( path[ 2 ] == '?' ) )
609
   && ( path[ 3 ] == '\\' ) )
610
  {
611
    if( path[ 2 ] == '.' )
612
    {
613
      *path_type = LIBCPATH_TYPE_DEVICE;
614
    }
615
    /* Determine if the path in an extended-length UNC path
616
     * \\?\UNC\server\share
617
     */
618
    else if( ( path_length >= 8 )
619
          && ( path[ 4 ] == 'U' )
620
          && ( path[ 5 ] == 'N' )
621
          && ( path[ 6 ] == 'C' )
622
          && ( path[ 7 ] == '\\' ) )
623
    {
624
      *path_type = LIBCPATH_TYPE_EXTENDED_LENGTH_UNC;
625
    }
626
    else
627
    {
628
      *path_type = LIBCPATH_TYPE_EXTENDED_LENGTH;
629
    }
630
  }
631
  /* Determine if the path is an UNC path
632
   * \\server\share
633
   */
634
  else if( ( path_length >= 2 )
635
        && ( path[ 0 ] == '\\' )
636
        && ( path[ 1 ] == '\\' ) )
637
  {
638
    *path_type = LIBCPATH_TYPE_UNC;
639
  }
640
  else if( path[ 0 ] == '\\' )
641
  {
642
    *path_type = LIBCPATH_TYPE_ABSOLUTE;
643
  }
644
  else if( ( path_length >= 3 )
645
        && ( path[ 1 ] == ':' )
646
        && ( path[ 2 ] == '\\' )
647
        && ( ( ( path[ 0 ] >= 'A' )
648
          &&   ( path[ 0 ] <= 'Z' ) )
649
         ||  ( ( path[ 0 ] >= 'a' )
650
          &&   ( path[ 0 ] <= 'z' ) ) ) )
651
  {
652
    *path_type = LIBCPATH_TYPE_ABSOLUTE;
653
  }
654
  return( 1 );
655
}
656
657
/* Determines the volume name
658
 * Returns 1 if succesful or -1 on error
659
 */
660
int libcpath_path_get_volume_name(
661
     const char *path,
662
     size_t path_length,
663
     char **volume_name,
664
     size_t *volume_name_length,
665
     size_t *directory_name_index,
666
     libcerror_error_t **error )
667
{
668
  static char *function    = "libcpath_path_get_volume_name";
669
  size_t path_index        = 0;
670
  size_t share_name_index  = 0;
671
  size_t volume_name_index = 0;
672
673
  if( path == NULL )
674
  {
675
    libcerror_error_set(
676
     error,
677
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
678
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
679
     "%s: invalid path.",
680
     function );
681
682
    return( -1 );
683
  }
684
  if( path_length == 0 )
685
  {
686
    libcerror_error_set(
687
     error,
688
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
689
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
690
     "%s: invalid path length is zero.",
691
     function );
692
693
    return( -1 );
694
  }
695
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
696
  {
697
    libcerror_error_set(
698
     error,
699
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
700
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
701
     "%s: invalid path length value exceeds maximum.",
702
     function );
703
704
    return( -1 );
705
  }
706
  if( volume_name == NULL )
707
  {
708
    libcerror_error_set(
709
     error,
710
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
711
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
712
     "%s: invalid volume name.",
713
     function );
714
715
    return( -1 );
716
  }
717
  if( volume_name_length == NULL )
718
  {
719
    libcerror_error_set(
720
     error,
721
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
722
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
723
     "%s: invalid volume name length.",
724
     function );
725
726
    return( -1 );
727
  }
728
  if( directory_name_index == NULL )
729
  {
730
    libcerror_error_set(
731
     error,
732
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
733
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
734
     "%s: invalid directory name index.",
735
     function );
736
737
    return( -1 );
738
  }
739
  *volume_name          = NULL;
740
  *volume_name_length   = 0;
741
  *directory_name_index = 0;
742
743
  /* Determine if the path is a special path
744
   * device path prefix:          \\.\
745
   * extended-length path prefix: \\?\
746
   */
747
  if( ( path_length >= 4 )
748
   && ( path[ 0 ] == '\\' )
749
   && ( path[ 1 ] == '\\' )
750
   && ( ( path[ 2 ] == '.' )
751
    ||  ( path[ 2 ] == '?' ) )
752
   && ( path[ 3 ] == '\\' ) )
753
  {
754
    if( path[ 2 ] == '.' )
755
    {
756
      volume_name_index = 4;
757
    }
758
    /* Determine if the path in an extended-length UNC path
759
     * \\?\UNC\server\share
760
     */
761
    else if( ( path_length >= 8 )
762
          && ( path[ 4 ] == 'U' )
763
          && ( path[ 5 ] == 'N' )
764
          && ( path[ 6 ] == 'C' )
765
          && ( path[ 7 ] == '\\' ) )
766
    {
767
      volume_name_index = 8;
768
    }
769
    else
770
    {
771
      volume_name_index = 4;
772
    }
773
  }
774
  /* Determine if the path is an UNC path
775
   * \\server\share
776
   */
777
  else if( ( path_length >= 2 )
778
        && ( path[ 0 ] == '\\' )
779
        && ( path[ 1 ] == '\\' ) )
780
  {
781
    volume_name_index = 2;
782
  }
783
  /* Check if the path contains a volume letter
784
   */
785
  if( ( path_length >= 2 )
786
   && ( volume_name_index <= ( path_length - 2 ) )
787
   && ( path[ volume_name_index + 1 ] == ':' )
788
   && ( ( ( path[ volume_name_index ] >= 'A' )
789
     &&   ( path[ volume_name_index ] <= 'Z' ) )
790
    ||  ( ( path[ volume_name_index ] >= 'a' )
791
     &&   ( path[ volume_name_index ] <= 'z' ) ) ) )
792
  {
793
    path_index = volume_name_index + 2;
794
795
    if( ( path_index < path_length )
796
     && ( path[ path_index ] == '\\' ) )
797
    {
798
      path_index++;
799
    }
800
    *volume_name        = (char *) &( path[ volume_name_index ] );
801
    *volume_name_length = path_index - volume_name_index;
802
803
    if( path[ path_index - 1 ] == '\\' )
804
    {
805
      *volume_name_length -= 1;
806
    }
807
    *directory_name_index = path_index;
808
  }
809
  else if( volume_name_index == 4 )
810
  {
811
    for( path_index = volume_name_index;
812
         path_index < path_length;
813
         path_index++ )
814
    {
815
      if( path[ path_index ] == '\\' )
816
      {
817
        path_index++;
818
819
        break;
820
      }
821
    }
822
    *volume_name        = (char *) &( path[ 4 ] );
823
    *volume_name_length = path_index - 4;
824
825
    if( path[ path_index - 1 ] == '\\' )
826
    {
827
      *volume_name_length -= 1;
828
    }
829
    *directory_name_index = path_index;
830
  }
831
  else if( ( volume_name_index == 2 )
832
        || ( volume_name_index == 8 ) )
833
  {
834
    for( share_name_index = volume_name_index;
835
         share_name_index < path_length;
836
         share_name_index++ )
837
    {
838
      if( path[ share_name_index ] == '\\' )
839
      {
840
        share_name_index++;
841
842
        break;
843
      }
844
    }
845
    if( share_name_index > path_length )
846
    {
847
      libcerror_error_set(
848
       error,
849
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
850
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
851
       "%s: invalid path - missing share name.",
852
       function );
853
854
      return( -1 );
855
    }
856
    for( path_index = share_name_index;
857
         path_index < path_length;
858
         path_index++ )
859
    {
860
      if( path[ path_index ] == '\\' )
861
      {
862
        path_index++;
863
864
        break;
865
      }
866
    }
867
    *volume_name        = (char *) &( path[ volume_name_index ] );
868
    *volume_name_length = path_index - volume_name_index;
869
870
    if( path[ path_index - 1 ] == '\\' )
871
    {
872
      *volume_name_length -= 1;
873
    }
874
    *directory_name_index = path_index;
875
  }
876
  return( 1 );
877
}
878
879
/* Retrieves the current working directory of a specific volume
880
 * Returns 1 if successful or -1 on error
881
 */
882
int libcpath_path_get_current_working_directory_by_volume(
883
     char *volume_name,
884
     size_t volume_name_length,
885
     char **current_working_directory,
886
     size_t *current_working_directory_size,
887
     libcerror_error_t **error )
888
{
889
  char *change_volume_name                     = NULL;
890
  char *current_volume_working_directory       = NULL;
891
  static char *function                        = "libcpath_path_get_current_working_directory_by_volume";
892
  size_t current_volume_working_directory_size = 0;
893
  int result                                   = 1;
894
895
  if( current_working_directory == NULL )
896
  {
897
    libcerror_error_set(
898
     error,
899
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
900
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
901
     "%s: invalid current working directory.",
902
     function );
903
904
    return( -1 );
905
  }
906
  if( current_working_directory_size == NULL )
907
  {
908
    libcerror_error_set(
909
     error,
910
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
911
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
912
     "%s: invalid current working directory size.",
913
     function );
914
915
    return( -1 );
916
  }
917
  /* If the path contains a volume name switch to that
918
   * volume to determine the current directory
919
   */
920
  if( volume_name != NULL )
921
  {
922
    if( volume_name_length > (size_t) ( SSIZE_MAX - 1 ) )
923
    {
924
      libcerror_error_set(
925
       error,
926
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
927
       LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
928
       "%s: invalid volume name length value exceeds maximum.",
929
       function );
930
931
      goto on_error;
932
    }
933
    if( libcpath_path_get_current_working_directory(
934
         &current_volume_working_directory,
935
         &current_volume_working_directory_size,
936
         error ) != 1 )
937
    {
938
      libcerror_error_set(
939
       error,
940
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
941
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
942
       "%s: unable to retrieve current volume working directory.",
943
       function );
944
945
      goto on_error;
946
    }
947
    change_volume_name = narrow_string_allocate(
948
                          volume_name_length + 1 );
949
950
    if( change_volume_name == NULL )
951
    {
952
      libcerror_error_set(
953
       error,
954
       LIBCERROR_ERROR_DOMAIN_MEMORY,
955
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
956
       "%s: unable to create change volume name.",
957
       function );
958
959
      goto on_error;
960
    }
961
    if( narrow_string_copy(
962
         change_volume_name,
963
         volume_name,
964
         volume_name_length ) == NULL )
965
    {
966
      libcerror_error_set(
967
       error,
968
       LIBCERROR_ERROR_DOMAIN_MEMORY,
969
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
970
       "%s: unable to set change volume name.",
971
       function );
972
973
      goto on_error;
974
    }
975
    change_volume_name[ volume_name_length ] = 0;
976
977
    if( libcpath_path_change_directory(
978
         change_volume_name,
979
         error ) != 1 )
980
    {
981
      libcerror_error_set(
982
       error,
983
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
984
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
985
       "%s: unable to change current working directory.",
986
       function );
987
988
      goto on_error;
989
    }
990
    memory_free(
991
     change_volume_name );
992
993
    change_volume_name = NULL;
994
  }
995
  if( libcpath_path_get_current_working_directory(
996
       current_working_directory,
997
       current_working_directory_size,
998
       error ) != 1 )
999
  {
1000
    libcerror_error_set(
1001
     error,
1002
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1003
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1004
     "%s: unable to retrieve current directory.",
1005
     function );
1006
1007
    /* Make sure the current working directory has been changed
1008
     * back to its original value
1009
     */
1010
    result = -1;
1011
  }
1012
  if( current_volume_working_directory != NULL )
1013
  {
1014
    if( libcpath_path_change_directory(
1015
         current_volume_working_directory,
1016
         error ) != 1 )
1017
    {
1018
      libcerror_error_set(
1019
       error,
1020
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1021
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1022
       "%s: unable to change current working directory.",
1023
       function );
1024
1025
      goto on_error;
1026
    }
1027
    memory_free(
1028
     current_volume_working_directory );
1029
1030
    current_volume_working_directory = NULL;
1031
  }
1032
  return( result );
1033
1034
on_error:
1035
  if( change_volume_name != NULL )
1036
  {
1037
    memory_free(
1038
     change_volume_name );
1039
  }
1040
  if( current_volume_working_directory != NULL )
1041
  {
1042
    memory_free(
1043
     current_volume_working_directory );
1044
  }
1045
  if( *current_working_directory != NULL )
1046
  {
1047
    memory_free(
1048
     *current_working_directory );
1049
1050
    *current_working_directory = NULL;
1051
  }
1052
  *current_working_directory_size = 0;
1053
1054
  return( -1 );
1055
}
1056
1057
/* Determines the full path of the Windows path specified
1058
 * The function uses the extended-length path format
1059
 * (path with \\?\ prefix)
1060
 *
1061
 * Multiple successive \ not at the start of the path are combined into one
1062
 *
1063
 * Scenario's that are considered full paths:
1064
 * Device path:     \\.\PhysicalDrive0
1065
 * Extended-length path:  \\?\C:\directory\file.txt
1066
 * Extended-length UNC path:  \\?\UNC\server\share\directory\file.txt
1067
 *
1068
 * Scenario's that are not considered full paths:
1069
 * Local 'absolute' path: \directory\file.txt
1070
 *                        \directory\\file.txt
1071
 * Local 'relative' path: ..\directory\file.txt
1072
 * Local 'relative' path: .\directory\file.txt
1073
 * Volume 'absolute' path:  C:\directory\file.txt
1074
 *                              C:\..\directory\file.txt
1075
 * Volume 'relative' path:  C:directory\file.txt
1076
 * UNC path:      \\server\share\directory\file.txt
1077
 *
1078
 * TODO handle:
1079
 * Volume device path:    \\.\C:
1080
 * Volume file system path: \\.\C:\
1081
 *
1082
 * Returns 1 if succesful or -1 on error
1083
 */
1084
int libcpath_path_get_full_path(
1085
     const char *path,
1086
     size_t path_length,
1087
     char **full_path,
1088
     size_t *full_path_size,
1089
     libcerror_error_t **error )
1090
{
1091
  libcsplit_narrow_split_string_t *current_directory_split_string = NULL;
1092
  libcsplit_narrow_split_string_t *path_split_string              = NULL;
1093
  char *current_directory                                         = NULL;
1094
  char *current_directory_string_segment                          = NULL;
1095
  char *full_path_prefix                                          = NULL;
1096
  char *last_used_path_string_segment                             = NULL;
1097
  char *path_string_segment                                       = NULL;
1098
  char *volume_name                                               = NULL;
1099
  static char *function                                           = "libcpath_path_get_full_path";
1100
  size_t current_directory_length                                 = 0;
1101
  size_t current_directory_name_index                             = 0;
1102
  size_t current_directory_size                                   = 0;
1103
  size_t current_directory_string_segment_size                    = 0;
1104
  size_t full_path_index                                          = 0;
1105
  size_t full_path_prefix_length                                  = 0;
1106
  size_t last_used_path_string_segment_size                       = 0;
1107
  size_t path_directory_name_index                                = 0;
1108
  size_t path_string_segment_size                                 = 0;
1109
  size_t safe_full_path_size                                      = 0;
1110
  size_t volume_name_length                                       = 0;
1111
  uint8_t path_type                                               = LIBCPATH_TYPE_RELATIVE;
1112
  int current_directory_number_of_segments                        = 0;
1113
  int current_directory_segment_index                             = 0;
1114
  int last_used_path_segment_index                                = -1;
1115
  int path_number_of_segments                                     = 0;
1116
  int path_segment_index                                          = 0;
1117
1118
  if( path == NULL )
1119
  {
1120
    libcerror_error_set(
1121
     error,
1122
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1123
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1124
     "%s: invalid path.",
1125
     function );
1126
1127
    return( -1 );
1128
  }
1129
  if( path_length == 0 )
1130
  {
1131
    libcerror_error_set(
1132
     error,
1133
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1134
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
1135
     "%s: invalid path length is zero.",
1136
     function );
1137
1138
    return( -1 );
1139
  }
1140
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
1141
  {
1142
    libcerror_error_set(
1143
     error,
1144
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1145
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1146
     "%s: invalid path length value exceeds maximum.",
1147
     function );
1148
1149
    return( -1 );
1150
  }
1151
  if( full_path == NULL )
1152
  {
1153
    libcerror_error_set(
1154
     error,
1155
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1156
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1157
     "%s: invalid full path.",
1158
     function );
1159
1160
    return( -1 );
1161
  }
1162
  if( *full_path != NULL )
1163
  {
1164
    libcerror_error_set(
1165
     error,
1166
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1167
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1168
     "%s: invalid full path value already set.",
1169
     function );
1170
1171
    return( -1 );
1172
  }
1173
  if( full_path_size == NULL )
1174
  {
1175
    libcerror_error_set(
1176
     error,
1177
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1178
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1179
     "%s: invalid full path size.",
1180
     function );
1181
1182
    return( -1 );
1183
  }
1184
  if( libcpath_path_get_path_type(
1185
       path,
1186
       path_length,
1187
       &path_type,
1188
       error ) != 1 )
1189
  {
1190
    libcerror_error_set(
1191
     error,
1192
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1193
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1194
     "%s: unable to determine path type.",
1195
     function );
1196
1197
    goto on_error;
1198
  }
1199
  if( libcpath_path_get_volume_name(
1200
       path,
1201
       path_length,
1202
       &volume_name,
1203
       &volume_name_length,
1204
       &path_directory_name_index,
1205
       error ) != 1 )
1206
  {
1207
    libcerror_error_set(
1208
     error,
1209
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1210
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1211
     "%s: unable to determine volume name.",
1212
     function );
1213
1214
    goto on_error;
1215
  }
1216
  /* If the path is a device path, an extended-length path or an UNC
1217
   * do not bother to lookup the current working directory
1218
   */
1219
  if( ( path_type != LIBCPATH_TYPE_DEVICE )
1220
   && ( path_type != LIBCPATH_TYPE_EXTENDED_LENGTH )
1221
   && ( path_type != LIBCPATH_TYPE_EXTENDED_LENGTH_UNC )
1222
   && ( path_type != LIBCPATH_TYPE_UNC ) )
1223
  {
1224
    if( libcpath_path_get_current_working_directory_by_volume(
1225
         volume_name,
1226
         volume_name_length,
1227
         &current_directory,
1228
         &current_directory_size,
1229
         error ) != 1 )
1230
    {
1231
      libcerror_error_set(
1232
       error,
1233
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1234
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1235
       "%s: unable to retrieve current working directory by volume.",
1236
       function );
1237
1238
      goto on_error;
1239
    }
1240
    /* Determine the volume name using the current working directory if necessary
1241
     */
1242
    if( libcpath_path_get_volume_name(
1243
         current_directory,
1244
         current_directory_size - 1,
1245
         &volume_name,
1246
         &volume_name_length,
1247
         &current_directory_name_index,
1248
         error ) != 1 )
1249
    {
1250
      libcerror_error_set(
1251
       error,
1252
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1253
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1254
       "%s: unable to determine volume name from current working directory.",
1255
       function );
1256
1257
      goto on_error;
1258
    }
1259
  }
1260
  if( ( current_directory != NULL )
1261
   && ( current_directory_name_index < current_directory_size ) )
1262
  {
1263
    current_directory_length = narrow_string_length(
1264
                                &( current_directory[ current_directory_name_index ] ) );
1265
1266
    if( libcsplit_narrow_string_split(
1267
         &( current_directory[ current_directory_name_index ] ),
1268
         current_directory_length + 1,
1269
         '\\',
1270
         &current_directory_split_string,
1271
         error ) != 1 )
1272
    {
1273
      libcerror_error_set(
1274
       error,
1275
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1276
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1277
       "%s: unable to split current working directory.",
1278
       function );
1279
1280
      goto on_error;
1281
    }
1282
  }
1283
  if( libcsplit_narrow_string_split(
1284
       &( path[ path_directory_name_index ] ),
1285
       path_length - path_directory_name_index + 1,
1286
       '\\',
1287
       &path_split_string,
1288
       error ) != 1 )
1289
  {
1290
    libcerror_error_set(
1291
     error,
1292
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1293
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1294
     "%s: unable to split path.",
1295
     function );
1296
1297
    goto on_error;
1298
  }
1299
  /* The full path prefix consists of "\\?\" or "\\.\"
1300
   */
1301
  full_path_prefix_length = 4;
1302
1303
  if( volume_name != NULL )
1304
  {
1305
    /* Add the volume name and a directory separator
1306
     */
1307
    full_path_prefix_length += volume_name_length + 1;
1308
  }
1309
  if( ( path_type == LIBCPATH_TYPE_EXTENDED_LENGTH_UNC )
1310
   || ( path_type == LIBCPATH_TYPE_UNC ) )
1311
  {
1312
    /* Add the UNC\ prefix
1313
     */
1314
    full_path_prefix_length += 4;
1315
  }
1316
  safe_full_path_size = 0;
1317
1318
  /* If the path is relative
1319
   * add the size of the current working directory
1320
   * a directory separator, if necessary
1321
   */
1322
  if( ( path_type == LIBCPATH_TYPE_RELATIVE )
1323
   && ( current_directory_name_index < current_directory_size ) )
1324
  {
1325
    safe_full_path_size += ( current_directory_size - ( current_directory_name_index + 1 ) );
1326
1327
    if( ( current_directory_size >= 2 )
1328
     && ( current_directory[ current_directory_size - 2 ] != '\\' ) )
1329
    {
1330
      safe_full_path_size += 1;
1331
    }
1332
  }
1333
  if( current_directory_split_string != NULL )
1334
  {
1335
    if( libcsplit_narrow_split_string_get_number_of_segments(
1336
         current_directory_split_string,
1337
         &current_directory_number_of_segments,
1338
         error ) != 1 )
1339
    {
1340
      libcerror_error_set(
1341
       error,
1342
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1343
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1344
       "%s: unable to retrieve number of current working directory string segments.",
1345
       function );
1346
1347
      goto on_error;
1348
    }
1349
    current_directory_segment_index = current_directory_number_of_segments - 1;
1350
  }
1351
  if( path_split_string != NULL )
1352
  {
1353
    if( libcsplit_narrow_split_string_get_number_of_segments(
1354
         path_split_string,
1355
         &path_number_of_segments,
1356
         error ) != 1 )
1357
    {
1358
      libcerror_error_set(
1359
       error,
1360
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1361
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1362
       "%s: unable to retrieve number of path string segments.",
1363
       function );
1364
1365
      goto on_error;
1366
    }
1367
    for( path_segment_index = 0;
1368
         path_segment_index < path_number_of_segments;
1369
         path_segment_index++ )
1370
    {
1371
      if( libcsplit_narrow_split_string_get_segment_by_index(
1372
           path_split_string,
1373
           path_segment_index,
1374
           &path_string_segment,
1375
           &path_string_segment_size,
1376
           error ) != 1 )
1377
      {
1378
        libcerror_error_set(
1379
         error,
1380
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1381
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1382
         "%s: unable to retrieve path string segment: %d.",
1383
         function,
1384
         path_segment_index );
1385
1386
        goto on_error;
1387
      }
1388
      if( path_string_segment == NULL )
1389
      {
1390
        libcerror_error_set(
1391
         error,
1392
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1393
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1394
         "%s: missing path string segment: %d.",
1395
         function,
1396
         path_segment_index );
1397
1398
        goto on_error;
1399
      }
1400
      /* If the path is .. reverse the current path by one directory
1401
       */
1402
      if( ( path_string_segment_size == 3 )
1403
       && ( path_string_segment[ 0 ] == '.' )
1404
       && ( path_string_segment[ 1 ] == '.' ) )
1405
      {
1406
        if( ( current_directory_split_string != NULL )
1407
         && ( last_used_path_segment_index == -1 ) )
1408
        {
1409
          if( libcsplit_narrow_split_string_get_segment_by_index(
1410
               current_directory_split_string,
1411
               current_directory_segment_index,
1412
               &current_directory_string_segment,
1413
               &current_directory_string_segment_size,
1414
               error ) != 1 )
1415
          {
1416
            libcerror_error_set(
1417
             error,
1418
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1419
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1420
             "%s: unable to retrieve current working directory string segment: %d.",
1421
             function,
1422
             current_directory_segment_index );
1423
1424
            goto on_error;
1425
          }
1426
          if( current_directory_string_segment == NULL )
1427
          {
1428
            libcerror_error_set(
1429
             error,
1430
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1431
             LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1432
             "%s: missing current working directory string segment: %d.",
1433
             function,
1434
             current_directory_segment_index );
1435
1436
            goto on_error;
1437
          }
1438
          /* Remove the size of the parent directory name and a directory separator
1439
           * Note that the size includes the end of string character
1440
           */
1441
          if( current_directory_string_segment_size < safe_full_path_size )
1442
          {
1443
            safe_full_path_size -= current_directory_string_segment_size;
1444
          }
1445
          else
1446
          {
1447
            safe_full_path_size = 0;
1448
          }
1449
          if( libcsplit_narrow_split_string_set_segment_by_index(
1450
               current_directory_split_string,
1451
               current_directory_segment_index,
1452
               NULL,
1453
               0,
1454
               error ) != 1 )
1455
          {
1456
            libcerror_error_set(
1457
             error,
1458
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1459
             LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1460
             "%s: unable to set current working directory string segment: %d.",
1461
             function,
1462
             current_directory_segment_index );
1463
1464
            goto on_error;
1465
          }
1466
          current_directory_segment_index--;
1467
        }
1468
        else if( last_used_path_segment_index >= 0 )
1469
        {
1470
          if( libcsplit_narrow_split_string_get_segment_by_index(
1471
               path_split_string,
1472
               last_used_path_segment_index,
1473
               &last_used_path_string_segment,
1474
               &last_used_path_string_segment_size,
1475
               error ) != 1 )
1476
          {
1477
            libcerror_error_set(
1478
             error,
1479
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1480
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1481
             "%s: unable to retrieve last used path string segment: %d.",
1482
             function,
1483
             last_used_path_segment_index );
1484
1485
            goto on_error;
1486
          }
1487
          if( last_used_path_string_segment == NULL )
1488
          {
1489
            libcerror_error_set(
1490
             error,
1491
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1492
             LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1493
             "%s: missing last used path string string segment: %d.",
1494
             function,
1495
             last_used_path_segment_index );
1496
1497
            goto on_error;
1498
          }
1499
          /* Remove the size of the parent directory name and a directory separator
1500
           * Note that the size includes the end of string character
1501
           */
1502
          if( current_directory_string_segment_size < safe_full_path_size )
1503
          {
1504
            safe_full_path_size -= last_used_path_string_segment_size;
1505
          }
1506
          else
1507
          {
1508
            safe_full_path_size = 0;
1509
          }
1510
          if( libcsplit_narrow_split_string_set_segment_by_index(
1511
               path_split_string,
1512
               last_used_path_segment_index,
1513
               NULL,
1514
               0,
1515
               error ) != 1 )
1516
          {
1517
            libcerror_error_set(
1518
             error,
1519
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1520
             LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1521
             "%s: unable to set path string segment: %d.",
1522
             function,
1523
             last_used_path_segment_index );
1524
1525
            goto on_error;
1526
          }
1527
          /* Find the previous path split value that contains a name
1528
           */
1529
          while( last_used_path_segment_index > 0 )
1530
          {
1531
            last_used_path_segment_index--;
1532
1533
            if( libcsplit_narrow_split_string_get_segment_by_index(
1534
                 path_split_string,
1535
                 last_used_path_segment_index,
1536
                 &last_used_path_string_segment,
1537
                 &last_used_path_string_segment_size,
1538
                 error ) != 1 )
1539
            {
1540
              libcerror_error_set(
1541
               error,
1542
               LIBCERROR_ERROR_DOMAIN_RUNTIME,
1543
               LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1544
               "%s: unable to retrieve last used path string segment: %d.",
1545
               function,
1546
               last_used_path_segment_index );
1547
1548
              goto on_error;
1549
            }
1550
            if( last_used_path_string_segment_size != 0 )
1551
            {
1552
              break;
1553
            }
1554
          }
1555
        }
1556
        if( libcsplit_narrow_split_string_set_segment_by_index(
1557
             path_split_string,
1558
             path_segment_index,
1559
             NULL,
1560
             0,
1561
             error ) != 1 )
1562
        {
1563
          libcerror_error_set(
1564
           error,
1565
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1566
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1567
           "%s: unable to set path string segment: %d.",
1568
           function,
1569
           path_segment_index );
1570
1571
          goto on_error;
1572
        }
1573
      }
1574
      /* If the path is . ignore the entry
1575
       */
1576
      else if( ( path_string_segment_size == 2 )
1577
            && ( path_string_segment[ 0 ] == '.' ) )
1578
      {
1579
        if( libcsplit_narrow_split_string_set_segment_by_index(
1580
             path_split_string,
1581
             path_segment_index,
1582
             NULL,
1583
             0,
1584
             error ) != 1 )
1585
        {
1586
          libcerror_error_set(
1587
           error,
1588
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1589
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1590
           "%s: unable to set path string segment: %d.",
1591
           function,
1592
           path_segment_index );
1593
1594
          goto on_error;
1595
        }
1596
      }
1597
      /* If the path is empty ignore the entry
1598
       */
1599
      else if( path_string_segment_size <= 1 )
1600
      {
1601
        if( libcsplit_narrow_split_string_set_segment_by_index(
1602
             path_split_string,
1603
             path_segment_index,
1604
             NULL,
1605
             0,
1606
             error ) != 1 )
1607
        {
1608
          libcerror_error_set(
1609
           error,
1610
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1611
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1612
           "%s: unable to set path string segment: %d.",
1613
           function,
1614
           path_segment_index );
1615
1616
          goto on_error;
1617
        }
1618
      }
1619
      else
1620
      {
1621
        /* Add the size of the directory or file name and a directory separator
1622
         * Note that the size includes the end of string character
1623
         */
1624
        safe_full_path_size += path_string_segment_size;
1625
1626
        last_used_path_segment_index = path_segment_index;
1627
      }
1628
    }
1629
  }
1630
  safe_full_path_size += full_path_prefix_length;
1631
1632
  /* Note that the last path separator serves as the end of string
1633
   */
1634
  full_path_index = 0;
1635
1636
  *full_path = narrow_string_allocate(
1637
                safe_full_path_size );
1638
1639
  if( *full_path == NULL )
1640
  {
1641
    libcerror_error_set(
1642
     error,
1643
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1644
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1645
     "%s: unable to create full path.",
1646
     function );
1647
1648
    goto on_error;
1649
  }
1650
  if( memory_set(
1651
       *full_path,
1652
       0,
1653
       sizeof( char ) * safe_full_path_size ) == NULL )
1654
  {
1655
    libcerror_error_set(
1656
     error,
1657
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1658
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
1659
     "%s: unable to clear full path.",
1660
     function );
1661
1662
    goto on_error;
1663
  }
1664
  *full_path_size = safe_full_path_size;
1665
1666
  if( path_type == LIBCPATH_TYPE_DEVICE )
1667
  {
1668
    full_path_prefix        = "\\\\.\\";
1669
    full_path_prefix_length = 4;
1670
  }
1671
  else
1672
  {
1673
    full_path_prefix        = "\\\\?\\";
1674
    full_path_prefix_length = 4;
1675
  }
1676
  if( ( safe_full_path_size < full_path_prefix_length )
1677
   || ( full_path_index > ( safe_full_path_size - full_path_prefix_length ) ) )
1678
  {
1679
    libcerror_error_set(
1680
     error,
1681
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1682
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1683
     "%s: invalid full path size value out of bounds.",
1684
     function );
1685
1686
    goto on_error;
1687
  }
1688
  if( narrow_string_copy(
1689
       &( ( *full_path )[ full_path_index ] ),
1690
       full_path_prefix,
1691
       full_path_prefix_length ) == NULL )
1692
  {
1693
    libcerror_error_set(
1694
     error,
1695
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1696
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1697
     "%s: unable to set prefix in full path.",
1698
     function );
1699
1700
    goto on_error;
1701
  }
1702
  full_path_index += full_path_prefix_length;
1703
1704
  /* If there is a share name the path is an UNC path
1705
   */
1706
  if( ( path_type == LIBCPATH_TYPE_EXTENDED_LENGTH_UNC )
1707
   || ( path_type == LIBCPATH_TYPE_UNC ) )
1708
  {
1709
    if( ( safe_full_path_size < 4 )
1710
     || ( full_path_index > ( safe_full_path_size - 4 ) ) )
1711
    {
1712
      libcerror_error_set(
1713
       error,
1714
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1715
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1716
       "%s: invalid full path size value out of bounds.",
1717
       function );
1718
1719
      goto on_error;
1720
    }
1721
    if( narrow_string_copy(
1722
         &( ( *full_path )[ full_path_index ] ),
1723
         "UNC\\",
1724
         4 ) == NULL )
1725
    {
1726
      libcerror_error_set(
1727
       error,
1728
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1729
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1730
       "%s: unable to set UNC\\ prefix in full path.",
1731
       function );
1732
1733
      goto on_error;
1734
    }
1735
    full_path_index += 4;
1736
  }
1737
  if( volume_name != NULL )
1738
  {
1739
    if( ( safe_full_path_size < volume_name_length )
1740
     || ( full_path_index > ( safe_full_path_size - volume_name_length ) ) )
1741
    {
1742
      libcerror_error_set(
1743
       error,
1744
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1745
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1746
       "%s: invalid full path size value out of bounds.",
1747
       function );
1748
1749
      goto on_error;
1750
    }
1751
    if( narrow_string_copy(
1752
         &( ( *full_path )[ full_path_index ] ),
1753
         volume_name,
1754
         volume_name_length ) == NULL )
1755
    {
1756
      libcerror_error_set(
1757
       error,
1758
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1759
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1760
       "%s: unable to set volume name in full path.",
1761
       function );
1762
1763
      goto on_error;
1764
    }
1765
    full_path_index += volume_name_length;
1766
1767
    ( *full_path )[ full_path_index ] = '\\';
1768
1769
    full_path_index += 1;
1770
  }
1771
  /* If the path is relative
1772
   * add the current working directory elements
1773
   */
1774
  if( ( path_type == LIBCPATH_TYPE_RELATIVE )
1775
   && ( current_directory_split_string != NULL ) )
1776
  {
1777
    for( current_directory_segment_index = 0;
1778
         current_directory_segment_index < current_directory_number_of_segments;
1779
         current_directory_segment_index++ )
1780
    {
1781
      if( libcsplit_narrow_split_string_get_segment_by_index(
1782
           current_directory_split_string,
1783
           current_directory_segment_index,
1784
           &current_directory_string_segment,
1785
           &current_directory_string_segment_size,
1786
           error ) != 1 )
1787
      {
1788
        libcerror_error_set(
1789
         error,
1790
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1791
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1792
         "%s: unable to retrieve current working directory string segment: %d.",
1793
         function,
1794
         current_directory_segment_index );
1795
1796
        goto on_error;
1797
      }
1798
      if( current_directory_string_segment_size != 0 )
1799
      {
1800
        if( current_directory_string_segment == NULL )
1801
        {
1802
          libcerror_error_set(
1803
           error,
1804
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1805
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1806
           "%s: missing current working directory string segment: %d.",
1807
           function,
1808
           current_directory_segment_index );
1809
1810
          goto on_error;
1811
        }
1812
        if( ( safe_full_path_size < ( current_directory_string_segment_size - 1 ) )
1813
         || ( full_path_index > ( safe_full_path_size - ( current_directory_string_segment_size - 1 ) ) ) )
1814
        {
1815
          libcerror_error_set(
1816
           error,
1817
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1818
           LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1819
           "%s: invalid full path size value out of bounds.",
1820
           function );
1821
1822
          goto on_error;
1823
        }
1824
        if( narrow_string_copy(
1825
             &( ( *full_path )[ full_path_index ] ),
1826
             current_directory_string_segment,
1827
             current_directory_string_segment_size - 1 ) == NULL )
1828
        {
1829
          libcerror_error_set(
1830
           error,
1831
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1832
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1833
           "%s: unable to set current working directory split value: %d in full path.",
1834
           function,
1835
           current_directory_segment_index );
1836
1837
          goto on_error;
1838
        }
1839
        full_path_index += current_directory_string_segment_size - 1;
1840
1841
        ( *full_path )[ full_path_index ] = '\\';
1842
1843
        full_path_index += 1;
1844
      }
1845
    }
1846
  }
1847
  if( path_split_string != NULL )
1848
  {
1849
    for( path_segment_index = 0;
1850
         path_segment_index < path_number_of_segments;
1851
         path_segment_index++ )
1852
    {
1853
      if( libcsplit_narrow_split_string_get_segment_by_index(
1854
           path_split_string,
1855
           path_segment_index,
1856
           &path_string_segment,
1857
           &path_string_segment_size,
1858
           error ) != 1 )
1859
      {
1860
        libcerror_error_set(
1861
         error,
1862
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1863
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1864
         "%s: unable to retrieve path string segment: %d.",
1865
         function,
1866
         path_segment_index );
1867
1868
        goto on_error;
1869
      }
1870
      if( path_string_segment_size != 0 )
1871
      {
1872
        if( path_string_segment == NULL )
1873
        {
1874
          libcerror_error_set(
1875
           error,
1876
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1877
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1878
           "%s: missing path string segment: %d.",
1879
           function,
1880
           path_segment_index );
1881
1882
          goto on_error;
1883
        }
1884
        if( ( safe_full_path_size < ( path_string_segment_size - 1 ) )
1885
         || ( full_path_index > ( safe_full_path_size - ( path_string_segment_size - 1 ) ) ) )
1886
        {
1887
          libcerror_error_set(
1888
           error,
1889
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1890
           LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1891
           "%s: invalid full path size value out of bounds.",
1892
           function );
1893
1894
          goto on_error;
1895
        }
1896
        if( narrow_string_copy(
1897
             &( ( *full_path )[ full_path_index ] ),
1898
             path_string_segment,
1899
             path_string_segment_size - 1 ) == NULL )
1900
        {
1901
          libcerror_error_set(
1902
           error,
1903
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1904
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1905
           "%s: unable to set path split value: %d in full path.",
1906
           function,
1907
           path_segment_index );
1908
1909
          goto on_error;
1910
        }
1911
        full_path_index += path_string_segment_size - 1;
1912
1913
        ( *full_path )[ full_path_index ] = '\\';
1914
1915
        full_path_index += 1;
1916
      }
1917
    }
1918
  }
1919
  ( *full_path )[ full_path_index - 1 ] = 0;
1920
1921
  if( path_split_string != NULL )
1922
  {
1923
    if( libcsplit_narrow_split_string_free(
1924
         &path_split_string,
1925
         error ) != 1 )
1926
    {
1927
      libcerror_error_set(
1928
       error,
1929
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1930
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1931
       "%s: unable to free path split string.",
1932
       function );
1933
1934
      goto on_error;
1935
    }
1936
  }
1937
  if( current_directory_split_string != NULL )
1938
  {
1939
    if( libcsplit_narrow_split_string_free(
1940
         &current_directory_split_string,
1941
         error ) != 1 )
1942
    {
1943
      libcerror_error_set(
1944
       error,
1945
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1946
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1947
       "%s: unable to free current working directory split string.",
1948
       function );
1949
1950
      goto on_error;
1951
    }
1952
  }
1953
  if( current_directory != NULL )
1954
  {
1955
    memory_free(
1956
     current_directory );
1957
  }
1958
  return( 1 );
1959
1960
on_error:
1961
  if( *full_path != NULL )
1962
  {
1963
    memory_free(
1964
     *full_path );
1965
1966
    *full_path = NULL;
1967
  }
1968
  *full_path_size = 0;
1969
1970
  if( path_split_string != NULL )
1971
  {
1972
    libcsplit_narrow_split_string_free(
1973
     &path_split_string,
1974
     NULL );
1975
  }
1976
  if( current_directory_split_string != NULL )
1977
  {
1978
    libcsplit_narrow_split_string_free(
1979
     &current_directory_split_string,
1980
     NULL );
1981
  }
1982
  if( current_directory != NULL )
1983
  {
1984
    memory_free(
1985
     current_directory );
1986
  }
1987
  return( -1 );
1988
}
1989
1990
#else
1991
1992
/* Determines the full path of the POSIX path specified
1993
 * Multiple successive / are combined into one
1994
 *
1995
 * Scenarios:
1996
 * /home/user/file.txt
1997
 * /home/user//file.txt
1998
 * /home/user/../user/file.txt
1999
 * /../home/user/file.txt
2000
 * user/../user/file.txt
2001
 *
2002
 * Returns 1 if succesful or -1 on error
2003
 */
2004
int libcpath_path_get_full_path(
2005
     const char *path,
2006
     size_t path_length,
2007
     char **full_path,
2008
     size_t *full_path_size,
2009
     libcerror_error_t **error )
2010
0
{
2011
0
  libcsplit_narrow_split_string_t *current_directory_split_string = NULL;
2012
0
  libcsplit_narrow_split_string_t *path_split_string              = NULL;
2013
0
  char *current_directory                                         = NULL;
2014
0
  char *current_directory_string_segment                          = NULL;
2015
0
  char *last_used_path_string_segment                             = NULL;
2016
0
  char *path_string_segment                                       = NULL;
2017
0
  static char *function                                           = "libcpath_path_get_full_path";
2018
0
  size_t current_directory_length                                 = 0;
2019
0
  size_t current_directory_size                                   = 0;
2020
0
  size_t current_directory_string_segment_size                    = 0;
2021
0
  size_t full_path_index                                          = 0;
2022
0
  size_t last_used_path_string_segment_size                       = 0;
2023
0
  size_t path_string_segment_size                                 = 0;
2024
0
  size_t safe_full_path_size                                      = 0;
2025
0
  uint8_t path_type                                               = LIBCPATH_TYPE_RELATIVE;
2026
0
  int current_directory_number_of_segments                        = 0;
2027
0
  int current_directory_segment_index                             = 0;
2028
0
  int last_used_path_segment_index                                = -1;
2029
0
  int path_number_of_segments                                     = 0;
2030
0
  int path_segment_index                                          = 0;
2031
2032
0
  if( path == NULL )
2033
0
  {
2034
0
    libcerror_error_set(
2035
0
     error,
2036
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2037
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2038
0
     "%s: invalid path.",
2039
0
     function );
2040
2041
0
    return( -1 );
2042
0
  }
2043
0
  if( path_length == 0 )
2044
0
  {
2045
0
    libcerror_error_set(
2046
0
     error,
2047
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2048
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
2049
0
     "%s: invalid path length is zero.",
2050
0
     function );
2051
2052
0
    return( -1 );
2053
0
  }
2054
0
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
2055
0
  {
2056
0
    libcerror_error_set(
2057
0
     error,
2058
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2059
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2060
0
     "%s: invalid path length value exceeds maximum.",
2061
0
     function );
2062
2063
0
    return( -1 );
2064
0
  }
2065
0
  if( full_path == NULL )
2066
0
  {
2067
0
    libcerror_error_set(
2068
0
     error,
2069
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2070
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2071
0
     "%s: invalid full path.",
2072
0
     function );
2073
2074
0
    return( -1 );
2075
0
  }
2076
0
  if( *full_path != NULL )
2077
0
  {
2078
0
    libcerror_error_set(
2079
0
     error,
2080
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2081
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2082
0
     "%s: invalid full path value already set.",
2083
0
     function );
2084
2085
0
    return( -1 );
2086
0
  }
2087
0
  if( full_path_size == NULL )
2088
0
  {
2089
0
    libcerror_error_set(
2090
0
     error,
2091
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2092
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2093
0
     "%s: invalid full path size.",
2094
0
     function );
2095
2096
0
    return( -1 );
2097
0
  }
2098
0
  if( path[ 0 ] == '/' )
2099
0
  {
2100
0
    path_type = LIBCPATH_TYPE_ABSOLUTE;
2101
0
  }
2102
0
  else
2103
0
  {
2104
0
    if( libcpath_path_get_current_working_directory(
2105
0
         &current_directory,
2106
0
         &current_directory_size,
2107
0
         error ) != 1 )
2108
0
    {
2109
0
      libcerror_error_set(
2110
0
       error,
2111
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2112
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2113
0
       "%s: unable to retrieve current working directory.",
2114
0
       function );
2115
2116
0
      goto on_error;
2117
0
    }
2118
0
  }
2119
0
  if( current_directory != NULL )
2120
0
  {
2121
0
    current_directory_length = narrow_string_length(
2122
0
                                current_directory );
2123
2124
0
    if( libcsplit_narrow_string_split(
2125
0
         current_directory,
2126
0
         current_directory_length + 1,
2127
0
         '/',
2128
0
         &current_directory_split_string,
2129
0
         error ) != 1 )
2130
0
    {
2131
0
      libcerror_error_set(
2132
0
       error,
2133
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2134
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2135
0
       "%s: unable to split current working directory.",
2136
0
       function );
2137
2138
0
      goto on_error;
2139
0
    }
2140
0
  }
2141
0
  if( libcsplit_narrow_string_split(
2142
0
       path,
2143
0
       path_length + 1,
2144
0
       '/',
2145
0
       &path_split_string,
2146
0
       error ) != 1 )
2147
0
  {
2148
0
    libcerror_error_set(
2149
0
     error,
2150
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2151
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2152
0
     "%s: unable to split path.",
2153
0
     function );
2154
2155
0
    goto on_error;
2156
0
  }
2157
  /* Determine the full path size
2158
   */
2159
  /* If the path is absolute
2160
   * a directory separator
2161
   */
2162
0
  if( path_type == LIBCPATH_TYPE_ABSOLUTE )
2163
0
  {
2164
0
    safe_full_path_size = 1;
2165
0
  }
2166
  /* If the path is relative
2167
   * add the size of the current working directory
2168
   * a directory separator, if necessary
2169
   */
2170
0
  else if( path_type == LIBCPATH_TYPE_RELATIVE )
2171
0
  {
2172
0
    if( current_directory == NULL )
2173
0
    {
2174
0
      libcerror_error_set(
2175
0
       error,
2176
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2177
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2178
0
       "%s: missing current working directory.",
2179
0
       function );
2180
2181
0
      goto on_error;
2182
0
    }
2183
    /* We need to use the length here since current_directory_size will be PATH_MAX
2184
     */
2185
0
    safe_full_path_size = current_directory_length;
2186
2187
0
    if( ( current_directory_length >= 1 )
2188
0
     && ( current_directory[ current_directory_length - 1 ] != '/' ) )
2189
0
    {
2190
0
      safe_full_path_size++;
2191
0
    }
2192
0
  }
2193
0
  if( current_directory_split_string != NULL )
2194
0
  {
2195
0
    if( libcsplit_narrow_split_string_get_number_of_segments(
2196
0
         current_directory_split_string,
2197
0
         &current_directory_number_of_segments,
2198
0
         error ) != 1 )
2199
0
    {
2200
0
      libcerror_error_set(
2201
0
       error,
2202
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2203
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2204
0
       "%s: unable to retrieve number of current working directory string segments.",
2205
0
       function );
2206
2207
0
      goto on_error;
2208
0
    }
2209
0
    current_directory_segment_index = current_directory_number_of_segments - 1;
2210
0
  }
2211
0
  if( path_split_string != NULL )
2212
0
  {
2213
0
    if( libcsplit_narrow_split_string_get_number_of_segments(
2214
0
         path_split_string,
2215
0
         &path_number_of_segments,
2216
0
         error ) != 1 )
2217
0
    {
2218
0
      libcerror_error_set(
2219
0
       error,
2220
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2221
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2222
0
       "%s: unable to retrieve number of path string segments.",
2223
0
       function );
2224
2225
0
      goto on_error;
2226
0
    }
2227
0
    for( path_segment_index = 0;
2228
0
         path_segment_index < path_number_of_segments;
2229
0
         path_segment_index++ )
2230
0
    {
2231
0
      if( libcsplit_narrow_split_string_get_segment_by_index(
2232
0
           path_split_string,
2233
0
           path_segment_index,
2234
0
           &path_string_segment,
2235
0
           &path_string_segment_size,
2236
0
           error ) != 1 )
2237
0
      {
2238
0
        libcerror_error_set(
2239
0
         error,
2240
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2241
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2242
0
         "%s: unable to retrieve path string segment: %d.",
2243
0
         function,
2244
0
         path_segment_index );
2245
2246
0
        goto on_error;
2247
0
      }
2248
0
      if( path_string_segment == NULL )
2249
0
      {
2250
0
        libcerror_error_set(
2251
0
         error,
2252
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2253
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2254
0
         "%s: missing path string segment: %d.",
2255
0
         function,
2256
0
         path_segment_index );
2257
2258
0
        goto on_error;
2259
0
      }
2260
      /* If the path is .. reverse the current path by one directory
2261
       */
2262
0
      if( ( path_string_segment_size == 3 )
2263
0
       && ( path_string_segment[ 0 ] == '.' )
2264
0
       && ( path_string_segment[ 1 ] == '.' ) )
2265
0
      {
2266
0
        if( ( current_directory_split_string != NULL )
2267
0
         && ( last_used_path_segment_index == -1 ) )
2268
0
        {
2269
0
          if( libcsplit_narrow_split_string_get_segment_by_index(
2270
0
               current_directory_split_string,
2271
0
               current_directory_segment_index,
2272
0
               &current_directory_string_segment,
2273
0
               &current_directory_string_segment_size,
2274
0
               error ) != 1 )
2275
0
          {
2276
0
            libcerror_error_set(
2277
0
             error,
2278
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
2279
0
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2280
0
             "%s: unable to retrieve current working directory string segment: %d.",
2281
0
             function,
2282
0
             current_directory_segment_index );
2283
2284
0
            goto on_error;
2285
0
          }
2286
0
          if( current_directory_string_segment == NULL )
2287
0
          {
2288
0
            libcerror_error_set(
2289
0
             error,
2290
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
2291
0
             LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2292
0
             "%s: missing current working directory string segment: %d.",
2293
0
             function,
2294
0
             current_directory_segment_index );
2295
2296
0
            goto on_error;
2297
0
          }
2298
          /* Remove the size of the parent directory name and a directory separator
2299
           * Note that the size includes the end of string character
2300
           */
2301
0
          safe_full_path_size -= current_directory_string_segment_size;
2302
2303
0
          if( libcsplit_narrow_split_string_set_segment_by_index(
2304
0
               current_directory_split_string,
2305
0
               current_directory_segment_index,
2306
0
               NULL,
2307
0
               0,
2308
0
               error ) != 1 )
2309
0
          {
2310
0
            libcerror_error_set(
2311
0
             error,
2312
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
2313
0
             LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2314
0
             "%s: unable to set current working directory string segment: %d.",
2315
0
             function,
2316
0
             current_directory_segment_index );
2317
2318
0
            goto on_error;
2319
0
          }
2320
0
          current_directory_segment_index--;
2321
0
        }
2322
0
        else if( last_used_path_segment_index >= 0 )
2323
0
        {
2324
0
          if( libcsplit_narrow_split_string_get_segment_by_index(
2325
0
               path_split_string,
2326
0
               last_used_path_segment_index,
2327
0
               &last_used_path_string_segment,
2328
0
               &last_used_path_string_segment_size,
2329
0
               error ) != 1 )
2330
0
          {
2331
0
            libcerror_error_set(
2332
0
             error,
2333
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
2334
0
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2335
0
             "%s: unable to retrieve last used path string segment: %d.",
2336
0
             function,
2337
0
             last_used_path_segment_index );
2338
2339
0
            goto on_error;
2340
0
          }
2341
0
          if( last_used_path_string_segment == NULL )
2342
0
          {
2343
0
            libcerror_error_set(
2344
0
             error,
2345
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
2346
0
             LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2347
0
             "%s: missing last used path string string segment: %d.",
2348
0
             function,
2349
0
             last_used_path_segment_index );
2350
2351
0
            goto on_error;
2352
0
          }
2353
          /* Remove the size of the parent directory name and a directory separator
2354
           * Note that the size includes the end of string character
2355
           */
2356
0
          safe_full_path_size -= last_used_path_string_segment_size;
2357
2358
0
          if( libcsplit_narrow_split_string_set_segment_by_index(
2359
0
               path_split_string,
2360
0
               last_used_path_segment_index,
2361
0
               NULL,
2362
0
               0,
2363
0
               error ) != 1 )
2364
0
          {
2365
0
            libcerror_error_set(
2366
0
             error,
2367
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
2368
0
             LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2369
0
             "%s: unable to set path string segment: %d.",
2370
0
             function,
2371
0
             last_used_path_segment_index );
2372
2373
0
            goto on_error;
2374
0
          }
2375
          /* Find the previous path split value that contains a name
2376
           */
2377
0
          while( last_used_path_segment_index > 0 )
2378
0
          {
2379
0
            last_used_path_segment_index--;
2380
2381
0
            if( libcsplit_narrow_split_string_get_segment_by_index(
2382
0
                 path_split_string,
2383
0
                 last_used_path_segment_index,
2384
0
                 &last_used_path_string_segment,
2385
0
                 &last_used_path_string_segment_size,
2386
0
                 error ) != 1 )
2387
0
            {
2388
0
              libcerror_error_set(
2389
0
               error,
2390
0
               LIBCERROR_ERROR_DOMAIN_RUNTIME,
2391
0
               LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2392
0
               "%s: unable to retrieve last used path string segment: %d.",
2393
0
               function,
2394
0
               last_used_path_segment_index );
2395
2396
0
              goto on_error;
2397
0
            }
2398
0
            if( last_used_path_string_segment_size != 0 )
2399
0
            {
2400
0
              break;
2401
0
            }
2402
0
          }
2403
0
        }
2404
0
        if( libcsplit_narrow_split_string_set_segment_by_index(
2405
0
             path_split_string,
2406
0
             path_segment_index,
2407
0
             NULL,
2408
0
             0,
2409
0
             error ) != 1 )
2410
0
        {
2411
0
          libcerror_error_set(
2412
0
           error,
2413
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2414
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2415
0
           "%s: unable to set path string segment: %d.",
2416
0
           function,
2417
0
           path_segment_index );
2418
2419
0
          goto on_error;
2420
0
        }
2421
0
      }
2422
      /* If the path is . ignore the entry
2423
       */
2424
0
      else if( ( path_string_segment_size == 2 )
2425
0
            && ( path_string_segment[ 0 ] == '.' ) )
2426
0
      {
2427
0
        if( libcsplit_narrow_split_string_set_segment_by_index(
2428
0
             path_split_string,
2429
0
             path_segment_index,
2430
0
             NULL,
2431
0
             0,
2432
0
             error ) != 1 )
2433
0
        {
2434
0
          libcerror_error_set(
2435
0
           error,
2436
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2437
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2438
0
           "%s: unable to set path string segment: %d.",
2439
0
           function,
2440
0
           path_segment_index );
2441
2442
0
          goto on_error;
2443
0
        }
2444
0
      }
2445
      /* If the path is empty ignore the entry
2446
       */
2447
0
      else if( path_string_segment_size <= 1 )
2448
0
      {
2449
0
        if( libcsplit_narrow_split_string_set_segment_by_index(
2450
0
             path_split_string,
2451
0
             path_segment_index,
2452
0
             NULL,
2453
0
             0,
2454
0
             error ) != 1 )
2455
0
        {
2456
0
          libcerror_error_set(
2457
0
           error,
2458
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2459
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2460
0
           "%s: unable to set path string segment: %d.",
2461
0
           function,
2462
0
           path_segment_index );
2463
2464
0
          goto on_error;
2465
0
        }
2466
0
      }
2467
0
      else
2468
0
      {
2469
        /* Add the size of the directory or file name and a directory separator
2470
         * Note that the size includes the end of string character
2471
         */
2472
0
        safe_full_path_size += path_string_segment_size;
2473
2474
0
        last_used_path_segment_index = path_segment_index;
2475
0
      }
2476
0
    }
2477
0
  }
2478
  /* Note that the last path separator serves as the end of string
2479
   */
2480
0
  full_path_index = 0;
2481
2482
0
  *full_path = narrow_string_allocate(
2483
0
                safe_full_path_size );
2484
2485
0
  if( *full_path == NULL )
2486
0
  {
2487
0
    libcerror_error_set(
2488
0
     error,
2489
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
2490
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2491
0
     "%s: unable to create full path.",
2492
0
     function );
2493
2494
0
    goto on_error;
2495
0
  }
2496
0
  if( memory_set(
2497
0
       *full_path,
2498
0
       0,
2499
0
       sizeof( char ) * safe_full_path_size ) == NULL )
2500
0
  {
2501
0
    libcerror_error_set(
2502
0
     error,
2503
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
2504
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
2505
0
     "%s: unable to clear full path.",
2506
0
     function );
2507
2508
0
    goto on_error;
2509
0
  }
2510
0
  *full_path_size = safe_full_path_size;
2511
2512
0
  if( path_type == LIBCPATH_TYPE_ABSOLUTE )
2513
0
  {
2514
0
    ( *full_path )[ full_path_index ] = '/';
2515
2516
0
    full_path_index += 1;
2517
0
  }
2518
  /* If the path is relative
2519
   * add the current working directory elements
2520
   */
2521
0
  if( ( path_type == LIBCPATH_TYPE_RELATIVE )
2522
0
   && ( current_directory_split_string != NULL ) )
2523
0
  {
2524
0
    for( current_directory_segment_index = 0;
2525
0
         current_directory_segment_index < current_directory_number_of_segments;
2526
0
         current_directory_segment_index++ )
2527
0
    {
2528
0
      if( libcsplit_narrow_split_string_get_segment_by_index(
2529
0
           current_directory_split_string,
2530
0
           current_directory_segment_index,
2531
0
           &current_directory_string_segment,
2532
0
           &current_directory_string_segment_size,
2533
0
           error ) != 1 )
2534
0
      {
2535
0
        libcerror_error_set(
2536
0
         error,
2537
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2538
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2539
0
         "%s: unable to retrieve current working directory string segment: %d.",
2540
0
         function,
2541
0
         current_directory_segment_index );
2542
2543
0
        goto on_error;
2544
0
      }
2545
0
      if( current_directory_string_segment_size != 0 )
2546
0
      {
2547
0
        if( current_directory_string_segment == NULL )
2548
0
        {
2549
0
          libcerror_error_set(
2550
0
           error,
2551
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2552
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2553
0
           "%s: missing current working directory string segment: %d.",
2554
0
           function,
2555
0
           current_directory_segment_index );
2556
2557
0
          goto on_error;
2558
0
        }
2559
0
        if( narrow_string_copy(
2560
0
             &( ( *full_path )[ full_path_index ] ),
2561
0
             current_directory_string_segment,
2562
0
             current_directory_string_segment_size - 1 ) == NULL )
2563
0
        {
2564
0
          libcerror_error_set(
2565
0
           error,
2566
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2567
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2568
0
           "%s: unable to set current working directory split value: %d in full path.",
2569
0
           function,
2570
0
           current_directory_segment_index );
2571
2572
0
          goto on_error;
2573
0
        }
2574
0
        full_path_index += current_directory_string_segment_size - 1;
2575
2576
0
        ( *full_path )[ full_path_index ] = '/';
2577
2578
0
        full_path_index += 1;
2579
0
      }
2580
0
    }
2581
0
  }
2582
0
  if( path_split_string != NULL )
2583
0
  {
2584
0
    for( path_segment_index = 0;
2585
0
         path_segment_index < path_number_of_segments;
2586
0
         path_segment_index++ )
2587
0
    {
2588
0
      if( libcsplit_narrow_split_string_get_segment_by_index(
2589
0
           path_split_string,
2590
0
           path_segment_index,
2591
0
           &path_string_segment,
2592
0
           &path_string_segment_size,
2593
0
           error ) != 1 )
2594
0
      {
2595
0
        libcerror_error_set(
2596
0
         error,
2597
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2598
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2599
0
         "%s: unable to retrieve path string segment: %d.",
2600
0
         function,
2601
0
         path_segment_index );
2602
2603
0
        goto on_error;
2604
0
      }
2605
0
      if( path_string_segment_size != 0 )
2606
0
      {
2607
0
        if( path_string_segment == NULL )
2608
0
        {
2609
0
          libcerror_error_set(
2610
0
           error,
2611
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2612
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2613
0
           "%s: missing path string segment: %d.",
2614
0
           function,
2615
0
           path_segment_index );
2616
2617
0
          goto on_error;
2618
0
        }
2619
0
        if( narrow_string_copy(
2620
0
             &( ( *full_path )[ full_path_index ] ),
2621
0
             path_string_segment,
2622
0
             path_string_segment_size - 1 ) == NULL )
2623
0
        {
2624
0
          libcerror_error_set(
2625
0
           error,
2626
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2627
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2628
0
           "%s: unable to set path split value: %d in full path.",
2629
0
           function,
2630
0
           path_segment_index );
2631
2632
0
          goto on_error;
2633
0
        }
2634
0
        full_path_index += path_string_segment_size - 1;
2635
2636
0
        ( *full_path )[ full_path_index ] = '/';
2637
2638
0
        full_path_index += 1;
2639
0
      }
2640
0
    }
2641
0
  }
2642
0
  ( *full_path )[ full_path_index - 1 ] = 0;
2643
2644
0
  if( path_split_string != NULL )
2645
0
  {
2646
0
    if( libcsplit_narrow_split_string_free(
2647
0
         &path_split_string,
2648
0
         error ) != 1 )
2649
0
    {
2650
0
      libcerror_error_set(
2651
0
       error,
2652
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2653
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2654
0
       "%s: unable to free path split string.",
2655
0
       function );
2656
2657
0
      goto on_error;
2658
0
    }
2659
0
  }
2660
0
  if( current_directory_split_string != NULL )
2661
0
  {
2662
0
    if( libcsplit_narrow_split_string_free(
2663
0
         &current_directory_split_string,
2664
0
         error ) != 1 )
2665
0
    {
2666
0
      libcerror_error_set(
2667
0
       error,
2668
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2669
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2670
0
       "%s: unable to free current working directory split string.",
2671
0
       function );
2672
2673
0
      goto on_error;
2674
0
    }
2675
0
  }
2676
0
  if( current_directory != NULL )
2677
0
  {
2678
0
    memory_free(
2679
0
     current_directory );
2680
0
  }
2681
0
  return( 1 );
2682
2683
0
on_error:
2684
0
  if( *full_path != NULL )
2685
0
  {
2686
0
    memory_free(
2687
0
     *full_path );
2688
2689
0
    *full_path = NULL;
2690
0
  }
2691
0
  *full_path_size = 0;
2692
2693
0
  if( path_split_string != NULL )
2694
0
  {
2695
0
    libcsplit_narrow_split_string_free(
2696
0
     &path_split_string,
2697
0
     NULL );
2698
0
  }
2699
0
  if( current_directory_split_string != NULL )
2700
0
  {
2701
0
    libcsplit_narrow_split_string_free(
2702
0
     &current_directory_split_string,
2703
0
     NULL );
2704
0
  }
2705
0
  if( current_directory != NULL )
2706
0
  {
2707
0
    memory_free(
2708
0
     current_directory );
2709
0
  }
2710
0
  return( -1 );
2711
0
}
2712
2713
#endif /* defined( WINAPI ) */
2714
2715
/* Retrieves the size of a sanitized version of the path character
2716
 * Returns 1 if successful or -1 on error
2717
 */
2718
int libcpath_path_get_sanitized_character_size(
2719
     char character,
2720
     size_t *sanitized_character_size,
2721
     libcerror_error_t **error )
2722
0
{
2723
0
  static char *function = "libcpath_path_get_sanitized_character_size";
2724
2725
0
  if( sanitized_character_size == NULL )
2726
0
  {
2727
0
    libcerror_error_set(
2728
0
     error,
2729
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2730
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2731
0
     "%s: invalid sanitized character size.",
2732
0
     function );
2733
2734
0
    return( -1 );
2735
0
  }
2736
0
  if( ( character >= 0x00 )
2737
0
   && ( character <= 0x1f ) )
2738
0
  {
2739
0
    *sanitized_character_size = 4;
2740
0
  }
2741
0
  else if( character == LIBCPATH_ESCAPE_CHARACTER )
2742
0
  {
2743
0
    *sanitized_character_size = 2;
2744
0
  }
2745
#if defined( WINAPI )
2746
  else if( character == '/' )
2747
  {
2748
    *sanitized_character_size = 4;
2749
  }
2750
#endif
2751
0
  else if( ( character == '!' )
2752
0
        || ( character == '$' )
2753
0
        || ( character == '%' )
2754
0
        || ( character == '&' )
2755
0
        || ( character == '*' )
2756
0
        || ( character == '+' )
2757
0
        || ( character == ':' )
2758
0
        || ( character == ';' )
2759
0
        || ( character == '<' )
2760
0
        || ( character == '>' )
2761
0
        || ( character == '?' )
2762
0
        || ( character == '|' )
2763
0
        || ( character == 0x7f ) )
2764
0
  {
2765
0
    *sanitized_character_size = 4;
2766
0
  }
2767
0
  else
2768
0
  {
2769
0
    *sanitized_character_size = 1;
2770
0
  }
2771
0
  return( 1 );
2772
0
}
2773
2774
/* Retrieves a sanitized version of the path character
2775
 * Returns 1 if successful or -1 on error
2776
 */
2777
int libcpath_path_get_sanitized_character(
2778
     char character,
2779
     size_t sanitized_character_size,
2780
     char *sanitized_path,
2781
     size_t sanitized_path_size,
2782
     size_t *sanitized_path_index,
2783
     libcerror_error_t **error )
2784
0
{
2785
0
  static char *function            = "libcpath_path_get_sanitized_character";
2786
0
  size_t safe_sanitized_path_index = 0;
2787
0
  char lower_nibble                = 0;
2788
0
  char upper_nibble                = 0;
2789
2790
0
  if( ( sanitized_character_size != 1 )
2791
0
   && ( sanitized_character_size != 2 )
2792
0
   && ( sanitized_character_size != 4 ) )
2793
0
  {
2794
0
    libcerror_error_set(
2795
0
     error,
2796
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2797
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
2798
0
     "%s: invalid sanitized character size value out of bounds.",
2799
0
     function );
2800
2801
0
    return( -1 );
2802
0
  }
2803
0
  if( sanitized_path == NULL )
2804
0
  {
2805
0
    libcerror_error_set(
2806
0
     error,
2807
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2808
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2809
0
     "%s: invalid sanitized path.",
2810
0
     function );
2811
2812
0
    return( -1 );
2813
0
  }
2814
0
  if( sanitized_path_size > (size_t) SSIZE_MAX )
2815
0
  {
2816
0
    libcerror_error_set(
2817
0
     error,
2818
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2819
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2820
0
     "%s: invalid sanitized path size value exceeds maximum.",
2821
0
     function );
2822
2823
0
    return( -1 );
2824
0
  }
2825
0
  if( sanitized_path_index == NULL )
2826
0
  {
2827
0
    libcerror_error_set(
2828
0
     error,
2829
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2830
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2831
0
     "%s: invalid sanitized path index.",
2832
0
     function );
2833
2834
0
    return( -1 );
2835
0
  }
2836
0
  safe_sanitized_path_index = *sanitized_path_index;
2837
2838
0
  if( safe_sanitized_path_index > sanitized_path_size )
2839
0
  {
2840
0
    libcerror_error_set(
2841
0
     error,
2842
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2843
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
2844
0
     "%s: invalid sanitized path index value out of bounds.",
2845
0
     function );
2846
2847
0
    return( -1 );
2848
0
  }
2849
0
  if( ( sanitized_character_size > sanitized_path_size )
2850
0
   || ( safe_sanitized_path_index > ( sanitized_path_size - sanitized_character_size ) ) )
2851
0
  {
2852
0
    libcerror_error_set(
2853
0
     error,
2854
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2855
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2856
0
     "%s: invalid sanitized path size value too small.",
2857
0
     function );
2858
2859
0
    return( -1 );
2860
0
  }
2861
0
  if( sanitized_character_size == 1 )
2862
0
  {
2863
0
    sanitized_path[ safe_sanitized_path_index++ ] = character;
2864
0
  }
2865
0
  else if( sanitized_character_size == 2 )
2866
0
  {
2867
0
    sanitized_path[ safe_sanitized_path_index++ ] = LIBCPATH_ESCAPE_CHARACTER;
2868
0
    sanitized_path[ safe_sanitized_path_index++ ] = LIBCPATH_ESCAPE_CHARACTER;
2869
0
  }
2870
0
  else if( sanitized_character_size == 4 )
2871
0
  {
2872
0
    lower_nibble = character & 0x0f;
2873
0
    upper_nibble = ( character >> 4 ) & 0x0f;
2874
2875
0
    if( lower_nibble > 10 )
2876
0
    {
2877
0
      lower_nibble += 'a' - 10;
2878
0
    }
2879
0
    else
2880
0
    {
2881
0
      lower_nibble += '0';
2882
0
    }
2883
0
    if( upper_nibble > 10 )
2884
0
    {
2885
0
      upper_nibble += 'a' - 10;
2886
0
    }
2887
0
    else
2888
0
    {
2889
0
      upper_nibble += '0';
2890
0
    }
2891
0
    sanitized_path[ safe_sanitized_path_index++ ] = LIBCPATH_ESCAPE_CHARACTER;
2892
0
    sanitized_path[ safe_sanitized_path_index++ ] = 'x';
2893
0
    sanitized_path[ safe_sanitized_path_index++ ] = upper_nibble;
2894
0
    sanitized_path[ safe_sanitized_path_index++ ] = lower_nibble;
2895
0
  }
2896
0
  *sanitized_path_index = safe_sanitized_path_index;
2897
2898
0
  return( 1 );
2899
0
}
2900
2901
/* Retrieves a sanitized version of the filename
2902
 * Returns 1 if successful or -1 on error
2903
 */
2904
int libcpath_path_get_sanitized_filename(
2905
     const char *filename,
2906
     size_t filename_length,
2907
     char **sanitized_filename,
2908
     size_t *sanitized_filename_size,
2909
     libcerror_error_t **error )
2910
0
{
2911
0
  static char *function               = "libcpath_path_get_sanitized_filename";
2912
0
  char *safe_sanitized_filename       = NULL;
2913
0
  size_t filename_index               = 0;
2914
0
  size_t sanitized_character_size     = 0;
2915
0
  size_t safe_sanitized_filename_size = 0;
2916
0
  size_t sanitized_filename_index     = 0;
2917
2918
0
  if( filename == NULL )
2919
0
  {
2920
0
    libcerror_error_set(
2921
0
     error,
2922
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2923
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2924
0
     "%s: invalid filename.",
2925
0
     function );
2926
2927
0
    return( -1 );
2928
0
  }
2929
0
  if( filename_length == 0 )
2930
0
  {
2931
0
    libcerror_error_set(
2932
0
     error,
2933
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2934
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
2935
0
     "%s: invalid filename length is zero.",
2936
0
     function );
2937
2938
0
    return( -1 );
2939
0
  }
2940
0
  if( filename_length > (size_t) ( SSIZE_MAX - 1 ) )
2941
0
  {
2942
0
    libcerror_error_set(
2943
0
     error,
2944
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2945
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2946
0
     "%s: invalid filename length value exceeds maximum.",
2947
0
     function );
2948
2949
0
    return( -1 );
2950
0
  }
2951
0
  if( sanitized_filename == NULL )
2952
0
  {
2953
0
    libcerror_error_set(
2954
0
     error,
2955
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2956
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2957
0
     "%s: invalid sanitized filename.",
2958
0
     function );
2959
2960
0
    return( -1 );
2961
0
  }
2962
0
  if( *sanitized_filename != NULL )
2963
0
  {
2964
0
    libcerror_error_set(
2965
0
     error,
2966
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2967
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2968
0
     "%s: invalid sanitized filename value already set.",
2969
0
     function );
2970
2971
0
    return( -1 );
2972
0
  }
2973
0
  if( sanitized_filename_size == NULL )
2974
0
  {
2975
0
    libcerror_error_set(
2976
0
     error,
2977
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2978
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2979
0
     "%s: invalid sanitized filename size.",
2980
0
     function );
2981
2982
0
    return( -1 );
2983
0
  }
2984
0
  safe_sanitized_filename_size = 1;
2985
2986
0
  for( filename_index = 0;
2987
0
       filename_index < filename_length;
2988
0
       filename_index++ )
2989
0
  {
2990
0
    if( filename[ filename_index ] == LIBCPATH_SEPARATOR )
2991
0
    {
2992
0
      sanitized_character_size = 4;
2993
0
    }
2994
0
    else if( libcpath_path_get_sanitized_character_size(
2995
0
              filename[ filename_index ],
2996
0
              &sanitized_character_size,
2997
0
              error ) != 1 )
2998
0
    {
2999
0
      libcerror_error_set(
3000
0
       error,
3001
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3002
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3003
0
       "%s: unable to determine sanitize character size.",
3004
0
       function );
3005
3006
0
      goto on_error;
3007
0
    }
3008
0
    safe_sanitized_filename_size += sanitized_character_size;
3009
0
  }
3010
0
  if( safe_sanitized_filename_size > (size_t) SSIZE_MAX )
3011
0
  {
3012
0
    libcerror_error_set(
3013
0
     error,
3014
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3015
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3016
0
     "%s: invalid sanitized filename size value exceeds maximum.",
3017
0
     function );
3018
3019
0
    goto on_error;
3020
0
  }
3021
0
  safe_sanitized_filename = narrow_string_allocate(
3022
0
                             safe_sanitized_filename_size );
3023
3024
0
  if( safe_sanitized_filename == NULL )
3025
0
  {
3026
0
    libcerror_error_set(
3027
0
     error,
3028
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
3029
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
3030
0
     "%s: unable to create sanitized filename.",
3031
0
     function );
3032
3033
0
    goto on_error;
3034
0
  }
3035
0
  for( filename_index = 0;
3036
0
       filename_index < filename_length;
3037
0
       filename_index++ )
3038
0
  {
3039
0
    if( filename[ filename_index ] == LIBCPATH_SEPARATOR )
3040
0
    {
3041
0
      sanitized_character_size = 4;
3042
0
    }
3043
0
    else if( libcpath_path_get_sanitized_character_size(
3044
0
              filename[ filename_index ],
3045
0
              &sanitized_character_size,
3046
0
              error ) != 1 )
3047
0
    {
3048
0
      libcerror_error_set(
3049
0
       error,
3050
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3051
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3052
0
       "%s: unable to determine sanitize character size.",
3053
0
       function );
3054
3055
0
      goto on_error;
3056
0
    }
3057
0
    if( libcpath_path_get_sanitized_character(
3058
0
         filename[ filename_index ],
3059
0
         sanitized_character_size,
3060
0
         safe_sanitized_filename,
3061
0
         safe_sanitized_filename_size,
3062
0
         &sanitized_filename_index,
3063
0
         error ) != 1 )
3064
0
    {
3065
0
      libcerror_error_set(
3066
0
       error,
3067
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3068
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3069
0
       "%s: unable to determine sanitize character size.",
3070
0
       function );
3071
3072
0
      goto on_error;
3073
0
    }
3074
0
  }
3075
0
  safe_sanitized_filename[ sanitized_filename_index ] = 0;
3076
3077
0
  *sanitized_filename      = safe_sanitized_filename;
3078
0
  *sanitized_filename_size = safe_sanitized_filename_size;
3079
3080
0
  return( 1 );
3081
3082
0
on_error:
3083
0
  if( safe_sanitized_filename != NULL )
3084
0
  {
3085
0
    memory_free(
3086
0
     safe_sanitized_filename );
3087
0
  }
3088
0
  return( -1 );
3089
0
}
3090
3091
/* Retrieves a sanitized version of the path
3092
 * Returns 1 if successful or -1 on error
3093
 */
3094
int libcpath_path_get_sanitized_path(
3095
     const char *path,
3096
     size_t path_length,
3097
     char **sanitized_path,
3098
     size_t *sanitized_path_size,
3099
     libcerror_error_t **error )
3100
0
{
3101
0
  static char *function                    = "libcpath_path_get_sanitized_path";
3102
0
  char *safe_sanitized_path                = NULL;
3103
0
  size_t path_index                        = 0;
3104
0
  size_t safe_sanitized_path_size          = 0;
3105
0
  size_t sanitized_character_size          = 0;
3106
0
  size_t sanitized_path_index              = 0;
3107
3108
#if defined( WINAPI )
3109
  size_t last_path_segment_seperator_index = 0;
3110
#endif
3111
3112
0
  if( path == NULL )
3113
0
  {
3114
0
    libcerror_error_set(
3115
0
     error,
3116
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3117
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3118
0
     "%s: invalid path.",
3119
0
     function );
3120
3121
0
    return( -1 );
3122
0
  }
3123
0
  if( path_length == 0 )
3124
0
  {
3125
0
    libcerror_error_set(
3126
0
     error,
3127
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3128
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
3129
0
     "%s: invalid path length is zero.",
3130
0
     function );
3131
3132
0
    return( -1 );
3133
0
  }
3134
0
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
3135
0
  {
3136
0
    libcerror_error_set(
3137
0
     error,
3138
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3139
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3140
0
     "%s: invalid path length value exceeds maximum.",
3141
0
     function );
3142
3143
0
    return( -1 );
3144
0
  }
3145
0
  if( sanitized_path == NULL )
3146
0
  {
3147
0
    libcerror_error_set(
3148
0
     error,
3149
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3150
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3151
0
     "%s: invalid sanitized path.",
3152
0
     function );
3153
3154
0
    return( -1 );
3155
0
  }
3156
0
  if( *sanitized_path != NULL )
3157
0
  {
3158
0
    libcerror_error_set(
3159
0
     error,
3160
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3161
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3162
0
     "%s: invalid sanitized path value already set.",
3163
0
     function );
3164
3165
0
    return( -1 );
3166
0
  }
3167
0
  if( sanitized_path_size == NULL )
3168
0
  {
3169
0
    libcerror_error_set(
3170
0
     error,
3171
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3172
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3173
0
     "%s: invalid sanitized path size.",
3174
0
     function );
3175
3176
0
    return( -1 );
3177
0
  }
3178
0
  safe_sanitized_path_size = 1;
3179
3180
0
  for( path_index = 0;
3181
0
       path_index < path_length;
3182
0
       path_index++ )
3183
0
  {
3184
0
    if( libcpath_path_get_sanitized_character_size(
3185
0
         path[ path_index ],
3186
0
         &sanitized_character_size,
3187
0
         error ) != 1 )
3188
0
    {
3189
0
      libcerror_error_set(
3190
0
       error,
3191
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3192
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3193
0
       "%s: unable to determine sanitize character size.",
3194
0
       function );
3195
3196
0
      goto on_error;
3197
0
    }
3198
0
    safe_sanitized_path_size += sanitized_character_size;
3199
3200
#if defined( WINAPI )
3201
    if( path[ path_index ] == LIBCPATH_SEPARATOR )
3202
    {
3203
      last_path_segment_seperator_index = path_index;
3204
    }
3205
#endif
3206
0
  }
3207
0
  if( safe_sanitized_path_size > (size_t) SSIZE_MAX )
3208
0
  {
3209
0
    libcerror_error_set(
3210
0
     error,
3211
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3212
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3213
0
     "%s: invalid sanitized path size value exceeds maximum.",
3214
0
     function );
3215
3216
0
    goto on_error;
3217
0
  }
3218
#if defined( WINAPI )
3219
  if( last_path_segment_seperator_index > 32767 )
3220
  {
3221
    libcerror_error_set(
3222
     error,
3223
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3224
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3225
     "%s: last path segment separator value out of bounds.",
3226
     function );
3227
3228
    goto on_error;
3229
  }
3230
  if( safe_sanitized_path_size > 32767 )
3231
  {
3232
    safe_sanitized_path_size = 32767;
3233
  }
3234
#endif
3235
0
  safe_sanitized_path = narrow_string_allocate(
3236
0
                         safe_sanitized_path_size );
3237
3238
0
  if( safe_sanitized_path == NULL )
3239
0
  {
3240
0
    libcerror_error_set(
3241
0
     error,
3242
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
3243
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
3244
0
     "%s: unable to create sanitized path.",
3245
0
     function );
3246
3247
0
    goto on_error;
3248
0
  }
3249
0
  for( path_index = 0;
3250
0
       path_index < path_length;
3251
0
       path_index++ )
3252
0
  {
3253
0
    if( libcpath_path_get_sanitized_character_size(
3254
0
         path[ path_index ],
3255
0
         &sanitized_character_size,
3256
0
         error ) != 1 )
3257
0
    {
3258
0
      libcerror_error_set(
3259
0
       error,
3260
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3261
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3262
0
       "%s: unable to determine sanitize character size.",
3263
0
       function );
3264
3265
0
      goto on_error;
3266
0
    }
3267
0
    if( libcpath_path_get_sanitized_character(
3268
0
         path[ path_index ],
3269
0
         sanitized_character_size,
3270
0
         safe_sanitized_path,
3271
0
         safe_sanitized_path_size,
3272
0
         &sanitized_path_index,
3273
0
         error ) != 1 )
3274
0
    {
3275
0
      libcerror_error_set(
3276
0
       error,
3277
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3278
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3279
0
       "%s: unable to determine sanitize character size.",
3280
0
       function );
3281
3282
0
      goto on_error;
3283
0
    }
3284
0
  }
3285
0
  safe_sanitized_path[ sanitized_path_index ] = 0;
3286
3287
0
  *sanitized_path      = safe_sanitized_path;
3288
0
  *sanitized_path_size = safe_sanitized_path_size;
3289
3290
0
  return( 1 );
3291
3292
0
on_error:
3293
0
  if( safe_sanitized_path != NULL )
3294
0
  {
3295
0
    memory_free(
3296
0
     safe_sanitized_path );
3297
0
  }
3298
0
  return( -1 );
3299
0
}
3300
3301
/* Combines the directory name and filename into a path
3302
 * Returns 1 if successful or -1 on error
3303
 */
3304
int libcpath_path_join(
3305
     char **path,
3306
     size_t *path_size,
3307
     const char *directory_name,
3308
     size_t directory_name_length,
3309
     const char *filename,
3310
     size_t filename_length,
3311
     libcerror_error_t **error )
3312
0
{
3313
0
  static char *function = "libcpath_path_join";
3314
0
  size_t filename_index = 0;
3315
0
  size_t path_index     = 0;
3316
3317
0
  if( path == NULL )
3318
0
  {
3319
0
    libcerror_error_set(
3320
0
     error,
3321
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3322
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3323
0
     "%s: invalid path.",
3324
0
     function );
3325
3326
0
    return( -1 );
3327
0
  }
3328
0
  if( *path != NULL )
3329
0
  {
3330
0
    libcerror_error_set(
3331
0
     error,
3332
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3333
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3334
0
     "%s: invalid path value already set.",
3335
0
     function );
3336
3337
0
    return( -1 );
3338
0
  }
3339
0
  if( path_size == NULL )
3340
0
  {
3341
0
    libcerror_error_set(
3342
0
     error,
3343
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3344
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3345
0
     "%s: invalid path size.",
3346
0
     function );
3347
3348
0
    return( -1 );
3349
0
  }
3350
0
  if( directory_name == NULL )
3351
0
  {
3352
0
    libcerror_error_set(
3353
0
     error,
3354
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3355
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3356
0
     "%s: invalid directory name.",
3357
0
     function );
3358
3359
0
    return( -1 );
3360
0
  }
3361
0
  if( directory_name_length > (size_t) SSIZE_MAX )
3362
0
  {
3363
0
    libcerror_error_set(
3364
0
     error,
3365
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3366
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3367
0
     "%s: invalid directory name length value exceeds maximum.",
3368
0
     function );
3369
3370
0
    return( -1 );
3371
0
  }
3372
0
  if( filename == NULL )
3373
0
  {
3374
0
    libcerror_error_set(
3375
0
     error,
3376
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3377
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3378
0
     "%s: invalid filename.",
3379
0
     function );
3380
3381
0
    return( -1 );
3382
0
  }
3383
0
  if( filename_length > (size_t) SSIZE_MAX )
3384
0
  {
3385
0
    libcerror_error_set(
3386
0
     error,
3387
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3388
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3389
0
     "%s: invalid filename length value exceeds maximum.",
3390
0
     function );
3391
3392
0
    return( -1 );
3393
0
  }
3394
/* TODO strip other patterns like /./ */
3395
0
  while( directory_name_length > 0 )
3396
0
  {
3397
0
    if( directory_name[ directory_name_length - 1 ] != (char) LIBCPATH_SEPARATOR )
3398
0
    {
3399
0
      break;
3400
0
    }
3401
0
    directory_name_length--;
3402
0
  }
3403
0
  while( filename_length > 0 )
3404
0
  {
3405
0
    if( filename[ filename_index ] != (char) LIBCPATH_SEPARATOR )
3406
0
    {
3407
0
      break;
3408
0
    }
3409
0
    filename_index++;
3410
0
    filename_length--;
3411
0
  }
3412
0
  *path_size = directory_name_length + filename_length + 2;
3413
3414
0
  *path = narrow_string_allocate(
3415
0
           *path_size );
3416
3417
0
  if( *path == NULL )
3418
0
  {
3419
0
    libcerror_error_set(
3420
0
     error,
3421
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
3422
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
3423
0
     "%s: unable to create path.",
3424
0
     function );
3425
3426
0
    goto on_error;
3427
0
  }
3428
0
  if( narrow_string_copy(
3429
0
       *path,
3430
0
       directory_name,
3431
0
       directory_name_length ) == NULL )
3432
0
  {
3433
0
    libcerror_error_set(
3434
0
     error,
3435
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
3436
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
3437
0
     "%s: unable to copy directory name to path.",
3438
0
     function );
3439
3440
0
    goto on_error;
3441
0
  }
3442
0
  path_index = directory_name_length;
3443
3444
0
  ( *path )[ path_index++ ] = (char) LIBCPATH_SEPARATOR;
3445
3446
0
  if( narrow_string_copy(
3447
0
       &( ( *path )[ path_index ] ),
3448
0
       &( filename[ filename_index ] ),
3449
0
       filename_length ) == NULL )
3450
0
  {
3451
0
    libcerror_error_set(
3452
0
     error,
3453
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3454
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
3455
0
     "%s: unable to copy filename to path.",
3456
0
     function );
3457
3458
0
    goto on_error;
3459
0
  }
3460
0
  path_index += filename_length;
3461
3462
0
  ( *path )[ path_index ] = 0;
3463
3464
0
  return( 1 );
3465
3466
0
on_error:
3467
0
  if( *path != NULL )
3468
0
  {
3469
0
    memory_free(
3470
0
     *path );
3471
3472
0
    *path = NULL;
3473
0
  }
3474
0
  *path_size = 0;
3475
3476
0
  return( -1 );
3477
0
}
3478
3479
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
3480
3481
/* Cross Windows safe version of CreateDirectoryA
3482
 * Returns TRUE if successful or FALSE on error
3483
 */
3484
BOOL libcpath_CreateDirectoryA(
3485
      LPCSTR path,
3486
      SECURITY_ATTRIBUTES *security_attributes )
3487
{
3488
  FARPROC function       = NULL;
3489
  HMODULE library_handle = NULL;
3490
  BOOL result            = FALSE;
3491
3492
  if( path == NULL )
3493
  {
3494
    return( 0 );
3495
  }
3496
  library_handle = LoadLibrary(
3497
                    _SYSTEM_STRING( "kernel32.dll" ) );
3498
3499
  if( library_handle == NULL )
3500
  {
3501
    return( 0 );
3502
  }
3503
  function = GetProcAddress(
3504
        library_handle,
3505
        (LPCSTR) "CreateDirectoryA" );
3506
3507
  if( function != NULL )
3508
  {
3509
    result = function(
3510
        path,
3511
        security_attributes );
3512
  }
3513
  /* This call should be after using the function
3514
   * in most cases kernel32.dll will still be available after free
3515
   */
3516
  if( FreeLibrary(
3517
       library_handle ) != TRUE )
3518
  {
3519
    libcpath_CloseHandle(
3520
     library_handle );
3521
3522
    return( 0 );
3523
  }
3524
  return( result );
3525
}
3526
3527
#endif /* defined( WINAPI ) && ( WINVER <= 0x0500 ) */
3528
3529
#if defined( WINAPI )
3530
3531
/* Makes the directory
3532
 * This function uses the WINAPI function for Windows XP (0x0501) or later
3533
 * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
3534
 * Returns 1 if successful or -1 on error
3535
 */
3536
int libcpath_path_make_directory(
3537
     const char *directory_name,
3538
     libcerror_error_t **error )
3539
{
3540
  static char *function = "libcpath_path_make_directory";
3541
  DWORD error_code      = 0;
3542
3543
  if( directory_name == NULL )
3544
  {
3545
    libcerror_error_set(
3546
     error,
3547
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3548
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3549
     "%s: invalid directory name.",
3550
     function );
3551
3552
    return( -1 );
3553
  }
3554
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
3555
  if( libcpath_CreateDirectoryA(
3556
       directory_name,
3557
       NULL ) == 0 )
3558
#else
3559
  if( CreateDirectoryA(
3560
       directory_name,
3561
       NULL ) == 0 )
3562
#endif
3563
  {
3564
    error_code = GetLastError();
3565
3566
    libcerror_system_set_error(
3567
     error,
3568
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3569
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3570
     error_code,
3571
     "%s: unable to make directory.",
3572
     function );
3573
3574
    return( -1 );
3575
  }
3576
  return( 1 );
3577
}
3578
3579
#elif defined( HAVE_MKDIR )
3580
3581
/* Makes the directory
3582
 * This function uses the POSIX mkdir function or equivalent
3583
 * Returns 1 if successful or -1 on error
3584
 */
3585
int libcpath_path_make_directory(
3586
     const char *directory_name,
3587
     libcerror_error_t **error )
3588
0
{
3589
0
  static char *function = "libcpath_path_make_directory";
3590
3591
0
  if( directory_name == NULL )
3592
0
  {
3593
0
    libcerror_error_set(
3594
0
     error,
3595
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3596
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3597
0
     "%s: invalid directory name.",
3598
0
     function );
3599
3600
0
    return( -1 );
3601
0
  }
3602
0
  if( mkdir(
3603
0
       directory_name,
3604
0
       0755 ) != 0 )
3605
0
  {
3606
0
    libcerror_system_set_error(
3607
0
     error,
3608
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3609
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3610
0
     errno,
3611
0
     "%s: unable to make directory.",
3612
0
     function );
3613
3614
0
    return( -1 );
3615
0
  }
3616
3617
0
  return( 1 );
3618
0
}
3619
3620
#else
3621
#error Missing make directory function
3622
#endif
3623
3624
#if defined( HAVE_WIDE_CHARACTER_TYPE )
3625
3626
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
3627
3628
/* Cross Windows safe version of SetCurrentDirectoryW
3629
 * Returns TRUE if successful or FALSE on error
3630
 */
3631
BOOL libcpath_SetCurrentDirectoryW(
3632
      LPCWSTR path )
3633
{
3634
  FARPROC function       = NULL;
3635
  HMODULE library_handle = NULL;
3636
  BOOL result            = FALSE;
3637
3638
  if( path == NULL )
3639
  {
3640
    return( FALSE );
3641
  }
3642
  library_handle = LoadLibrary(
3643
                    _SYSTEM_STRING( "kernel32.dll" ) );
3644
3645
  if( library_handle == NULL )
3646
  {
3647
    return( FALSE );
3648
  }
3649
  function = GetProcAddress(
3650
        library_handle,
3651
        (LPCSTR) "SetCurrentDirectoryW" );
3652
3653
  if( function != NULL )
3654
  {
3655
    result = function(
3656
        path );
3657
  }
3658
  /* This call should be after using the function
3659
   * in most cases kernel32.dll will still be available after free
3660
   */
3661
  if( FreeLibrary(
3662
       library_handle ) != TRUE )
3663
  {
3664
    libcpath_CloseHandle(
3665
     library_handle );
3666
3667
    return( FALSE );
3668
  }
3669
  return( result );
3670
}
3671
3672
#endif /* defined( WINAPI ) && ( WINVER <= 0x0500 ) */
3673
3674
#if defined( WINAPI )
3675
3676
/* Changes the directory
3677
 * This function uses the WINAPI function for Windows XP (0x0501) or later
3678
 * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
3679
 * Returns 1 if successful or -1 on error
3680
 */
3681
int libcpath_path_change_directory_wide(
3682
     const wchar_t *directory_name,
3683
     libcerror_error_t **error )
3684
{
3685
  static char *function = "libcpath_path_change_directory_wide";
3686
  DWORD error_code      = 0;
3687
3688
  if( directory_name == NULL )
3689
  {
3690
    libcerror_error_set(
3691
     error,
3692
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3693
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3694
     "%s: invalid directory name.",
3695
     function );
3696
3697
    return( -1 );
3698
  }
3699
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
3700
  if( libcpath_SetCurrentDirectoryW(
3701
       directory_name ) == 0 )
3702
#else
3703
  if( SetCurrentDirectoryW(
3704
       directory_name ) == 0 )
3705
#endif
3706
  {
3707
    error_code = GetLastError();
3708
3709
    libcerror_system_set_error(
3710
     error,
3711
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3712
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3713
     error_code,
3714
     "%s: unable to change directory.",
3715
     function );
3716
3717
    return( -1 );
3718
  }
3719
  return( 1 );
3720
}
3721
3722
#elif defined( HAVE_CHDIR )
3723
3724
/* Changes the directory
3725
 * This function uses the POSIX chdir function or equivalent
3726
 * Returns 1 if successful or -1 on error
3727
 */
3728
int libcpath_path_change_directory_wide(
3729
     const wchar_t *directory_name,
3730
     libcerror_error_t **error )
3731
{
3732
  static char *function             = "libcpath_path_change_directory_wide";
3733
  char *narrow_directory_name       = 0;
3734
  size_t directory_name_length      = 0;
3735
  size_t narrow_directory_name_size = 0;
3736
3737
  if( directory_name == NULL )
3738
  {
3739
    libcerror_error_set(
3740
     error,
3741
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3742
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3743
     "%s: invalid directory name.",
3744
     function );
3745
3746
    return( -1 );
3747
  }
3748
  directory_name_length = wide_string_length(
3749
                           directory_name );
3750
3751
  if( libcpath_system_string_size_from_wide_string(
3752
       directory_name,
3753
       directory_name_length + 1,
3754
       &narrow_directory_name_size,
3755
       error ) != 1 )
3756
  {
3757
    libcerror_error_set(
3758
     error,
3759
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
3760
     LIBCERROR_CONVERSION_ERROR_GENERIC,
3761
     "%s: unable to determine narrow directory name size.",
3762
     function );
3763
3764
    goto on_error;
3765
  }
3766
  if( ( narrow_directory_name_size > (size_t) SSIZE_MAX )
3767
   || ( ( sizeof( char ) * narrow_directory_name_size )  > (size_t) SSIZE_MAX ) )
3768
  {
3769
    libcerror_error_set(
3770
     error,
3771
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3772
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
3773
     "%s: invalid narrow directory name size value exceeds maximum.",
3774
     function );
3775
3776
    goto on_error;
3777
  }
3778
  narrow_directory_name = narrow_string_allocate(
3779
                           narrow_directory_name_size );
3780
3781
  if( narrow_directory_name == NULL )
3782
  {
3783
    libcerror_error_set(
3784
     error,
3785
     LIBCERROR_ERROR_DOMAIN_MEMORY,
3786
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
3787
     "%s: unable to create narrow directory name.",
3788
     function );
3789
3790
    goto on_error;
3791
  }
3792
  if( libcpath_system_string_copy_from_wide_string(
3793
       narrow_directory_name,
3794
       narrow_directory_name_size,
3795
       directory_name,
3796
       directory_name_length + 1,
3797
       error ) != 1 )
3798
  {
3799
    libcerror_error_set(
3800
     error,
3801
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
3802
     LIBCERROR_CONVERSION_ERROR_GENERIC,
3803
     "%s: unable to set name.",
3804
     function );
3805
3806
    goto on_error;
3807
  }
3808
  if( chdir(
3809
       narrow_directory_name ) != 0 )
3810
  {
3811
    libcerror_system_set_error(
3812
     error,
3813
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3814
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3815
     errno,
3816
     "%s: unable to change directory.",
3817
     function );
3818
3819
    return( -1 );
3820
  }
3821
  memory_free(
3822
   narrow_directory_name );
3823
3824
  return( 1 );
3825
3826
on_error:
3827
  if( narrow_directory_name != NULL )
3828
  {
3829
    memory_free(
3830
     narrow_directory_name );
3831
  }
3832
  return( -1 );
3833
}
3834
3835
#else
3836
#error Missing change directory function
3837
#endif
3838
3839
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
3840
3841
/* Cross Windows safe version of GetCurrentDirectoryW
3842
 * Returns the number of characters in the current directory string or 0 on error
3843
 */
3844
DWORD libcpath_GetCurrentDirectoryW(
3845
       DWORD buffer_size,
3846
       LPCWSTR buffer )
3847
{
3848
  FARPROC function       = NULL;
3849
  HMODULE library_handle = NULL;
3850
  DWORD result           = 0;
3851
3852
  library_handle = LoadLibrary(
3853
                    _SYSTEM_STRING( "kernel32.dll" ) );
3854
3855
  if( library_handle == NULL )
3856
  {
3857
    return( 0 );
3858
  }
3859
  function = GetProcAddress(
3860
        library_handle,
3861
        (LPCSTR) "GetCurrentDirectoryW" );
3862
3863
  if( function != NULL )
3864
  {
3865
    result = function(
3866
        buffer_size,
3867
        buffer );
3868
  }
3869
  /* This call should be after using the function
3870
   * in most cases kernel32.dll will still be available after free
3871
   */
3872
  if( FreeLibrary(
3873
       library_handle ) != TRUE )
3874
  {
3875
    libcpath_CloseHandle(
3876
     library_handle );
3877
3878
    return( 0 );
3879
  }
3880
  return( result );
3881
}
3882
3883
#endif /* defined( WINAPI ) && ( WINVER <= 0x0500 ) */
3884
3885
#if defined( WINAPI )
3886
3887
/* Retrieves the current working directory
3888
 * This function uses the WINAPI function for Windows XP (0x0501) or later
3889
 * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
3890
 * Returns 1 if successful or -1 on error
3891
 */
3892
int libcpath_path_get_current_working_directory_wide(
3893
     wchar_t **current_working_directory,
3894
     size_t *current_working_directory_size,
3895
     libcerror_error_t **error )
3896
{
3897
  static char *function                     = "libcpath_path_get_current_working_directory_wide";
3898
  DWORD safe_current_working_directory_size = 0;
3899
  DWORD error_code                          = 0;
3900
3901
  if( current_working_directory == NULL )
3902
  {
3903
    libcerror_error_set(
3904
     error,
3905
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3906
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3907
     "%s: invalid current working directory.",
3908
     function );
3909
3910
    return( -1 );
3911
  }
3912
  if( *current_working_directory != NULL )
3913
  {
3914
    libcerror_error_set(
3915
     error,
3916
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3917
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3918
     "%s: invalid current working directory value already set.",
3919
     function );
3920
3921
    return( -1 );
3922
  }
3923
  if( current_working_directory_size == NULL )
3924
  {
3925
    libcerror_error_set(
3926
     error,
3927
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3928
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3929
     "%s: invalid current working directory size.",
3930
     function );
3931
3932
    return( -1 );
3933
  }
3934
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
3935
  safe_current_working_directory_size = libcpath_GetCurrentDirectoryW(
3936
                                         0,
3937
                                         NULL );
3938
#else
3939
  safe_current_working_directory_size = GetCurrentDirectoryW(
3940
                                         0,
3941
                                         NULL );
3942
#endif
3943
  if( safe_current_working_directory_size == 0 )
3944
  {
3945
    libcerror_error_set(
3946
     error,
3947
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3948
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3949
     "%s: unable to retrieve current working directory size.",
3950
     function );
3951
3952
    goto on_error;
3953
  }
3954
  if( (size_t) safe_current_working_directory_size > (size_t) SSIZE_MAX )
3955
  {
3956
    libcerror_error_set(
3957
     error,
3958
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3959
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3960
     "%s: current working directory size value out of bounds.",
3961
     function );
3962
3963
    goto on_error;
3964
  }
3965
  *current_working_directory_size = (size_t) safe_current_working_directory_size;
3966
3967
  *current_working_directory = wide_string_allocate(
3968
                                *current_working_directory_size );
3969
3970
  if( *current_working_directory == NULL )
3971
  {
3972
    libcerror_error_set(
3973
     error,
3974
     LIBCERROR_ERROR_DOMAIN_MEMORY,
3975
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
3976
     "%s: unable to create current working directory.",
3977
     function );
3978
3979
    goto on_error;
3980
  }
3981
  if( memory_set(
3982
       *current_working_directory,
3983
       0,
3984
       sizeof( wchar_t ) * *current_working_directory_size ) == NULL )
3985
  {
3986
    libcerror_error_set(
3987
     error,
3988
     LIBCERROR_ERROR_DOMAIN_MEMORY,
3989
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
3990
     "%s: unable to clear current working directory.",
3991
     function );
3992
3993
    goto on_error;
3994
  }
3995
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
3996
  if( libcpath_GetCurrentDirectoryW(
3997
       safe_current_working_directory_size,
3998
       *current_working_directory ) != ( safe_current_working_directory_size - 1 ) )
3999
#else
4000
  if( GetCurrentDirectoryW(
4001
       safe_current_working_directory_size,
4002
       *current_working_directory ) != ( safe_current_working_directory_size - 1 ) )
4003
#endif
4004
  {
4005
    error_code = GetLastError();
4006
4007
    libcerror_system_set_error(
4008
     error,
4009
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4010
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4011
     error_code,
4012
     "%s: unable to retrieve current working directory.",
4013
     function );
4014
4015
    goto on_error;
4016
  }
4017
  return( 1 );
4018
4019
on_error:
4020
  if( *current_working_directory != NULL )
4021
  {
4022
    memory_free(
4023
     *current_working_directory );
4024
4025
    *current_working_directory = NULL;
4026
  }
4027
  *current_working_directory_size = 0;
4028
4029
  return( -1 );
4030
}
4031
4032
#elif defined( HAVE_GETCWD )
4033
4034
/* Retrieves the current working directory
4035
 * This function uses the POSIX getcwd function or equivalent
4036
 * Returns 1 if successful or -1 on error
4037
 */
4038
int libcpath_path_get_current_working_directory_wide(
4039
     wchar_t **current_working_directory,
4040
     size_t *current_working_directory_size,
4041
     libcerror_error_t **error )
4042
{
4043
  static char *function                          = "libcpath_path_get_current_working_directory_wide";
4044
  char *narrow_current_working_directory         = 0;
4045
  size_t narrow_current_working_directory_length = 0;
4046
4047
  if( current_working_directory == NULL )
4048
  {
4049
    libcerror_error_set(
4050
     error,
4051
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4052
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4053
     "%s: invalid current working directory.",
4054
     function );
4055
4056
    return( -1 );
4057
  }
4058
  if( *current_working_directory != NULL )
4059
  {
4060
    libcerror_error_set(
4061
     error,
4062
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4063
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4064
     "%s: invalid current working directory value already set.",
4065
     function );
4066
4067
    return( -1 );
4068
  }
4069
  if( current_working_directory_size == NULL )
4070
  {
4071
    libcerror_error_set(
4072
     error,
4073
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4074
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4075
     "%s: invalid current working directory size.",
4076
     function );
4077
4078
    return( -1 );
4079
  }
4080
  narrow_current_working_directory = narrow_string_allocate(
4081
                                      PATH_MAX );
4082
4083
  if( narrow_current_working_directory == NULL )
4084
  {
4085
    libcerror_error_set(
4086
     error,
4087
     LIBCERROR_ERROR_DOMAIN_MEMORY,
4088
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
4089
     "%s: unable to create narrow current working directory.",
4090
     function );
4091
4092
    goto on_error;
4093
  }
4094
  if( getcwd(
4095
       narrow_current_working_directory,
4096
       PATH_MAX ) == NULL )
4097
  {
4098
    libcerror_system_set_error(
4099
     error,
4100
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4101
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4102
     errno,
4103
     "%s: unable to retrieve current working directory.",
4104
     function );
4105
4106
    goto on_error;
4107
  }
4108
  narrow_current_working_directory_length = narrow_string_length(
4109
                                             narrow_current_working_directory );
4110
4111
  /* Convert the current working directory to a wide string
4112
   * if the platform has no wide character open function
4113
   */
4114
  if( libcpath_system_string_size_from_narrow_string(
4115
       narrow_current_working_directory,
4116
       narrow_current_working_directory_length + 1,
4117
       current_working_directory_size,
4118
       error ) != 1 )
4119
  {
4120
    libcerror_error_set(
4121
     error,
4122
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
4123
     LIBCERROR_CONVERSION_ERROR_GENERIC,
4124
     "%s: unable to determine wide character current working directory size.",
4125
     function );
4126
4127
    return( -1 );
4128
  }
4129
  *current_working_directory = wide_string_allocate(
4130
                                *current_working_directory_size );
4131
4132
  if( *current_working_directory == NULL )
4133
  {
4134
    libcerror_error_set(
4135
     error,
4136
     LIBCERROR_ERROR_DOMAIN_MEMORY,
4137
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
4138
     "%s: unable to create current working directory.",
4139
     function );
4140
4141
    goto on_error;
4142
  }
4143
  if( memory_set(
4144
       *current_working_directory,
4145
       0,
4146
       sizeof( wchar_t ) * *current_working_directory_size ) == NULL )
4147
  {
4148
    libcerror_error_set(
4149
     error,
4150
     LIBCERROR_ERROR_DOMAIN_MEMORY,
4151
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
4152
     "%s: unable to clear current working directory.",
4153
     function );
4154
4155
    goto on_error;
4156
  }
4157
  if( libcpath_system_string_copy_to_wide_string(
4158
       narrow_current_working_directory,
4159
       narrow_current_working_directory_length + 1,
4160
       *current_working_directory,
4161
       *current_working_directory_size,
4162
       error ) != 1 )
4163
  {
4164
    libcerror_error_set(
4165
     error,
4166
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
4167
     LIBCERROR_CONVERSION_ERROR_GENERIC,
4168
     "%s: unable to set current working directory.",
4169
     function );
4170
4171
    goto on_error;
4172
  }
4173
  memory_free(
4174
   narrow_current_working_directory );
4175
4176
  return( 1 );
4177
4178
on_error:
4179
  if( narrow_current_working_directory != NULL )
4180
  {
4181
    memory_free(
4182
     narrow_current_working_directory );
4183
  }
4184
  if( *current_working_directory != NULL )
4185
  {
4186
    memory_free(
4187
     *current_working_directory );
4188
4189
    *current_working_directory = NULL;
4190
  }
4191
  *current_working_directory_size = 0;
4192
4193
  return( -1 );
4194
}
4195
4196
#else
4197
#error Missing get current working directory function
4198
#endif
4199
4200
#if defined( WINAPI )
4201
4202
/* Determines the path type
4203
 * Returns 1 if succesful or -1 on error
4204
 */
4205
int libcpath_path_get_path_type_wide(
4206
     const wchar_t *path,
4207
     size_t path_length,
4208
     uint8_t *path_type,
4209
     libcerror_error_t **error )
4210
{
4211
  static char *function = "libcpath_path_get_path_type_wide";
4212
4213
  if( path == NULL )
4214
  {
4215
    libcerror_error_set(
4216
     error,
4217
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4218
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4219
     "%s: invalid path.",
4220
     function );
4221
4222
    return( -1 );
4223
  }
4224
  if( path_length == 0 )
4225
  {
4226
    libcerror_error_set(
4227
     error,
4228
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4229
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
4230
     "%s: invalid path length is zero.",
4231
     function );
4232
4233
    return( -1 );
4234
  }
4235
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
4236
  {
4237
    libcerror_error_set(
4238
     error,
4239
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4240
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4241
     "%s: invalid path length value exceeds maximum.",
4242
     function );
4243
4244
    return( -1 );
4245
  }
4246
  if( path_type == NULL )
4247
  {
4248
    libcerror_error_set(
4249
     error,
4250
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4251
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4252
     "%s: invalid path type.",
4253
     function );
4254
4255
    return( -1 );
4256
  }
4257
  *path_type = LIBCPATH_TYPE_RELATIVE;
4258
4259
  /* Determine if the path is a special path
4260
   * device path prefix:          \\.\
4261
   * extended-length path prefix: \\?\
4262
   */
4263
  if( ( path_length >= 4 )
4264
   && ( path[ 0 ] == (wchar_t) '\\' )
4265
   && ( path[ 1 ] == (wchar_t) '\\' )
4266
   && ( ( path[ 2 ] == (wchar_t) '.' )
4267
    ||  ( path[ 2 ] == (wchar_t) '?' ) )
4268
   && ( path[ 3 ] == (wchar_t) '\\' ) )
4269
  {
4270
    if( path[ 2 ] == (wchar_t) '.' )
4271
    {
4272
      *path_type = LIBCPATH_TYPE_DEVICE;
4273
    }
4274
    /* Determine if the path in an extended-length UNC path
4275
     * \\?\UNC\server\share
4276
     */
4277
    else if( ( path_length >= 8 )
4278
          && ( path[ 4 ] == (wchar_t) 'U' )
4279
          && ( path[ 5 ] == (wchar_t) 'N' )
4280
          && ( path[ 6 ] == (wchar_t) 'C' )
4281
          && ( path[ 7 ] == (wchar_t) '\\' ) )
4282
    {
4283
      *path_type = LIBCPATH_TYPE_EXTENDED_LENGTH_UNC;
4284
    }
4285
    else
4286
    {
4287
      *path_type = LIBCPATH_TYPE_EXTENDED_LENGTH;
4288
    }
4289
  }
4290
  /* Determine if the path is an UNC path
4291
   * \\server\share
4292
   */
4293
  else if( ( path_length >= 2 )
4294
        && ( path[ 0 ] == (wchar_t) '\\' )
4295
        && ( path[ 1 ] == (wchar_t) '\\' ) )
4296
  {
4297
    *path_type = LIBCPATH_TYPE_UNC;
4298
  }
4299
  else if( path[ 0 ] == (wchar_t) '\\' )
4300
  {
4301
    *path_type = LIBCPATH_TYPE_ABSOLUTE;
4302
  }
4303
  else if( ( path_length >= 3 )
4304
        && ( path[ 1 ] == (wchar_t) ':' )
4305
        && ( path[ 2 ] == (wchar_t) '\\' )
4306
        && ( ( ( path[ 0 ] >= (wchar_t) 'A' )
4307
          &&   ( path[ 0 ] <= (wchar_t) 'Z' ) )
4308
         ||  ( ( path[ 0 ] >= (wchar_t) 'a' )
4309
          &&   ( path[ 0 ] <= (wchar_t) 'z' ) ) ) )
4310
  {
4311
    *path_type = LIBCPATH_TYPE_ABSOLUTE;
4312
  }
4313
  return( 1 );
4314
}
4315
4316
/* Determines the volume name
4317
 * Returns 1 if succesful or -1 on error
4318
 */
4319
int libcpath_path_get_volume_name_wide(
4320
     const wchar_t *path,
4321
     size_t path_length,
4322
     wchar_t **volume_name,
4323
     size_t *volume_name_length,
4324
     size_t *directory_name_index,
4325
     libcerror_error_t **error )
4326
{
4327
  static char *function    = "libcpath_path_get_volume_name_wide";
4328
  size_t path_index        = 0;
4329
  size_t share_name_index  = 0;
4330
  size_t volume_name_index = 0;
4331
4332
  if( path == NULL )
4333
  {
4334
    libcerror_error_set(
4335
     error,
4336
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4337
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4338
     "%s: invalid path.",
4339
     function );
4340
4341
    return( -1 );
4342
  }
4343
  if( path_length == 0 )
4344
  {
4345
    libcerror_error_set(
4346
     error,
4347
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4348
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
4349
     "%s: invalid path length is zero.",
4350
     function );
4351
4352
    return( -1 );
4353
  }
4354
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
4355
  {
4356
    libcerror_error_set(
4357
     error,
4358
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4359
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4360
     "%s: invalid path length value exceeds maximum.",
4361
     function );
4362
4363
    return( -1 );
4364
  }
4365
  if( volume_name == NULL )
4366
  {
4367
    libcerror_error_set(
4368
     error,
4369
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4370
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4371
     "%s: invalid volume name.",
4372
     function );
4373
4374
    return( -1 );
4375
  }
4376
  if( volume_name_length == NULL )
4377
  {
4378
    libcerror_error_set(
4379
     error,
4380
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4381
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4382
     "%s: invalid volume name length.",
4383
     function );
4384
4385
    return( -1 );
4386
  }
4387
  if( directory_name_index == NULL )
4388
  {
4389
    libcerror_error_set(
4390
     error,
4391
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4392
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4393
     "%s: invalid directory name index.",
4394
     function );
4395
4396
    return( -1 );
4397
  }
4398
  *volume_name          = NULL;
4399
  *volume_name_length   = 0;
4400
  *directory_name_index = 0;
4401
4402
  /* Determine if the path is a special path
4403
   * device path prefix:          \\.\
4404
   * extended-length path prefix: \\?\
4405
   */
4406
  if( ( path_length >= 4 )
4407
   && ( path[ 0 ] == (wchar_t) '\\' )
4408
   && ( path[ 1 ] == (wchar_t) '\\' )
4409
   && ( ( path[ 2 ] == (wchar_t) '.' )
4410
    ||  ( path[ 2 ] == (wchar_t) '?' ) )
4411
   && ( path[ 3 ] == (wchar_t) '\\' ) )
4412
  {
4413
    if( path[ 2 ] == (wchar_t) '.' )
4414
    {
4415
      volume_name_index = 4;
4416
    }
4417
    /* Determine if the path in an extended-length UNC path
4418
     * \\?\UNC\server\share
4419
     */
4420
    else if( ( path_length >= 8 )
4421
          && ( path[ 4 ] == (wchar_t) 'U' )
4422
          && ( path[ 5 ] == (wchar_t) 'N' )
4423
          && ( path[ 6 ] == (wchar_t) 'C' )
4424
          && ( path[ 7 ] == (wchar_t) '\\' ) )
4425
    {
4426
      volume_name_index = 8;
4427
    }
4428
    else
4429
    {
4430
      volume_name_index = 4;
4431
    }
4432
  }
4433
  /* Determine if the path is an UNC path
4434
   * \\server\share
4435
   */
4436
  else if( ( path_length >= 2 )
4437
        && ( path[ 0 ] == (wchar_t) '\\' )
4438
        && ( path[ 1 ] == (wchar_t) '\\' ) )
4439
  {
4440
    volume_name_index = 2;
4441
  }
4442
  /* Check if the path contains a volume letter
4443
   */
4444
  if( ( path_length >= 2 )
4445
   && ( volume_name_index <= ( path_length - 2 ) )
4446
   && ( path[ volume_name_index + 1 ] == (wchar_t) ':' )
4447
   && ( ( ( path[ volume_name_index ] >= (wchar_t) 'A' )
4448
     &&   ( path[ volume_name_index ] <= (wchar_t) 'Z' ) )
4449
    ||  ( ( path[ volume_name_index ] >= (wchar_t) 'a' )
4450
     &&   ( path[ volume_name_index ] <= (wchar_t) 'z' ) ) ) )
4451
  {
4452
    path_index = volume_name_index + 2;
4453
4454
    if( ( path_index < path_length )
4455
     && ( path[ path_index ] == (wchar_t) '\\' ) )
4456
    {
4457
      path_index++;
4458
    }
4459
    *volume_name        = (wchar_t *) &( path[ volume_name_index ] );
4460
    *volume_name_length = path_index - volume_name_index;
4461
4462
    if( path[ path_index - 1 ] == (wchar_t) '\\' )
4463
    {
4464
      *volume_name_length -= 1;
4465
    }
4466
    *directory_name_index = path_index;
4467
  }
4468
  else if( volume_name_index == 4 )
4469
  {
4470
    for( path_index = volume_name_index;
4471
         path_index < path_length;
4472
         path_index++ )
4473
    {
4474
      if( path[ path_index ] == (wchar_t) '\\' )
4475
      {
4476
        path_index++;
4477
4478
        break;
4479
      }
4480
    }
4481
    *volume_name        = (wchar_t *) &( path[ 4 ] );
4482
    *volume_name_length = path_index - 4;
4483
4484
    if( path[ path_index - 1 ] == (wchar_t) '\\' )
4485
    {
4486
      *volume_name_length -= 1;
4487
    }
4488
    *directory_name_index = path_index;
4489
  }
4490
  else if( ( volume_name_index == 2 )
4491
        || ( volume_name_index == 8 ) )
4492
  {
4493
    for( share_name_index = volume_name_index;
4494
         share_name_index < path_length;
4495
         share_name_index++ )
4496
    {
4497
      if( path[ share_name_index ] == (wchar_t) '\\' )
4498
      {
4499
        share_name_index++;
4500
4501
        break;
4502
      }
4503
    }
4504
    if( share_name_index > path_length )
4505
    {
4506
      libcerror_error_set(
4507
       error,
4508
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4509
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4510
       "%s: invalid path - missing share name.",
4511
       function );
4512
4513
      return( -1 );
4514
    }
4515
    for( path_index = share_name_index;
4516
         path_index < path_length;
4517
         path_index++ )
4518
    {
4519
      if( path[ path_index ] == (wchar_t) '\\' )
4520
      {
4521
        path_index++;
4522
4523
        break;
4524
      }
4525
    }
4526
    *volume_name        = (wchar_t *) &( path[ volume_name_index ] );
4527
    *volume_name_length = path_index - volume_name_index;
4528
4529
    if( path[ path_index - 1 ] == (wchar_t) '\\' )
4530
    {
4531
      *volume_name_length -= 1;
4532
    }
4533
    *directory_name_index = path_index;
4534
  }
4535
  return( 1 );
4536
}
4537
4538
/* Retrieves the current working directory of a specific volume
4539
 * Returns 1 if successful or -1 on error
4540
 */
4541
int libcpath_path_get_current_working_directory_by_volume_wide(
4542
     wchar_t *volume_name,
4543
     size_t volume_name_length,
4544
     wchar_t **current_working_directory,
4545
     size_t *current_working_directory_size,
4546
     libcerror_error_t **error )
4547
{
4548
  wchar_t *change_volume_name                  = NULL;
4549
  wchar_t *current_volume_working_directory    = NULL;
4550
  static char *function                        = "libcpath_path_get_current_working_directory_by_volume_wide";
4551
  size_t current_volume_working_directory_size = 0;
4552
  int result                                   = 1;
4553
4554
  if( current_working_directory == NULL )
4555
  {
4556
    libcerror_error_set(
4557
     error,
4558
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4559
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4560
     "%s: invalid current working directory.",
4561
     function );
4562
4563
    return( -1 );
4564
  }
4565
  if( current_working_directory_size == NULL )
4566
  {
4567
    libcerror_error_set(
4568
     error,
4569
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4570
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4571
     "%s: invalid current working directory size.",
4572
     function );
4573
4574
    return( -1 );
4575
  }
4576
  /* If the path contains a volume name switch to that
4577
   * volume to determine the current directory
4578
   */
4579
  if( volume_name != NULL )
4580
  {
4581
    if( volume_name_length > (size_t) ( SSIZE_MAX - 1 ) )
4582
    {
4583
      libcerror_error_set(
4584
       error,
4585
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4586
       LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4587
       "%s: invalid volume name length value exceeds maximum.",
4588
       function );
4589
4590
      goto on_error;
4591
    }
4592
    if( libcpath_path_get_current_working_directory_wide(
4593
         &current_volume_working_directory,
4594
         &current_volume_working_directory_size,
4595
         error ) != 1 )
4596
    {
4597
      libcerror_error_set(
4598
       error,
4599
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4600
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4601
       "%s: unable to retrieve current volume working directory.",
4602
       function );
4603
4604
      goto on_error;
4605
    }
4606
    change_volume_name = wide_string_allocate(
4607
                          volume_name_length + 1 );
4608
4609
    if( change_volume_name == NULL )
4610
    {
4611
      libcerror_error_set(
4612
       error,
4613
       LIBCERROR_ERROR_DOMAIN_MEMORY,
4614
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
4615
       "%s: unable to create change volume name.",
4616
       function );
4617
4618
      goto on_error;
4619
    }
4620
    if( wide_string_copy(
4621
         change_volume_name,
4622
         volume_name,
4623
         volume_name_length ) == NULL )
4624
    {
4625
      libcerror_error_set(
4626
       error,
4627
       LIBCERROR_ERROR_DOMAIN_MEMORY,
4628
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
4629
       "%s: unable to set change volume name.",
4630
       function );
4631
4632
      goto on_error;
4633
    }
4634
    change_volume_name[ volume_name_length ] = 0;
4635
4636
    if( libcpath_path_change_directory_wide(
4637
         change_volume_name,
4638
         error ) != 1 )
4639
    {
4640
      libcerror_error_set(
4641
       error,
4642
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4643
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4644
       "%s: unable to change current working directory.",
4645
       function );
4646
4647
      goto on_error;
4648
    }
4649
    memory_free(
4650
     change_volume_name );
4651
4652
    change_volume_name = NULL;
4653
  }
4654
  if( libcpath_path_get_current_working_directory_wide(
4655
       current_working_directory,
4656
       current_working_directory_size,
4657
       error ) != 1 )
4658
  {
4659
    libcerror_error_set(
4660
     error,
4661
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4662
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4663
     "%s: unable to retrieve current directory.",
4664
     function );
4665
4666
    /* Make sure the current working directory has been changed
4667
     * back to its original value
4668
     */
4669
    result = -1;
4670
  }
4671
  if( current_volume_working_directory != NULL )
4672
  {
4673
    if( libcpath_path_change_directory_wide(
4674
         current_volume_working_directory,
4675
         error ) != 1 )
4676
    {
4677
      libcerror_error_set(
4678
       error,
4679
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4680
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4681
       "%s: unable to change current working directory.",
4682
       function );
4683
4684
      goto on_error;
4685
    }
4686
    memory_free(
4687
     current_volume_working_directory );
4688
4689
    current_volume_working_directory = NULL;
4690
  }
4691
  return( result );
4692
4693
on_error:
4694
  if( change_volume_name != NULL )
4695
  {
4696
    memory_free(
4697
     change_volume_name );
4698
  }
4699
  if( current_volume_working_directory != NULL )
4700
  {
4701
    memory_free(
4702
     current_volume_working_directory );
4703
  }
4704
  if( *current_working_directory != NULL )
4705
  {
4706
    memory_free(
4707
     *current_working_directory );
4708
4709
    *current_working_directory = NULL;
4710
  }
4711
  *current_working_directory_size = 0;
4712
4713
  return( -1 );
4714
}
4715
4716
/* Determines the full path of the Windows path specified
4717
 * The function uses the extended-length path format
4718
 * (path with \\?\ prefix)
4719
 *
4720
 * Multiple successive \ not at the start of the path are combined into one
4721
 *
4722
 * Scenario's that are considered full paths:
4723
 * Device path:     \\.\PhysicalDrive0
4724
 * Extended-length path:  \\?\C:\directory\file.txt
4725
 * Extended-length UNC path:  \\?\UNC\server\share\directory\file.txt
4726
 *
4727
 * Scenario's that are not considered full paths:
4728
 * Local 'absolute' path: \directory\file.txt
4729
 * Local 'relative' path: ..\directory\file.txt
4730
 * Local 'relative' path: .\directory\file.txt
4731
 * Volume 'absolute' path:  C:\directory\file.txt
4732
 *                              C:\..\directory\file.txt
4733
 * Volume 'relative' path:  C:directory\file.txt
4734
 * UNC path:      \\server\share\directory\file.txt
4735
 *
4736
 * Returns 1 if succesful or -1 on error
4737
 */
4738
int libcpath_path_get_full_path_wide(
4739
     const wchar_t *path,
4740
     size_t path_length,
4741
     wchar_t **full_path,
4742
     size_t *full_path_size,
4743
     libcerror_error_t **error )
4744
{
4745
  libcsplit_wide_split_string_t *current_directory_split_string = NULL;
4746
  libcsplit_wide_split_string_t *path_split_string              = NULL;
4747
  wchar_t *current_directory                                    = NULL;
4748
  wchar_t *current_directory_string_segment                     = NULL;
4749
  wchar_t *full_path_prefix                                     = NULL;
4750
  wchar_t *last_used_path_string_segment                        = NULL;
4751
  wchar_t *path_string_segment                                  = NULL;
4752
  wchar_t *volume_name                                          = NULL;
4753
  static char *function                                         = "libcpath_path_get_full_path_wide";
4754
  size_t current_directory_length                               = 0;
4755
  size_t current_directory_name_index                           = 0;
4756
  size_t current_directory_size                                 = 0;
4757
  size_t current_directory_string_segment_size                  = 0;
4758
  size_t full_path_index                                        = 0;
4759
  size_t full_path_prefix_length                                = 0;
4760
  size_t last_used_path_string_segment_size                     = 0;
4761
  size_t path_directory_name_index                              = 0;
4762
  size_t path_string_segment_size                               = 0;
4763
  size_t safe_full_path_size                                    = 0;
4764
  size_t volume_name_length                                     = 0;
4765
  uint8_t path_type                                             = LIBCPATH_TYPE_RELATIVE;
4766
  int current_directory_number_of_segments                      = 0;
4767
  int current_directory_segment_index                           = 0;
4768
  int last_used_path_segment_index                              = -1;
4769
  int path_number_of_segments                                   = 0;
4770
  int path_segment_index                                        = 0;
4771
4772
  if( path == NULL )
4773
  {
4774
    libcerror_error_set(
4775
     error,
4776
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4777
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4778
     "%s: invalid path.",
4779
     function );
4780
4781
    return( -1 );
4782
  }
4783
  if( path_length == 0 )
4784
  {
4785
    libcerror_error_set(
4786
     error,
4787
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4788
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
4789
     "%s: invalid path length is zero.",
4790
     function );
4791
4792
    return( -1 );
4793
  }
4794
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
4795
  {
4796
    libcerror_error_set(
4797
     error,
4798
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4799
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4800
     "%s: invalid path length value exceeds maximum.",
4801
     function );
4802
4803
    return( -1 );
4804
  }
4805
  if( full_path == NULL )
4806
  {
4807
    libcerror_error_set(
4808
     error,
4809
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4810
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4811
     "%s: invalid full path.",
4812
     function );
4813
4814
    return( -1 );
4815
  }
4816
  if( *full_path != NULL )
4817
  {
4818
    libcerror_error_set(
4819
     error,
4820
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4821
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4822
     "%s: invalid full path value already set.",
4823
     function );
4824
4825
    return( -1 );
4826
  }
4827
  if( full_path_size == NULL )
4828
  {
4829
    libcerror_error_set(
4830
     error,
4831
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4832
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4833
     "%s: invalid full path size.",
4834
     function );
4835
4836
    return( -1 );
4837
  }
4838
  if( libcpath_path_get_path_type_wide(
4839
       path,
4840
       path_length,
4841
       &path_type,
4842
       error ) != 1 )
4843
  {
4844
    libcerror_error_set(
4845
     error,
4846
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4847
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4848
     "%s: unable to determine path type.",
4849
     function );
4850
4851
    goto on_error;
4852
  }
4853
  if( libcpath_path_get_volume_name_wide(
4854
       path,
4855
       path_length,
4856
       &volume_name,
4857
       &volume_name_length,
4858
       &path_directory_name_index,
4859
       error ) != 1 )
4860
  {
4861
    libcerror_error_set(
4862
     error,
4863
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4864
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4865
     "%s: unable to determine volume name.",
4866
     function );
4867
4868
    goto on_error;
4869
  }
4870
  /* If the path is a device path, an extended-length path or an UNC
4871
   * do not bother to lookup the current working directory
4872
   */
4873
  if( ( path_type != LIBCPATH_TYPE_DEVICE )
4874
   && ( path_type != LIBCPATH_TYPE_EXTENDED_LENGTH )
4875
   && ( path_type != LIBCPATH_TYPE_EXTENDED_LENGTH_UNC )
4876
   && ( path_type != LIBCPATH_TYPE_UNC ) )
4877
  {
4878
    if( libcpath_path_get_current_working_directory_by_volume_wide(
4879
         volume_name,
4880
         volume_name_length,
4881
         &current_directory,
4882
         &current_directory_size,
4883
         error ) != 1 )
4884
    {
4885
      libcerror_error_set(
4886
       error,
4887
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4888
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4889
       "%s: unable to retrieve current working directory by volume.",
4890
       function );
4891
4892
      goto on_error;
4893
    }
4894
    /* Determine the volume name using the current working directory if necessary
4895
     */
4896
    if( libcpath_path_get_volume_name_wide(
4897
         current_directory,
4898
         current_directory_size - 1,
4899
         &volume_name,
4900
         &volume_name_length,
4901
         &current_directory_name_index,
4902
         error ) != 1 )
4903
    {
4904
      libcerror_error_set(
4905
       error,
4906
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4907
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4908
       "%s: unable to determine volume name from current working directory.",
4909
       function );
4910
4911
      goto on_error;
4912
    }
4913
  }
4914
  if( ( current_directory != NULL )
4915
   && ( current_directory_name_index < current_directory_size ) )
4916
  {
4917
    current_directory_length = wide_string_length(
4918
                                &( current_directory[ current_directory_name_index ] ) );
4919
4920
    if( libcsplit_wide_string_split(
4921
         &( current_directory[ current_directory_name_index ] ),
4922
         current_directory_length + 1,
4923
         (wchar_t) '\\',
4924
         &current_directory_split_string,
4925
         error ) != 1 )
4926
    {
4927
      libcerror_error_set(
4928
       error,
4929
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4930
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4931
       "%s: unable to split current working directory.",
4932
       function );
4933
4934
      goto on_error;
4935
    }
4936
  }
4937
  if( libcsplit_wide_string_split(
4938
       &( path[ path_directory_name_index ] ),
4939
       path_length - path_directory_name_index + 1,
4940
       (wchar_t) '\\',
4941
       &path_split_string,
4942
       error ) != 1 )
4943
  {
4944
    libcerror_error_set(
4945
     error,
4946
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4947
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4948
     "%s: unable to split path.",
4949
     function );
4950
4951
    goto on_error;
4952
  }
4953
  /* The full path prefix consists of "\\?\" or "\\.\"
4954
   */
4955
  full_path_prefix_length = 4;
4956
4957
  if( volume_name != NULL )
4958
  {
4959
    /* Add the volume name and a directory separator
4960
     */
4961
    full_path_prefix_length += volume_name_length + 1;
4962
  }
4963
  if( ( path_type == LIBCPATH_TYPE_EXTENDED_LENGTH_UNC )
4964
   || ( path_type == LIBCPATH_TYPE_UNC ) )
4965
  {
4966
    /* Add the UNC\ prefix
4967
     */
4968
    full_path_prefix_length += 4;
4969
  }
4970
  safe_full_path_size = 0;
4971
4972
  /* If the path is relative
4973
   * add the size of the current working directory
4974
   * a directory separator, if necessary
4975
   */
4976
  if( ( path_type == LIBCPATH_TYPE_RELATIVE )
4977
   && ( current_directory_name_index < current_directory_size ) )
4978
  {
4979
    safe_full_path_size += ( current_directory_size - ( current_directory_name_index + 1 ) );
4980
4981
    if( ( current_directory_size >= 2 )
4982
     && ( current_directory[ current_directory_size - 2 ] != (wchar_t) '\\' ) )
4983
    {
4984
      safe_full_path_size += 1;
4985
    }
4986
  }
4987
  if( current_directory_split_string != NULL )
4988
  {
4989
    if( libcsplit_wide_split_string_get_number_of_segments(
4990
         current_directory_split_string,
4991
         &current_directory_number_of_segments,
4992
         error ) != 1 )
4993
    {
4994
      libcerror_error_set(
4995
       error,
4996
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4997
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4998
       "%s: unable to retrieve number of current working directory string segments.",
4999
       function );
5000
5001
      goto on_error;
5002
    }
5003
    current_directory_segment_index = current_directory_number_of_segments - 1;
5004
  }
5005
  if( path_split_string != NULL )
5006
  {
5007
    if( libcsplit_wide_split_string_get_number_of_segments(
5008
         path_split_string,
5009
         &path_number_of_segments,
5010
         error ) != 1 )
5011
    {
5012
      libcerror_error_set(
5013
       error,
5014
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5015
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5016
       "%s: unable to retrieve number of path string segments.",
5017
       function );
5018
5019
      goto on_error;
5020
    }
5021
    for( path_segment_index = 0;
5022
         path_segment_index < path_number_of_segments;
5023
         path_segment_index++ )
5024
    {
5025
      if( libcsplit_wide_split_string_get_segment_by_index(
5026
           path_split_string,
5027
           path_segment_index,
5028
           &path_string_segment,
5029
           &path_string_segment_size,
5030
           error ) != 1 )
5031
      {
5032
        libcerror_error_set(
5033
         error,
5034
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5035
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5036
         "%s: unable to retrieve path string segment: %d.",
5037
         function,
5038
         path_segment_index );
5039
5040
        goto on_error;
5041
      }
5042
      if( path_string_segment == NULL )
5043
      {
5044
        libcerror_error_set(
5045
         error,
5046
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5047
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5048
         "%s: missing path string segment: %d.",
5049
         function,
5050
         path_segment_index );
5051
5052
        goto on_error;
5053
      }
5054
      /* If the path is .. reverse the current path by one directory
5055
       */
5056
      if( ( path_string_segment_size == 3 )
5057
       && ( path_string_segment[ 0 ] == (wchar_t) '.' )
5058
       && ( path_string_segment[ 1 ] == (wchar_t) '.' ) )
5059
      {
5060
        if( ( current_directory_split_string != NULL )
5061
         && ( last_used_path_segment_index == -1 ) )
5062
        {
5063
          if( libcsplit_wide_split_string_get_segment_by_index(
5064
               current_directory_split_string,
5065
               current_directory_segment_index,
5066
               &current_directory_string_segment,
5067
               &current_directory_string_segment_size,
5068
               error ) != 1 )
5069
          {
5070
            libcerror_error_set(
5071
             error,
5072
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
5073
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5074
             "%s: unable to retrieve current working directory string segment: %d.",
5075
             function,
5076
             current_directory_segment_index );
5077
5078
            goto on_error;
5079
          }
5080
          if( current_directory_string_segment == NULL )
5081
          {
5082
            libcerror_error_set(
5083
             error,
5084
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
5085
             LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5086
             "%s: missing current working directory string segment: %d.",
5087
             function,
5088
             current_directory_segment_index );
5089
5090
            goto on_error;
5091
          }
5092
          /* Remove the size of the parent directory name and a directory separator
5093
           * Note that the size includes the end of string character
5094
           */
5095
          if( current_directory_string_segment_size < safe_full_path_size )
5096
          {
5097
            safe_full_path_size -= current_directory_string_segment_size;
5098
          }
5099
          else
5100
          {
5101
            safe_full_path_size = 0;
5102
          }
5103
          if( libcsplit_wide_split_string_set_segment_by_index(
5104
               current_directory_split_string,
5105
               current_directory_segment_index,
5106
               NULL,
5107
               0,
5108
               error ) != 1 )
5109
          {
5110
            libcerror_error_set(
5111
             error,
5112
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
5113
             LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5114
             "%s: unable to set current working directory string segment: %d.",
5115
             function,
5116
             current_directory_segment_index );
5117
5118
            goto on_error;
5119
          }
5120
          current_directory_segment_index--;
5121
        }
5122
        else if( last_used_path_segment_index >= 0 )
5123
        {
5124
          if( libcsplit_wide_split_string_get_segment_by_index(
5125
               path_split_string,
5126
               last_used_path_segment_index,
5127
               &last_used_path_string_segment,
5128
               &last_used_path_string_segment_size,
5129
               error ) != 1 )
5130
          {
5131
            libcerror_error_set(
5132
             error,
5133
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
5134
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5135
             "%s: unable to retrieve last used path string segment: %d.",
5136
             function,
5137
             last_used_path_segment_index );
5138
5139
            goto on_error;
5140
          }
5141
          if( last_used_path_string_segment == NULL )
5142
          {
5143
            libcerror_error_set(
5144
             error,
5145
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
5146
             LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5147
             "%s: missing last used path string string segment: %d.",
5148
             function,
5149
             last_used_path_segment_index );
5150
5151
            goto on_error;
5152
          }
5153
          /* Remove the size of the parent directory name and a directory separator
5154
           * Note that the size includes the end of string character
5155
           */
5156
          if( last_used_path_string_segment_size < safe_full_path_size )
5157
          {
5158
            safe_full_path_size -= last_used_path_string_segment_size;
5159
          }
5160
          else
5161
          {
5162
            safe_full_path_size = 0;
5163
          }
5164
          if( libcsplit_wide_split_string_set_segment_by_index(
5165
               path_split_string,
5166
               last_used_path_segment_index,
5167
               NULL,
5168
               0,
5169
               error ) != 1 )
5170
          {
5171
            libcerror_error_set(
5172
             error,
5173
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
5174
             LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5175
             "%s: unable to set path string segment: %d.",
5176
             function,
5177
             last_used_path_segment_index );
5178
5179
            goto on_error;
5180
          }
5181
          /* Find the previous path split value that contains a name
5182
           */
5183
          while( last_used_path_segment_index > 0 )
5184
          {
5185
            last_used_path_segment_index--;
5186
5187
            if( libcsplit_wide_split_string_get_segment_by_index(
5188
                 path_split_string,
5189
                 last_used_path_segment_index,
5190
                 &last_used_path_string_segment,
5191
                 &last_used_path_string_segment_size,
5192
                 error ) != 1 )
5193
            {
5194
              libcerror_error_set(
5195
               error,
5196
               LIBCERROR_ERROR_DOMAIN_RUNTIME,
5197
               LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5198
               "%s: unable to retrieve last used path string segment: %d.",
5199
               function,
5200
               last_used_path_segment_index );
5201
5202
              goto on_error;
5203
            }
5204
            if( last_used_path_string_segment_size != 0 )
5205
            {
5206
              break;
5207
            }
5208
          }
5209
        }
5210
        if( libcsplit_wide_split_string_set_segment_by_index(
5211
             path_split_string,
5212
             path_segment_index,
5213
             NULL,
5214
             0,
5215
             error ) != 1 )
5216
        {
5217
          libcerror_error_set(
5218
           error,
5219
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
5220
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5221
           "%s: unable to set path string segment: %d.",
5222
           function,
5223
           path_segment_index );
5224
5225
          goto on_error;
5226
        }
5227
      }
5228
      /* If the path is . ignore the entry
5229
       */
5230
      else if( ( path_string_segment_size == 2 )
5231
            && ( path_string_segment[ 0 ] == (wchar_t) '.' ) )
5232
      {
5233
        if( libcsplit_wide_split_string_set_segment_by_index(
5234
             path_split_string,
5235
             path_segment_index,
5236
             NULL,
5237
             0,
5238
             error ) != 1 )
5239
        {
5240
          libcerror_error_set(
5241
           error,
5242
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
5243
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5244
           "%s: unable to set path string segment: %d.",
5245
           function,
5246
           path_segment_index );
5247
5248
          goto on_error;
5249
        }
5250
      }
5251
      /* If the path is empty ignore the entry
5252
       */
5253
      else if( path_string_segment_size <= 1 )
5254
      {
5255
        if( libcsplit_wide_split_string_set_segment_by_index(
5256
             path_split_string,
5257
             path_segment_index,
5258
             NULL,
5259
             0,
5260
             error ) != 1 )
5261
        {
5262
          libcerror_error_set(
5263
           error,
5264
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
5265
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5266
           "%s: unable to set path string segment: %d.",
5267
           function,
5268
           path_segment_index );
5269
5270
          goto on_error;
5271
        }
5272
      }
5273
      else
5274
      {
5275
        /* Add the size of the directory or file name and a directory separator
5276
         * Note that the size includes the end of string character
5277
         */
5278
        safe_full_path_size += path_string_segment_size;
5279
5280
        last_used_path_segment_index = path_segment_index;
5281
      }
5282
    }
5283
  }
5284
  safe_full_path_size += full_path_prefix_length;
5285
5286
  /* Note that the last path separator serves as the end of string
5287
   */
5288
  full_path_index = 0;
5289
5290
  *full_path = wide_string_allocate(
5291
                safe_full_path_size );
5292
5293
  if( *full_path == NULL )
5294
  {
5295
    libcerror_error_set(
5296
     error,
5297
     LIBCERROR_ERROR_DOMAIN_MEMORY,
5298
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
5299
     "%s: unable to create full path.",
5300
     function );
5301
5302
    goto on_error;
5303
  }
5304
  if( memory_set(
5305
       *full_path,
5306
       0,
5307
       sizeof( wchar_t ) * safe_full_path_size ) == NULL )
5308
  {
5309
    libcerror_error_set(
5310
     error,
5311
     LIBCERROR_ERROR_DOMAIN_MEMORY,
5312
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
5313
     "%s: unable to clear full path.",
5314
     function );
5315
5316
    goto on_error;
5317
  }
5318
  *full_path_size = safe_full_path_size;
5319
5320
  if( path_type == LIBCPATH_TYPE_DEVICE )
5321
  {
5322
    full_path_prefix        = L"\\\\.\\";
5323
    full_path_prefix_length = 4;
5324
  }
5325
  else
5326
  {
5327
    full_path_prefix        = L"\\\\?\\";
5328
    full_path_prefix_length = 4;
5329
  }
5330
  if( ( safe_full_path_size < full_path_prefix_length )
5331
   || ( full_path_index > ( safe_full_path_size - full_path_prefix_length ) ) )
5332
  {
5333
    libcerror_error_set(
5334
     error,
5335
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5336
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
5337
     "%s: invalid full path size value out of bounds.",
5338
     function );
5339
5340
    goto on_error;
5341
  }
5342
  if( wide_string_copy(
5343
       &( ( *full_path )[ full_path_index ] ),
5344
       full_path_prefix,
5345
       full_path_prefix_length ) == NULL )
5346
  {
5347
    libcerror_error_set(
5348
     error,
5349
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5350
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5351
     "%s: unable to set prefix in full path.",
5352
     function );
5353
5354
    goto on_error;
5355
  }
5356
  full_path_index += full_path_prefix_length;
5357
5358
  /* If there is a share name the path is an UNC path
5359
   */
5360
  if( ( path_type == LIBCPATH_TYPE_EXTENDED_LENGTH_UNC )
5361
   || ( path_type == LIBCPATH_TYPE_UNC ) )
5362
  {
5363
    if( ( safe_full_path_size < 4 )
5364
     || ( full_path_index > ( safe_full_path_size - 4 ) ) )
5365
    {
5366
      libcerror_error_set(
5367
       error,
5368
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5369
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
5370
       "%s: invalid full path size value out of bounds.",
5371
       function );
5372
5373
      goto on_error;
5374
    }
5375
    if( wide_string_copy(
5376
         &( ( *full_path )[ full_path_index ] ),
5377
         L"UNC\\",
5378
         4 ) == NULL )
5379
    {
5380
      libcerror_error_set(
5381
       error,
5382
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5383
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5384
       "%s: unable to set UNC\\ prefix in full path.",
5385
       function );
5386
5387
      goto on_error;
5388
    }
5389
    full_path_index += 4;
5390
  }
5391
  if( volume_name != NULL )
5392
  {
5393
    if( ( safe_full_path_size < volume_name_length )
5394
     || ( full_path_index > ( safe_full_path_size - volume_name_length ) ) )
5395
    {
5396
      libcerror_error_set(
5397
       error,
5398
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5399
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
5400
       "%s: invalid full path size value out of bounds.",
5401
       function );
5402
5403
      goto on_error;
5404
    }
5405
    if( wide_string_copy(
5406
         &( ( *full_path )[ full_path_index ] ),
5407
         volume_name,
5408
         volume_name_length ) == NULL )
5409
    {
5410
      libcerror_error_set(
5411
       error,
5412
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5413
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5414
       "%s: unable to set volume name in full path.",
5415
       function );
5416
5417
      goto on_error;
5418
    }
5419
    full_path_index += volume_name_length;
5420
5421
    ( *full_path )[ full_path_index ] = (wchar_t) '\\';
5422
5423
    full_path_index += 1;
5424
  }
5425
  /* If the path is relative
5426
   * add the current working directory elements
5427
   */
5428
  if( ( path_type == LIBCPATH_TYPE_RELATIVE )
5429
   && ( current_directory_split_string != NULL ) )
5430
  {
5431
    for( current_directory_segment_index = 0;
5432
         current_directory_segment_index < current_directory_number_of_segments;
5433
         current_directory_segment_index++ )
5434
    {
5435
      if( libcsplit_wide_split_string_get_segment_by_index(
5436
           current_directory_split_string,
5437
           current_directory_segment_index,
5438
           &current_directory_string_segment,
5439
           &current_directory_string_segment_size,
5440
           error ) != 1 )
5441
      {
5442
        libcerror_error_set(
5443
         error,
5444
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5445
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5446
         "%s: unable to retrieve current working directory string segment: %d.",
5447
         function,
5448
         current_directory_segment_index );
5449
5450
        goto on_error;
5451
      }
5452
      if( current_directory_string_segment_size != 0 )
5453
      {
5454
        if( current_directory_string_segment == NULL )
5455
        {
5456
          libcerror_error_set(
5457
           error,
5458
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
5459
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5460
           "%s: missing current working directory string segment: %d.",
5461
           function,
5462
           current_directory_segment_index );
5463
5464
          goto on_error;
5465
        }
5466
        if( ( safe_full_path_size < ( current_directory_string_segment_size - 1 ) )
5467
         || ( full_path_index > ( safe_full_path_size - ( current_directory_string_segment_size - 1 ) ) ) )
5468
        {
5469
          libcerror_error_set(
5470
           error,
5471
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5472
           LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
5473
           "%s: invalid full path size value out of bounds.",
5474
           function );
5475
5476
          goto on_error;
5477
        }
5478
        if( wide_string_copy(
5479
             &( ( *full_path )[ full_path_index ] ),
5480
             current_directory_string_segment,
5481
             current_directory_string_segment_size - 1 ) == NULL )
5482
        {
5483
          libcerror_error_set(
5484
           error,
5485
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
5486
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5487
           "%s: unable to set current working directory split value: %d in full path.",
5488
           function,
5489
           current_directory_segment_index );
5490
5491
          goto on_error;
5492
        }
5493
        full_path_index += current_directory_string_segment_size - 1;
5494
5495
        ( *full_path )[ full_path_index ] = (wchar_t) '\\';
5496
5497
        full_path_index += 1;
5498
      }
5499
    }
5500
  }
5501
  if( path_split_string != NULL )
5502
  {
5503
    for( path_segment_index = 0;
5504
         path_segment_index < path_number_of_segments;
5505
         path_segment_index++ )
5506
    {
5507
      if( libcsplit_wide_split_string_get_segment_by_index(
5508
           path_split_string,
5509
           path_segment_index,
5510
           &path_string_segment,
5511
           &path_string_segment_size,
5512
           error ) != 1 )
5513
      {
5514
        libcerror_error_set(
5515
         error,
5516
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5517
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5518
         "%s: unable to retrieve path string segment: %d.",
5519
         function,
5520
         path_segment_index );
5521
5522
        goto on_error;
5523
      }
5524
      if( path_string_segment_size != 0 )
5525
      {
5526
        if( path_string_segment == NULL )
5527
        {
5528
          libcerror_error_set(
5529
           error,
5530
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
5531
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5532
           "%s: missing path string segment: %d.",
5533
           function,
5534
           path_segment_index );
5535
5536
          goto on_error;
5537
        }
5538
        if( ( safe_full_path_size < ( path_string_segment_size - 1 ) )
5539
         || ( full_path_index > ( safe_full_path_size - ( path_string_segment_size - 1 ) ) ) )
5540
        {
5541
          libcerror_error_set(
5542
           error,
5543
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5544
           LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
5545
           "%s: invalid full path size value out of bounds.",
5546
           function );
5547
5548
          goto on_error;
5549
        }
5550
        if( wide_string_copy(
5551
             &( ( *full_path )[ full_path_index ] ),
5552
             path_string_segment,
5553
             path_string_segment_size - 1 ) == NULL )
5554
        {
5555
          libcerror_error_set(
5556
           error,
5557
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
5558
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5559
           "%s: unable to set path split value: %d in full path.",
5560
           function,
5561
           path_segment_index );
5562
5563
          goto on_error;
5564
        }
5565
        full_path_index += path_string_segment_size - 1;
5566
5567
        ( *full_path )[ full_path_index ] = (wchar_t) '\\';
5568
5569
        full_path_index += 1;
5570
      }
5571
    }
5572
  }
5573
  ( *full_path )[ full_path_index - 1 ] = 0;
5574
5575
  if( path_split_string != NULL )
5576
  {
5577
    if( libcsplit_wide_split_string_free(
5578
         &path_split_string,
5579
         error ) != 1 )
5580
    {
5581
      libcerror_error_set(
5582
       error,
5583
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5584
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
5585
       "%s: unable to free path split string.",
5586
       function );
5587
5588
      goto on_error;
5589
    }
5590
  }
5591
  if( current_directory_split_string != NULL )
5592
  {
5593
    if( libcsplit_wide_split_string_free(
5594
         &current_directory_split_string,
5595
         error ) != 1 )
5596
    {
5597
      libcerror_error_set(
5598
       error,
5599
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5600
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
5601
       "%s: unable to free current working directory split string.",
5602
       function );
5603
5604
      goto on_error;
5605
    }
5606
  }
5607
  if( current_directory != NULL )
5608
  {
5609
    memory_free(
5610
     current_directory );
5611
  }
5612
  return( 1 );
5613
5614
on_error:
5615
  if( *full_path != NULL )
5616
  {
5617
    memory_free(
5618
     *full_path );
5619
5620
    *full_path = NULL;
5621
  }
5622
  *full_path_size = 0;
5623
5624
  if( path_split_string != NULL )
5625
  {
5626
    libcsplit_wide_split_string_free(
5627
     &path_split_string,
5628
     NULL );
5629
  }
5630
  if( current_directory_split_string != NULL )
5631
  {
5632
    libcsplit_wide_split_string_free(
5633
     &current_directory_split_string,
5634
     NULL );
5635
  }
5636
  if( current_directory != NULL )
5637
  {
5638
    memory_free(
5639
     current_directory );
5640
  }
5641
  return( -1 );
5642
}
5643
5644
#else
5645
5646
/* Determines the full path of the POSIX path specified
5647
 * Multiple successive / are combined into one
5648
 *
5649
 * Scenarios:
5650
 * /home/user/file.txt
5651
 * /home/user//file.txt
5652
 * /home/user/../user/file.txt
5653
 * /../home/user/file.txt
5654
 * user/../user/file.txt
5655
 *
5656
 * Returns 1 if succesful or -1 on error
5657
 */
5658
int libcpath_path_get_full_path_wide(
5659
     const wchar_t *path,
5660
     size_t path_length,
5661
     wchar_t **full_path,
5662
     size_t *full_path_size,
5663
     libcerror_error_t **error )
5664
{
5665
  libcsplit_wide_split_string_t *current_directory_split_string = NULL;
5666
  libcsplit_wide_split_string_t *path_split_string              = NULL;
5667
  wchar_t *current_directory                                    = NULL;
5668
  wchar_t *current_directory_string_segment                     = NULL;
5669
  wchar_t *last_used_path_string_segment                        = NULL;
5670
  wchar_t *path_string_segment                                  = NULL;
5671
  static char *function                                         = "libcpath_path_get_full_path_wide";
5672
  size_t current_directory_length                               = 0;
5673
  size_t current_directory_size                                 = 0;
5674
  size_t current_directory_string_segment_size                  = 0;
5675
  size_t full_path_index                                        = 0;
5676
  size_t last_used_path_string_segment_size                     = 0;
5677
  size_t path_string_segment_size                               = 0;
5678
  size_t safe_full_path_size                                    = 0;
5679
  uint8_t path_type                                             = LIBCPATH_TYPE_RELATIVE;
5680
  int current_directory_number_of_segments                      = 0;
5681
  int current_directory_segment_index                           = 0;
5682
  int last_used_path_segment_index                              = -1;
5683
  int path_number_of_segments                                   = 0;
5684
  int path_segment_index                                        = 0;
5685
5686
  if( path == NULL )
5687
  {
5688
    libcerror_error_set(
5689
     error,
5690
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5691
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5692
     "%s: invalid path.",
5693
     function );
5694
5695
    return( -1 );
5696
  }
5697
  if( path_length == 0 )
5698
  {
5699
    libcerror_error_set(
5700
     error,
5701
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5702
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
5703
     "%s: invalid path length is zero.",
5704
     function );
5705
5706
    return( -1 );
5707
  }
5708
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
5709
  {
5710
    libcerror_error_set(
5711
     error,
5712
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5713
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
5714
     "%s: invalid path length value exceeds maximum.",
5715
     function );
5716
5717
    return( -1 );
5718
  }
5719
  if( full_path == NULL )
5720
  {
5721
    libcerror_error_set(
5722
     error,
5723
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5724
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5725
     "%s: invalid full path.",
5726
     function );
5727
5728
    return( -1 );
5729
  }
5730
  if( *full_path != NULL )
5731
  {
5732
    libcerror_error_set(
5733
     error,
5734
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5735
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
5736
     "%s: invalid full path value already set.",
5737
     function );
5738
5739
    return( -1 );
5740
  }
5741
  if( full_path_size == NULL )
5742
  {
5743
    libcerror_error_set(
5744
     error,
5745
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5746
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5747
     "%s: invalid full path size.",
5748
     function );
5749
5750
    return( -1 );
5751
  }
5752
  if( path[ 0 ] == (wchar_t) '/' )
5753
  {
5754
    path_type = LIBCPATH_TYPE_ABSOLUTE;
5755
  }
5756
  else
5757
  {
5758
    if( libcpath_path_get_current_working_directory_wide(
5759
         &current_directory,
5760
         &current_directory_size,
5761
         error ) != 1 )
5762
    {
5763
      libcerror_error_set(
5764
       error,
5765
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5766
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5767
       "%s: unable to retrieve current working directory.",
5768
       function );
5769
5770
      goto on_error;
5771
    }
5772
  }
5773
  if( current_directory != NULL )
5774
  {
5775
    current_directory_length = wide_string_length(
5776
                                current_directory );
5777
5778
    if( libcsplit_wide_string_split(
5779
         current_directory,
5780
         current_directory_length + 1,
5781
         (wchar_t) '/',
5782
         &current_directory_split_string,
5783
         error ) != 1 )
5784
    {
5785
      libcerror_error_set(
5786
       error,
5787
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5788
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
5789
       "%s: unable to split current working directory.",
5790
       function );
5791
5792
      goto on_error;
5793
    }
5794
  }
5795
  if( libcsplit_wide_string_split(
5796
       path,
5797
       path_length + 1,
5798
       (wchar_t) '/',
5799
       &path_split_string,
5800
       error ) != 1 )
5801
  {
5802
    libcerror_error_set(
5803
     error,
5804
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5805
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
5806
     "%s: unable to split path.",
5807
     function );
5808
5809
    goto on_error;
5810
  }
5811
  /* Determine the full path size
5812
   */
5813
  /* If the path is absolute
5814
   * a directory separator
5815
   */
5816
  if( path_type == LIBCPATH_TYPE_ABSOLUTE )
5817
  {
5818
    safe_full_path_size = 1;
5819
  }
5820
  /* If the path is relative
5821
   * add the size of the current working directory
5822
   * a directory separator, if necessary
5823
   */
5824
  else if( path_type == LIBCPATH_TYPE_RELATIVE )
5825
  {
5826
    if( current_directory == NULL )
5827
    {
5828
      libcerror_error_set(
5829
       error,
5830
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5831
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5832
       "%s: missing current working directory.",
5833
       function );
5834
5835
      goto on_error;
5836
    }
5837
    /* We need to use the length here since current_directory_size will be PATH_MAX
5838
     */
5839
    safe_full_path_size = current_directory_length;
5840
5841
    if( ( current_directory_length >= 1 )
5842
     && ( current_directory[ current_directory_length - 1 ] != (wchar_t) '/' ) )
5843
    {
5844
      safe_full_path_size++;
5845
    }
5846
  }
5847
  if( current_directory_split_string != NULL )
5848
  {
5849
    if( libcsplit_wide_split_string_get_number_of_segments(
5850
         current_directory_split_string,
5851
         &current_directory_number_of_segments,
5852
         error ) != 1 )
5853
    {
5854
      libcerror_error_set(
5855
       error,
5856
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5857
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5858
       "%s: unable to retrieve number of current working directory string segments.",
5859
       function );
5860
5861
      goto on_error;
5862
    }
5863
    current_directory_segment_index = current_directory_number_of_segments - 1;
5864
  }
5865
  if( path_split_string != NULL )
5866
  {
5867
    if( libcsplit_wide_split_string_get_number_of_segments(
5868
         path_split_string,
5869
         &path_number_of_segments,
5870
         error ) != 1 )
5871
    {
5872
      libcerror_error_set(
5873
       error,
5874
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5875
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5876
       "%s: unable to retrieve number of path string segments.",
5877
       function );
5878
5879
      goto on_error;
5880
    }
5881
    for( path_segment_index = 0;
5882
         path_segment_index < path_number_of_segments;
5883
         path_segment_index++ )
5884
    {
5885
      if( libcsplit_wide_split_string_get_segment_by_index(
5886
           path_split_string,
5887
           path_segment_index,
5888
           &path_string_segment,
5889
           &path_string_segment_size,
5890
           error ) != 1 )
5891
      {
5892
        libcerror_error_set(
5893
         error,
5894
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5895
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5896
         "%s: unable to retrieve path string segment: %d.",
5897
         function,
5898
         path_segment_index );
5899
5900
        goto on_error;
5901
      }
5902
      if( path_string_segment == NULL )
5903
      {
5904
        libcerror_error_set(
5905
         error,
5906
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5907
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5908
         "%s: missing path string segment: %d.",
5909
         function,
5910
         path_segment_index );
5911
5912
        goto on_error;
5913
      }
5914
      /* If the path is .. reverse the current path by one directory
5915
       */
5916
      if( ( path_string_segment_size == 3 )
5917
       && ( path_string_segment[ 0 ] == (wchar_t) '.' )
5918
       && ( path_string_segment[ 1 ] == (wchar_t) '.' ) )
5919
      {
5920
        if( ( current_directory_split_string != NULL )
5921
         && ( last_used_path_segment_index == -1 ) )
5922
        {
5923
          if( libcsplit_wide_split_string_get_segment_by_index(
5924
               current_directory_split_string,
5925
               current_directory_segment_index,
5926
               &current_directory_string_segment,
5927
               &current_directory_string_segment_size,
5928
               error ) != 1 )
5929
          {
5930
            libcerror_error_set(
5931
             error,
5932
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
5933
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5934
             "%s: unable to retrieve current working directory string segment: %d.",
5935
             function,
5936
             current_directory_segment_index );
5937
5938
            goto on_error;
5939
          }
5940
          if( current_directory_string_segment == NULL )
5941
          {
5942
            libcerror_error_set(
5943
             error,
5944
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
5945
             LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5946
             "%s: missing current working directory string segment: %d.",
5947
             function,
5948
             current_directory_segment_index );
5949
5950
            goto on_error;
5951
          }
5952
          /* Remove the size of the parent directory name and a directory separator
5953
           * Note that the size includes the end of string character
5954
           */
5955
          safe_full_path_size -= current_directory_string_segment_size;
5956
5957
          if( libcsplit_wide_split_string_set_segment_by_index(
5958
               current_directory_split_string,
5959
               current_directory_segment_index,
5960
               NULL,
5961
               0,
5962
               error ) != 1 )
5963
          {
5964
            libcerror_error_set(
5965
             error,
5966
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
5967
             LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5968
             "%s: unable to set current working directory string segment: %d.",
5969
             function,
5970
             current_directory_segment_index );
5971
5972
            goto on_error;
5973
          }
5974
          current_directory_segment_index--;
5975
        }
5976
        else if( last_used_path_segment_index >= 0 )
5977
        {
5978
          if( libcsplit_wide_split_string_get_segment_by_index(
5979
               path_split_string,
5980
               last_used_path_segment_index,
5981
               &last_used_path_string_segment,
5982
               &last_used_path_string_segment_size,
5983
               error ) != 1 )
5984
          {
5985
            libcerror_error_set(
5986
             error,
5987
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
5988
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5989
             "%s: unable to retrieve last used path string segment: %d.",
5990
             function,
5991
             last_used_path_segment_index );
5992
5993
            goto on_error;
5994
          }
5995
          if( last_used_path_string_segment == NULL )
5996
          {
5997
            libcerror_error_set(
5998
             error,
5999
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
6000
             LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
6001
             "%s: missing last used path string string segment: %d.",
6002
             function,
6003
             last_used_path_segment_index );
6004
6005
            goto on_error;
6006
          }
6007
          /* Remove the size of the parent directory name and a directory separator
6008
           * Note that the size includes the end of string character
6009
           */
6010
          safe_full_path_size -= last_used_path_string_segment_size;
6011
6012
          if( libcsplit_wide_split_string_set_segment_by_index(
6013
               path_split_string,
6014
               last_used_path_segment_index,
6015
               NULL,
6016
               0,
6017
               error ) != 1 )
6018
          {
6019
            libcerror_error_set(
6020
             error,
6021
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
6022
             LIBCERROR_RUNTIME_ERROR_SET_FAILED,
6023
             "%s: unable to set path string segment: %d.",
6024
             function,
6025
             last_used_path_segment_index );
6026
6027
            goto on_error;
6028
          }
6029
          /* Find the previous path split value that contains a name
6030
           */
6031
          while( last_used_path_segment_index > 0 )
6032
          {
6033
            last_used_path_segment_index--;
6034
6035
            if( libcsplit_wide_split_string_get_segment_by_index(
6036
                 path_split_string,
6037
                 last_used_path_segment_index,
6038
                 &last_used_path_string_segment,
6039
                 &last_used_path_string_segment_size,
6040
                 error ) != 1 )
6041
            {
6042
              libcerror_error_set(
6043
               error,
6044
               LIBCERROR_ERROR_DOMAIN_RUNTIME,
6045
               LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6046
               "%s: unable to retrieve last used path string segment: %d.",
6047
               function,
6048
               last_used_path_segment_index );
6049
6050
              goto on_error;
6051
            }
6052
            if( last_used_path_string_segment_size != 0 )
6053
            {
6054
              break;
6055
            }
6056
          }
6057
        }
6058
        if( libcsplit_wide_split_string_set_segment_by_index(
6059
             path_split_string,
6060
             path_segment_index,
6061
             NULL,
6062
             0,
6063
             error ) != 1 )
6064
        {
6065
          libcerror_error_set(
6066
           error,
6067
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
6068
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
6069
           "%s: unable to set path string segment: %d.",
6070
           function,
6071
           path_segment_index );
6072
6073
          goto on_error;
6074
        }
6075
      }
6076
      /* If the path is . ignore the entry
6077
       */
6078
      else if( ( path_string_segment_size == 2 )
6079
            && ( path_string_segment[ 0 ] == (wchar_t) '.' ) )
6080
      {
6081
        if( libcsplit_wide_split_string_set_segment_by_index(
6082
             path_split_string,
6083
             path_segment_index,
6084
             NULL,
6085
             0,
6086
             error ) != 1 )
6087
        {
6088
          libcerror_error_set(
6089
           error,
6090
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
6091
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
6092
           "%s: unable to set path string segment: %d.",
6093
           function,
6094
           path_segment_index );
6095
6096
          goto on_error;
6097
        }
6098
      }
6099
      /* If the path is empty ignore the entry
6100
       */
6101
      else if( path_string_segment_size <= 1 )
6102
      {
6103
        if( libcsplit_wide_split_string_set_segment_by_index(
6104
             path_split_string,
6105
             path_segment_index,
6106
             NULL,
6107
             0,
6108
             error ) != 1 )
6109
        {
6110
          libcerror_error_set(
6111
           error,
6112
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
6113
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
6114
           "%s: unable to set path string segment: %d.",
6115
           function,
6116
           path_segment_index );
6117
6118
          goto on_error;
6119
        }
6120
      }
6121
      else
6122
      {
6123
        /* Add the size of the directory or file name and a directory separator
6124
         * Note that the size includes the end of string character
6125
         */
6126
        safe_full_path_size += path_string_segment_size;
6127
6128
        last_used_path_segment_index = path_segment_index;
6129
      }
6130
    }
6131
  }
6132
  /* Note that the last path separator serves as the end of string
6133
   */
6134
  full_path_index = 0;
6135
6136
  *full_path = wide_string_allocate(
6137
                safe_full_path_size );
6138
6139
  if( *full_path == NULL )
6140
  {
6141
    libcerror_error_set(
6142
     error,
6143
     LIBCERROR_ERROR_DOMAIN_MEMORY,
6144
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
6145
     "%s: unable to create full path.",
6146
     function );
6147
6148
    goto on_error;
6149
  }
6150
  if( memory_set(
6151
       *full_path,
6152
       0,
6153
       sizeof( wchar_t ) * safe_full_path_size ) == NULL )
6154
  {
6155
    libcerror_error_set(
6156
     error,
6157
     LIBCERROR_ERROR_DOMAIN_MEMORY,
6158
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
6159
     "%s: unable to clear full path.",
6160
     function );
6161
6162
    goto on_error;
6163
  }
6164
  *full_path_size = safe_full_path_size;
6165
6166
  if( path_type == LIBCPATH_TYPE_ABSOLUTE )
6167
  {
6168
    ( *full_path )[ full_path_index ] = (wchar_t) '/';
6169
6170
    full_path_index += 1;
6171
  }
6172
  /* If the path is relative
6173
   * add the current working directory elements
6174
   */
6175
  if( ( path_type == LIBCPATH_TYPE_RELATIVE )
6176
   && ( current_directory_split_string != NULL ) )
6177
  {
6178
    for( current_directory_segment_index = 0;
6179
         current_directory_segment_index < current_directory_number_of_segments;
6180
         current_directory_segment_index++ )
6181
    {
6182
      if( libcsplit_wide_split_string_get_segment_by_index(
6183
           current_directory_split_string,
6184
           current_directory_segment_index,
6185
           &current_directory_string_segment,
6186
           &current_directory_string_segment_size,
6187
           error ) != 1 )
6188
      {
6189
        libcerror_error_set(
6190
         error,
6191
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
6192
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6193
         "%s: unable to retrieve current working directory string segment: %d.",
6194
         function,
6195
         current_directory_segment_index );
6196
6197
        goto on_error;
6198
      }
6199
      if( current_directory_string_segment_size != 0 )
6200
      {
6201
        if( current_directory_string_segment == NULL )
6202
        {
6203
          libcerror_error_set(
6204
           error,
6205
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
6206
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
6207
           "%s: missing current working directory string segment: %d.",
6208
           function,
6209
           current_directory_segment_index );
6210
6211
          goto on_error;
6212
        }
6213
        if( wide_string_copy(
6214
             &( ( *full_path )[ full_path_index ] ),
6215
             current_directory_string_segment,
6216
             current_directory_string_segment_size - 1 ) == NULL )
6217
        {
6218
          libcerror_error_set(
6219
           error,
6220
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
6221
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
6222
           "%s: unable to set current working directory split value: %d in full path.",
6223
           function,
6224
           current_directory_segment_index );
6225
6226
          goto on_error;
6227
        }
6228
        full_path_index += current_directory_string_segment_size - 1;
6229
6230
        ( *full_path )[ full_path_index ] = (wchar_t) '/';
6231
6232
        full_path_index += 1;
6233
      }
6234
    }
6235
  }
6236
  if( path_split_string != NULL )
6237
  {
6238
    for( path_segment_index = 0;
6239
         path_segment_index < path_number_of_segments;
6240
         path_segment_index++ )
6241
    {
6242
      if( libcsplit_wide_split_string_get_segment_by_index(
6243
           path_split_string,
6244
           path_segment_index,
6245
           &path_string_segment,
6246
           &path_string_segment_size,
6247
           error ) != 1 )
6248
      {
6249
        libcerror_error_set(
6250
         error,
6251
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
6252
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6253
         "%s: unable to retrieve path string segment: %d.",
6254
         function,
6255
         path_segment_index );
6256
6257
        goto on_error;
6258
      }
6259
      if( path_string_segment_size != 0 )
6260
      {
6261
        if( path_string_segment == NULL )
6262
        {
6263
          libcerror_error_set(
6264
           error,
6265
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
6266
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
6267
           "%s: missing path string segment: %d.",
6268
           function,
6269
           path_segment_index );
6270
6271
          goto on_error;
6272
        }
6273
        if( wide_string_copy(
6274
             &( ( *full_path )[ full_path_index ] ),
6275
             path_string_segment,
6276
             path_string_segment_size - 1 ) == NULL )
6277
        {
6278
          libcerror_error_set(
6279
           error,
6280
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
6281
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
6282
           "%s: unable to set path split value: %d in full path.",
6283
           function,
6284
           path_segment_index );
6285
6286
          goto on_error;
6287
        }
6288
        full_path_index += path_string_segment_size - 1;
6289
6290
        ( *full_path )[ full_path_index ] = (wchar_t) '/';
6291
6292
        full_path_index += 1;
6293
      }
6294
    }
6295
  }
6296
  ( *full_path )[ full_path_index - 1 ] = 0;
6297
6298
  if( path_split_string != NULL )
6299
  {
6300
    if( libcsplit_wide_split_string_free(
6301
         &path_split_string,
6302
         error ) != 1 )
6303
    {
6304
      libcerror_error_set(
6305
       error,
6306
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6307
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
6308
       "%s: unable to free path split string.",
6309
       function );
6310
6311
      goto on_error;
6312
    }
6313
  }
6314
  if( current_directory_split_string != NULL )
6315
  {
6316
    if( libcsplit_wide_split_string_free(
6317
         &current_directory_split_string,
6318
         error ) != 1 )
6319
    {
6320
      libcerror_error_set(
6321
       error,
6322
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6323
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
6324
       "%s: unable to free current working directory split string.",
6325
       function );
6326
6327
      goto on_error;
6328
    }
6329
  }
6330
  if( current_directory != NULL )
6331
  {
6332
    memory_free(
6333
     current_directory );
6334
  }
6335
  return( 1 );
6336
6337
on_error:
6338
  if( *full_path != NULL )
6339
  {
6340
    memory_free(
6341
     *full_path );
6342
6343
    *full_path = NULL;
6344
  }
6345
  *full_path_size = 0;
6346
6347
  if( path_split_string != NULL )
6348
  {
6349
    libcsplit_wide_split_string_free(
6350
     &path_split_string,
6351
     NULL );
6352
  }
6353
  if( current_directory_split_string != NULL )
6354
  {
6355
    libcsplit_wide_split_string_free(
6356
     &current_directory_split_string,
6357
     NULL );
6358
  }
6359
  if( current_directory != NULL )
6360
  {
6361
    memory_free(
6362
     current_directory );
6363
  }
6364
  return( -1 );
6365
}
6366
6367
#endif /* defined( WINAPI ) */
6368
6369
/* Retrieves the size of a sanitized version of the path character
6370
 * Returns 1 if successful or -1 on error
6371
 */
6372
int libcpath_path_get_sanitized_character_size_wide(
6373
     wchar_t character,
6374
     size_t *sanitized_character_size,
6375
     libcerror_error_t **error )
6376
{
6377
  static char *function = "libcpath_path_get_sanitized_character_size_wide";
6378
6379
  if( sanitized_character_size == NULL )
6380
  {
6381
    libcerror_error_set(
6382
     error,
6383
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6384
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6385
     "%s: invalid sanitized character size.",
6386
     function );
6387
6388
    return( -1 );
6389
  }
6390
  if( ( character >= 0x00 )
6391
   && ( character <= 0x1f ) )
6392
  {
6393
    *sanitized_character_size = 4;
6394
  }
6395
  else if( character == (wchar_t) LIBCPATH_ESCAPE_CHARACTER )
6396
  {
6397
    *sanitized_character_size = 2;
6398
  }
6399
#if defined( WINAPI )
6400
  else if( character == (wchar_t) '/' )
6401
  {
6402
    *sanitized_character_size = 4;
6403
  }
6404
#endif
6405
  else if( ( character == (wchar_t) '!' )
6406
        || ( character == (wchar_t) '$' )
6407
        || ( character == (wchar_t) '%' )
6408
        || ( character == (wchar_t) '&' )
6409
        || ( character == (wchar_t) '*' )
6410
        || ( character == (wchar_t) '+' )
6411
        || ( character == (wchar_t) ':' )
6412
        || ( character == (wchar_t) ';' )
6413
        || ( character == (wchar_t) '<' )
6414
        || ( character == (wchar_t) '>' )
6415
        || ( character == (wchar_t) '?' )
6416
        || ( character == (wchar_t) '|' )
6417
        || ( character == 0x7f ) )
6418
  {
6419
    *sanitized_character_size = 4;
6420
  }
6421
  else
6422
  {
6423
    *sanitized_character_size = 1;
6424
  }
6425
  return( 1 );
6426
}
6427
6428
/* Retrieves a sanitized version of the path character
6429
 * Returns 1 if successful or -1 on error
6430
 */
6431
int libcpath_path_get_sanitized_character_wide(
6432
     wchar_t character,
6433
     size_t sanitized_character_size,
6434
     wchar_t *sanitized_path,
6435
     size_t sanitized_path_size,
6436
     size_t *sanitized_path_index,
6437
     libcerror_error_t **error )
6438
{
6439
  static char *function            = "libcpath_path_get_sanitized_character_wide";
6440
  size_t safe_sanitized_path_index = 0;
6441
  wchar_t lower_nibble             = 0;
6442
  wchar_t upper_nibble             = 0;
6443
6444
  if( ( sanitized_character_size != 1 )
6445
   && ( sanitized_character_size != 2 )
6446
   && ( sanitized_character_size != 4 ) )
6447
  {
6448
    libcerror_error_set(
6449
     error,
6450
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6451
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
6452
     "%s: invalid sanitized character size value out of bounds.",
6453
     function );
6454
6455
    return( -1 );
6456
  }
6457
  if( sanitized_path == NULL )
6458
  {
6459
    libcerror_error_set(
6460
     error,
6461
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6462
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6463
     "%s: invalid sanitized path.",
6464
     function );
6465
6466
    return( -1 );
6467
  }
6468
  if( sanitized_path_size > (size_t) SSIZE_MAX )
6469
  {
6470
    libcerror_error_set(
6471
     error,
6472
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6473
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
6474
     "%s: invalid sanitized path size value exceeds maximum.",
6475
     function );
6476
6477
    return( -1 );
6478
  }
6479
  if( sanitized_path_index == NULL )
6480
  {
6481
    libcerror_error_set(
6482
     error,
6483
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6484
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6485
     "%s: invalid sanitized path index.",
6486
     function );
6487
6488
    return( -1 );
6489
  }
6490
  safe_sanitized_path_index = *sanitized_path_index;
6491
6492
  if( safe_sanitized_path_index > sanitized_path_size )
6493
  {
6494
    libcerror_error_set(
6495
     error,
6496
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6497
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
6498
     "%s: invalid sanitized path index value out of bounds.",
6499
     function );
6500
6501
    return( -1 );
6502
  }
6503
  if( ( sanitized_character_size > sanitized_path_size )
6504
   || ( safe_sanitized_path_index > ( sanitized_path_size - sanitized_character_size ) ) )
6505
  {
6506
    libcerror_error_set(
6507
     error,
6508
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6509
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
6510
     "%s: invalid sanitized path size value too small.",
6511
     function );
6512
6513
    return( -1 );
6514
  }
6515
  if( sanitized_character_size == 1 )
6516
  {
6517
    sanitized_path[ safe_sanitized_path_index++ ] = character;
6518
  }
6519
  else if( sanitized_character_size == 2 )
6520
  {
6521
    sanitized_path[ safe_sanitized_path_index++ ] = (wchar_t) LIBCPATH_ESCAPE_CHARACTER;
6522
    sanitized_path[ safe_sanitized_path_index++ ] = (wchar_t) LIBCPATH_ESCAPE_CHARACTER;
6523
  }
6524
  else if( sanitized_character_size == 4 )
6525
  {
6526
    lower_nibble = character & 0x0f;
6527
    upper_nibble = ( character >> 4 ) & 0x0f;
6528
6529
    if( lower_nibble > 10 )
6530
    {
6531
      lower_nibble += (wchar_t) 'a' - 10;
6532
    }
6533
    else
6534
    {
6535
      lower_nibble += '0';
6536
    }
6537
    if( upper_nibble > 10 )
6538
    {
6539
      upper_nibble += (wchar_t) 'a' - 10;
6540
    }
6541
    else
6542
    {
6543
      upper_nibble += '0';
6544
    }
6545
    sanitized_path[ safe_sanitized_path_index++ ] = (wchar_t) LIBCPATH_ESCAPE_CHARACTER;
6546
    sanitized_path[ safe_sanitized_path_index++ ] = (wchar_t) 'x';
6547
    sanitized_path[ safe_sanitized_path_index++ ] = upper_nibble;
6548
    sanitized_path[ safe_sanitized_path_index++ ] = lower_nibble;
6549
  }
6550
  *sanitized_path_index = safe_sanitized_path_index;
6551
6552
  return( 1 );
6553
}
6554
6555
/* Retrieves a sanitized version of the filename
6556
 * Returns 1 if successful or -1 on error
6557
 */
6558
int libcpath_path_get_sanitized_filename_wide(
6559
     const wchar_t *filename,
6560
     size_t filename_length,
6561
     wchar_t **sanitized_filename,
6562
     size_t *sanitized_filename_size,
6563
     libcerror_error_t **error )
6564
{
6565
  static char *function               = "libcpath_path_get_sanitized_filename_wide";
6566
  wchar_t *safe_sanitized_filename    = NULL;
6567
  size_t filename_index               = 0;
6568
  size_t sanitized_character_size     = 0;
6569
  size_t safe_sanitized_filename_size = 0;
6570
  size_t sanitized_filename_index     = 0;
6571
6572
  if( filename == NULL )
6573
  {
6574
    libcerror_error_set(
6575
     error,
6576
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6577
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6578
     "%s: invalid filename.",
6579
     function );
6580
6581
    return( -1 );
6582
  }
6583
  if( filename_length == 0 )
6584
  {
6585
    libcerror_error_set(
6586
     error,
6587
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6588
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
6589
     "%s: invalid filename length is zero.",
6590
     function );
6591
6592
    return( -1 );
6593
  }
6594
  if( filename_length > (size_t) ( SSIZE_MAX - 1 ) )
6595
  {
6596
    libcerror_error_set(
6597
     error,
6598
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6599
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
6600
     "%s: invalid filename length value exceeds maximum.",
6601
     function );
6602
6603
    return( -1 );
6604
  }
6605
  if( sanitized_filename == NULL )
6606
  {
6607
    libcerror_error_set(
6608
     error,
6609
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6610
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6611
     "%s: invalid sanitized filename.",
6612
     function );
6613
6614
    return( -1 );
6615
  }
6616
  if( *sanitized_filename != NULL )
6617
  {
6618
    libcerror_error_set(
6619
     error,
6620
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6621
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
6622
     "%s: invalid sanitized filename value already set.",
6623
     function );
6624
6625
    return( -1 );
6626
  }
6627
  if( sanitized_filename_size == NULL )
6628
  {
6629
    libcerror_error_set(
6630
     error,
6631
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6632
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6633
     "%s: invalid sanitized filename size.",
6634
     function );
6635
6636
    return( -1 );
6637
  }
6638
  safe_sanitized_filename_size = 1;
6639
6640
  for( filename_index = 0;
6641
       filename_index < filename_length;
6642
       filename_index++ )
6643
  {
6644
    if( filename[ filename_index ] == LIBCPATH_SEPARATOR )
6645
    {
6646
      sanitized_character_size = 4;
6647
    }
6648
    else if( libcpath_path_get_sanitized_character_size_wide(
6649
              filename[ filename_index ],
6650
              &sanitized_character_size,
6651
              error ) != 1 )
6652
    {
6653
      libcerror_error_set(
6654
       error,
6655
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6656
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6657
       "%s: unable to determine sanitize character size.",
6658
       function );
6659
6660
      goto on_error;
6661
    }
6662
    safe_sanitized_filename_size += sanitized_character_size;
6663
  }
6664
  if( safe_sanitized_filename_size > (size_t) SSIZE_MAX )
6665
  {
6666
    libcerror_error_set(
6667
     error,
6668
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6669
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
6670
     "%s: invalid sanitized filename size value exceeds maximum.",
6671
     function );
6672
6673
    goto on_error;
6674
  }
6675
  safe_sanitized_filename = wide_string_allocate(
6676
                             safe_sanitized_filename_size );
6677
6678
  if( safe_sanitized_filename == NULL )
6679
  {
6680
    libcerror_error_set(
6681
     error,
6682
     LIBCERROR_ERROR_DOMAIN_MEMORY,
6683
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
6684
     "%s: unable to create sanitized filename.",
6685
     function );
6686
6687
    goto on_error;
6688
  }
6689
  for( filename_index = 0;
6690
       filename_index < filename_length;
6691
       filename_index++ )
6692
  {
6693
    if( filename[ filename_index ] == LIBCPATH_SEPARATOR )
6694
    {
6695
      sanitized_character_size = 4;
6696
    }
6697
    else if( libcpath_path_get_sanitized_character_size_wide(
6698
              filename[ filename_index ],
6699
              &sanitized_character_size,
6700
              error ) != 1 )
6701
    {
6702
      libcerror_error_set(
6703
       error,
6704
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6705
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6706
       "%s: unable to determine sanitize character size.",
6707
       function );
6708
6709
      goto on_error;
6710
    }
6711
    if( libcpath_path_get_sanitized_character_wide(
6712
         filename[ filename_index ],
6713
         sanitized_character_size,
6714
         safe_sanitized_filename,
6715
         safe_sanitized_filename_size,
6716
         &sanitized_filename_index,
6717
         error ) != 1 )
6718
    {
6719
      libcerror_error_set(
6720
       error,
6721
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6722
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6723
       "%s: unable to determine sanitize character size.",
6724
       function );
6725
6726
      goto on_error;
6727
    }
6728
  }
6729
  safe_sanitized_filename[ sanitized_filename_index ] = 0;
6730
6731
  *sanitized_filename      = safe_sanitized_filename;
6732
  *sanitized_filename_size = safe_sanitized_filename_size;
6733
6734
  return( 1 );
6735
6736
on_error:
6737
  if( safe_sanitized_filename != NULL )
6738
  {
6739
    memory_free(
6740
     safe_sanitized_filename );
6741
  }
6742
  return( -1 );
6743
}
6744
6745
/* Retrieves a sanitized version of the path
6746
 * Returns 1 if successful or -1 on error
6747
 */
6748
int libcpath_path_get_sanitized_path_wide(
6749
     const wchar_t *path,
6750
     size_t path_length,
6751
     wchar_t **sanitized_path,
6752
     size_t *sanitized_path_size,
6753
     libcerror_error_t **error )
6754
{
6755
  static char *function                    = "libcpath_path_get_sanitized_path_wide";
6756
  wchar_t *safe_sanitized_path             = NULL;
6757
  size_t path_index                        = 0;
6758
  size_t safe_sanitized_path_size          = 0;
6759
  size_t sanitized_character_size          = 0;
6760
  size_t sanitized_path_index              = 0;
6761
6762
#if defined( WINAPI )
6763
  size_t last_path_segment_seperator_index = 0;
6764
#endif
6765
6766
  if( path == NULL )
6767
  {
6768
    libcerror_error_set(
6769
     error,
6770
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6771
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6772
     "%s: invalid path.",
6773
     function );
6774
6775
    return( -1 );
6776
  }
6777
  if( path_length == 0 )
6778
  {
6779
    libcerror_error_set(
6780
     error,
6781
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6782
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
6783
     "%s: invalid path length is zero.",
6784
     function );
6785
6786
    return( -1 );
6787
  }
6788
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
6789
  {
6790
    libcerror_error_set(
6791
     error,
6792
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6793
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
6794
     "%s: invalid path length value exceeds maximum.",
6795
     function );
6796
6797
    return( -1 );
6798
  }
6799
  if( sanitized_path == NULL )
6800
  {
6801
    libcerror_error_set(
6802
     error,
6803
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6804
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6805
     "%s: invalid sanitized path.",
6806
     function );
6807
6808
    return( -1 );
6809
  }
6810
  if( *sanitized_path != NULL )
6811
  {
6812
    libcerror_error_set(
6813
     error,
6814
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6815
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
6816
     "%s: invalid sanitized path value already set.",
6817
     function );
6818
6819
    return( -1 );
6820
  }
6821
  if( sanitized_path_size == NULL )
6822
  {
6823
    libcerror_error_set(
6824
     error,
6825
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6826
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6827
     "%s: invalid sanitized path size.",
6828
     function );
6829
6830
    return( -1 );
6831
  }
6832
  safe_sanitized_path_size = 1;
6833
6834
  for( path_index = 0;
6835
       path_index < path_length;
6836
       path_index++ )
6837
  {
6838
    if( libcpath_path_get_sanitized_character_size_wide(
6839
         path[ path_index ],
6840
         &sanitized_character_size,
6841
         error ) != 1 )
6842
    {
6843
      libcerror_error_set(
6844
       error,
6845
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6846
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6847
       "%s: unable to determine sanitize character size.",
6848
       function );
6849
6850
      goto on_error;
6851
    }
6852
    safe_sanitized_path_size += sanitized_character_size;
6853
6854
#if defined( WINAPI )
6855
    if( path[ path_index ] == LIBCPATH_SEPARATOR )
6856
    {
6857
      last_path_segment_seperator_index = path_index;
6858
    }
6859
#endif
6860
  }
6861
  if( safe_sanitized_path_size > (size_t) SSIZE_MAX )
6862
  {
6863
    libcerror_error_set(
6864
     error,
6865
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6866
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
6867
     "%s: invalid sanitized path size value exceeds maximum.",
6868
     function );
6869
6870
    goto on_error;
6871
  }
6872
#if defined( WINAPI )
6873
  if( last_path_segment_seperator_index > 32767 )
6874
  {
6875
    libcerror_error_set(
6876
     error,
6877
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6878
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
6879
     "%s: last path segment separator value out of bounds.",
6880
     function );
6881
6882
    goto on_error;
6883
  }
6884
  if( safe_sanitized_path_size > 32767 )
6885
  {
6886
    safe_sanitized_path_size = 32767;
6887
  }
6888
#endif
6889
  safe_sanitized_path = wide_string_allocate(
6890
                         safe_sanitized_path_size );
6891
6892
  if( safe_sanitized_path == NULL )
6893
  {
6894
    libcerror_error_set(
6895
     error,
6896
     LIBCERROR_ERROR_DOMAIN_MEMORY,
6897
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
6898
     "%s: unable to create sanitized path.",
6899
     function );
6900
6901
    goto on_error;
6902
  }
6903
  for( path_index = 0;
6904
       path_index < path_length;
6905
       path_index++ )
6906
  {
6907
    if( libcpath_path_get_sanitized_character_size_wide(
6908
         path[ path_index ],
6909
         &sanitized_character_size,
6910
         error ) != 1 )
6911
    {
6912
      libcerror_error_set(
6913
       error,
6914
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6915
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6916
       "%s: unable to determine sanitize character size.",
6917
       function );
6918
6919
      goto on_error;
6920
    }
6921
    if( libcpath_path_get_sanitized_character_wide(
6922
         path[ path_index ],
6923
         sanitized_character_size,
6924
         safe_sanitized_path,
6925
         safe_sanitized_path_size,
6926
         &sanitized_path_index,
6927
         error ) != 1 )
6928
    {
6929
      libcerror_error_set(
6930
       error,
6931
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6932
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6933
       "%s: unable to determine sanitize character size.",
6934
       function );
6935
6936
      goto on_error;
6937
    }
6938
  }
6939
  safe_sanitized_path[ sanitized_path_index ] = 0;
6940
6941
  *sanitized_path      = safe_sanitized_path;
6942
  *sanitized_path_size = safe_sanitized_path_size;
6943
6944
  return( 1 );
6945
6946
on_error:
6947
  if( safe_sanitized_path != NULL )
6948
  {
6949
    memory_free(
6950
     safe_sanitized_path );
6951
  }
6952
  return( -1 );
6953
}
6954
6955
/* Combines the directory name and filename into a path
6956
 * Returns 1 if successful or -1 on error
6957
 */
6958
int libcpath_path_join_wide(
6959
     wchar_t **path,
6960
     size_t *path_size,
6961
     const wchar_t *directory_name,
6962
     size_t directory_name_length,
6963
     const wchar_t *filename,
6964
     size_t filename_length,
6965
     libcerror_error_t **error )
6966
{
6967
  static char *function = "libcpath_path_join_wide";
6968
  size_t filename_index = 0;
6969
  size_t path_index     = 0;
6970
6971
  if( path == NULL )
6972
  {
6973
    libcerror_error_set(
6974
     error,
6975
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6976
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6977
     "%s: invalid path.",
6978
     function );
6979
6980
    return( -1 );
6981
  }
6982
  if( *path != NULL )
6983
  {
6984
    libcerror_error_set(
6985
     error,
6986
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6987
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
6988
     "%s: invalid path value already set.",
6989
     function );
6990
6991
    return( -1 );
6992
  }
6993
  if( path_size == NULL )
6994
  {
6995
    libcerror_error_set(
6996
     error,
6997
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6998
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6999
     "%s: invalid path size.",
7000
     function );
7001
7002
    return( -1 );
7003
  }
7004
  if( directory_name == NULL )
7005
  {
7006
    libcerror_error_set(
7007
     error,
7008
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
7009
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
7010
     "%s: invalid directory name.",
7011
     function );
7012
7013
    return( -1 );
7014
  }
7015
  if( directory_name_length > (size_t) SSIZE_MAX )
7016
  {
7017
    libcerror_error_set(
7018
     error,
7019
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
7020
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
7021
     "%s: invalid directory name length value exceeds maximum.",
7022
     function );
7023
7024
    return( -1 );
7025
  }
7026
  if( filename == NULL )
7027
  {
7028
    libcerror_error_set(
7029
     error,
7030
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
7031
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
7032
     "%s: invalid filename.",
7033
     function );
7034
7035
    return( -1 );
7036
  }
7037
  if( filename_length > (size_t) SSIZE_MAX )
7038
  {
7039
    libcerror_error_set(
7040
     error,
7041
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
7042
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
7043
     "%s: invalid filename length value exceeds maximum.",
7044
     function );
7045
7046
    return( -1 );
7047
  }
7048
/* TODO strip other patterns like /./ */
7049
  while( directory_name_length > 0 )
7050
  {
7051
    if( directory_name[ directory_name_length - 1 ] != (wchar_t) LIBCPATH_SEPARATOR )
7052
    {
7053
      break;
7054
    }
7055
    directory_name_length--;
7056
  }
7057
  while( filename_length > 0 )
7058
  {
7059
    if( filename[ filename_index ] != (wchar_t) LIBCPATH_SEPARATOR )
7060
    {
7061
      break;
7062
    }
7063
    filename_index++;
7064
    filename_length--;
7065
  }
7066
  *path_size = directory_name_length + filename_length + 2;
7067
7068
  *path = wide_string_allocate(
7069
           *path_size );
7070
7071
  if( *path == NULL )
7072
  {
7073
    libcerror_error_set(
7074
     error,
7075
     LIBCERROR_ERROR_DOMAIN_MEMORY,
7076
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
7077
     "%s: unable to create path.",
7078
     function );
7079
7080
    goto on_error;
7081
  }
7082
  if( wide_string_copy(
7083
       *path,
7084
       directory_name,
7085
       directory_name_length ) == NULL )
7086
  {
7087
    libcerror_error_set(
7088
     error,
7089
     LIBCERROR_ERROR_DOMAIN_MEMORY,
7090
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
7091
     "%s: unable to copy directory name to path.",
7092
     function );
7093
7094
    goto on_error;
7095
  }
7096
  path_index = directory_name_length;
7097
7098
  ( *path )[ path_index++ ] = (wchar_t) LIBCPATH_SEPARATOR;
7099
7100
  if( wide_string_copy(
7101
       &( ( *path )[ path_index ] ),
7102
       &( filename[ filename_index ] ),
7103
       filename_length ) == NULL )
7104
  {
7105
    libcerror_error_set(
7106
     error,
7107
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
7108
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
7109
     "%s: unable to copy filename to path.",
7110
     function );
7111
7112
    goto on_error;
7113
  }
7114
  path_index += filename_length;
7115
7116
  ( *path )[ path_index ] = 0;
7117
7118
  return( 1 );
7119
7120
on_error:
7121
  if( *path != NULL )
7122
  {
7123
    memory_free(
7124
     *path );
7125
7126
    *path = NULL;
7127
  }
7128
  *path_size = 0;
7129
7130
  return( -1 );
7131
}
7132
7133
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
7134
7135
/* Cross Windows safe version of CreateDirectoryW
7136
 * Returns TRUE if successful or FALSE on error
7137
 */
7138
BOOL libcpath_CreateDirectoryW(
7139
      LPCWSTR path,
7140
      SECURITY_ATTRIBUTES *security_attributes )
7141
{
7142
  FARPROC function       = NULL;
7143
  HMODULE library_handle = NULL;
7144
  BOOL result            = FALSE;
7145
7146
  if( path == NULL )
7147
  {
7148
    return( 0 );
7149
  }
7150
  library_handle = LoadLibrary(
7151
                    _SYSTEM_STRING( "kernel32.dll" ) );
7152
7153
  if( library_handle == NULL )
7154
  {
7155
    return( 0 );
7156
  }
7157
  function = GetProcAddress(
7158
        library_handle,
7159
        (LPCSTR) "CreateDirectoryW" );
7160
7161
  if( function != NULL )
7162
  {
7163
    result = function(
7164
        path,
7165
        security_attributes );
7166
  }
7167
  /* This call should be after using the function
7168
   * in most cases kernel32.dll will still be available after free
7169
   */
7170
  if( FreeLibrary(
7171
       library_handle ) != TRUE )
7172
  {
7173
    libcpath_CloseHandle(
7174
     library_handle );
7175
7176
    return( 0 );
7177
  }
7178
  return( result );
7179
}
7180
7181
#endif /* defined( WINAPI ) && ( WINVER <= 0x0500 ) */
7182
7183
#if defined( WINAPI )
7184
7185
/* Makes the directory
7186
 * This function uses the WINAPI function for Windows XP (0x0501) or later
7187
 * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
7188
 * Returns 1 if successful or -1 on error
7189
 */
7190
int libcpath_path_make_directory_wide(
7191
     const wchar_t *directory_name,
7192
     libcerror_error_t **error )
7193
{
7194
  static char *function = "libcpath_path_make_directory_wide";
7195
  DWORD error_code      = 0;
7196
7197
  if( directory_name == NULL )
7198
  {
7199
    libcerror_error_set(
7200
     error,
7201
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
7202
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
7203
     "%s: invalid directory name.",
7204
     function );
7205
7206
    return( -1 );
7207
  }
7208
#if defined( WINAPI ) && ( WINVER <= 0x0500 )
7209
  if( libcpath_CreateDirectoryW(
7210
       directory_name,
7211
       NULL ) == 0 )
7212
#else
7213
  if( CreateDirectoryW(
7214
       directory_name,
7215
       NULL ) == 0 )
7216
#endif
7217
  {
7218
    error_code = GetLastError();
7219
7220
    libcerror_system_set_error(
7221
     error,
7222
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
7223
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
7224
     error_code,
7225
     "%s: unable to make directory.",
7226
     function );
7227
7228
    return( -1 );
7229
  }
7230
  return( 1 );
7231
}
7232
7233
#elif defined( HAVE_MKDIR )
7234
7235
/* Makes the directory
7236
 * This function uses the POSIX mkdir function or equivalent
7237
 * Returns 1 if successful or -1 on error
7238
 */
7239
int libcpath_path_make_directory_wide(
7240
     const wchar_t *directory_name,
7241
     libcerror_error_t **error )
7242
{
7243
  static char *function             = "libcpath_path_make_directory_wide";
7244
  char *narrow_directory_name       = 0;
7245
  size_t directory_name_length      = 0;
7246
  size_t narrow_directory_name_size = 0;
7247
7248
  if( directory_name == NULL )
7249
  {
7250
    libcerror_error_set(
7251
     error,
7252
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
7253
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
7254
     "%s: invalid directory name.",
7255
     function );
7256
7257
    return( -1 );
7258
  }
7259
  directory_name_length = wide_string_length(
7260
                           directory_name );
7261
7262
  if( libcpath_system_string_size_from_wide_string(
7263
       directory_name,
7264
       directory_name_length + 1,
7265
       &narrow_directory_name_size,
7266
       error ) != 1 )
7267
  {
7268
    libcerror_error_set(
7269
     error,
7270
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
7271
     LIBCERROR_CONVERSION_ERROR_GENERIC,
7272
     "%s: unable to determine narrow directory name size.",
7273
     function );
7274
7275
    goto on_error;
7276
  }
7277
  if( ( narrow_directory_name_size > (size_t) SSIZE_MAX )
7278
   || ( ( sizeof( char ) * narrow_directory_name_size )  > (size_t) SSIZE_MAX ) )
7279
  {
7280
    libcerror_error_set(
7281
     error,
7282
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
7283
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
7284
     "%s: invalid narrow directory name size value exceeds maximum.",
7285
     function );
7286
7287
    goto on_error;
7288
  }
7289
  narrow_directory_name = narrow_string_allocate(
7290
                           narrow_directory_name_size );
7291
7292
  if( narrow_directory_name == NULL )
7293
  {
7294
    libcerror_error_set(
7295
     error,
7296
     LIBCERROR_ERROR_DOMAIN_MEMORY,
7297
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
7298
     "%s: unable to create narrow directory name.",
7299
     function );
7300
7301
    goto on_error;
7302
  }
7303
  if( libcpath_system_string_copy_from_wide_string(
7304
       narrow_directory_name,
7305
       narrow_directory_name_size,
7306
       directory_name,
7307
       directory_name_length + 1,
7308
       error ) != 1 )
7309
  {
7310
    libcerror_error_set(
7311
     error,
7312
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
7313
     LIBCERROR_CONVERSION_ERROR_GENERIC,
7314
     "%s: unable to set name.",
7315
     function );
7316
7317
    goto on_error;
7318
  }
7319
  if( mkdir(
7320
       narrow_directory_name,
7321
       0755 ) != 0 )
7322
  {
7323
    libcerror_system_set_error(
7324
     error,
7325
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
7326
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
7327
     errno,
7328
     "%s: unable to make directory.",
7329
     function );
7330
7331
    goto on_error;
7332
  }
7333
  memory_free(
7334
   narrow_directory_name );
7335
7336
  return( 1 );
7337
7338
on_error:
7339
  if( narrow_directory_name != NULL )
7340
  {
7341
    memory_free(
7342
     narrow_directory_name );
7343
  }
7344
  return( -1 );
7345
}
7346
7347
#else
7348
#error Missing make directory function
7349
#endif
7350
7351
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
7352