Subversion Repositories DevTools

Rev

Rev 2764 | Go to most recent revision | 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
    /*
5882 dpurdie 387
    ** Sometimes symlinks are handled differently
388
    */
389
    if (strstr( argv[5], "+l" ))
390
    {
391
        rv = lstat(src, &lfstat); 
392
        if ( rv == 0 && S_ISLNK(lfstat.st_mode))
393
        {
394
            if ( verbose > 2)
395
                fprintf(stderr, "Copy Symlink: %s\n", src);
396
            symlink = 1;
397
            if ( ! CopyLink( src, dst, lfstat.st_size ) )
398
            {
399
                ErrorExit("Copy Symlink Error: ", argv[4]);
400
            }
401
        }
402
    }
403
 
404
    /*
2310 dpurdie 405
    **   Copy the file
406
    */
407
    if ( ! CopyFile( src, dst, fstat.st_mode ) )
408
    {
409
        ErrorExit("Copy Error: ", argv[4]);
410
    }
411
 
412
    /*
413
    **  Test for files existence
414
    */
2354 dpurdie 415
    if ( verbose > 1 )
2310 dpurdie 416
        fprintf(stderr, "Test target was copied: %s\n", dst);
417
 
418
    rv = stat( dst, &fstat );
419
    if ( rv != 0 )
420
    {
421
/* Need to be a better message */
422
        ErrorExit("File not found after copy: ", argv[3]);
423
    }
424
 
425
    /*
5882 dpurdie 426
    **  Set the files attributes, unless copying a symlink
2310 dpurdie 427
    **      Assume read-only
428
    */
5882 dpurdie 429
    if (!symlink)
2310 dpurdie 430
    {
5882 dpurdie 431
        if (strstr(argv[5], "-w")) 
432
        {
433
            if ( verbose > 1 )
434
                fprintf(stderr, "Set target read-only: %s\n", dst);
435
            fstat.st_mode &= ~(S_IWRITE | S_IWOTH | S_IWGRP );
436
        }
2310 dpurdie 437
 
5882 dpurdie 438
        if ( strstr( argv[5], "+w" ) )
439
        {
440
            if ( verbose > 1 )
441
                fprintf(stderr, "Set target writable: %s\n", dst);
442
            fstat.st_mode |= (S_IWRITE | S_IWOTH | S_IWGRP );
443
        }
2310 dpurdie 444
 
5882 dpurdie 445
        if ( strstr( argv[5], "+x" ) )
446
        {
447
            if ( verbose > 1 )
448
                fprintf(stderr, "Set target executable: %s\n", dst);
449
            fstat.st_mode |= ( S_IXUSR | S_IXOTH | S_IXGRP );
450
        }
451
 
452
        if ( strstr( argv[5], "-x" ) )
453
        {
454
            if ( verbose > 1)
455
                fprintf(stderr, "Set target not executable: %s\n", dst);
456
            fstat.st_mode &= ~( S_IXUSR | S_IXOTH | S_IXGRP );
457
        }
458
 
2310 dpurdie 459
        if ( verbose > 1 )
5882 dpurdie 460
            fprintf(stderr, "Set target perms: %s, 0%o\n", dst, fstat.st_mode);
461
        rv = chmod( dst, fstat.st_mode );
462
        if ( rv != 0 )
463
        {
464
            ErrorExit("Setting ReadOnly: ", argv[3]);
465
        }
2310 dpurdie 466
    }
467
}
468
 
469
/*----------------------------------------------------------------------------
2073 dpurdie 470
** FUNCTION           : CopyFile
471
**
472
** DESCRIPTION        : Just copy a file
473
**
474
**
475
** INPUTS             : src - source path - already exists
476
**                      dst - path. Dirs already exist
477
**                      st_mode - Creation  mode. Copied from source file
478
**
479
** RETURNS            : false - Error
480
**
481
----------------------------------------------------------------------------*/
482
 
