Subversion Repositories DevTools

Rev

Rev 2075 | Rev 2310 | 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
**
9
**  Description     :
10
**                      The program mimics - but a lot faster a Jats Makefile fragment
11
**                      The program will:
12
**
13
**                      Operate in two modes
14
**                          CopyFile
15
**                          DeleteFile
2075 dpurdie 16
**                          Remove Files
2085 dpurdie 17
**                          DeleteDir after deleting specified files
2073 dpurdie 18
**
19
**                      CopyFile (5 args)
20
**                          1) Display the ----- Text dest
21
**                          2) Error if the source is not found
22
**                          3) Create target path if not alraedy existing
23
**                          4) Copy the source to the target - overwritting the target
24
**                          5) Set File mode
25
**                          6) Test for file existence
26
**
27
**                      DeleteFile (3 args)
28
**                          1) Display the ----- Text dest
29
**                          2) Delete the target file
30
**
2075 dpurdie 31
**                      RemoveFiles ( >1 arg)
32
**                          1) Silenty delete a list of files. The files may
33
**                             be readonly so the attributes will need to be fixed.
34
**
2085 dpurdie 35
**                             Assumes the current directory
36
**
37
**                       DeleteDir (> 2 args)
38
**                          1) Silenty delete a list of files. The files may
39
**                             be readonly so the attributes will need to be fixed.
40
**                          2) Delete the directory if its empty
41
**
2073 dpurdie 42
**                      Make paths use '/'
43
**
44
**
45
**  Information     :
46
**   Compiler       : ANSI C++
47
**   Target         : 
48
**
49
***==========================================================================*/
50
 
51
#include <stdio.h>
52
#include <sys/types.h>
53
#include <sys/stat.h>
54
#include <fcntl.h>
55
#include <unistd.h>
56
#include <stdlib.h>
2085 dpurdie 57
#include <dirent.h>
2073 dpurdie 58
#include <string.h>
59
 
2085 dpurdie 60
#define MAX_FILE 2000
61
 
2073 dpurdie 62
void ErrorExit (char * lpszMessage, char * lpszMessage2);
63
void createPaths ( char *path );
2075 dpurdie 64
int CopyFile ( char *src, char *dst, mode_t st_mode );
65
void deleteFileList( int argc, char* argv[] );
2085 dpurdie 66
void DeleteDir( int argc, char* argv[] );
67
int wildcmp(char *string, char *wild );
2073 dpurdie 68
 
69
/*
70
**  Global
71
*/
72
char  verbose = 1;                          /* Debugging aid */
73
char  copyMode = 0;                         /* Mode */
2085 dpurdie 74
char  dst [MAX_FILE + 1];                   /* Scratch string workspace */
2073 dpurdie 75
 
76
/*----------------------------------------------------------------------------
77
** FUNCTION           : main
78
**
79
** DESCRIPTION        : Main entry points
80
**
81
**
82
** INPUTS             : Arguments are fixed
83
**                          Mode    - ModeDebug
84
**                          Text    - Text to output
85
**                          dest    - Target Path
86
**                          file    - Source path   [Copy Only]
87
**                          fmode   - File mode     [Copy Only]
88
**
89
** RETURNS            : 0 - All is good
90
**
91
----------------------------------------------------------------------------*/
92
 
