Subversion Repositories DevTools

Rev

Rev 2764 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2073 dpurdie 1
/*============================================================================
2
** Copyright (C) 1998-2012 Vix Technology, All rights reserved
3
**============================================================================
4
**
5
**  Project/Product : 
2075 dpurdie 6
**  Filename        : JatsFileUtil.c
2073 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
2073 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
2073 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
2764 dpurdie 28
**                          (P) Print Arguments
2311 dpurdie 29
**
30
**                      Example Usage
31
**
32
**                          JatsFileUtil c9 'copyFile'    aaa/bbb/ccc/dddd/file build_test.pl +w
33
**                          JatsFileUtil d9 'unCopyFile'  aaa/bbb/ccc/dddd/file
34
**                          JatsFileUtil r9 'deleteFile'  a1 b2 c3
35
**                          JatsFileUtil D9 'DeleteFiles' src/WIN32P.OBJ *.err *.pch '*'
36
**                          JatsFileUtil T9 'DeleteTree'  interface
2354 dpurdie 37
**                          JatsFileUtil R9 'RmItem'       build
2311 dpurdie 38
**
2310 dpurdie 39
**                      First two arguments are common to all
40
**                          argv[1]     - Mode specifier, Debug specifier
41
**                          argv[2]     - Display Text
42
**
2073 dpurdie 43
**  Information     :
2311 dpurdie 44
**   Compiler       : ANSI C
45
**   Target         : Windows 2000+, Linux, Solaris8+
2073 dpurdie 46
**
47
***==========================================================================*/
48
 
49
#include <stdio.h>
50
#include <sys/types.h>
51
#include <sys/stat.h>
52
#include <fcntl.h>
53
#include <unistd.h>
54
#include <stdlib.h>
2085 dpurdie 55
#include <dirent.h>
2073 dpurdie 56
#include <string.h>
57
 
58
void ErrorExit (char * lpszMessage, char * lpszMessage2);
59
void createPaths ( char *path );
2085 dpurdie 60
void DeleteDir( int argc, char* argv[] );
2310 dpurdie 61
char * makePath( char *base, char *path);
62
void DeleteOneDirectoryTree( char* baseDir );
63
void copyOneFile( int argc, char* argv[] );
2311 dpurdie 64
int CopyFile ( char *src, char *dst, mode_t st_mode );
2354 dpurdie 65
void RmItem( int argc, char* argv[] );
2311 dpurdie 66
int wildcmp(char *string, char *wild );
2354 dpurdie 67
int DeleteOneFile (char * dst );
68
void DeleteOneDirectory (char *path );
69
void stdCheck( char *name, int argBad, char *txt );
2764 dpurdie 70
void url_decode(char *str);
2073 dpurdie 71
 
72
/*
73
**  Global
74
*/
75
char  verbose = 1;                          /* Debugging aid */
2354 dpurdie 76
char  *helpText =
77
         "Usage: JatsFileUtil Mode Text Arguments\n"
78
         "\n"
79
         "  Where 'Mode' is two characters:\n"
80
         "      1 - Operation Specifier\n"
81
         "      2 - Debug Mode. 0..9\n"
82
         "  Where 'Text' is a, possibly empty, display string\n"
83
         "\n"
84
         "  By Example:\n"
85
         "      c9 copyFile     dstPath srcPath chmod\n"
86
         "      d9 unCopyFile   dstPath\n"
87
         "      r9 RmFile       file+\n"
88
         "      D9 DeleteFiles  dstDir file+ - supports (?*)\n"
89
         "      T9 DeleteTree   dstDir+\n"
2764 dpurdie 90
         "      R9 RmItem       (dir|file)+\n"
91
         "      P9 PrintArgs    ...\n";
2073 dpurdie 92
 
93
/*----------------------------------------------------------------------------
94
** FUNCTION           : main
95
**
96
** DESCRIPTION        : Main entry points
97
**
98
**
2311 dpurdie 99
** INPUTS             : argc            - Argument Count
100
**                      argv            - Argument Vector
2073 dpurdie 101
**
102
** RETURNS            : 0 - All is good
103
**
104
----------------------------------------------------------------------------*/
105
 