483
#define COPYSIZE  1024
484
int CopyFile ( char *src, char *dst, mode_t st_mode )
485
{
486
 
487
     ssize_t rlen = 0 ;
488
     ssize_t wlen = 0 ;
489
     int in;
490
     int out;
491
     int ferror = 0;
492
    char buffer[COPYSIZE] = { '\0' } ;
493
 
2354 dpurdie 494
    if ( verbose > 2 )
2073 dpurdie 495
    {
496
        fprintf(stderr, "CopyFile: Output Mode: 0%o\n", st_mode);
497
        fflush(stderr) ;
498
    }
499
 
500
    in = open( src, O_RDONLY ) ;
501
    if ( in < 0 )
2075 dpurdie 502
        ErrorExit("Could not open source:", src);
2073 dpurdie 503
 
504
    out = open( dst, O_WRONLY | O_CREAT, st_mode | S_IWRITE );
505
    if ( out < 0 )
2075 dpurdie 506
        ErrorExit("Could not open dst:", dst);
2073 dpurdie 507
 
508
    while( (rlen = read( in, buffer, COPYSIZE )) > 0 )
509
    {
510
        wlen = write( out, buffer, rlen ) ;
511
        if ( wlen != rlen )
512
        {
513
            ferror = 1;
514
            break;
515
        }
516
    }
517
 
518
    close(in) ;
519
    close(out) ;
520
 
521
    /*
522
    **  File error
523
    **  Delete target
524
    */
525
    if ( ferror || rlen < 0 )
526
    {
527
        unlink(dst) ;
528
        return 0;
529
    }
530
    return 1;
531
}
532
 
2075 dpurdie 533
/*----------------------------------------------------------------------------
5882 dpurdie 534
** FUNCTION           : CopyLink
535
**
536
** DESCRIPTION        : Just copy a symlink
537
**
538
**
539
** INPUTS             : src - source path to a symlink - already exists
540
**                      dst - path. Dirs already exist
541
**                      lsize - size of the link text
542
**
543
** RETURNS            : false - Error
544
**
545
----------------------------------------------------------------------------*/
546
 
547
int CopyLink ( char *src, char *dst, int lsize )
548
{
549
    char *linkname = malloc(lsize + 1);
550
    ssize_t rlen = 0 ;
551
    int rv;
552
 
553
    if (linkname == NULL)
554
    {
555
        ErrorExit("Malloc error: %s", src);
556
    }
557
 
558
    rlen = readlink(src, linkname, lsize + 1);
559
    if (rlen < 0)
560
    {
561
        ErrorExit("Reading Link: %s", src);
562
    }
563
 
564
    rv = symlink( linkname, dst);
565
    if (rv)
566
    {
567
        unlink(dst) ;
568
        ErrorExit("Reading Link: %s", src);
569
    }
570
 
571
    return 1;
572
}
573
 
574
/*----------------------------------------------------------------------------
2085 dpurdie 575
** FUNCTION           : DeleteDir
576
**
577
** DESCRIPTION        : Delete a list of files in a specified directory
578
**                      Ensure files are writable
579
**                      Wilcarding is supported
580
**
581
**                      Then delete the directory - if its empty
582
**
583
**
584
** INPUTS             : argc    - count of args
585
**                      argv    - list of files to delete
2354 dpurdie 586
**                                [3]:  Base directory
587
**                                [4]+  Files in dir to delete
2085 dpurdie 588
**
2310 dpurdie 589
** RETURNS            : Will not return on error
2085 dpurdie 590
**
591
----------------------------------------------------------------------------*/
2075 dpurdie 592
 