93
int main(int argc, char* argv[])
94
{
95
 
96
	int rv;
97
    struct stat fstat;
98
    char *dst;
99
    char *src;
100
    mode_t src_mode;
101
 
102
    /*
103
    **  Examine the first argument
104
    **  Must be a character string of
2085 dpurdie 105
    **      [0] - Mode : c or d or r or l
2073 dpurdie 106
    **      [1] - Verbose : 0 .. 9
107
    */
108
    if ( argc > 1 )
109
    {
110
        if ( argv[1][0] == 'c' ) {
111
            copyMode = 1;
112
        } else if ( argv[1][0] == 'd' ) {
113
            copyMode = 2;
2075 dpurdie 114
        } else if ( argv[1][0] == 'r' ) {
115
            copyMode = 3;
2085 dpurdie 116
        } else if ( argv[1][0] == 'D' ) {
117
            copyMode = 4;
2073 dpurdie 118
        } else {
2075 dpurdie 119
            ErrorExit("Unknown mode: ",argv[1]);
2073 dpurdie 120
        }
121
 
122
        if ( argv[1][1] >= '0' && argv[1][1] <= '9' ) {
123
            verbose = argv[1][1] - '0';
124
        }
125
    }
126
 
127
    /*
128
    **  If Verbose, then display arguments
129
    */
2075 dpurdie 130
    if ( verbose > 1 )
2073 dpurdie 131
    {
132
        int ii;
133
        for ( ii = 0; ii < argc ; ii++ )
134
        {
135
            fprintf(stderr, "Arg%d: %s:\n", ii, argv[ii] );
136
        }
137
        fprintf(stderr, "Mode   : %d:\n", copyMode );
138
        fprintf(stderr, "Verbose: %d:\n", verbose );
139
        fflush(stderr) ;
140
    }
141
 
142
    /*
2075 dpurdie 143
    **  Determine required operation
144
    */
145
    if ( copyMode == 3 )
146
    {
147
        deleteFileList(argc - 2, argv + 2 );
148
        return 0;
149
    }
150
 
2085 dpurdie 151
    if ( copyMode == 4 )
152
    {
153
        DeleteDir(argc - 2, argv + 2 );
154
        return 0;
155
    }
156
 
2075 dpurdie 157
    /*
2073 dpurdie 158
    **  Determine mode of operation
159
    **      Copy or Delete
160
    */
161
    if ( copyMode == 1 && argc == 6 ) {
162
        src = argv[4];
163
        dst = argv[3];
164
 
165
    } else if ( copyMode == 2 && argc == 4) {
166
        dst = argv[3];
167
 
168
    } else {
169
        fprintf(stderr, "Mode: %d, Args: %d\n", copyMode, argc);
170
        ErrorExit("Incorrect argument count for mode","");
171
    }
172
 
173
    /*
174
    **  Display user text
175
    */
176
    fprintf(stderr, "---- %s %s\n", argv[2], argv[3]);
177
    fflush(stderr) ;
178
 
179
    /*
180
    **   Check that the source is a file
181
    */
182
    if ( copyMode == 1 )
183
    {
184
        if ( verbose )
185
            fprintf(stderr, "Validate Source File: %s\n", src);
186
 
187
        rv = stat( src, &fstat );
188
        if ( rv != 0 )
189
        {
190
    /* Need to be a better message */
191
            fprintf(stderr, "Source: %s\n", src);
2075 dpurdie 192
            ErrorExit("Source File not found: ", argv[4]);
2073 dpurdie 193
        }
194
        src_mode = fstat.st_mode;
195
    }
196
 
197
    /*
198
    **  Remove the ReadOnly attribute on the dest file
199
    */
200
    if ( verbose )
201
        fprintf(stderr, "Remove target file: %s\n", dst);
202
    rv = stat( dst, &fstat );
203
    if ( rv == 0 )
204
    {
205
        if ( verbose )
206
            fprintf(stderr, "FileExists with attr: 0%o\n", fstat.st_mode);
207
        if ( !(fstat.st_mode & S_IWRITE) )
208
        {
209
            fstat.st_mode |= S_IWRITE;
210
            rv = chmod( dst, fstat.st_mode );
211
            if ( rv != 0 )
212
            {
2075 dpurdie 213
                ErrorExit("Attempt to allow write access: ", argv[3]);
2073 dpurdie 214
            }
215
        }
216
 
217
        if ( unlink( dst ) )
218
        {
2075 dpurdie 219
                ErrorExit("Deleting file: ", argv[3]);
2073 dpurdie 220
        }
221
    }
222
 
223
    if ( copyMode == 1 )
224
    {
225
        /*
226
        **  Create directories
227
        **  Use the path to the target - not the provided directory
228
        **  as the createPaths function will not create the last element
229
        */
230
        createPaths( dst );
231
 
232
        /*
233
        **   Copy the file
234
        */
235
        if ( ! CopyFile( src, dst, src_mode ) )
236
        {
2075 dpurdie 237
            ErrorExit("Copy Error: ", argv[4]);
2073 dpurdie 238
        }
239
 
240
        /*
241
        **  Test for files existence
242
        */
243
        if ( verbose )
244
            fprintf(stderr, "Test target was copied: %s\n", dst);
245
        rv = stat( dst, &fstat );
246
        if ( rv != 0 )
247
        {
248
    /* Need to be a better message */
2075 dpurdie 249
            ErrorExit("File not found after copy: ", argv[3]);
2073 dpurdie 250
        }
251
 
252
        /*
253
        **  Set the files attributes
254
        **      Assume read-only
255
        */
256
        if ( strstr( argv[5], "-w" ) )
257
        {
258
            if ( verbose > 1 )
259
                fprintf(stderr, "Set target read-only: %s\n", dst);
260
            fstat.st_mode &= ~(S_IWRITE | S_IWOTH | S_IWGRP );
261
        }
262
 
263
        if ( strstr( argv[5], "+w" ) )
264
        {
265
            if ( verbose > 1 )
266
                fprintf(stderr, "Set target writable: %s\n", dst);
267
            fstat.st_mode |= (S_IWRITE | S_IWOTH | S_IWGRP );
268
        }
269
 
270
        if ( strstr( argv[5], "+x" ) )
271
        {
272
            if ( verbose > 1 )
273
                fprintf(stderr, "Set target executable: %s\n", dst);
274
            fstat.st_mode |= ( S_IXUSR | S_IXOTH | S_IXGRP );
275
        }
276
 
277
        if ( strstr( argv[5], "-x" ) )
278
        {
279
            if ( verbose > 1)
280
                fprintf(stderr, "Set target executable: %s\n", dst);
281
            fstat.st_mode &= ~( S_IXUSR | S_IXOTH | S_IXGRP );
282
        }
283
 
284
        if ( verbose )
285
            fprintf(stderr, "Set target perms: %s, 0%o\n", dst, fstat.st_mode);
286
        rv = chmod( dst, fstat.st_mode );
287
        if ( rv != 0 )
288
        {
2075 dpurdie 289
            ErrorExit("Setting ReadOnly: ", argv[3]);
2073 dpurdie 290
            }
291
        }
292
 
293
    return 0;
294
}
295
 
