Subversion Repositories DevTools

Rev

Rev 2073 | Rev 2085 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*============================================================================
** Copyright (C) 1998-2012 Vix Technology, All rights reserved
**============================================================================
**
**  Project/Product : 
**  Filename        : JatsFileUtil.c
**  Author(s)       : DDP
**
**  Description     :
**                      The program mimics - but a lot faster a Jats Makefile fragment
**                      The program will:
**
**                      Operate in two modes
**                          CopyFile
**                          DeleteFile
**                          Remove Files
**
**                      CopyFile (5 args)
**                          1) Display the ----- Text dest
**                          2) Error if the source is not found
**                          3) Create target path if not alraedy existing
**                          4) Copy the source to the target - overwritting the target
**                          5) Set File mode
**                          6) Test for file existence
**
**                      DeleteFile (3 args)
**                          1) Display the ----- Text dest
**                          2) Delete the target file
**
**                      RemoveFiles ( >1 arg)
**                          1) Silenty delete a list of files. The files may
**                             be readonly so the attributes will need to be fixed.
**
**                      Make paths use '/'
**
**
**  Information     :
**   Compiler       : ANSI C++
**   Target         : 
**
***==========================================================================*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

void ErrorExit (char * lpszMessage, char * lpszMessage2);
void createPaths ( char *path );
int CopyFile ( char *src, char *dst, mode_t st_mode );
void deleteFileList( int argc, char* argv[] );

/*
**  Global
*/
char  verbose = 1;                          /* Debugging aid */
char  copyMode = 0;                         /* Mode */

/*----------------------------------------------------------------------------
** FUNCTION           : main
**
** DESCRIPTION        : Main entry points
**
**
** INPUTS             : Arguments are fixed
**                          Mode    - ModeDebug
**                          Text    - Text to output
**                          dest    - Target Path
**                          file    - Source path   [Copy Only]
**                          fmode   - File mode     [Copy Only]
**
** RETURNS            : 0 - All is good
**
----------------------------------------------------------------------------*/