2085 dpurdie 593
void DeleteDir( int argc, char* argv[] )
594
{
5882 dpurdie 595
    int rv;
2085 dpurdie 596
    struct stat fstat;
597
    char* baseDir;
598
    DIR *dir;
599
    struct dirent *dirent;
2310 dpurdie 600
    char *target;
2085 dpurdie 601
 
2310 dpurdie 602
 
2085 dpurdie 603
    /*
604
    **  Extract the base directory from the argument list
605
    **  This must be a directory
606
    */
2354 dpurdie 607
    baseDir = argv[3];
2085 dpurdie 608
 
609
    /*
610
    **  Ensure that the base directory exists
611
    */
612
    rv = stat( baseDir, &fstat );
613
    if ( rv != 0 )
614
    {
615
        /*
616
        **  Directory does not exists
2354 dpurdie 617
        **  Assume its already deleted
2085 dpurdie 618
        */
619
        if ( verbose > 1 )
620
            fprintf(stderr, "Base dir does not exist: %s\n", baseDir);
621
        return;
622
    }
623
 
624
    if ( !(fstat.st_mode & S_IFDIR))
625
    {
626
        /*
627
        **  Target is not a directory
628
        **  Don't do anything
629
        */
630
        if ( verbose > 1 )
631
            fprintf(stderr, "Base dir is not a directory: %s\n", baseDir);
632
        return;
633
    }
634
 
635
    /*
636
    **  Process all the suffixes
637
    **  They may contain a wild card
638
    */
639
    dir = opendir( baseDir );
640
    if ( dir == NULL )
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
    **  Read next directory entry
653
    */
654
    while ( (dirent = readdir(dir)) != NULL )
655
    {
656
        int ii;
657
        if ( strcmp( ".", dirent->d_name ) == 0 )
658
            continue;
659
 
660
        if ( strcmp( "..", dirent->d_name ) == 0 )
661
            continue;
662
 
2313 dpurdie 663
        if ( verbose > 2 )
664
            fprintf(stderr, "Directory Entry:%s,%s\n", baseDir, dirent->d_name );
665
 
2085 dpurdie 666
        /*
667
        **  Compare against each item in the user list
668
        */
2354 dpurdie 669
        for ( ii = 4; ii < argc ; ii++)
2085 dpurdie 670
        {
671
 
672
            if ( wildcmp(dirent->d_name, argv[ii] )  )
673
            {
674
                if ( verbose > 1 )
675
                    fprintf(stderr, "Matching: %s, %s --- Found\n", dirent->d_name, argv[ii] );
2310 dpurdie 676
 
2085 dpurdie 677
                /*
678
                **  Matching file found
679
                */
2310 dpurdie 680
                target = makePath( baseDir, dirent->d_name);
681
                DeleteOneFile(target);
682
                free(target);
2085 dpurdie 683
            }
684
        }
685
    }
686
    closedir(dir);
687
 
688
    /*
689
    **  Finally delete the diretory
690
    **      Unless its '.'
691
    */
692
    if ( strcmp( ".", baseDir) != 0 )
693
    {
2354 dpurdie 694
        DeleteOneDirectory(baseDir);
2085 dpurdie 695
    }
696
}
697
 
2073 dpurdie 698
/*----------------------------------------------------------------------------
2310 dpurdie 699
** FUNCTION           : DeleteOneDirectoryTree
700
**
701
** DESCRIPTION        : Delete an entire directory tree(s)
2313 dpurdie 702
**                      Force it writable and searchable before deletion
703
**                      Don't follow symbolic links - just delete them
2310 dpurdie 704
**
705
** INPUTS             : path    - Dir to delete
706
**
707
** RETURNS            : Will not return on error
708
**
709
----------------------------------------------------------------------------*/
710
 