296
/*----------------------------------------------------------------------------
297
** FUNCTION           : createPaths
298
**
299
** DESCRIPTION        : Create the path to the target
300
**
301
**
302
** INPUTS             : path
303
**
304
** RETURNS            : Will not return in error
305
**
306
----------------------------------------------------------------------------*/
307
 
308
void createPaths ( char *path )
309
{
310
    struct stat fstat;
311
    int  rv;
312
    char *ptr = path;
313
 
314
    while ( *ptr )
315
    {
316
        if ( *ptr == '/' )
317
        {
318
            *ptr = 0;
319
 
320
            rv = stat( path, &fstat );
321
            if ( rv )
322
            {
323
                if ( verbose > 1 )
324
                {
325
                    fprintf(stderr, "createPaths: %s\n", path);
326
                    fflush(stderr) ;
327
                }
328
                rv = mkdir( path, 0777 );
329
                if ( rv )
330
                {
2075 dpurdie 331
                    ErrorExit("Could not create directories:", path);
2073 dpurdie 332
                }
333
            }
334
            *ptr = '/';
335
        }
336
        ptr++;
337
    }
338
}
339
 
340
/*----------------------------------------------------------------------------
341
** FUNCTION           : CopyFile
342
**
343
** DESCRIPTION        : Just copy a file
344
**
345
**
346
** INPUTS             : src - source path - already exists
347
**                      dst - path. Dirs already exist
348
**                      st_mode - Creation  mode. Copied from source file
349
**
350
** RETURNS            : false - Error
351
**
352
----------------------------------------------------------------------------*/
353
 
354
#define COPYSIZE  1024
355
int CopyFile ( char *src, char *dst, mode_t st_mode )
356
{
357
 
358
     ssize_t rlen = 0 ;
359
     ssize_t wlen = 0 ;
360
     int in;
361
     int out;
362
     int ferror = 0;
363
    char buffer[COPYSIZE] = { '\0' } ;
364
 
365
    if ( verbose )
366
    {
367
        fprintf(stderr, "CopyFile: Output Mode: 0%o\n", st_mode);
368
        fflush(stderr) ;
369
    }
370
 
371
    in = open( src, O_RDONLY ) ;
372
    if ( in < 0 )
2075 dpurdie 373
        ErrorExit("Could not open source:", src);
2073 dpurdie 374
 
375
    out = open( dst, O_WRONLY | O_CREAT, st_mode | S_IWRITE );
376
    if ( out < 0 )
2075 dpurdie 377
        ErrorExit("Could not open dst:", dst);
2073 dpurdie 378
 
379
    while( (rlen = read( in, buffer, COPYSIZE )) > 0 )
380
    {
381
        wlen = write( out, buffer, rlen ) ;
382
        if ( wlen != rlen )
383
        {
384
            ferror = 1;
385
            break;
386
        }
387
    }
388
 
389
    close(in) ;
390
    close(out) ;
391
 
392
    /*
393
    **  File error
394
    **  Delete target
395
    */
396
    if ( ferror || rlen < 0 )
397
    {
398
        unlink(dst) ;
399
        return 0;
400
    }
401
    return 1;
402
}
403
 