106
int main(int argc, char* argv[])
107
{
2354 dpurdie 108
    int ii;
109
 
2073 dpurdie 110
    /*
2313 dpurdie 111
    **  User must provide some thing
112
    */
113
    if ( argc < 2 )
114
    {
2354 dpurdie 115
       fprintf(stderr, helpText );
116
       return 1;
2313 dpurdie 117
    }
118
 
119
    /*
2073 dpurdie 120
    **  Examine the first argument
121
    **  Must be a character string of
2311 dpurdie 122
    **      [0] - Mode : One character
2073 dpurdie 123
    **      [1] - Verbose : 0 .. 9
124
    */
2310 dpurdie 125
    if ( argc > 1 && ( argv[1][1] >= '0' && argv[1][1] <= '9' ) )
2073 dpurdie 126
    {
2311 dpurdie 127
        verbose = argv[1][1] - '0';
2764 dpurdie 128
    }
2073 dpurdie 129
 
2764 dpurdie 130
    /*
131
    **  URL Decode most arguments
132
    **  To get past the stupidities of shells and make the arguments
133
    **  will have been URL(modified) encoded
134
    **
135
    **  Decode all args in place
136
    */
137
    for ( ii = 2; ii < argc ; ii++ )
138
    {
139
        url_decode(argv[ii]);
2311 dpurdie 140
        /*
141
        **  If Verbose, then display arguments
142
        */
143
        if ( verbose > 2 )
2764 dpurdie 144
            fprintf(stderr, "Arg%d: %s:\n", ii, argv[ii] );
2073 dpurdie 145
    }
2764 dpurdie 146
     fflush(stderr) ;
2311 dpurdie 147
 
2073 dpurdie 148
    /*
2310 dpurdie 149
    **  Switch to required operation
2075 dpurdie 150
    */
2311 dpurdie 151
    switch( argv[1][0] )
2075 dpurdie 152
    {
2311 dpurdie 153
        /*
154
        **  CopyFile
155
        **      argv[2] - Text
156
        **      argv[3] - target path
157
        **      argv[4] - Source path
158
        **      argv[5] - File attributes
159
        */
2310 dpurdie 160
        case 'c':
2354 dpurdie 161
            stdCheck( "CopyFile", argc != 6, NULL );
162
            fprintf(stderr, "---- %s %s\n", argv[2], argv[3]);
163
            fflush(stderr) ;
2310 dpurdie 164
            copyOneFile(argc, argv);
165
            break;
2075 dpurdie 166
 
2311 dpurdie 167
        /*
168
        **  UnCopy a file
169
        **      argv[2] - Text
170
        **      argv[3] - target path
171
        */
2310 dpurdie 172
        case 'd':
2354 dpurdie 173
            stdCheck( "UnCopy", argc != 4, NULL );
174
            fprintf(stderr, "---- %s %s\n", argv[2], argv[3]);
175
            fflush(stderr) ;
2085 dpurdie 176
 
2354 dpurdie 177
            DeleteOneFile(argv[3]);
2310 dpurdie 178
            break;
2073 dpurdie 179
 
2311 dpurdie 180
        /*
181
        **  Remove named files
182
        **      argv[2]     - Text
183
        **      argv[3]+    - target path
184
        */
2310 dpurdie 185
        case 'r':
2354 dpurdie 186
            stdCheck( "RmFile", argc <= 3, argv[2] );
187
            for ( ii = 3; ii < argc ; ii++ )
188
            {
189
                DeleteOneFile(argv[ii]);
190
            }
2310 dpurdie 191
            break;
2073 dpurdie 192
 
2311 dpurdie 193
        /*
194
        **  Delete files in directory - with wildcards
195
        **      argv[2]     - Text
196
        **      argv[3]     - Base directory
197
        **      argv[4]+    - Files in dir to delete.
198
        */
2310 dpurdie 199
        case 'D':
2354 dpurdie 200
            stdCheck( "DeleteDir", argc < 4, argv[2] );
201
            DeleteDir(argc, argv );
2310 dpurdie 202
            break;
2073 dpurdie 203
 
2311 dpurdie 204
        /*
205
        **  Delete files recursively
206
        **      argv[2] - Text
207
        **      argv[3]+  Base directory
208
        */
2310 dpurdie 209
        case 'T':
2354 dpurdie 210
            stdCheck( "DeleteDirTree", argc < 3, argv[2] );
211
            for ( ii = 3; ii < argc ; ii++)
212
            {
213
                DeleteOneDirectoryTree( argv[ii] );
214
            }
2310 dpurdie 215
            break;
2313 dpurdie 216
 
217
        /*
218
        **  Delete Empty Directories
219
        **      argv[2] - Text
220
        **      argv[3]+  Base directory
221
        */
222
        case 'R':
2354 dpurdie 223
            stdCheck( "RmItem", argc < 3, argv[2] );
224
            RmItem(argc, argv );
2313 dpurdie 225
            break;
2764 dpurdie 226
 
227
        /*
228
        **  Print arguments with a space betweenn them
229
        **  All on the same line
230
        **      argv[2]+ - Text
231
        */
232
        case 'P':
233
            for ( ii = 2; ii < argc ; ii++ )
234
            {
235
                if ( ii > 2 )
236
                    fprintf(stderr, " ");
237
                fprintf(stderr, "%s", argv[ii] );
238
            }
239
            fprintf(stderr, "\n");
240
            break;
2310 dpurdie 241
 
242
        default :
243
            ErrorExit("Unknown mode: ",argv[1]);
244
            break;
2073 dpurdie 245
    }
246
    return 0;
247
}
248
 
