Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2073 dpurdie 1
/*============================================================================
2072 dpurdie 2
** Copyright (C) 1998-2012 Vix Technology, All rights reserved
3
**============================================================================
4
**
5
**  Project/Product : 
2075 dpurdie 6
**  Filename        : JatsFileUtil.c
2072 dpurdie 7
**  Author(s)       : DDP
8
**
2311 dpurdie 9
**  Description     :   Jats Build System File utility
10
**                      Used by the generated makefiles to perform specific operations
2072 dpurdie 11
**
2311 dpurdie 12
**                      The program exists to solve problems:
13
**                          Windows: Shell is very very slow to start up
14
**                          Windows: Some commands have ~260 character path length issue
15
**                          Windows/Solaris/Linux: Compatibility issues with the 'rm' command
16
**                          All: Consistent use of '/' as a path separator
2072 dpurdie 17
**
2311 dpurdie 18
**                      Note: There are two flavors of this program that MUST be
19
**                            kept in sync.
2310 dpurdie 20
**
2311 dpurdie 21
**                      The program will perform the following operations:
22
**                          (c) CopyFile
23
**                          (d) DeleteFile
24
**                          (r) Remove Files (wildcard)
25
**                          (D) DeleteDir after deleting specified files (wildcard)
26
**                          (T) Delete Directory Tree
27
**
28
**                      Example Usage
29
**
30
**                          JatsFileUtil c9 'copyFile'    aaa/bbb/ccc/dddd/file build_test.pl +w
31
**                          JatsFileUtil d9 'unCopyFile'  aaa/bbb/ccc/dddd/file
32
**                          JatsFileUtil r9 'deleteFile'  a1 b2 c3
33
**                          JatsFileUtil D9 'DeleteFiles' src/WIN32P.OBJ *.err *.pch '*'
34
**                          JatsFileUtil T9 'DeleteTree'  interface
35
**
2310 dpurdie 36
**                      First two arguments are common to all
37
**                          argv[1]     - Mode specifier, Debug specifier
38
**                          argv[2]     - Display Text
39
**
2072 dpurdie 40
**  Information     :
2311 dpurdie 41
**   Compiler       : ANSI C
42
**   Target         : Windows 2000+, Linux, Solaris8+
2072 dpurdie 43
**
44
***==========================================================================*/
45
 
2073 dpurdie 46
#include <tchar.h>
2072 dpurdie 47
#include <stdio.h>
48
#include <windows.h>
49
 
50
#define INVALID_FILE_ATTIBUTES ((DWORD) -1)
51
 
2073 dpurdie 52
VOID ErrorExit (char *lpszMessage, LPTSTR lpszMessage2);
53
void createPaths ( _TCHAR *path );
2085 dpurdie 54
void DeleteDir( int argc, _TCHAR* argv[] );
2310 dpurdie 55
void DeleteDirTree( int argc, _TCHAR* argv[] );
56
_TCHAR * makePath( _TCHAR *base, _TCHAR *path);
57
int DeleteOneFile (_TCHAR * dst );
58
void DeleteOneDirectoryTree( _TCHAR* baseDir );
59
void copyOneFile( int argc, _TCHAR* argv[] );
2072 dpurdie 60
 
2073 dpurdie 61
/*
62
**  Global
63
*/
64
char  verbose = 1;                          /* Debugging aid */
65
 
2072 dpurdie 66
/*----------------------------------------------------------------------------
67
** FUNCTION           : main
68
**
69
** DESCRIPTION        : Main entry points
70
**
71
**
2311 dpurdie 72
** INPUTS             : argc            - Argument Count
73
**                      argv            - Argument Vector
2072 dpurdie 74
**
75
** RETURNS            : 0 - All is good
76
**
77
----------------------------------------------------------------------------*/
2073 dpurdie 78
 