711
void DeleteOneDirectoryTree( char* baseDir )
712
{
713
    struct stat fstat;
714
    DIR *dir;
715
    struct dirent *dirent;
716
    char *target;
717
    int rv;
718
 
719
    /*
720
    **  A bit of a sanity test
721
    */
722
    if ( strcmp( ".", baseDir) == 0 || strcmp( "..", baseDir) == 0 )
723
    {
724
        fprintf(stderr, "DeleteOneDirectoryTree will not delete '.' or '..'\n");
725
        return;
726
    }
727
 
728
    /*
2313 dpurdie 729
    **  Ensure that the directory exists
730
    **  Force writable and searchable
731
    */
732
    rv = stat( baseDir, &fstat );
733
    if ( rv == 0 )
734
    {
735
        if ( fstat.st_mode & S_IFDIR )
736
        {
737
            mode_t newMode =  fstat.st_mode | S_IRUSR | S_IWUSR  | S_IXUSR;
738
            if ( fstat.st_mode != newMode )
739
            {
740
                if ( verbose > 1 )
741
                    fprintf(stderr, "Force u+rwx: %s\n", baseDir);
742
 
743
                rv = chmod( baseDir, newMode );
744
                if ( rv != 0 )
745
                {
746
                    fprintf(stderr, "Warning: Attempt to allow u+rwx access: %s\n", baseDir);
747
                }
748
            }
749
        }
750
    }
751
 
752
 
753
    /*
2310 dpurdie 754
    **  Process all entries
755
    */
756
    dir = opendir( baseDir );
757
    if ( dir == NULL )
758
    {
759
        /*
760
        **  Target is not a directory
761
        **  Don't do anything
762
        */
763
        if ( verbose > 1 )
764
            fprintf(stderr, "Base dir is not a directory: %s\n", baseDir);
765
        return;
766
    }
767
 
768
    /*
769
    **  Read next directory entry
770
    */
771
    while ( (dirent = readdir(dir)) != NULL )
772
    {
773
        if ( strcmp( ".", dirent->d_name ) == 0 )
774
            continue;
775
 
776
        if ( strcmp( "..", dirent->d_name ) == 0 )
777
            continue;
778
 
2313 dpurdie 779
        if ( verbose > 2 )
780
            fprintf(stderr, "Directory Entry:%s,%s\n", baseDir, dirent->d_name );
781
 
2310 dpurdie 782
        target = makePath( baseDir, dirent->d_name);
2313 dpurdie 783
        rv = lstat( target, &fstat );
2310 dpurdie 784
        if ( rv == 0 )
785
        {
786
            if ( fstat.st_mode & S_IFDIR )
787
            {
788
                DeleteOneDirectoryTree( target );
789
            }
790
            else
791
            {
792
                DeleteOneFile (target);
793
            }
794
        }
795
        free(target);
796
    }
797
    closedir(dir);
798
 
799
    /*
800
    **  Finally delete the directory
2354 dpurdie 801
    **  It should now be empty
2310 dpurdie 802
    */
2354 dpurdie 803
    DeleteOneDirectory(baseDir);
804
}
2310 dpurdie 805
 
2354 dpurdie 806
/*----------------------------------------------------------------------------
807
** FUNCTION           : RmItem
808
**
809
** DESCRIPTION        : Remove Empty directories and files
810
**
811
** INPUTS             : argc    - count of args
812
**                      argv    - list of files to delete
813
**                                [3]+  Base directory
814
**
815
** RETURNS            : Will not return on error
816
**
817
----------------------------------------------------------------------------*/
818
 
819
void RmItem( int argc, char* argv[] )
820
{
821
    int ii;
822
    struct stat fstat;
823
 
824
 
825
    for ( ii = 3; ii < argc ; ii++)
2310 dpurdie 826
    {
2354 dpurdie 827
        int rv;
828
 
829
        if ( verbose > 2)
830
            fprintf(stderr, "RmItem: %s\n", argv[ii]);
831
 
832
        rv = lstat( argv[ii], &fstat );
833
        if ( rv == 0 )
834
        {
835
            if (fstat.st_mode & S_IFDIR)
836
            {
837
                DeleteOneDirectory(argv[ii]);
838
            }
839
            else
840
            {
841
                DeleteOneFile(argv[ii]);
842
            }
843
        }
2310 dpurdie 844
    }
845
}
846
 
847
/*----------------------------------------------------------------------------
848
** FUNCTION           : DeleteOneFile
849
**
850
** DESCRIPTION        : Delete a file
2354 dpurdie 851
**                      Low level deletion operation to be used by other functions
2310 dpurdie 852
**                      Force it writable before deletion
2313 dpurdie 853
**                      Don't follow symbolic links - just delete them
2310 dpurdie 854
**
855
** INPUTS             : path        - path to the file
856
**
857
** RETURNS            : 0           - OK (file deleted or not present)
858
**
859
----------------------------------------------------------------------------*/
860
 