249
/*----------------------------------------------------------------------------
2354 dpurdie 250
** FUNCTION           : stdCheck
251
**
252
** DESCRIPTION        : Check arg count
253
**                      Print standard header
254
**
255
**
256
** INPUTS             : name        - Name of the operation
257
**                      argBad      - Arg count Not Ok
258
**                      text        - Text to print
259
**
260
** RETURNS            : Will not return on error
261
**
262
----------------------------------------------------------------------------*/
263
 
264
void stdCheck( char *name, int argBad, char *txt )
265
{
266
    if ( argBad  )
267
    {
268
       fprintf(stderr, "JatsFileUtil:Incorrect argument count for %s\n", name);
269
       ErrorExit(NULL, NULL);
270
    }
271
 
272
    /*
273
    **  Display user text
274
    **      Suppress display if the message is empty
275
    */
276
    if ( txt && *txt )
277
    {
278
        fprintf(stderr, "%s\n",txt);
279
        fflush(stderr) ;
280
    }
281
}
282
 
283
 
284
/*----------------------------------------------------------------------------
2073 dpurdie 285
** FUNCTION           : createPaths
286
**
287
** DESCRIPTION        : Create the path to the target
288
**
289
**
290
** INPUTS             : path
291
**
292
** RETURNS            : Will not return in error
293
**
294
----------------------------------------------------------------------------*/
295
 
296
void createPaths ( char *path )
297
{
298
    struct stat fstat;
299
    int  rv;
300
    char *ptr = path;
301
 
302
    while ( *ptr )
303
    {
304
        if ( *ptr == '/' )
305
        {
306
            *ptr = 0;
2310 dpurdie 307
/* fprintf(stderr, "createPaths: %s\n", path); */
2073 dpurdie 308
            rv = stat( path, &fstat );
309
            if ( rv )
310
            {
311
                if ( verbose > 1 )
312
                {
313
                    fprintf(stderr, "createPaths: %s\n", path);
314
                    fflush(stderr) ;
315
                }
316
                rv = mkdir( path, 0777 );
317
                if ( rv )
318
                {
2075 dpurdie 319
                    ErrorExit("Could not create directories:", path);
2073 dpurdie 320
                }
321
            }
322
            *ptr = '/';
323
        }
324
        ptr++;
325
    }
326
}
327
 
328
/*----------------------------------------------------------------------------
2310 dpurdie 329
** FUNCTION           : copyOneFile
330
**
331
** DESCRIPTION        : Copy one file to a target
332
**                      Used to package and install files
333
**
334
**
335
** INPUTS             : argc            - Argc count
336
**                      argv            - Argument list
337
**                          argv[2]     - Display text Prefix
338
**                          argv[3]     - Target path
339
**                          argv[4]     - Source Path
340
**                          argv[5]     - File attributes
341
**
342
** RETURNS            :
343
**
344
----------------------------------------------------------------------------*/
345
 