79
int _tmain(int argc, _TCHAR* argv[])
2072 dpurdie 80
{
81
    /*
2073 dpurdie 82
    **  Examine the first argument
83
    **  Must be a character string of
2311 dpurdie 84
    **      [0] - Mode : One character
2073 dpurdie 85
    **      [1] - Verbose : 0 .. 9
2072 dpurdie 86
    */
2310 dpurdie 87
    if ( argc > 1 && ( argv[1][1] >= '0' && argv[1][1] <= '9' ) )
2072 dpurdie 88
    {
2311 dpurdie 89
        verbose = argv[1][1] - '0';
2073 dpurdie 90
 
2311 dpurdie 91
        /*
92
        **  If Verbose, then display arguments
93
        */
94
        if ( verbose > 2 )
2072 dpurdie 95
        {
2311 dpurdie 96
            int ii;
97
            for ( ii = 0; ii < argc ; ii++ )
98
            {
99
                fprintf(stderr, "Arg%d: %ls:\n", ii, argv[ii] );
100
            }
101
            fflush(stderr) ;
2072 dpurdie 102
        }
103
    }
2311 dpurdie 104
 
2072 dpurdie 105
    /*
2310 dpurdie 106
    **  Switch to required operation
2073 dpurdie 107
    */
2311 dpurdie 108
    switch( argv[1][0] )
2075 dpurdie 109
    {
2311 dpurdie 110
        /*
111
        **  CopyFile
112
        **      argv[2] - Text
113
        **      argv[3] - target path
114
        **      argv[4] - Source path
115
        **      argv[5] - File attributes
116
        */
2310 dpurdie 117
        case 'c':
118
            copyOneFile(argc, argv);
119
            break;
2075 dpurdie 120
 
2311 dpurdie 121
        /*
122
        **  UnCopy a file
123
        **      argv[2] - Text
124
        **      argv[3] - target path
125
        */
2310 dpurdie 126
        case 'd':
127
            {
128
                _TCHAR * dst;
129
 
130
                if ( argc != 4 )
131
                    ErrorExit("Incorrect argument count for mode",L"");
2085 dpurdie 132
 
2310 dpurdie 133
                /*
134
                **  Display user text
135
                */
136
                fprintf(stderr, "---- %ls %ls\n", argv[2], argv[3]);
137
                fflush(stderr) ;
2073 dpurdie 138
 
2310 dpurdie 139
                dst = makePath(argv[3], NULL);
140
                DeleteOneFile(dst);
141
                free (dst);
142
            }
143
            break;
2073 dpurdie 144
 
2311 dpurdie 145
        /*
146
        **  Remove named files
147
        **      argv[2]     - Text
148
        **      argv[3]+    - target path
149
        */
2310 dpurdie 150
        case 'r':
151
                {
152
                    int ii;
2072 dpurdie 153
 
2310 dpurdie 154
                    if ( argc < 4 )
155
                        ErrorExit("Incorrect argument count for mode",L"");
2072 dpurdie 156
 
2310 dpurdie 157
                    /*
158
                    **  Display user text
159
                    */
160
                    if ( argv[2][0] )
161
                    {
162
                        fprintf(stderr, "%s\n", argv[2]);
163
                        fflush(stderr) ;
164
                    }
2072 dpurdie 165
 
2310 dpurdie 166
                    for ( ii = 3; ii < argc ; ii++ )
167
                    {
168
                        _TCHAR * dst = makePath(argv[ii], NULL);
169
                        DeleteOneFile(dst);
170
                        free (dst);
171
                    }
172
                }
173
            break;
2072 dpurdie 174
 
2311 dpurdie 175
        /*
176
        **  Delete files in directory - with wildcards
177
        **      argv[2]     - Text
178
        **      argv[3]     - Base directory
179
        **      argv[4]+    - Files in dir to delete.
180
        */
2310 dpurdie 181
        case 'D':
182
            DeleteDir(argc - 2, argv + 2 );
183
            break;
2072 dpurdie 184
 
2311 dpurdie 185
        /*
186
        **  Delete files recursively
187
        **      argv[2] - Text
188
        **      argv[3]+  Base directory
189
        */
2310 dpurdie 190
        case 'T':
191
            DeleteDirTree(argc - 2, argv + 2 );
192
            break;
2073 dpurdie 193
 
2310 dpurdie 194
        default :
195
            ErrorExit("Unknown mode: ",argv[1]);
196
            break;
2072 dpurdie 197
    }
198
    return 0;
199
}
200
 
