|
|
/*
* UPD: update * * HISTORY: * * 4/13/86 danl Fix /d bug. Print warning on eq time ne length * 4/11/86 danl Remove test for length just before copyfile * 4/09/86 danl Converted to ztools\lib * 5/07/86 danl Add msg if no such source found * 5/29/86 danl Add /s flag * 6/02/86 danl Add /g flag * 6/04/86 danl Allow %n with /g flag * 6/10/86 danl Allow blank lines in /g file, # are not echo'd * 6/12/86 danl Output \n and ends of lines * 6/26/86 danl Convert from fatal to usage * 7/01/86 danl Add /a flag * 12/04/86 danl Add /p flag * 12/24/86 danl Use malloc for pPat * 2/24/87 brianwi Use findclose() * 2/25/87 brianwi Add 'echo' and 'rem' to /g files * 07-Apr-87 danl Add fAnyUpd * 13-Apr-87 brianwi Issue error message if source dir invalid * 07-May-87 danl Add /e switch * 22-May-87 brianwi Fix descent from root directory bug * 20-Aug-87 brianwi Fix Null Pointer with /o ( free(pPat) in walk() ) */ #include <malloc.h>
#include <math.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include <string.h>
#include <stdio.h>
#include <process.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <windows.h>
#include <tools.h>
// Forward Function Declarations...
int savespec( char * ); int copyfile( char *, struct findType *, char * ); void walk( char *, struct findType *, void *); void RecWalk( char *, struct findType *, void * ); void saveext( char * ); void __cdecl usage( char *, ... ); void getfile( int, char ** );
char const rgstrUsage[] = { "Usage: UPD [/nxdfvosape] {src directories}+ dest directory [{wildcard specs}*]\n" " UPD /g file\n" " Options:\n" " -n No saving of replaced files to deleted directory\n" " -x eXclude files, see tools.ini\n" " -d Descend into subdirectories\n" " -f Files differ, then update\n" " -v Verbose\n" " -o Only files already existing in dest are updated\n" " -s Subdirectory DEBUG has priority\n" " -a Archive bit on source should NOT be reset\n" " -p Print actions, but do nothing\n" " -e Exit codes 1-error or no src else 0\n" " Default is 1-update done 0-no updates done\n" " -g Get params from file\n" };
#define BUFLEN MAX_PATH
#define MAXSPEC 32
#define MAXFIL 256
#define MAXARGV 20
char *exclude[MAXFIL], dir[BUFLEN]; unsigned _stack = 4096; flagType fInGetfile = FALSE; flagType _fExpand = FALSE; flagType fDescend = FALSE; flagType fAll = FALSE; flagType fExclude = FALSE; flagType fDel = TRUE; flagType fVerbose = FALSE; flagType fOnly = FALSE; flagType fSubDebug = FALSE; /* TRUE => priority to subdir DEBUG */ flagType fArchiveReset = TRUE; flagType fPrintOnly = FALSE; flagType fErrorExit = FALSE; /* TRUE => exit (1) errors or no src else 0 */ flagType fNoSrc = FALSE; /* TRUE => "No src msg emitted" */
int numexcl = 0; int cCopied = 0; int fAnyUpd = 0; int nWildSpecs = 0; char *wildSpecs[MAXSPEC]; struct findType buf; char source[BUFLEN], dest[BUFLEN], srcDebug[BUFLEN];
/* for use by getfile */ char *argv[MAXARGV]; char bufIn[BUFLEN]; char strLine[BUFLEN]; char ekoLine[BUFLEN]; /* undestroyed copy of line for echo */
savespec (p) char *p; { char namebuf[ 16 ]; int i;
buf.fbuf.dwFileAttributes = 0; namebuf[ 0 ] = 0; if (strchr(p, '\\') || strchr(p, ':' ) ) return FALSE; ffirst( p, FILE_ATTRIBUTE_DIRECTORY, &buf ); findclose( &buf ); if ( /* !HASATTR( buf.attr, FILE_ATTRIBUTE_DIRECTORY ) && */ filename( p, namebuf ) ) { fileext( p, namebuf); upper( namebuf ); for (i=0; i<nWildSpecs; i++) if (!strcmp( namebuf, wildSpecs[ i ])) return TRUE;
if (nWildSpecs < MAXSPEC) { wildSpecs[ nWildSpecs++ ] = _strdup (namebuf); return TRUE; } else usage( "Too many wild card specifications - ", namebuf, 0 ); }
return FALSE; }
copyfile( src, srctype, dst ) char *src, *dst; struct findType *srctype; { int i; char *result, temp[ 20 ]; /* temp for storing file names */ flagType fNewfile = FALSE;
if ( fExclude ) { fileext( src, temp );
for (i = 0; i< numexcl; i++) { if( !_strcmpi( exclude[i], temp ) ) { return( FALSE ); } } } fflush( stdout ); /* if the file already exists, fdelete will return 0; then don't */ /* notify the user that a file transfer has taken place. Otherwise */ /* a new file has been created so tell the user about it. */ printf( " %s => %s", src, dst ); fAnyUpd = 1; if ( !fPrintOnly ) { if (fDel) fNewfile = (flagType)((fdelete(dst)) ? TRUE : FALSE ); if (!(result = fcopy( src, dst ))) { if (fArchiveReset) SetFileAttributes( src, srctype->fbuf.dwFileAttributes & ~FILE_ATTRIBUTE_ARCHIVE ); if (fVerbose || fNewfile) printf( " [OK]" ); } else printf( " %s - %s", result, error() ); } else printf ( " [no upd]" ); printf( "\n" ); fflush( stdout ); return TRUE; }
void walk ( char *p, struct findType *b, void *dummy ) { int fNotFound; char *pPat; char *pT = p; struct findType *bT = b; struct findType bufT;
if( strcmp( bT->fbuf.cFileName, "." ) && strcmp( bT->fbuf.cFileName, ".." ) ) { if (HASATTR (bT->fbuf.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) { /* do nothing if you find a dir */ } else if( !HASATTR( bT->fbuf.dwFileAttributes, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM ) ) { //
// Note: windows does not support FILE_ATTRIBUTE_VOLUME_LABEL, so
// it was removed from above
//
pPat = malloc ( BUFLEN ); if (pPat) { strcpy( pPat, dest ); if (*(strend( pPat ) - 1) != '\\') { strcat( pPat, "\\" ); } fileext( pT, strend ( pPat ) ); /* ffirst == 0 => file found */ if (fOnly && ffirst( pPat, -1, &buf ) ) { free ( pPat ); return; } if (fOnly) { findclose( &buf ); } /* so far we know src\file and dest\file exist */ if (fSubDebug) { /* now check to see if src\DEBUG\file exists */ drive(pT, srcDebug); path(pT, srcDebug + strlen(srcDebug)); strcat(srcDebug + strlen(srcDebug), "debug\\"); fileext(pT, srcDebug + strlen(srcDebug)); if( !ffirst( srcDebug, -1, &bufT ) ) { findclose( &bufT ); /* it exists so use it for the compares below */ pT = srcDebug; bT = &bufT; } } cCopied++; if( ( fNotFound = ffirst( pPat, -1, &buf ) ) || ( CompareFileTime( &buf.fbuf.ftLastWriteTime, &bT->fbuf.ftLastWriteTime ) < 0 ) || ( fAll && CompareFileTime( &buf.fbuf.ftLastWriteTime, &bT->fbuf.ftLastWriteTime ) > 0 ) ) { copyfile( pT, bT, pPat ); } else if( !fNotFound && CompareFileTime( &buf.fbuf.ftLastWriteTime, &bT->fbuf.ftLastWriteTime ) == 0 && buf.fbuf.nFileSizeLow != bT->fbuf.nFileSizeLow ) { printf("\n\007UPD: warning - %s not copied\n", pT); printf("\007UPD: warning - same time, different length in src & dest\n", pT); } findclose( &buf ); free ( pPat ); } } } dummy; }
/* a first walking routine, just copies the files on given directory */ /* doesn't deal with nested subdirectories. Ie split the process up into */ /* two parts, first deal with files on current directory, then deal with */ /* subdirectories as necessary. */
/* only called when fDescend is true */ void RecWalk ( char *p, struct findType *b, void *dummy ) { char *pPat; char *pDestEnd; int i;
if (strcmp (b->fbuf.cFileName, ".") && strcmp (b->fbuf.cFileName, "..")) if (HASATTR (b->fbuf.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY) && !HASATTR (b->fbuf.dwFileAttributes, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) { /* ignore Hidden and System directories */ pPat = malloc ( BUFLEN ); if (pPat) { if ( (pDestEnd = strend(dest))[-1] != '\\' ) strcat(pDestEnd, "\\"); fileext(p, strend(pDestEnd)); sprintf( pPat, "%s\\*.*", p); forfile( pPat, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, RecWalk, NULL ); for (i=0; i<nWildSpecs; i++) { sprintf( pPat, "%s\\%s", p, wildSpecs[ i ] ); forfile( pPat, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, walk, NULL ); } *pDestEnd = '\0'; free ( pPat ); } } dummy; }
void saveext (p) char *p; { upper (p) ; if (numexcl < MAXFIL) exclude [numexcl++] = _strdup (p); }
void __cdecl usage( char *p, ... ) { char **rgstr;
rgstr = &p; if (*rgstr) { fprintf (stderr, "UPD: "); while (*rgstr) fprintf (stderr, "%s", *rgstr++); fprintf (stderr, "\n"); } fputs(rgstrUsage, stderr);
exit ((fErrorExit ? 1 : 0)); }
__cdecl main (c, v) int c; char *v[]; { int i, j, k; FILE *fh; char *p, *p1, namebuf[ BUFLEN ];
_fExpand = FALSE; fDescend = FALSE; fAll = FALSE; fExclude = FALSE; fDel = TRUE; fOnly = FALSE; fSubDebug = FALSE; fArchiveReset = TRUE; fPrintOnly = FALSE; numexcl = 0; cCopied = 0; nWildSpecs = 0;
if (!fInGetfile) SHIFT(c, v); /* Flush the command name */ /*
* 13-SEPT-90 w-barry * Added test for arguments remaining before test for switch char. */ while( c && fSwitChr ( *v[ 0 ] ) ) { p = v[ 0 ]; SHIFT(c, v); while (*++p) switch (tolower(*p)) { case 'a': fArchiveReset = FALSE; break; case 'g': if (fInGetfile) usage( "/g allowed only on command line", 0); getfile(c, v); break; case 'e': fErrorExit = TRUE; case 'x': fExclude = TRUE; break; case 'v': fVerbose = TRUE; break; case 'd': fDescend = TRUE; break; case 'f': fAll = TRUE; break; case 'n': fDel = FALSE; break; case 'o': fOnly = TRUE; break; case 'p': fPrintOnly = TRUE; break; case 's': fSubDebug = TRUE; break; default: usage( "Invalid switch - ", p, 0); } }
if (fSubDebug && fDescend) { printf("UPD: /s and /d both specified, /d ignored\n"); fDescend = FALSE; }
if (fExclude) if ((fh = swopen ("$USER:\\tools.ini", "upd")) ) { while (swread (p1 = dir, BUFLEN, fh)) { while (*(p = strbskip (p1, " "))) { if (*(p1 = strbscan (p, " "))) *p1++ = 0; saveext (p) ; } } swclose (fh) ; }
/* Must be at least one source dir and the dest dir. */ if (c < 2) usage( 0 );
/* Save away any wildcard specs at end of argument list */ for (i=c-1; i>=2; i--) if (!savespec( v[ i ] )) break; else c--;
/* Still must be at least one source dir and the dest dir. */ if (c < 2) usage( 0 );
/* Make sure destination is a valid directory */
rootpath( v[ c-1 ], dest ); if (ffirst( dest, FILE_ATTRIBUTE_DIRECTORY, &buf ) == -1) usage( "Destination directory does not exist - ", v[ c-1 ], 0 ); else { findclose( &buf ); c--; }
if (!nWildSpecs) savespec( "*.*" );
if (fVerbose) { printf( "Copying all files matching:" ); for (i=0; i<nWildSpecs; i++) printf( " %s", wildSpecs[ i ] ); printf( "\n" ); printf( "To destination directory: %s\n", dest ); printf( "From the following source directories:\n" ); } for (i=0; i<c; i++) { if (rootpath( v[ i ], namebuf )) { printf( "\aSource directory does not exist - %s\n", v[ i ]); continue; }
if (fVerbose) printf( " %s\n", namebuf );
if (namebuf[k = strlen( namebuf ) - 1] == '\\') namebuf[k] = '\0';
for (j=0; j<nWildSpecs; j++) { sprintf( source, "%s\\%s", namebuf, wildSpecs[ j ] ); cCopied = 0; forfile( source, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, walk, NULL ); if (!cCopied) { printf( "UPD: no src file matching %s\\%s\n", namebuf, wildSpecs[ j ] ); fNoSrc = 1; } } if (fDescend) { sprintf( source, "%s\\*.*", namebuf ); forfile( source, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, RecWalk, NULL ); } /* if (fVerbose) printf( "\n" ); */ }
if (!fInGetfile) return( (int)fErrorExit ? (int)fNoSrc : fAnyUpd );
return 0; }
/* call if UPD /g getfile, reads lines from getfile and for each line
calls main */
void getfile(c, v) int c; char *v[]; { FILE *fp; int cargv = 0; int i, j; char *p;
ConvertAppToOem( c, v ); if( c == 0 ) { usage("no getfile specified", 0); } fInGetfile = TRUE; if( ( fp = fopen( *v, "r" ) ) == (FILE *)NULL ) { usage("error opening ", *v, 0); } SHIFT(c, v);
/*
* 13-SEPT-90 w-barry * Changed open to fopen and switched to fgets instead of assembly * routines 'getl' and 'getlinit'. * * getlinit((char far *)bufIn, BUFLEN, fh); * while (getl(strLine, BUFLEN) != NULL) { */ while( fgets( strLine, BUFLEN, fp ) != NULL ) { if( *strLine == '#' ) continue; if( *strLine == ';') { printf( "%s\n", strLine ); continue; } /* fgets doesn't strip the trailing \n */ *strbscan(strLine, "\n") = '\0'; cargv = 0; /* convert strLine into argv */ p = strbskip(strLine, " "); strcpy (ekoLine, p + 5); while (*p) { argv[cargv++] = p; p = strbscan(p, " "); if (*p) *p++ = '\0'; p = strbskip(p, " "); }
if (!_stricmp (argv[0], "rem")) continue; if (!_stricmp (argv[0], "echo")) { if (!_stricmp (argv[1], "on" )) { fVerbose = TRUE; printf ("Verbose On\n"); } else if (!_stricmp (argv[1], "off")) { fVerbose = FALSE; printf ("Verbose Off\n"); } else printf ("%s\n", ekoLine); continue; }
for (i = 0; i < cargv; i++) { if (*(p = argv[i]) == '%') { if ((j = atoi(++p)) < c) argv[i] = v[j]; else usage("bad arg ", argv[i], 0); } }
if (cargv) main(cargv, argv); } fclose( fp );
exit( (int)fErrorExit ? (int)fNoSrc : fAnyUpd ); }
|