346
void copyOneFile( int argc, char* argv[] )
347
{
348
	int    rv;
349
    char * src;
350
    char * dst;
351
    struct stat fstat;
352
 
353
    dst = argv[3];
354
    src = argv[4];
355
 
356
    /*
357
    **   Check that the source is a file
358
    */
2354 dpurdie 359
    if ( verbose > 2)
2310 dpurdie 360
        fprintf(stderr, "Validate Source File: %s\n", src);
361
 
362
    rv = stat( src, &fstat );
363
    if ( rv != 0 )
364
    {
365
/* Need to be a better message */
366
        fprintf(stderr, "Source: %s\n", src);
367
        ErrorExit("Source File not found: ", argv[4]);
368
    }
369
 
370
    /*
2354 dpurdie 371
    **  Delete the destination file before the copy
372
    **  Will force it to be writable
2310 dpurdie 373
    */
374
    DeleteOneFile(dst);
375
 
376
    /*
377
    **  Create directories
378
    **  Use the path to the target - not the provided directory
379
    **  as the createPaths function will not create the last element
380
    */
381
    createPaths( dst );
382
 
383
    /*
384
    **   Copy the file
385
    */
386
    if ( ! CopyFile( src, dst, fstat.st_mode ) )
387
    {
388
        ErrorExit("Copy Error: ", argv[4]);
389
    }
390
 
391
    /*
392
    **  Test for files existence
393
    */
2354 dpurdie 394
    if ( verbose > 1 )
2310 dpurdie 395
        fprintf(stderr, "Test target was copied: %s\n", dst);
396
 
397
    rv = stat( dst, &fstat );
398
    if ( rv != 0 )
399
    {
400
/* Need to be a better message */
401
        ErrorExit("File not found after copy: ", argv[3]);
402
    }
403
 
404
    /*
405
    **  Set the files attributes
406
    **      Assume read-only
407
    */
408
    if ( strstr( argv[5], "-w" ) )
409
    {
410
        if ( verbose > 1 )
411
            fprintf(stderr, "Set target read-only: %s\n", dst);
412
        fstat.st_mode &= ~(S_IWRITE | S_IWOTH | S_IWGRP );
413
    }
414
 
415
    if ( strstr( argv[5], "+w" ) )
416
    {
417
        if ( verbose > 1 )
418
            fprintf(stderr, "Set target writable: %s\n", dst);
419
        fstat.st_mode |= (S_IWRITE | S_IWOTH | S_IWGRP );
420
    }
421
 
422
    if ( strstr( argv[5], "+x" ) )
423
    {
424
        if ( verbose > 1 )
425
            fprintf(stderr, "Set target executable: %s\n", dst);
426
        fstat.st_mode |= ( S_IXUSR | S_IXOTH | S_IXGRP );
427
    }
428
 
429
    if ( strstr( argv[5], "-x" ) )
430
    {
431
        if ( verbose > 1)
432
            fprintf(stderr, "Set target executable: %s\n", dst);
433
        fstat.st_mode &= ~( S_IXUSR | S_IXOTH | S_IXGRP );
434
    }
435
 
2354 dpurdie 436
    if ( verbose > 1 )
2310 dpurdie 437
        fprintf(stderr, "Set target perms: %s, 0%o\n", dst, fstat.st_mode);
438
    rv = chmod( dst, fstat.st_mode );
439
    if ( rv != 0 )
440
    {
441
        ErrorExit("Setting ReadOnly: ", argv[3]);
442
    }
443
}
444
 
445
/*----------------------------------------------------------------------------
2073 dpurdie 446
** FUNCTION           : CopyFile
447
**
448
** DESCRIPTION        : Just copy a file
449
**
450
**
451
** INPUTS             : src - source path - already exists
452
**                      dst - path. Dirs already exist
453
**                      st_mode - Creation  mode. Copied from source file
454
**
455
** RETURNS            : false - Error
456
**
457
----------------------------------------------------------------------------*/
458
 
459
#define COPYSIZE  1024
460
int CopyFile ( char *src, char *dst, mode_t st_mode )
461
{
462
 
463
     ssize_t rlen = 0 ;
464
     ssize_t wlen = 0 ;
465
     int in;
466
     int out;
467
     int ferror = 0;
468
    char buffer[COPYSIZE] = { '\0' } ;
469
 
2354 dpurdie 470
    if ( verbose > 2 )
2073 dpurdie 471
    {
472
        fprintf(stderr, "CopyFile: Output Mode: 0%o\n", st_mode);
473
        fflush(stderr) ;
474
    }
475
 
476
    in = open( src, O_RDONLY ) ;
477
    if ( in < 0 )
2075 dpurdie 478
        ErrorExit("Could not open source:", src);
2073 dpurdie 479
 
480
    out = open( dst, O_WRONLY | O_CREAT, st_mode | S_IWRITE );
481
    if ( out < 0 )
2075 dpurdie 482
        ErrorExit("Could not open dst:", dst);
2073 dpurdie 483
 
484
    while( (rlen = read( in, buffer, COPYSIZE )) > 0 )
485
    {
486
        wlen = write( out, buffer, rlen ) ;
487
        if ( wlen != rlen )
488
        {
489
            ferror = 1;
490
            break;
491
        }
492
    }
493
 
494
    close(in) ;
495
    close(out) ;
496
 
497
    /*
498
    **  File error
499
    **  Delete target
500
    */
501
    if ( ferror || rlen < 0 )
502
    {
503
        unlink(dst) ;
504
        return 0;
505
    }
506
    return 1;
507
}
508
 