201
/*----------------------------------------------------------------------------
202
** FUNCTION           : createPaths
203
**
204
** DESCRIPTION        : Create the path to the target
205
**
206
**
207
** INPUTS             : path
2073 dpurdie 208
**                      Assumed to be a \\?\X:\ style
2072 dpurdie 209
**
210
** RETURNS            : Will not return in error
211
**
212
----------------------------------------------------------------------------*/
213
 
2073 dpurdie 214
void createPaths ( _TCHAR *path )
2072 dpurdie 215
{
216
    DWORD rv;
2073 dpurdie 217
    _TCHAR *ptr = path + 7;
2072 dpurdie 218
    while ( *ptr )
219
    {
2073 dpurdie 220
        if ( *ptr == '/' || *ptr == '\\')
2072 dpurdie 221
        {
222
            *ptr = 0;
2073 dpurdie 223
//fprintf(stderr, "createPaths: %ls\n", path);
224
            if ( ! CreateDirectoryW ( path, NULL ))
2072 dpurdie 225
            {
226
                rv = GetLastError();
227
                if ( rv != ERROR_ALREADY_EXISTS )
2075 dpurdie 228
                    ErrorExit("Could not create directories:", path);
2072 dpurdie 229
            }
230
            *ptr = '\\';
231
        }
232
        ptr++;
233
    }
234
}
235
 
236
/*----------------------------------------------------------------------------
2310 dpurdie 237
** FUNCTION           : copyOneFile
2073 dpurdie 238
**
2310 dpurdie 239
** DESCRIPTION        : Copy one file to a target
240
**                      Used to package and install files
2073 dpurdie 241
**
242
**
2310 dpurdie 243
** INPUTS             : argc            - Argc count
244
**                      argv            - Argument list
245
**                          argv[2]     - Display text Prefix
246
**                          argv[3]     - Target path
247
**                          argv[4]     - Source Path
248
**                          argv[5]     - File attributes
2073 dpurdie 249
**
2310 dpurdie 250
** RETURNS            :
2073 dpurdie 251
**
252
----------------------------------------------------------------------------*/
253
 
