Subversion Repositories DevTools

Rev

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