int main(int argc, char* argv[])
{

        int rv;
    struct stat fstat;
    char *dst;
    char *src;
    mode_t src_mode;

    /*
    **  Examine the first argument
    **  Must be a character string of
    **      [0] - Mode : c or d or r
    **      [1] - Verbose : 0 .. 9
    */
    if ( argc > 1 )
    {
        if ( argv[1][0] == 'c' ) {
            copyMode = 1;
        } else if ( argv[1][0] == 'd' ) {
            copyMode = 2;
        } else if ( argv[1][0] == 'r' ) {
            copyMode = 3;
        } else {
            ErrorExit("Unknown mode: ",argv[1]);
        }

        if ( argv[1][1] >= '0' && argv[1][1] <= '9' ) {
            verbose = argv[1][1] - '0';
        }
    }

    /*
    **  If Verbose, then display arguments
    */
    if ( verbose > 1 )
    {
        int ii;
        for ( ii = 0; ii < argc ; ii++ )
        {
            fprintf(stderr, "Arg%d: %s:\n", ii, argv[ii] );
        }
        fprintf(stderr, "Mode   : %d:\n", copyMode );
        fprintf(stderr, "Verbose: %d:\n", verbose );
        fflush(stderr) ;
    }

    /*
    **  Determine required operation
    */
    if ( copyMode == 3 )
    {
        deleteFileList(argc - 2, argv + 2 );
        return 0;
    }

    /*
    **  Determine mode of operation
    **      Copy or Delete
    */
    if ( copyMode == 1 && argc == 6 ) {
        src = argv[4];
        dst = argv[3];

    } else if ( copyMode == 2 && argc == 4) {
        dst = argv[3];

    } else {
        fprintf(stderr, "Mode: %d, Args: %d\n", copyMode, argc);
        ErrorExit("Incorrect argument count for mode","");
    }

    /*
    **  Display user text
    */
    fprintf(stderr, "---- %s %s\n", argv[2], argv[3]);
    fflush(stderr) ;

    /*
    **   Check that the source is a file
    */
    if ( copyMode == 1 )
    {
        if ( verbose )
            fprintf(stderr, "Validate Source File: %s\n", src);
        
        rv = stat( src, &fstat );
        if ( rv != 0 )
        {
    /* Need to be a better message */
            fprintf(stderr, "Source: %s\n", src);
            ErrorExit("Source File not found: ", argv[4]);
        }
        src_mode = fstat.st_mode;
    }

    /*
    **  Remove the ReadOnly attribute on the dest file
    */
    if ( verbose )
        fprintf(stderr, "Remove target file: %s\n", dst);
    rv = stat( dst, &fstat );
    if ( rv == 0 )
    {
        if ( verbose )
            fprintf(stderr, "FileExists with attr: 0%o\n", fstat.st_mode);
        if ( !(fstat.st_mode & S_IWRITE) )
        {
            fstat.st_mode |= S_IWRITE;
            rv = chmod( dst, fstat.st_mode );
            if ( rv != 0 )
            {
                ErrorExit("Attempt to allow write access: ", argv[3]);
            }
        }

        if ( unlink( dst ) )
        {
                ErrorExit("Deleting file: ", argv[3]);
        }
    }
    
    if ( copyMode == 1 )
    {
        /*
        **  Create directories
        **  Use the path to the target - not the provided directory
        **  as the createPaths function will not create the last element
        */
        createPaths( dst );

        /*
        **   Copy the file
        */
        if ( ! CopyFile( src, dst, src_mode ) )
        {
            ErrorExit("Copy Error: ", argv[4]);
        }

        /*
        **  Test for files existence
        */
        if ( verbose )
            fprintf(stderr, "Test target was copied: %s\n", dst);
        rv = stat( dst, &fstat );
        if ( rv != 0 )
        {
    /* Need to be a better message */
            ErrorExit("File not found after copy: ", argv[3]);
        }

        /*
        **  Set the files attributes
        **      Assume read-only
        */
        if ( strstr( argv[5], "-w" ) )
        {
            if ( verbose > 1 )
                fprintf(stderr, "Set target read-only: %s\n", dst);
            fstat.st_mode &= ~(S_IWRITE | S_IWOTH | S_IWGRP );
        }

        if ( strstr( argv[5], "+w" ) )
        {
            if ( verbose > 1 )
                fprintf(stderr, "Set target writable: %s\n", dst);
            fstat.st_mode |= (S_IWRITE | S_IWOTH | S_IWGRP );
        }

        if ( strstr( argv[5], "+x" ) )
        {
            if ( verbose > 1 )
                fprintf(stderr, "Set target executable: %s\n", dst);
            fstat.st_mode |= ( S_IXUSR | S_IXOTH | S_IXGRP );
        }

        if ( strstr( argv[5], "-x" ) )
        {
            if ( verbose > 1)
                fprintf(stderr, "Set target executable: %s\n", dst);
            fstat.st_mode &= ~( S_IXUSR | S_IXOTH | S_IXGRP );
        }
        
        if ( verbose )
            fprintf(stderr, "Set target perms: %s, 0%o\n", dst, fstat.st_mode);
        rv = chmod( dst, fstat.st_mode );
        if ( rv != 0 )
        {
            ErrorExit("Setting ReadOnly: ", argv[3]);
            }
        }

    return 0;
}

/*----------------------------------------------------------------------------
** FUNCTION           : createPaths
**
** DESCRIPTION        : Create the path to the target
**
**
** INPUTS             : path
**
** RETURNS            : Will not return in error
**
----------------------------------------------------------------------------*/