2310 dpurdie 254
void copyOneFile( int argc, _TCHAR* argv[] )
2073 dpurdie 255
{
2310 dpurdie 256
	DWORD rv;
257
    _TCHAR * src;
258
    _TCHAR * dst;
259
 
260
    if ( argc != 6 )
261
        ErrorExit("Incorrect argument count for file copy",L"");
262
 
263
    /*
264
    **  Display user text
265
    */
266
    fprintf(stderr, "---- %ls %ls\n", argv[2], argv[3]);
267
    fflush(stderr) ;
268
 
269
    dst = makePath(argv[3], NULL);
270
    src = makePath(argv[4], NULL);
271
 
272
    /*
273
    **   Check that the source is a file
274
    */
275
    if ( verbose )
276
        fprintf(stderr, "Validate Source File: %ls\n", src);
277
 
278
    rv = GetFileAttributesW( src );
279
    if ( rv == INVALID_FILE_ATTIBUTES )
2073 dpurdie 280
    {
2310 dpurdie 281
/* Need to be a better message */
282
        fprintf(stderr, "Source: %ls\n", src);
283
        ErrorExit("Source File not found: ", argv[4]);
2073 dpurdie 284
    }
2310 dpurdie 285
 
286
    /*
287
    **  Remove the ReadOnly attribute on the dest file
288
    */
289
    DeleteOneFile(dst);
290
 
291
    /*
292
    **  Create directories
293
    **  Use the path to the target - not the provided directory
294
    **  as the createPaths function will not create the last element
295
    */
296
    createPaths( dst );
297
 
298
    /*
299
    **   Copy the file
300
    */
301
    if ( ! CopyFile( src, dst, FALSE ) )
2073 dpurdie 302
    {
2310 dpurdie 303
        rv = GetLastError();
304
        fprintf(stderr, "CopyFile Last Error: %ld\n", rv);
305
        ErrorExit("Copy Error: ", argv[4]);
2073 dpurdie 306
    }
307
 
308
    /*
2310 dpurdie 309
    **  Test for files existence
2073 dpurdie 310
    */
2310 dpurdie 311
    if ( verbose )
312
        fprintf(stderr, "Test target was copied: %ls\n", dst);
313
 
314
    rv = GetFileAttributesW( dst );
315
    if ( rv == INVALID_FILE_ATTIBUTES )
2073 dpurdie 316
    {
2310 dpurdie 317
/* Need to be a better message */
318
        ErrorExit("File not found after copy: ", argv[3]);
2073 dpurdie 319
    }
320
 
2310 dpurdie 321
    /*
322
    **  Set the files attributes
323
    **      Assume read-only
324
    */
325
    if ( _tcsstr( argv[5], L"-w" ) )
2075 dpurdie 326
    {
2310 dpurdie 327
        if ( verbose )
328
            fprintf(stderr, "Set target read-only: %ls\n", dst);
329
 
330
        rv |= FILE_ATTRIBUTE_READONLY;
331
        rv &= ~FILE_ATTRIBUTE_NORMAL;
332
        rv = SetFileAttributesW( dst, rv );
333
        if ( rv == 0 )
2075 dpurdie 334
        {
2310 dpurdie 335
            ErrorExit("Setting ReadOnly: ", argv[3]);
2075 dpurdie 336
        }
337
    }
338
}
339
 
2073 dpurdie 340
/*----------------------------------------------------------------------------
2085 dpurdie 341
** FUNCTION           : DeleteDir
342
**
343
** DESCRIPTION        : Delete a list of files in a specified directory
344
**                      Ensure files are writable
345
**                      Wilcarding is supported
346
**
347
**                      Then delete the directory - if its empty
348
**
349
**
350
** INPUTS             : argc    - count of args
351
**                      argv    - list of files to delete
2310 dpurdie 352
**                                [0]:  Text to display
353
**                                [1]:  Base directory
354
**                                [2]+  Files in dir to delete
2085 dpurdie 355
**
2310 dpurdie 356
** RETURNS            : Will not return on error
2085 dpurdie 357
**
358
----------------------------------------------------------------------------*/
359
 