2075 dpurdie 509
/*----------------------------------------------------------------------------
2085 dpurdie 510
** FUNCTION           : DeleteDir
511
**
512
** DESCRIPTION        : Delete a list of files in a specified directory
513
**                      Ensure files are writable
514
**                      Wilcarding is supported
515
**
516
**                      Then delete the directory - if its empty
517
**
518
**
519
** INPUTS             : argc    - count of args
520
**                      argv    - list of files to delete
2354 dpurdie 521
**                                [3]:  Base directory
522
**                                [4]+  Files in dir to delete
2085 dpurdie 523
**
2310 dpurdie 524
** RETURNS            : Will not return on error
2085 dpurdie 525
**
526
----------------------------------------------------------------------------*/
2075 dpurdie 527
 
2085 dpurdie 528
void DeleteDir( int argc, char* argv[] )
529
{
530
	int rv;
531
    struct stat fstat;
532
    char* baseDir;
533
    DIR *dir;
534
    struct dirent *dirent;
2310 dpurdie 535
    char *target;
2085 dpurdie 536
 
2310 dpurdie 537
 
2085 dpurdie 538
    /*
539
    **  Extract the base directory from the argument list
540
    **  This must be a directory
541
    */
2354 dpurdie 542
    baseDir = argv[3];
2085 dpurdie 543
 
544
    /*
545
    **  Ensure that the base directory exists
546
    */
547
    rv = stat( baseDir, &fstat );
548
    if ( rv != 0 )
549
    {
550
        /*
551
        **  Directory does not exists
2354 dpurdie 552
        **  Assume its already deleted
2085 dpurdie 553
        */
554
        if ( verbose > 1 )
555
            fprintf(stderr, "Base dir does not exist: %s\n", baseDir);
556
        return;
557
    }
558
 
559
    if ( !(fstat.st_mode & S_IFDIR))
560
    {
561
        /*
562
        **  Target is not a directory
563
        **  Don't do anything
564
        */
565
        if ( verbose > 1 )
566
            fprintf(stderr, "Base dir is not a directory: %s\n", baseDir);
567
        return;
568
    }
569
 
570
    /*
571
    **  Process all the suffixes
572
    **  They may contain a wild card
573
    */
574
    dir = opendir( baseDir );
575
    if ( dir == NULL )
576
    {
577
        /*
578
        **  Target is not a directory
579
        **  Don't do anything
580
        */
581
        if ( verbose > 1 )
582
            fprintf(stderr, "Base dir is not a directory: %s\n", baseDir);
583
        return;
584
    }
585
 
586
    /*
587
    **  Read next directory entry
588
    */
589
    while ( (dirent = readdir(dir)) != NULL )
590
    {
591
        int ii;
592
        if ( strcmp( ".", dirent->d_name ) == 0 )
593
            continue;
594
 
595
        if ( strcmp( "..", dirent->d_name ) == 0 )
596
            continue;
597
 
2313 dpurdie 598
        if ( verbose > 2 )
599
            fprintf(stderr, "Directory Entry:%s,%s\n", baseDir, dirent->d_name );
600
 
2085 dpurdie 601
        /*
602
        **  Compare against each item in the user list
603
        */
2354 dpurdie 604
        for ( ii = 4; ii < argc ; ii++)
2085 dpurdie 605
        {
606
 
607
            if ( wildcmp(dirent->d_name, argv[ii] )  )
608
            {
609
                if ( verbose > 1 )
610
                    fprintf(stderr, "Matching: %s, %s --- Found\n", dirent->d_name, argv[ii] );
2310 dpurdie 611
 
2085 dpurdie 612
                /*
613
                **  Matching file found
614
                */
2310 dpurdie 615
                target = makePath( baseDir, dirent->d_name);
616
                DeleteOneFile(target);
617
                free(target);
2085 dpurdie 618
            }
619
        }
620
    }
621
    closedir(dir);
622
 
623
    /*
624
    **  Finally delete the diretory
625
    **      Unless its '.'
626
    */
627
    if ( strcmp( ".", baseDir) != 0 )
628
    {
2354 dpurdie 629
        DeleteOneDirectory(baseDir);
2085 dpurdie 630
    }
631
}
632
 