2075 dpurdie 404
/*----------------------------------------------------------------------------
405
** FUNCTION           : deleteFileList
406
**
407
** DESCRIPTION        : Delete a list of files
408
**                      Ensure files are writable
409
**
410
**
411
** INPUTS             : argc    - count of args
412
**                      argv    - list of files to delete
413
**
414
** RETURNS            : Wil not return on error
415
**
416
----------------------------------------------------------------------------*/
2073 dpurdie 417
 
2075 dpurdie 418
void deleteFileList( int argc, char* argv[] )
419
{
420
	int rv;
421
    struct stat fstat;
2073 dpurdie 422
 
2075 dpurdie 423
    for ( ; argc ; argc--, argv++ )
424
    {
425
        /*
426
        **  Remove the ReadOnly attribute on the dest file
427
        */
428
        if ( verbose > 1 )
429
            fprintf(stderr, "Remove target file: %s\n", *argv);
430
 
431
 
432
        rv = stat( *argv, &fstat );
433
        if ( rv == 0 )
434
        {
435
            if ( verbose )
436
                fprintf(stderr, "Delete file: %s : Attr: 0%o\n", *argv, fstat.st_mode);
437
            if ( !(fstat.st_mode & S_IWRITE) )
438
            {
439
                fstat.st_mode |= S_IWRITE;
440
                rv = chmod( *argv, fstat.st_mode );
441
                if ( rv != 0 )
442
                {
443
                    fprintf(stderr, "Warning: Attempt to allow write access: %s\n", *argv);
444
                }
445
            }
446
 
447
            if ( unlink( *argv ) )
448
            {
449
                fprintf(stderr, "Warning: Did not remove file: %s\n", *argv);
450
            }
451
        }
452
    }
453
}
454
 
2085 dpurdie 455
/*----------------------------------------------------------------------------
456
** FUNCTION           : DeleteDir
457
**
458
** DESCRIPTION        : Delete a list of files in a specified directory
459
**                      Ensure files are writable
460
**                      Wilcarding is supported
461
**
462
**                      Then delete the directory - if its empty
463
**
464
**
465
** INPUTS             : argc    - count of args
466
**                      argv    - list of files to delete
467
**                                [0]:  Text to display
468
**                                [1]:  Base directory
469
**                                [2]+  File in dir to delete
470
**
471
** RETURNS            : Wil not return on error
472
**
473
----------------------------------------------------------------------------*/
2075 dpurdie 474
 