360
void DeleteDir( int argc, _TCHAR* argv[] )
361
{
362
	DWORD rv;
363
    _TCHAR* baseDir;
364
    WIN32_FIND_DATA FindFileData;
365
    HANDLE hFind;
2310 dpurdie 366
    _TCHAR *target;
367
    _TCHAR *dirPath;
2085 dpurdie 368
 
369
    if ( argc < 3 )
2311 dpurdie 370
        ErrorExit("Insufficient arguments for DeleteDir",L"");
2085 dpurdie 371
 
372
    /*
373
    **  Display the user message
2311 dpurdie 374
    **      Suppress display if the message is empty
2085 dpurdie 375
    */
376
    if ( argv[0][0] )
377
    {
378
        fprintf(stderr, "%ls\n", argv[0]);
379
        fflush(stderr) ;
380
    }
381
 
382
    /*
383
    **  Extract the base directory from the argument list
384
    **  This must be a directory
385
    */
386
    baseDir = argv[1];
387
    argc -= 2;
388
    argv+=2;
389
 
390
    /*
391
    **  Ensure that the base directory exists
392
    */
2310 dpurdie 393
    dirPath = makePath(baseDir, NULL);
394
    rv = GetFileAttributesW( dirPath );
2085 dpurdie 395
    if ( rv == INVALID_FILE_ATTIBUTES )
396
    {
397
        /*
398
        **  Directory does not exists
2311 dpurdie 399
        **  Assume its already deleted
2085 dpurdie 400
        */
401
        if ( verbose > 1 )
402
            fprintf(stderr, "Base dir does not exist: %ls\n", baseDir);
2310 dpurdie 403
        free(dirPath);
2085 dpurdie 404
        return;
405
    }
406
 
407
    if ( !(rv & FILE_ATTRIBUTE_DIRECTORY) )
408
    {
409
        /*
410
        **  Target is not a directory
411
        **  Don't do anything
412
        */
413
        if ( verbose > 1 )
414
            fprintf(stderr, "Base dir is not a directory: %ls\n", baseDir);
2310 dpurdie 415
        free(dirPath);
2085 dpurdie 416
        return;
417
    }
418
 
419
    /*
420
    **  Process all the suffixes
421
    **  They may contain a wild card
422
    */
423
    for ( ; argc ; argc--, argv++ )
424
    {
2310 dpurdie 425
        _TCHAR * thisDir = makePath( baseDir, *argv);
426
        hFind = FindFirstFile(thisDir, &FindFileData);
427
        free(thisDir);
428
 
2085 dpurdie 429
        if (hFind == INVALID_HANDLE_VALUE)
430
        {
431
            /*
432
            **  No match
433
            */
434
            if ( verbose > 1 )
2310 dpurdie 435
                fprintf(stderr, "No Match: %ls, %ls\n", baseDir, *argv);
2085 dpurdie 436
            continue;
437
        }
438
 
439
        /*
440
        **  Iterate over all the files
441
        */
442
        do {
443
            if ( _tcscmp( TEXT("."), FindFileData.cFileName ) == 0 )
444
                continue;
445
 
446
            if ( _tcscmp( TEXT(".."), FindFileData.cFileName ) == 0 )
447
                continue;
448
 
449
            if ( verbose )
450
                fprintf(stderr, "Match: %ls\n", FindFileData.cFileName);
451
 
452
            /*
2310 dpurdie 453
            **  Matching file found
2085 dpurdie 454
            */
2310 dpurdie 455
            target = makePath( baseDir, FindFileData.cFileName);
456
            DeleteOneFile(target);
457
            free (target);
2085 dpurdie 458
 
459
        } while  (FindNextFile(hFind, &FindFileData) != 0);
460
        FindClose(hFind);
461
    }
462
 
463
    /*
2311 dpurdie 464
    **  Finally delete the directory
2085 dpurdie 465
    **      Unless its '.'
466
    */
467
    if ( _tcscmp( TEXT("."),baseDir) != 0 )
468
    {
469
        if ( verbose > 1 )
470
            fprintf(stderr, "Delete Directory: %ls\n", baseDir);
2310 dpurdie 471
 
472
        if ( ! RemoveDirectory( dirPath ) )
2085 dpurdie 473
        {
474
            if ( verbose )
475
                fprintf(stderr, "Directory not deleted: %ls\n", baseDir);
476
        }
477
    }
2310 dpurdie 478
    free(dirPath);
2085 dpurdie 479
}
480
 
2310 dpurdie 481
/*----------------------------------------------------------------------------
482
** FUNCTION           : DeleteDirTree
483
**
484
** DESCRIPTION        : Delete an entire directory tree(s)
485
**
486
** INPUTS             : argc    - count of args
487
**                      argv    - list of files to delete
488
**                                [0]:  Text to display
489
**                                [1]+  Base directory
490
**
491
** RETURNS            : Will not return on error
492
**
493
----------------------------------------------------------------------------*/
2085 dpurdie 494
 