2073 dpurdie 633
/*----------------------------------------------------------------------------
2310 dpurdie 634
** FUNCTION           : DeleteOneDirectoryTree
635
**
636
** DESCRIPTION        : Delete an entire directory tree(s)
2313 dpurdie 637
**                      Force it writable and searchable before deletion
638
**                      Don't follow symbolic links - just delete them
2310 dpurdie 639
**
640
** INPUTS             : path    - Dir to delete
641
**
642
** RETURNS            : Will not return on error
643
**
644
----------------------------------------------------------------------------*/
645
 
646
void DeleteOneDirectoryTree( char* baseDir )
647
{
648
    struct stat fstat;
649
    DIR *dir;
650
    struct dirent *dirent;
651
    char *target;
652
    int rv;
653
 
654
    /*
655
    **  A bit of a sanity test
656
    */
657
    if ( strcmp( ".", baseDir) == 0 || strcmp( "..", baseDir) == 0 )
658
    {
659
        fprintf(stderr, "DeleteOneDirectoryTree will not delete '.' or '..'\n");
660
        return;
661
    }
662
 
663
    /*
2313 dpurdie 664
    **  Ensure that the directory exists
665
    **  Force writable and searchable
666
    */
667
    rv = stat( baseDir, &fstat );
668
    if ( rv == 0 )
669
    {
670
        if ( fstat.st_mode & S_IFDIR )
671
        {
672
            mode_t newMode =  fstat.st_mode | S_IRUSR | S_IWUSR  | S_IXUSR;
673
            if ( fstat.st_mode != newMode )
674
            {
675
                if ( verbose > 1 )
676
                    fprintf(stderr, "Force u+rwx: %s\n", baseDir);
677
 
678
                rv = chmod( baseDir, newMode );
679
                if ( rv != 0 )
680
                {
681
                    fprintf(stderr, "Warning: Attempt to allow u+rwx access: %s\n", baseDir);
682
                }
683
            }
684
        }
685
    }
686
 
687
 
688
    /*
2310 dpurdie 689
    **  Process all entries
690
    */
691
    dir = opendir( baseDir );
692
    if ( dir == NULL )
693
    {
694
        /*
695
        **  Target is not a directory
696
        **  Don't do anything
697
        */
698
        if ( verbose > 1 )
699
            fprintf(stderr, "Base dir is not a directory: %s\n", baseDir);
700
        return;
701
    }
702
 
703
    /*
704
    **  Read next directory entry
705
    */
706
    while ( (dirent = readdir(dir)) != NULL )
707
    {
708
        if ( strcmp( ".", dirent->d_name ) == 0 )
709
            continue;
710
 
711
        if ( strcmp( "..", dirent->d_name ) == 0 )
712
            continue;
713
 
2313 dpurdie 714
        if ( verbose > 2 )
715
            fprintf(stderr, "Directory Entry:%s,%s\n", baseDir, dirent->d_name );
716
 
2310 dpurdie 717
        target = makePath( baseDir, dirent->d_name);
2313 dpurdie 718
        rv = lstat( target, &fstat );
2310 dpurdie 719
        if ( rv == 0 )
720
        {
721
            if ( fstat.st_mode & S_IFDIR )
722
            {
723
                DeleteOneDirectoryTree( target );
724
            }
725
            else
726
            {
727
                DeleteOneFile (target);
728
            }
729
        }
730
        free(target);
731
    }
732
    closedir(dir);
733
 
734
    /*
735
    **  Finally delete the directory
2354 dpurdie 736
    **  It should now be empty
2310 dpurdie 737
    */
2354 dpurdie 738
    DeleteOneDirectory(baseDir);
739
}
2310 dpurdie 740
 
2354 dpurdie 741
/*----------------------------------------------------------------------------
742
** FUNCTION           : RmItem
743
**
744
** DESCRIPTION        : Remove Empty directories and files
745
**
746
** INPUTS             : argc    - count of args
747
**                      argv    - list of files to delete
748
**                                [3]+  Base directory
749
**
750
** RETURNS            : Will not return on error
751
**
752
----------------------------------------------------------------------------*/
753
 