2085 dpurdie 475
void DeleteDir( int argc, char* argv[] )
476
{
477
	int rv;
478
    struct stat fstat;
479
    char* baseDir;
480
    DIR *dir;
481
    struct dirent *dirent;
482
 
483
    if ( argc < 3 )
484
        ErrorExit("Insuffiecient arguments for DeleteDir","");
485
 
486
    /*
487
    **  Display the user message
488
    **      Supress display if the message is empty
489
    */
490
    if ( argv[0][0] )
491
    {
492
        fprintf(stderr, "%s\n", argv[0]);
493
        fflush(stderr) ;
494
    }
495
 
496
    /*
497
    **  Extract the base directory from the argument list
498
    **  This must be a directory
499
    */
500
    baseDir = argv[1];
501
    argc -= 2;
502
    argv+=2;
503
 
504
    /*
505
    **  Ensure that the base directory exists
506
    */
507
    rv = stat( baseDir, &fstat );
508
    if ( rv != 0 )
509
    {
510
        /*
511
        **  Directory does not exists
512
        **  Assume its aleady deleted
513
        */
514
        if ( verbose > 1 )
515
            fprintf(stderr, "Base dir does not exist: %s\n", baseDir);
516
        return;
517
    }
518
 
519
    if ( !(fstat.st_mode & S_IFDIR))
520
    {
521
        /*
522
        **  Target is not a directory
523
        **  Don't do anything
524
        */
525
        if ( verbose > 1 )
526
            fprintf(stderr, "Base dir is not a directory: %s\n", baseDir);
527
        return;
528
    }
529
 
530
    /*
531
    **  Process all the suffixes
532
    **  They may contain a wild card
533
    */
534
    dir = opendir( baseDir );
535
    if ( dir == NULL )
536
    {
537
        /*
538
        **  Target is not a directory
539
        **  Don't do anything
540
        */
541
        if ( verbose > 1 )
542
            fprintf(stderr, "Base dir is not a directory: %s\n", baseDir);
543
        return;
544
    }
545
 
546
    /*
547
    **  Read next directory entry
548
    */
549
    while ( (dirent = readdir(dir)) != NULL )
550
    {
551
        int ii;
552
        if ( verbose > 2 )
553
            fprintf(stderr, "Directory Entry:%s,%s\n", baseDir, dirent->d_name );
554
 
555
        if ( strcmp( ".", dirent->d_name ) == 0 )
556
            continue;
557
 
558
        if ( strcmp( "..", dirent->d_name ) == 0 )
559
            continue;
560
 
561
        /*
562
        **  Compare against each item in the user list
563
        */
564
        for ( ii = 0; ii < argc ; ii++)
565
        {
566
 
567
            if ( wildcmp(dirent->d_name, argv[ii] )  )
568
            {
569
                if ( verbose > 1 )
570
                    fprintf(stderr, "Matching: %s, %s --- Found\n", dirent->d_name, argv[ii] );
571
                /*
572
                **  Matching file found
573
                */
574
                strcpy( dst, baseDir);
575
                strcat( dst, "/");
576
                strcat( dst, dirent->d_name);
577
 
578
                rv = stat( dst, &fstat );
579
                if ( rv == 0 )
580
                {
581
                    if ( verbose )
582
                        fprintf(stderr, "Delete file: %s : Attr: 0%o\n", dst, fstat.st_mode);
583
                    if ( !(fstat.st_mode & S_IWRITE) )
584
                    {
585
                        fstat.st_mode |= S_IWRITE;
586
                        rv = chmod( dst, fstat.st_mode );
587
                        if ( rv != 0 )
588
                        {
589
                            fprintf(stderr, "Warning: Attempt to allow write access: %s\n", dst);
590
                        }
591
                    }
592
 
593
                    if ( unlink(dst) )
594
                    {
595
                        fprintf(stderr, "Warning: Did not remove file: %s\n", dst);
596
                    }
597
                }
598
            }
599
        }
600
    }
601
    closedir(dir);
602
 
603
    /*
604
    **  Finally delete the diretory
605
    **      Unless its '.'
606
    */
607
    if ( strcmp( ".", baseDir) != 0 )
608
    {
609
        if ( verbose > 1 )
610
            fprintf(stderr, "Delete Directory: %s\n", baseDir);
611
        if ( rmdir (baseDir ) )
612
        {
613
            if ( verbose )
614
                fprintf(stderr, "Directory not deleted: %s\n", baseDir);
615
        }
616
    }
617
}
618
 
2073 dpurdie 619
/*----------------------------------------------------------------------------
2085 dpurdie 620
** FUNCTION           : wildcmp
621
**
622
** DESCRIPTION        : Wildcard comparision
623
**
624
**
625
** INPUTS             : string          - String
626
**                      wild            - Wildcard template
627
**
628
** RETURNS            : TRUE - Match
629
**
630
----------------------------------------------------------------------------*/
631
 
632
int wildcmp(char *string, char *wild )
633
{
634
    char *cp, *mp;
635
    while ((*string) && (*wild != '*'))
636
    {
637
        if ((*wild != *string) && (*wild != '?'))
638
        {
639
            return 0;
640
        }
641
         wild++;
642
         string++;
643
    }
644
 
645
    while (*string)
646
    {
647
        if (*wild == '*')
648
        {
649
            if (!*++wild)
650
            {
651
                return 1;
652
            }
653
            mp = wild;
654
            cp = string+1;
655
        }
656
        else if ((*wild == *string) || (*wild == '?'))
657
        {
658
            wild++;
659
            string++;
660
        }
661
        else
662
        {
663
            wild = mp;
664
            string = cp++;
665
        }
666
    }
667
 
668
    while (*wild == '*')
669
    {
670
        wild++;
671
    }
672
 
673
    return !*wild;
674
}
675
 
676
 
677
 
678
 
679
/*----------------------------------------------------------------------------
2073 dpurdie 680
** FUNCTION           : ErrorExit
681
**
682
** DESCRIPTION        : Error processing
683
**                      Report an error and terminate process
684
**
685
**
686
** INPUTS             : lpszMessage     - Message to display
687
**
688
** RETURNS            : Does't return
689
**                      Will exit with bad code
690
**
691
----------------------------------------------------------------------------*/
692
 
693
void ErrorExit (char * lpszMessage, char * lpszMessage2)
694
{ 
2075 dpurdie 695
   fprintf(stderr, "JatsFileUtil:Error: %s%s\n", lpszMessage,lpszMessage2);
2073 dpurdie 696
   fflush(stderr) ;
697
   exit(-1);
698
} 
699