2310 dpurdie 495
void DeleteDirTree( int argc, _TCHAR* argv[] )
496
{
497
    int ii;
498
 
499
    if ( argc < 2 )
2311 dpurdie 500
        ErrorExit("Insufficient arguments for DeleteDirTree",L"");
2310 dpurdie 501
 
502
    /*
503
    **  Display the user message
2311 dpurdie 504
    **      Suppress display if the message is empty
2310 dpurdie 505
    */
506
    if ( argv[0][0] )
507
    {
508
        fprintf(stderr, "%ls\n", argv[0]);
509
        fflush(stderr) ;
510
    }
511
 
512
    for ( ii = 1; ii < argc ; ii++)
513
    {
514
        DeleteOneDirectoryTree( argv[ii] );
515
    }
516
}
517
 
2085 dpurdie 518
/*----------------------------------------------------------------------------
2310 dpurdie 519
** FUNCTION           : DeleteOneDirectoryTree
520
**
521
** DESCRIPTION        : Delete an entire directory tree(s)
522
**
523
** INPUTS             : path    - Dir to delete
524
**
525
** RETURNS            : Will not return on error
526
**
527
----------------------------------------------------------------------------*/
528
 
529
void DeleteOneDirectoryTree( _TCHAR* baseDir )
530
{
531
	DWORD rv;
532
    WIN32_FIND_DATA FindFileData;
533
    HANDLE hFind;
534
    _TCHAR *target;
535
    _TCHAR *dirPath;
536
    _TCHAR *thisDir;
537
 
538
    /*
539
    **  A bit of a sanity test
540
    */
541
    if ( _tcscmp( L".", baseDir) == 0 || _tcscmp( L"..", baseDir) == 0 )
542
    {
543
        fprintf(stderr, "DeleteOneDirectoryTree will not delete '.' or '..'\n");
544
        return;
545
    }
546
 
547
    /*
548
    **  Ensure that the base directory exists
549
    */
550
    dirPath = makePath(baseDir, NULL);
551
    rv = GetFileAttributesW( dirPath );
552
    if ( rv == INVALID_FILE_ATTIBUTES )
553
    {
554
        /*
555
        **  Directory does not exists
2311 dpurdie 556
        **  Assume its already deleted
2310 dpurdie 557
        */
558
        if ( verbose > 1 )
559
            fprintf(stderr, "Base dir does not exist: %ls\n", baseDir);
560
        free(dirPath);
561
        return;
562
    }
563
 
564
    if ( !(rv & FILE_ATTRIBUTE_DIRECTORY) )
565
    {
566
        /*
567
        **  Target is not a directory
568
        **  Don't do anything
569
        */
570
        if ( verbose > 1 )
571
            fprintf(stderr, "Base dir is not a directory: %ls\n", baseDir);
572
        free(dirPath);
573
        return;
574
    }
575
 
576
    /*
577
    **  Read next directory entry
578
    */
579
    thisDir = makePath( baseDir, TEXT("*"));
580
    hFind = FindFirstFile(thisDir, &FindFileData);
581
    free(thisDir);
582
 
583
    if (hFind != INVALID_HANDLE_VALUE)
584
    {
585
 
586
        /*
587
        **  Iterate over all the files
588
        */
589
        do {
590
            if ( verbose > 2 )
591
                fprintf(stderr, "Directory Entry:%ls,%ls\n", baseDir, FindFileData.cFileName );
592
 
593
            if ( _tcscmp( TEXT("."), FindFileData.cFileName ) == 0 )
594
                continue;
595
 
596
            if ( _tcscmp( TEXT(".."), FindFileData.cFileName ) == 0 )
597
                continue;
598
 
599
            /*
600
            **  Create a full path to the file
601
            */
602
            target = makePath( baseDir, FindFileData.cFileName);
603
            if ( FindFileData.dwFileAttributes  & FILE_ATTRIBUTE_DIRECTORY)
604
            {
605
                DeleteOneDirectoryTree( target );
606
            }
607
            else
608
            {
609
                DeleteOneFile (target);
610
            }
611
            free (target);
612
 
613
        } while  (FindNextFile(hFind, &FindFileData) != 0);
614
        FindClose(hFind);
615
    }
616
 
617
    /*
2311 dpurdie 618
    **  Finally delete the directory
2310 dpurdie 619
    */
620
    if ( verbose > 1 )
621
        fprintf(stderr, "Delete Directory: %ls\n", baseDir);
622
 
623
    if ( ! RemoveDirectory( dirPath ) )
624
    {
625
        if ( verbose )
626
            fprintf(stderr, "Directory not deleted: %ls\n", baseDir);
627
    }
628
    free(dirPath);
629
}
630
 