754
void RmItem( int argc, char* argv[] )
755
{
756
    int ii;
757
    struct stat fstat;
758
 
759
 
760
    for ( ii = 3; ii < argc ; ii++)
2310 dpurdie 761
    {
2354 dpurdie 762
        int rv;
763
 
764
        if ( verbose > 2)
765
            fprintf(stderr, "RmItem: %s\n", argv[ii]);
766
 
767
        rv = lstat( argv[ii], &fstat );
768
        if ( rv == 0 )
769
        {
770
            if (fstat.st_mode & S_IFDIR)
771
            {
772
                DeleteOneDirectory(argv[ii]);
773
            }
774
            else
775
            {
776
                DeleteOneFile(argv[ii]);
777
            }
778
        }
2310 dpurdie 779
    }
780
}
781
 
782
/*----------------------------------------------------------------------------
783
** FUNCTION           : DeleteOneFile
784
**
785
** DESCRIPTION        : Delete a file
2354 dpurdie 786
**                      Low level deletion operation to be used by other functions
2310 dpurdie 787
**                      Force it writable before deletion
2313 dpurdie 788
**                      Don't follow symbolic links - just delete them
2310 dpurdie 789
**
790
** INPUTS             : path        - path to the file
791
**
792
** RETURNS            : 0           - OK (file deleted or not present)
793
**
794
----------------------------------------------------------------------------*/
795
 
796
int DeleteOneFile (char * dst )
797
{
798
	int rv;
799
    struct stat fstat;
800
    int result = 0;
801
 
802
    if ( verbose > 1)
803
        fprintf(stderr, "Delete File: %s\n", dst);
804
 
2313 dpurdie 805
    rv = lstat( dst, &fstat );
2310 dpurdie 806
    if ( rv == 0 )
807
    {
808
        if ( verbose )
809
            fprintf(stderr, "Delete file: %s : Attr: 0%o\n", dst, fstat.st_mode);
810
        if ( !(fstat.st_mode & S_IWRITE) )
811
        {
812
            fstat.st_mode |= S_IWRITE;
813
            rv = chmod( dst, fstat.st_mode );
814
            if ( rv != 0 )
815
            {
816
                fprintf(stderr, "Warning: Attempt to allow write access: %s\n", dst);
817
            }
818
        }
819
 
820
        if ( unlink(dst) )
821
        {
822
            fprintf(stderr, "Warning: Did not remove file: %s\n", dst);
823
            result = 1;
824
        }
825
    }
2354 dpurdie 826
 
2310 dpurdie 827
    return result;
828
}
829
 
830
/*----------------------------------------------------------------------------
2354 dpurdie 831
** FUNCTION           : DeleteOneDirectory
2313 dpurdie 832
**
2354 dpurdie 833
** DESCRIPTION        : Low level function to delete a directory
834
**                      Assumes that checks have been performed
835
**                          It is a directory
836
**                          It does exist
2313 dpurdie 837
**
838
**
2354 dpurdie 839
** INPUTS             : path            - Target Path
2313 dpurdie 840
**
2354 dpurdie 841
** RETURNS            : Nothing
842
**
2313 dpurdie 843
----------------------------------------------------------------------------*/
844
 
2354 dpurdie 845
void DeleteOneDirectory (char *path )
2313 dpurdie 846
{
2354 dpurdie 847
    if ( verbose )
848
        fprintf(stderr, "Delete Directory: %s\n", path);
2313 dpurdie 849
 
2354 dpurdie 850
    if ( rmdir(path))
2313 dpurdie 851
    {
2354 dpurdie 852
        if ( verbose )
853
            fprintf(stderr, "Directory not deleted: %s\n", path);
2313 dpurdie 854
    }
855
}
856
 
857
/*----------------------------------------------------------------------------
2310 dpurdie 858
** FUNCTION           : makePath
859
**
860
** DESCRIPTION        : Create a path from two elements
2354 dpurdie 861
**                      Join 2 components together
2310 dpurdie 862
**                      Allocate memory
863
**
864
**
865
** INPUTS             : base        - Part 1
2354 dpurdie 866
**                      file        - Part 2 or NULL
2310 dpurdie 867
**
868
** RETURNS            :
869
**
870
----------------------------------------------------------------------------*/
871
 
872
char * makePath( char *base, char *path)
873
{
874
    int len1 = strlen(base);
875
    int len2 = strlen(path);
876
    char *data;
877
 
878
    data = (char *)malloc(len1 + len2 + 10);
879
    if ( data == NULL )
880
    {
881
        ErrorExit ("Malloc error:makePath","");
882
    }
883
 
884
    strcpy( data,base);
885
    strcpy( data + len1, "/");
886
    strcpy( data + len1 + 1, path);
887
 
888
    return data;
889
}
890
 
