Rev 2075 | Rev 2310 | 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** DeleteDir after deleting specified 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.**** Assumes the current directory**** DeleteDir (> 2 args)** 1) Silenty delete a list of files. The files may** be readonly so the attributes will need to be fixed.** 2) Delete the directory if its empty**** 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 <dirent.h>#include <string.h>#define MAX_FILE 2000void 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[] );void DeleteDir( int argc, char* argv[] );int wildcmp(char *string, char *wild );/*** Global*/char verbose = 1; /* Debugging aid */char copyMode = 0; /* Mode */char dst [MAX_FILE + 1]; /* Scratch string workspace *//*----------------------------------------------------------------------------** 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 or l** [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 if ( argv[1][0] == 'D' ) {copyMode = 4;} 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;}if ( copyMode == 4 ){DeleteDir(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 1024int 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 : DeleteDir**** DESCRIPTION : Delete a list of files in a specified directory** Ensure files are writable** Wilcarding is supported**** Then delete the directory - if its empty****** INPUTS : argc - count of args** argv - list of files to delete** [0]: Text to display** [1]: Base directory** [2]+ File in dir to delete**** RETURNS : Wil not return on error**----------------------------------------------------------------------------*/void DeleteDir( int argc, char* argv[] ){int rv;struct stat fstat;char* baseDir;DIR *dir;struct dirent *dirent;if ( argc < 3 )ErrorExit("Insuffiecient arguments for DeleteDir","");/*** Display the user message** Supress display if the message is empty*/if ( argv[0][0] ){fprintf(stderr, "%s\n", argv[0]);fflush(stderr) ;}/*** Extract the base directory from the argument list** This must be a directory*/baseDir = argv[1];argc -= 2;argv+=2;/*** Ensure that the base directory exists*/rv = stat( baseDir, &fstat );if ( rv != 0 ){/*** Directory does not exists** Assume its aleady deleted*/if ( verbose > 1 )fprintf(stderr, "Base dir does not exist: %s\n", baseDir);return;}if ( !(fstat.st_mode & S_IFDIR)){/*** Target is not a directory** Don't do anything*/if ( verbose > 1 )fprintf(stderr, "Base dir is not a directory: %s\n", baseDir);return;}/*** Process all the suffixes** They may contain a wild card*/dir = opendir( baseDir );if ( dir == NULL ){/*** Target is not a directory** Don't do anything*/if ( verbose > 1 )fprintf(stderr, "Base dir is not a directory: %s\n", baseDir);return;}/*** Read next directory entry*/while ( (dirent = readdir(dir)) != NULL ){int ii;if ( verbose > 2 )fprintf(stderr, "Directory Entry:%s,%s\n", baseDir, dirent->d_name );if ( strcmp( ".", dirent->d_name ) == 0 )continue;if ( strcmp( "..", dirent->d_name ) == 0 )continue;/*** Compare against each item in the user list*/for ( ii = 0; ii < argc ; ii++){if ( wildcmp(dirent->d_name, argv[ii] ) ){if ( verbose > 1 )fprintf(stderr, "Matching: %s, %s --- Found\n", dirent->d_name, argv[ii] );/*** Matching file found*/strcpy( dst, baseDir);strcat( dst, "/");strcat( dst, dirent->d_name);rv = stat( dst, &fstat );if ( rv == 0 ){if ( verbose )fprintf(stderr, "Delete file: %s : Attr: 0%o\n", dst, fstat.st_mode);if ( !(fstat.st_mode & S_IWRITE) ){fstat.st_mode |= S_IWRITE;rv = chmod( dst, fstat.st_mode );if ( rv != 0 ){fprintf(stderr, "Warning: Attempt to allow write access: %s\n", dst);}}if ( unlink(dst) ){fprintf(stderr, "Warning: Did not remove file: %s\n", dst);}}}}}closedir(dir);/*** Finally delete the diretory** Unless its '.'*/if ( strcmp( ".", baseDir) != 0 ){if ( verbose > 1 )fprintf(stderr, "Delete Directory: %s\n", baseDir);if ( rmdir (baseDir ) ){if ( verbose )fprintf(stderr, "Directory not deleted: %s\n", baseDir);}}}/*----------------------------------------------------------------------------** FUNCTION : wildcmp**** DESCRIPTION : Wildcard comparision****** INPUTS : string - String** wild - Wildcard template**** RETURNS : TRUE - Match**----------------------------------------------------------------------------*/int wildcmp(char *string, char *wild ){char *cp, *mp;while ((*string) && (*wild != '*')){if ((*wild != *string) && (*wild != '?')){return 0;}wild++;string++;}while (*string){if (*wild == '*'){if (!*++wild){return 1;}mp = wild;cp = string+1;}else if ((*wild == *string) || (*wild == '?')){wild++;string++;}else{wild = mp;string = cp++;}}while (*wild == '*'){wild++;}return !*wild;}/*----------------------------------------------------------------------------** 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);}