631
/*----------------------------------------------------------------------------
632
** FUNCTION           : DeleteOneFile
633
**
634
** DESCRIPTION        : Delete a file
635
**                      Force it writable before deletion
636
**
637
** INPUTS             : path        - path to the file
638
**
639
** RETURNS            : 0           - OK (file deleted or not present)
640
**
641
----------------------------------------------------------------------------*/
642
 
643
int DeleteOneFile (_TCHAR * dst )
644
{
645
	DWORD rv;
646
    int result = 0;
647
 
648
    if ( verbose > 1)
649
        fprintf(stderr, "Delete File: %ls\n", dst);
650
 
651
    rv = GetFileAttributesW( dst );
652
    if ( rv != INVALID_FILE_ATTIBUTES )
653
    {
654
        if ( verbose )
655
            fprintf(stderr, "Delete file: %ls : Attr: 0x%lx\n", dst, rv);
656
        if ( rv & FILE_ATTRIBUTE_READONLY )
657
        {
658
            rv &= ~FILE_ATTRIBUTE_READONLY;
659
            rv = SetFileAttributesW( dst, rv );
660
            if ( rv == 0 )
661
            {
662
                fprintf(stderr, "Warning: Attempt to allow write access: %ls\n", dst);
663
            }
664
        }
665
 
666
        if (! DeleteFile( dst ) )
667
        {
668
            fprintf(stderr, "Warning: Did not remove file: %ls\n", dst);
669
            result = 1;
670
        }
671
    }
672
 
673
    return result;
674
}
675
 
676
/*----------------------------------------------------------------------------
677
** FUNCTION           : makePath
678
**
679
** DESCRIPTION        : Creates a full file path for user
680
**                      Join 2 components together
681
**                      Convert relative path to ABS path with \\?\ from
682
**                      Convert / into \ for windows
683
**
684
**                      Handle path elements
685
**                          ./                  - Remove
686
**                          /bbb/../            - Remove
687
**                          /aaa/bbb/../../     - Remove
688
**
689
**
690
** INPUTS             : base        - Part 1
691
**                                    May already contain \\?\
692
**                      file        - Part 2 or NULL
693
**
694
** RETURNS            : fullPath - User must free memory
695
**
696
----------------------------------------------------------------------------*/
697
 