891
/*----------------------------------------------------------------------------
2085 dpurdie 892
** FUNCTION           : wildcmp
893
**
894
** DESCRIPTION        : Wildcard comparision
895
**
896
**
897
** INPUTS             : string          - String
898
**                      wild            - Wildcard template
899
**
900
** RETURNS            : TRUE - Match
901
**
902
----------------------------------------------------------------------------*/
903
 
904
int wildcmp(char *string, char *wild )
905
{
906
    char *cp, *mp;
907
    while ((*string) && (*wild != '*'))
908
    {
909
        if ((*wild != *string) && (*wild != '?'))
910
        {
911
            return 0;
912
        }
913
         wild++;
914
         string++;
915
    }
916
 
917
    while (*string)
918
    {
919
        if (*wild == '*')
920
        {
921
            if (!*++wild)
922
            {
923
                return 1;
924
            }
925
            mp = wild;
926
            cp = string+1;
927
        }
928
        else if ((*wild == *string) || (*wild == '?'))
929
        {
930
            wild++;
931
            string++;
932
        }
933
        else
934
        {
935
            wild = mp;
936
            string = cp++;
937
        }
938
    }
939
 
940
    while (*wild == '*')
941
    {
942
        wild++;
943
    }
944
 
945
    return !*wild;
946
}
947
 
2764 dpurdie 948
/*----------------------------------------------------------------------------
949
** FUNCTION           : from_hex
950
**
951
** DESCRIPTION        : Converts a hex character to its integer value
952
**                      Expects well formed HEX
953
**
954
**
955
** INPUTS             : Character to convert
956
**
957
** RETURNS            : Character
958
**
959
----------------------------------------------------------------------------*/
960
char from_hex(char ch)
961
{
962
    if ( ch >= '0' && ch <= '9' )
963
    {
964
        return ch - '0';
965
    }
2085 dpurdie 966
 
2764 dpurdie 967
    if ( ch >= 'A' && ch <= 'F' )
968
    {
969
        return ch - 'A' + 10;
970
    }
2085 dpurdie 971
 
2764 dpurdie 972
    if ( ch >= 'a' && ch <= 'f' )
973
    {
974
        return ch - 'f' + 10;
975
    }
2085 dpurdie 976
 
2764 dpurdie 977
    return 0;
978
}
979
 
2085 dpurdie 980
/*----------------------------------------------------------------------------
2764 dpurdie 981
** FUNCTION           : url_decode
982
**
983
** DESCRIPTION        : Perform (modified) URL decoding of a string
984
**                      Only support %nn stuff
985
**                      Its done inplace
986
**
987
**
988
** INPUTS             : str             - String to process
989
**
990
** RETURNS            : Nothing
991
**
992
----------------------------------------------------------------------------*/
993
 
994
void url_decode(char *str)
995
{
996
  char *pstr = str;
997
  char *pbuf = str;
998
 
999
    while (*pstr)
1000
    {
1001
        if (*pstr == '%')
1002
        {
1003
            if (pstr[1] && pstr[2])
1004
            {
1005
                *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
1006
                pstr += 2;
1007
            }
1008
/*        } */
1009
/*      } else if (*pstr == '+') {  */
1010
/*              *pbuf++ = ' '; */
1011
    }
1012
    else
1013
    {
1014
        *pbuf++ = *pstr;
1015
    }
1016
        pstr++;
1017
    }
1018
    *pbuf = '\0';
1019
}
1020
 
1021
/*----------------------------------------------------------------------------
2073 dpurdie 1022
** FUNCTION           : ErrorExit
1023
**
1024
** DESCRIPTION        : Error processing
1025
**                      Report an error and terminate process
1026
**
1027
**
1028
** INPUTS             : lpszMessage     - Message to display
1029
**
1030
** RETURNS            : Does't return
1031
**                      Will exit with bad code
1032
**
1033
----------------------------------------------------------------------------*/
1034
 
1035
void ErrorExit (char * lpszMessage, char * lpszMessage2)
1036
{ 
2354 dpurdie 1037
    if ( lpszMessage  )
1038
    {
1039
        fprintf(stderr, "JatsFileUtil:Error:%s%s\n", lpszMessage,lpszMessage2);
1040
    }
2073 dpurdie 1041
   fflush(stderr) ;
1042
   exit(-1);
1043
} 
1044