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