698
_TCHAR * makePath ( _TCHAR * base, _TCHAR *file )
699
{
700
    int lenp = 0;
701
    int lencwd = 0;
702
    int len1 = _tcslen(base);
703
    int len2 = 0;
704
    _TCHAR *data;
705
    _TCHAR *cdata;
706
    _TCHAR *udst;
707
 
708
    /*
709
    **  If the base contains a \\?\ then we don't need to add it
710
    */
711
    if ( !( len1 > 3 && base[2] == '?' ) )
712
    {
713
        lenp = _tcslen(TEXT("\\\\?\\"));
714
    }
715
 
716
    /*
717
    **  Unless an absolute path we need to insert CWD too
718
    **  Just determine the length of the entry for now
719
    */
720
    if ( lenp && ( ( base[0] && (base[1] != ':') ) || base[0] == 0 ) )
721
    {
722
        lencwd = GetCurrentDirectory(0,0) - 1; // determine size needed
723
    }
724
 
725
    /*
726
    **  2nd file argument may be a NULL
727
    */
728
    if ( file )
729
    {
730
        len2 = _tcslen(file);
731
    }
732
 
733
    data = (_TCHAR *)malloc((lenp + lencwd+ len1 + len2 + 10) * sizeof(_TCHAR));
734
    cdata = data;
735
    if ( data == NULL )
736
    {
737
        ErrorExit ("Malloc error:makePath",L"");
738
    }
739
 
740
    /*
741
    **  Join all the strings together
742
    */
743
    if ( lenp )
744
    {
745
        _tcscpy( cdata,TEXT("\\\\?\\"));
746
        cdata += lenp;
747
    }
748
 
749
    if ( lencwd )
750
    {
751
        GetCurrentDirectory(lencwd+1, cdata);
752
        cdata += lencwd;
753
        _tcscpy( cdata, TEXT("\\"));
754
        cdata += 1;
755
    }
756
 
757
    _tcscpy( cdata, base);
758
    cdata += len1;
759
 
760
    if ( len2 )
761
    {
762
        _tcscpy( cdata, TEXT("\\"));
763
        _tcscpy( cdata+1, file);
764
        cdata += len2 + 1;
765
    }
766
 
767
    /*
768
    **  Convert / into \
769
    */
770
    for ( udst = data; *udst ; udst++)
771
    {
772
        if ( *udst == '/' )
773
            *udst = '\\';
774
    }
775
 
776
    /*
777
    **  Now remove silly relative path bits
778
    */
779
    udst = data;
780
    while ( *udst )
781
    {
782
        if ( udst[0] == '\\' && udst[1] == '.' && (udst[2] == '\\' || udst[2] == 0) )
783
        {
784
            TCHAR* ptr1 = udst;
785
            TCHAR* ptr2 = udst + 2;
786
            while ( *ptr1++ = *ptr2++ ) {}
787
        }
788
        else if ( udst[0] == '\\' && udst[1] == '.' && udst[2] == '.' && udst[3] == '\\'  )
789
        {
790
            TCHAR* ptr = udst - 1;
791
            TCHAR* ptr2 = udst + 3;
792
 
793
            while ( *ptr-- != '\\' )
794
            {
795
                if ( ptr - data < 6)
796
                {
797
                    *ptr = 0;
798
                    fprintf(stderr, "Path: %ls\n", data);
799
                    ErrorExit("Bad relative path: ", data);
800
                }
801
            }
802
            ptr++;
803
            udst = ptr;
804
            while ( *ptr++ = *ptr2++ ) {}
805
        }
806
        else
807
        {
808
            *udst++;
809
        }
810
    }
811
 
812
    if ( verbose > 2)
813
        fprintf(stderr, "makePath: %ls\n", data);
814
 
815
    return data;
816
}
817
 
818
/*----------------------------------------------------------------------------
2072 dpurdie 819
** FUNCTION           : ErrorExit
820
**
821
** DESCRIPTION        : Error processing
822
**                      Report an error and terminate process
823
**
824
**
825
** INPUTS             : lpszMessage     - Message to display
826
**
827
** RETURNS            : Does't return
828
**                      Will exit with bad code
829
**
830
----------------------------------------------------------------------------*/
831
 
2073 dpurdie 832
VOID ErrorExit (char *lpszMessage, LPTSTR lpszMessage2)
2072 dpurdie 833
{ 
2075 dpurdie 834
   fprintf(stderr, "JatsFileUtil:Error:%s%ls\n", lpszMessage,lpszMessage2);
2072 dpurdie 835
   fflush(stderr) ;
836
   ExitProcess(-1);
837
} 
838