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