861
int DeleteOneFile (char * dst )
862
{
5882 dpurdie 863
    int rv;
2310 dpurdie 864
    struct stat fstat;
865
    int result = 0;
866
 
867
    if ( verbose > 1)
868
        fprintf(stderr, "Delete File: %s\n", dst);
869
 
2313 dpurdie 870
    rv = lstat( dst, &fstat );
2310 dpurdie 871
    if ( rv == 0 )
872
    {
873
        if ( verbose )
874
            fprintf(stderr, "Delete file: %s : Attr: 0%o\n", dst, fstat.st_mode);
875
        if ( !(fstat.st_mode & S_IWRITE) )
876
        {
877
            fstat.st_mode |= S_IWRITE;
878
            rv = chmod( dst, fstat.st_mode );
879
            if ( rv != 0 )
880
            {
881
                fprintf(stderr, "Warning: Attempt to allow write access: %s\n", dst);
882
            }
883
        }
884
 
885
        if ( unlink(dst) )
886
        {
887
            fprintf(stderr, "Warning: Did not remove file: %s\n", dst);
888
            result = 1;
889
        }
890
    }
2354 dpurdie 891
 
2310 dpurdie 892
    return result;
893
}
894
 
895
/*----------------------------------------------------------------------------
2354 dpurdie 896
** FUNCTION           : DeleteOneDirectory
2313 dpurdie 897
**
2354 dpurdie 898
** DESCRIPTION        : Low level function to delete a directory
899
**                      Assumes that checks have been performed
900
**                          It is a directory
901
**                          It does exist
2313 dpurdie 902
**
903
**
2354 dpurdie 904
** INPUTS             : path            - Target Path
2313 dpurdie 905
**
2354 dpurdie 906
** RETURNS            : Nothing
907
**
2313 dpurdie 908
----------------------------------------------------------------------------*/
909
 
2354 dpurdie 910
void DeleteOneDirectory (char *path )
2313 dpurdie 911
{
2354 dpurdie 912
    if ( verbose )
913
        fprintf(stderr, "Delete Directory: %s\n", path);
2313 dpurdie 914
 
2354 dpurdie 915
    if ( rmdir(path))
2313 dpurdie 916
    {
2354 dpurdie 917
        if ( verbose )
918
            fprintf(stderr, "Directory not deleted: %s\n", path);
2313 dpurdie 919
    }
920
}
921
 
922
/*----------------------------------------------------------------------------
2310 dpurdie 923
** FUNCTION           : makePath
924
**
925
** DESCRIPTION        : Create a path from two elements
2354 dpurdie 926
**                      Join 2 components together
2310 dpurdie 927
**                      Allocate memory
928
**
929
**
930
** INPUTS             : base        - Part 1
2354 dpurdie 931
**                      file        - Part 2 or NULL
2310 dpurdie 932
**
933
** RETURNS            :
934
**
935
----------------------------------------------------------------------------*/
936
 
937
char * makePath( char *base, char *path)
938
{
939
    int len1 = strlen(base);
940
    int len2 = strlen(path);
941
    char *data;
942
 
943
    data = (char *)malloc(len1 + len2 + 10);
944
    if ( data == NULL )
945
    {
946
        ErrorExit ("Malloc error:makePath","");
947
    }
948
 
949
    strcpy( data,base);
950
    strcpy( data + len1, "/");
951
    strcpy( data + len1 + 1, path);
952
 
953
    return data;
954
}
955
 
956
/*----------------------------------------------------------------------------
2085 dpurdie 957
** FUNCTION           : wildcmp
958
**
959
** DESCRIPTION        : Wildcard comparision
960
**
961
**
962
** INPUTS             : string          - String
963
**                      wild            - Wildcard template
964
**
965
** RETURNS            : TRUE - Match
966
**
967
----------------------------------------------------------------------------*/
968
 