void createPaths ( char *path )
{
    struct stat fstat;
    int  rv;
    char *ptr = path;

    while ( *ptr )
    {
        if ( *ptr == '/' )
        {
            *ptr = 0;

            rv = stat( path, &fstat );
            if ( rv )
            {
                if ( verbose > 1 )
                {
                    fprintf(stderr, "createPaths: %s\n", path);
                    fflush(stderr) ;
                }
                rv = mkdir( path, 0777 );
                if ( rv )
                {
                    ErrorExit("Could not create directories:", path);
                }
            }
            *ptr = '/';
        }
        ptr++;
    }
}

/*----------------------------------------------------------------------------
** FUNCTION           : CopyFile
**
** DESCRIPTION        : Just copy a file
**
**
** INPUTS             : src - source path - already exists
**                      dst - path. Dirs already exist
**                      st_mode - Creation  mode. Copied from source file
**
** RETURNS            : false - Error
**
----------------------------------------------------------------------------*/

#define COPYSIZE  1024
int CopyFile ( char *src, char *dst, mode_t st_mode )
{

     ssize_t rlen = 0 ;
     ssize_t wlen = 0 ;
     int in;
     int out;
     int ferror = 0;
    char buffer[COPYSIZE] = { '\0' } ;

    if ( verbose )
    {
        fprintf(stderr, "CopyFile: Output Mode: 0%o\n", st_mode);
        fflush(stderr) ;
    }

    in = open( src, O_RDONLY ) ;
    if ( in < 0 )
        ErrorExit("Could not open source:", src);

    out = open( dst, O_WRONLY | O_CREAT, st_mode | S_IWRITE );
    if ( out < 0 )
        ErrorExit("Could not open dst:", dst);

    while( (rlen = read( in, buffer, COPYSIZE )) > 0 )
    {
        wlen = write( out, buffer, rlen ) ;
        if ( wlen != rlen )
        {
            ferror = 1;
            break;
        }
    }

    close(in) ;
    close(out) ;

    /*
    **  File error
    **  Delete target
    */
    if ( ferror || rlen < 0 )
    {
        unlink(dst) ;
        return 0;
    }
    return 1;
}

/*----------------------------------------------------------------------------
** FUNCTION           : deleteFileList
**
** DESCRIPTION        : Delete a list of files
**                      Ensure files are writable
**
**
** INPUTS             : argc    - count of args
**                      argv    - list of files to delete
**
** RETURNS            : Wil not return on error
**
----------------------------------------------------------------------------*/

void deleteFileList( int argc, char* argv[] )
{
        int rv;
    struct stat fstat;

    for ( ; argc ; argc--, argv++ )
    {
        /*
        **  Remove the ReadOnly attribute on the dest file
        */
        if ( verbose > 1 )
            fprintf(stderr, "Remove target file: %s\n", *argv);


        rv = stat( *argv, &fstat );
        if ( rv == 0 )
        {
            if ( verbose )
                fprintf(stderr, "Delete file: %s : Attr: 0%o\n", *argv, fstat.st_mode);
            if ( !(fstat.st_mode & S_IWRITE) )
            {
                fstat.st_mode |= S_IWRITE;
                rv = chmod( *argv, fstat.st_mode );
                if ( rv != 0 )
                {
                    fprintf(stderr, "Warning: Attempt to allow write access: %s\n", *argv);
                }
            }

            if ( unlink( *argv ) )
            {
                fprintf(stderr, "Warning: Did not remove file: %s\n", *argv);
            }
        }
    }
}


/*----------------------------------------------------------------------------
** FUNCTION           : ErrorExit
**
** DESCRIPTION        : Error processing
**                      Report an error and terminate process
**
**
** INPUTS             : lpszMessage     - Message to display
**
** RETURNS            : Does't return
**                      Will exit with bad code
**
----------------------------------------------------------------------------*/

void ErrorExit (char * lpszMessage, char * lpszMessage2)
{ 
   fprintf(stderr, "JatsFileUtil:Error: %s%s\n", lpszMessage,lpszMessage2);
   fflush(stderr) ;
   exit(-1);
}