Subversion Repositories DevTools

Rev

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