969
int wildcmp(char *string, char *wild )
970
{
971
    char *cp, *mp;
972
    while ((*string) && (*wild != '*'))
973
    {
974
        if ((*wild != *string) && (*wild != '?'))
975
        {
976
            return 0;
977
        }
978
         wild++;
979
         string++;
980
    }
981
 
982
    while (*string)
983
    {
984
        if (*wild == '*')
985
        {
986
            if (!*++wild)
987
            {
988
                return 1;
989
            }
990
            mp = wild;
991
            cp = string+1;
992
        }
993
        else if ((*wild == *string) || (*wild == '?'))
994
        {
995
            wild++;
996
            string++;
997
        }
998
        else
999
        {
1000
            wild = mp;
1001
            string = cp++;
1002
        }
1003
    }
1004
 
1005
    while (*wild == '*')
1006
    {
1007
        wild++;
1008
    }
1009
 
1010
    return !*wild;
1011
}
1012
 
2764 dpurdie 1013
/*----------------------------------------------------------------------------
1014
** FUNCTION           : from_hex
1015
**
1016
** DESCRIPTION        : Converts a hex character to its integer value
1017
**                      Expects well formed HEX
1018
**
1019
**
1020
** INPUTS             : Character to convert
1021
**
1022
** RETURNS            : Character
1023
**
1024
----------------------------------------------------------------------------*/
1025
char from_hex(char ch)
1026
{
1027
    if ( ch >= '0' && ch <= '9' )
1028
    {
1029
        return ch - '0';
1030
    }
2085 dpurdie 1031
 
2764 dpurdie 1032
    if ( ch >= 'A' && ch <= 'F' )
1033
    {
1034
        return ch - 'A' + 10;
1035
    }
2085 dpurdie 1036
 
2764 dpurdie 1037
    if ( ch >= 'a' && ch <= 'f' )
1038
    {
1039
        return ch - 'f' + 10;
1040
    }
2085 dpurdie 1041
 
2764 dpurdie 1042
    return 0;
1043
}
1044
 
2085 dpurdie 1045
/*----------------------------------------------------------------------------
2764 dpurdie 1046
** FUNCTION           : url_decode
1047
**
1048
** DESCRIPTION        : Perform (modified) URL decoding of a string
1049
**                      Only support %nn stuff
1050
**                      Its done inplace
1051
**
1052
**
1053
** INPUTS             : str             - String to process
1054
**
1055
** RETURNS            : Nothing
1056
**
1057
----------------------------------------------------------------------------*/
1058
 
1059
void url_decode(char *str)
1060
{
1061
  char *pstr = str;
1062
  char *pbuf = str;
1063
 
1064
    while (*pstr)
1065
    {
1066
        if (*pstr == '%')
1067
        {
1068
            if (pstr[1] && pstr[2])
1069
            {
1070
                *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
1071
                pstr += 2;
1072
            }
1073
/*        } */
1074
/*      } else if (*pstr == '+') {  */
1075
/*              *pbuf++ = ' '; */
1076
    }
1077
    else
1078
    {
1079
        *pbuf++ = *pstr;
1080
    }
1081
        pstr++;
1082
    }
1083
    *pbuf = '\0';
1084
}
1085
 
1086
/*----------------------------------------------------------------------------
2073 dpurdie 1087
** FUNCTION           : ErrorExit
1088
**
1089
** DESCRIPTION        : Error processing
1090
**                      Report an error and terminate process
1091
**
1092
**
1093
** INPUTS             : lpszMessage     - Message to display
1094
**
1095
** RETURNS            : Does't return
1096
**                      Will exit with bad code
1097
**
1098
----------------------------------------------------------------------------*/
1099
 
1100
void ErrorExit (char * lpszMessage, char * lpszMessage2)
1101
{ 
2354 dpurdie 1102
    if ( lpszMessage  )
1103
    {
1104
        fprintf(stderr, "JatsFileUtil:Error:%s%s\n", lpszMessage,lpszMessage2);
1105
    }
2073 dpurdie 1106
   fflush(stderr) ;
1107
   exit(-1);
1108
} 
1109