jlydiatt@van-bc.UUCP (Jeff Lydiatt) (05/23/87)
Here is a replacement for AmigaDog "copy" program that I have been working on for quite a while. It implements the AmigaDos pattern matching algorithm, the "all" command, and has the added bonus that it retains the date of copied file. It's my first posting to the net, and I have my fingers crossed that all goes well... Contents: cp.doc - documentation cp.c - the main program PatMatch.c - supporting routines to implement the pattern matching. setDate.c - gets and sets the file date. wb_parse.c - Aztec allows you to skip the workbench parms parse. makefile - to compile and link the whole thing. cp.uue - uuencoded cp ============ cat <cp.doc> ============ Cp - a replacement for AmigaDos Copy that retains the date. by Jeff Lydiatt Vancouver, Canada Release 1.0, May 17, 1987 Cp and the c source is freely redistributable for personal non-commercial use. Commercial rights are reserved by the author. Feel free to make any modifications or use any of the modules in other programs. I encourage you to do so and hope you will release the code so others can learn by it. Cp has most of the features of the AmigaDos copy command: -------------------------------------------------------- o Cp supports the AmigaDos style pattern matching in the "from" name. o Cp supports the All option. o Cp supports the optional "from" and "to" qualifiers for file names. o Cp will copy directories Cp has a number of features not found in AmigaDos copy: ------------------------------------------------------- o Cp will retain the date of the copied file. o Cp uses a 32000 byte buffer, which speeds copies when the from and to file is on the same disk. o You may specify the current directory by a "to" name of ".". For example if your current directory is "Df0:", "cp ram:x ." will copy the file called x in your ram: disk to "df0:x". o Cp will also create the "to" file for you if you use the "All" option. For example if "x" is a directory, "cp from x to y" will create a directory called "y", and will copy all the files in x to the newly created "y" directory. About the AmigaDos-style pattern matching. ----------------------------------------- Cp uses a compact function for regular expression pattern matching. The algorithm was taken from a paper by Martin Richards, that was published in the September 1979 issue of "Software, Practice and Experience". Professor Richards published his example in BCPL, and I have (sucessfully I think) translated it to C. It's interesting to note that I translated it verbatim, with no special modifications to adapt it to AmigaDos conventions. Cp recognises a number of special characters with special meanings, which can be used to recognise any other charcaters that match them. ? Matches any single character. % Matches the null character. #<p> Matches zero or more occurrences of the pattern <p> <p1>|<p2> Matches either pattern <p1> or <p2>. () Can be used to group expressions together. '# Can be used to turn off the special meaning of the special characters #, ?, %, |, (, ), or '. Some examples will help to make this clearer. cp a|b . copies a or b to the current directory. cp a#bc . copies ac abc abbc. cp a#(b|c)d . copies ad abd abcd. cp a?b . copies axb ayb aab. cp a#?b copies ab axxb ax.ab. cp '?#?'# . copies ?# ?ab# ??##. cp a(b|%)#c . copies a abc accc. ========== cat <Cp.c> ========== /* Cp: A replacement for AmigaDos Copy that does not modify the date * by Jeff Lydiatt * Vancouver, Canada. * * Features: * 1) Handles all functions of AmigaDos copy, including the All switch. * 2) Regular expression pattern matching that handles the AmigaDos' * pattern matching characters "#?|%'()". * 3) This copy keeps the date of the copied file! * 4) Uses a 32K buffer which should speed up single disk copies. * 5) In "Cp filex .", the "." is taken to mean the current directory. * * Created: 07May87 * * Cp has been compiled and tested under Aztec v3.40a with patch v3 * applied. The 16 bit integer and small code, small data option is * used in compiling and linking all modules. * * Maintenance Notes: * 17May87 - Version 1.0 Released. * */ /* Cp and the c source is freely redistributable for personal non-commercial use. Commercial rights are reserved by the author. Feel free to make any modifications or use any of the modules in other programs. I encourage you to do so and hope you will release the code so others can learn by it. */ #include <stdio.h> #include <libraries/dos.h> #include <exec/memory.h> #include <functions.h> #define BUFMAX 32768 #define MAXSTR 127 extern int Enable_Abort; extern char *malloc(); extern int CmplPat(), Match(); extern long Chk_Abort(); /*--- A poor man's "printf" which avoids the overhead of printf ---*/ static void msg(str, parm) char *str, *parm; { register char *s; register struct FileHandle *console; console = Output(); for ( s=str; *s; ++s ) { if ( *s == '%' && *(s+1) == 's' ) { (void)Write( console, str, (long)(s - str)); (void)Write( console, parm, (long)strlen(parm)); (void)Write( console, (char *)(s + 2), (long)strlen((char *)(s+2))); break; } } if ( *s == '\0' ) (void)Write( console, str, (long)strlen(str)); } static void error( str, parm ) char *str, *parm; { msg( str, parm ); exit(NULL); } static void useage(name) char *name; { msg( "%s V1.0 buffered file copy by Jeff Lydiatt. Usage:\n", name ); msg( " %s [From] filein [To] fileout [All]\n", name ); msg( " AmigaDos style pattern matching characters permitted in filein.\n" ); msg( " Pattern matching characters not allowed in Fileout.\n\n" ); } /*-----------------------------------------------------------*/ /* Parse the command string */ /*-----------------------------------------------------------*/ static int toupper(c) register char c; { if ( 'a' <= c && c <= 'z' ) return c + ('A' - 'a'); return c; } /* Case-blind implementation of strcmp() */ static int blindcmp( s1, s2 ) register char *s1, *s2; { while (*s1 && *s2) { if ( (toupper( *s1 )) == (toupper( *s2 )) ) { ++s1; ++s2; } else break; } if ( toupper(*s1) == toupper(*s2) ) return 0; /* It's Equal */ else if ( toupper(*s1) > toupper(*s2) ) return 1; else return -1; } static void parsecmd(fparm, tparm, All, argc, argv) char *fparm, *tparm; register char *argv[]; int *All, argc; { int nextparm; register char *parm; if ((argc < 2) || ( strcmp( argv[1], "?" ) == 0) ) { useage( argv[0] ); exit( NULL ); } *All = FALSE; nextparm = 1; argc--; fparm [0] = '\0'; tparm[0] = '\0'; while ( nextparm <= argc ) { parm = argv[ nextparm ]; if ( (nextparm < argc) && (blindcmp( parm, "from" ) == 0) ) { ++nextparm; (void)strncpy( fparm, argv [nextparm], MAXSTR); } else if ( (nextparm < argc) && (blindcmp( parm, "to" ) == 0) ) { ++nextparm; (void)strncpy( tparm, argv [nextparm], MAXSTR ); } else if ( (nextparm == argc) && (blindcmp( parm, "all") == 0) ) *All = TRUE; else if ( fparm[0] == '\0' ) (void)strncpy( fparm, parm, MAXSTR ); else (void)strncpy( tparm, parm, MAXSTR ); ++nextparm; } } /*--------------------------------------------------------------*/ /* Internal stack manipulation routines */ /*--------------------------------------------------------------*/ struct stackframe { struct stackframe *next; char *strptr; }; static struct stackframe *Stackhead; static void initstack() { Stackhead = NULL; } static int isempty() { return Stackhead == NULL; } /*--------------push a string on the stack------------------*/ static void push(str) char *str; /* Push a string on the stack */ { register struct stackframe *p; register char *s; if ( (p = (struct stackframe *)malloc(sizeof(struct stackframe))) == NULL ||(s = malloc( strlen(str)+1 )) == NULL) { msg("Not enough memory\n"); return; } strcpy( s, str ); p->next = Stackhead; p->strptr = s; Stackhead = p; } /*---------pop the next string from the stack------------------*/ static void pop(str) char *str; { register struct stackframe *p; if (isempty()) error("Can't happen: stack popped with nothing there\n"); p = Stackhead; strcpy( str, p->strptr ); free( p->strptr ); Stackhead = p->next; free( p ); } /*--------------------------------------------------------------*/ /* Some handy path manipulation routines. */ /*--------------------------------------------------------------*/ /*------------separate path and pattern from str----------------*/ static char *getpath( path, pattern, str) char *path, *pattern, *str; { register char *s1, *s2; char *mark; mark = NULL; for ( s1=str; *s1; ++s1) if ( *s1 == ':' || *s1 == '/' ) mark = s1; if ( isdir(str) ) { strcpy( path, str ); *pattern = '\0'; } else if ( !mark ) { strcpy( pattern, str ); *path = '\0'; } else { s2 = path; s1 = str; while ( s1 < mark ) *s2++ = *s1++; if ( *s1 == ':' ) *s2++ = *s1; *s2 = '\0'; strcpy( pattern, (char*)( mark+1)); } return path; } /*------return path from parent directory and member name-------*/ static char *makepath(path, parent, member) register char *path; char *member; register char *parent; { register int len; strcpy( path, parent ); len = strlen( path ); if ( len > 0 && *member ) if ( (path[len-1] != ':') && (path[len-1] != '/') ) strcat( path, "/" ); strcat( path, member ); return path; } /*--- isdir: Returns 0 if NOT a directory, 1 otherwise. ---*/ static int isdir(filename) char *filename; { struct FileInfoBlock *f; struct Lock *outlk; int result; result = 0; outlk = (struct Lock *)Lock(filename,ACCESS_READ); if (outlk) { f = (struct FileInfoBlock *) AllocMem((long)sizeof(struct FileInfoBlock), MEMF_CHIP); if (f == 0) error("Unable to allocate space for FileInfoBlock!\n"); if (Examine(outlk,f)) if (f->fib_DirEntryType >= 0) result = 1; UnLock(outlk); FreeMem((void *)f,(long) sizeof(struct FileInfoBlock)); } return(result); } static int iswild(pattern) register char *pattern; { for (; *pattern; ++pattern ) { switch( *pattern ) { case '#': case '?': case '(': case '%': case '\'': case '|': return 1; } } return 0; } static int cp(fpath, tpath, name ) char *fpath, *tpath, *name; { char fname[MAXSTR+1], tname[MAXSTR+1]; char *buffer; long status, count, bufsize; struct FileHandle *fin, *fout; struct DateStamp date; (void)makepath( fname, fpath, name ); if ( tpath[0] != '\0' && !isdir(tpath) ) strcpy( tname, tpath ); else (void)makepath( tname, tpath, name ); msg( "%s ==> ", fname ); msg( "%s\n", tname); if ( (fin = Open( fname, MODE_OLDFILE )) == NULL ) { msg( "Can't open %s for input.\n", fname ); return 1; } if ( (fout = Open( tname, MODE_NEWFILE )) == NULL ) { msg( "Can't open %s for ouput.\n", tname ); Close( fin ); return 1; } for ( bufsize = BUFMAX; bufsize > 2048; bufsize -= 2048 ) if ( (buffer = malloc( (unsigned int)bufsize)) != NULL ) break; if ( bufsize <= 2048 ) { Close( fin ); Close( fout ); msg( "Not enough memory.\n" ); return 1; } status = 1; while( status > 0 && (count = Read( fin, buffer, bufsize )) == bufsize ) if ( Chk_Abort() ) status = -1; else status = Write( fout, buffer, count ); if (status > 0 && count > 0 ) status = Write( fout, buffer, count ); Close( fin ); Close( fout); free( buffer ); if ( status < 0 || count < 0 ) { (void)DeleteFile( tname ); msg( " %s [removed].\n", tname ); return 1; } if ( getDate( fname, &date )) (void)setDate( tname, &date ); return 0; } main(argc,argv) int argc; char *argv[]; { int aux[MAXSTR+1]; char fparm[MAXSTR+1], tparm[MAXSTR+1]; char fpath[MAXSTR+1], tpath[MAXSTR+1]; char fparent[MAXSTR+1], dontSearch[MAXSTR+1]; char fpattern[MAXSTR+1]; char relpath[MAXSTR+1], junk[MAXSTR+1]; void *dirlock; register struct FileInfoBlock *fileptr; int All; Enable_Abort = 0; parsecmd( fparm, tparm, &All, argc, argv ); (void)getpath( fparent, fpattern, fparm ); if ( strcmp(tparm, ".") == 0 ) tparm[0] = '\0'; /*--- Are the parms ok? --- */ if ( iswild(fparent) ) error( "Regular expression not allowed in path: %s.\n", fparm ); if ( iswild(tparm) ) error( "Regular expression not allowed as output name.\n" ); /*----- if it's just a single file copy, just do it and exit----*/ if ( !All && !iswild( fpattern ) && !isdir( fparm )) { (void)cp( fparent, tparm, fpattern ); exit( NULL ); } /*--- For "All" option, don't search the "to" directory --- */ fileptr = (struct FileInfoBlock *) AllocMem( (long)sizeof(struct FileInfoBlock), MEMF_CHIP); strcpy( dontSearch, tparm ); if ( dontSearch[0] == '\0' ) { dirlock = Lock("", ACCESS_READ); if ( dirlock ) { (void)Examine( dirlock, fileptr ); strcpy( dontSearch, fileptr->fib_FileName ); UnLock( dirlock ); } } initstack(); push( "" ); if ( fpattern[0] == '\0' ) strcpy( fpattern, "#?" ); if ( CmplPat( fpattern, aux ) == 0 ) { msg("Bad regular expression pattern: %s.\n", fpattern); goto all_done; } while( !isempty() ) { pop( relpath ); (void)makepath( fpath, fparent, relpath ); (void)makepath( tpath, tparm, relpath ); if ( All && !isdir(tpath) ) { if ( (dirlock = CreateDir( tpath )) == NULL ) { msg( "Can't create %s \n", tpath ); continue; } else { msg("%s ... [created]\n", tpath); UnLock( dirlock ); } } if ( (dirlock = Lock( fpath, ACCESS_READ )) == NULL || !Examine( dirlock, fileptr) ) { msg( "Can't find directory %s\n", fpath ); if ( dirlock ) UnLock( dirlock ); goto all_done; } while ( ExNext( dirlock, fileptr ) ) { if ( fileptr->fib_DirEntryType > 0 ) { if ( All && strcmp( dontSearch, fileptr->fib_FileName) ) push( makepath( junk, relpath, fileptr->fib_FileName ) ); } else if (Match( fpattern, aux, fileptr->fib_FileName ) ) { if ( Chk_Abort() || cp( fpath, tpath, fileptr->fib_FileName ) ) { UnLock( dirlock ); goto all_done; } } } UnLock( dirlock ); } all_done: FreeMem( fileptr, (long)sizeof(struct FileInfoBlock)); exit(NULL); } ================ cat <PatMatch.c> ================ /* PatMatch.c - Implements AmigaDos Regular Expression Pattern Matching. ** ** This program will test whether a string is an AmigaDos regular expression ** It may be used to implement wild expressions such as: ** ** "copy #?.c to <dir>" to copy any file ending in .c ** ** The program has two entry points: CmplPat, and Match. ** ** CmplPat - takes a pattern and returns an auxilliary integer vector ** which is used by Match. The pattern is not modified in ** any way. CmplPat returns 1 if no errors were detected ** while compiling the pattern; otherwise it returns 0; ** ** Match - takes the pattern, the auxilliary vector, and the string ** to be matched. It returns 1 if the string matches the ** pattern; otherwise it returns 0; ** ** Translated from BCPL by: ** Jeff Lydiatt ** Richmond B.C. Canada ** 16 May 1986. ** ** Source: "A Compact Function for Regular Expression Pattern Matching", ** Software - Practice and Experience, September 1979. ** ** Useage: ** To test if "file.c" matches the regular expression "#?.c" ** char *Pat = "#?.c"; ** char *Str = "file.c"; ** WORD Aux[128]; ** ** if ( CmplPat( Pat, Aux ) == 0 ) ** { ** printf("Bad Wildcard Expression\n"); ** exit(1); ** } ** if ( Match( Pat, Aux, Str ) == 1 ) ** printf("String matches the pattern\n"); ** else ** printf("String does NOT match the pattern\n"); **/ /*--- Included files ----*/ #include <stdio.h> #include <exec/types.h> #include <ctype.h> #define EOS '\0' /*--- Global Variables ---*/ static char Ch; /* The current character in Pattern */ static char *Pat; /* Pointer to the Pattern */ static int *Aux; /* Pointer to returned auxilliary vector */ static int PatP; /* Current position in Pat */ static int Patlen; /* strlen(pat) */ static BOOL Errflag; /* TRUE if error */ static int *Work; /* Pointer to Active work area */ static int Wp; /* Current position in work */ static BOOL Succflag;/* True if "str" matches "pat" */ /*----------------------------------------------------------------*/ /* The Interpreter */ /*----------------------------------------------------------------*/ static void Put(N) int N; { register int *ip; register int *to; if ( N == 0 ) Succflag = TRUE; else { for ( ip = &Work[ 1 ], to = &Work[ Wp ]; ip <= to; ip++) if ( *ip == N ) return; Work[ ++Wp ] = N; } } int Match( Pat, Aux, Str ) char Pat[]; int Aux[]; char Str[]; { int W[ 128 ]; int S = 0; int I, N, Q, P, Strlength; char K; int strlen(); void Put(); Work = W; Wp = 0; Succflag = FALSE; Strlength = strlen( Str ); Put( 1 ); if ( Aux[ 0 ] != 0 ) Put( Aux[ 0 ] ); for(;;) { /* First complete the closure */ for( N=1; N <= Wp; N++ ) { P = Work[ N ]; K = Pat[ P-1 ]; Q = Aux[ P ]; switch( K ) { case '#': Put( P + 1 ); case '%': Put( Q ); default : break; case '(': case '|': Put( P + 1); if ( Q != 0 ) Put( Q ); } } if ( S >= Strlength ) return Succflag; if ( Wp == 0 ) return FALSE; Ch = Str[ S++ ]; /* Now deal with the match items */ N = Wp; Wp = 0; Succflag = FALSE; for ( I = 1; I <= N; I++) { P = Work[ I ]; K = Pat[ P - 1 ]; switch( K ) { case '#': case '|': case '%': case '(': break; case '\'': K = Pat[ P ]; default : if ( _toupper( Ch ) != _toupper( K ) ) break; case '?': /* Successful match */ Put ( Aux[ P ] ); } /* End Switch */ } /* End For I */ } /* End for(;;) */ } /*----------------------------------------------------------------*/ /* The Compiler */ /*----------------------------------------------------------------*/ static void Rch() /* Read next character from Pat */ { if ( PatP >= Patlen ) Ch = EOS; else Ch = Pat[ PatP++ ]; } static void Nextitem() /* Get next char from Pat; recognize the ' escape char */ { if ( Ch == '\'' ) Rch(); Rch(); } static void Setexits( List, Val ) int List; int Val; { int A; do { A = Aux[ List ]; Aux[ List ] = Val; List = A; } while ( List != 0 ); } static int Join( A, B ) int A, B; { int T = A; if ( A == 0 ) return B; while ( Aux[ A ] != 0 ) A = Aux[ A ]; Aux[ A ] = B; return T; } static int Prim() /* Parse a Prim symbol */ { int A = PatP; char Op = Ch; int Exp(); void Setexits(), Nextitem(); Nextitem(); switch( Op ) { case EOS: case ')': case '|': Errflag = TRUE; default : return A; case '#': Setexits( Prim(), A ); return A; case '(': A = Exp( A ); if ( Ch != ')' ) { Errflag = TRUE; } Nextitem(); return A; } } static int Exp( AltP ) /* Parse an expression */ int AltP; { int Exits = 0; int A; int Prim(), Exits(), Join(); void Nextitem(), Setexits(); for (;;) { A = Prim(); if ( Ch == '|' || Ch == ')' || Ch == EOS ) { Exits = Join( Exits, A ); if ( Ch != '|' ) return Exits; Aux[ AltP ] = PatP; AltP = PatP; Nextitem(); } else Setexits( A, PatP ); } } int CmplPat( Pattern, CmplPattern) char Pattern[]; int CmplPattern[]; { int i, strlen(); void Rch(), Setexits(); Pat = Pattern; Aux = CmplPattern; PatP = 0; Patlen = strlen( Pat ); Errflag = FALSE; for ( i = 0; i <= Patlen; i++ ) Aux[ i ] = 0; Rch(); Setexits( Exp(0), 0 ); return (!Errflag); } =============== cat <setDate.c> =============== #include "exec/types.h" #include "exec/ports.h" #include "exec/io.h" #include "exec/memory.h" #include "libraries/dos.h" #include "libraries/dosextens.h" #include <stdio.h> #define AZTEC 1 #ifdef AZTEC #include "functions.h" /* aztec C include */ #endif #define ACTION_SETDATE_MODE 34L /* The packet type we will be playing with */ #define DOSTRUE -1L /* AmigaDos TRUE */ #define MAXARGS 7L /* limit in packet structure (dosextens.h) */ #define NARGS 4L /* Number of args for setdate */ /*---------------------------------------------------------------------*/ /* sendpkt: generalized send a dos packet. */ /*---------------------------------------------------------------------*/ static long sendpkt(pid,action,args,nargs) struct MsgPort *pid; /* process indentifier ... (handlers message port ) */ long action, /* number of arguments in list */ nargs; /* number of arguments in list */ ULONG args[]; /* a pointer to a argument list */ { struct MsgPort *replyport; struct StandardPacket *packet; long count, res1; ULONG *pargs; if(nargs > MAXARGS) return NULL; replyport = (struct MsgPort *) CreatePort(NULL,NULL); /* make reply port */ if(!replyport) return NULL; packet = (struct StandardPacket *) AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC | MEMF_CLEAR); if(!packet) { FreeMem((void *)packet,(long)sizeof(struct StandardPacket)); return(NULL); } packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt); /* link packet- */ packet->sp_Pkt.dp_Link = &(packet->sp_Msg); /* to message */ packet->sp_Pkt.dp_Port = replyport; /* set-up reply port */ packet->sp_Pkt.dp_Type = action; /* what to do... */ /* move all the arguments to the packet */ pargs = (ULONG *)&(packet->sp_Pkt.dp_Arg1); /* address of first argument */ for(count=NULL;count < nargs && count < MAXARGS; ++count) pargs[count]=args[count]; PutMsg(pid,packet); /* send packet */ (void)WaitPort(replyport); /* wait for packet to come back */ (void)GetMsg(replyport); /* pull message */ res1 = packet->sp_Pkt.dp_Res1; /* get result */ /* all done clean up */ FreeMem((void *)packet,(long)sizeof(*packet)); DeletePort(replyport); return(res1); } /*---------------------------------------------------------------------*/ /* setDate: datestamp the given file with the given date. */ /*---------------------------------------------------------------------*/ BOOL setDate( name, date ) char *name; struct DateStamp *date; { struct MsgPort *task; /* for process id handler */ ULONG arg[4]; /* array of arguments */ char *bstr, strcpy(); /* of file to be set */ long rc; char *strchr(); int strlen(); rc = 0; if ( !(bstr = (char *)AllocMem(68L, (long)(MEMF_PUBLIC)))) goto exit2; if ( !(task = (struct MsgPort *)DeviceProc( name ))) goto exit1; /* Dos Packet needs the filename in Bstring format */ (void)strcpy( bstr+1, name ); *bstr = strlen( name ); arg[0] = (ULONG)NULL; arg[1] = (ULONG)IoErr(); /* lock on parent director set by DeviceProc() */ arg[2] = (ULONG) bstr >> 2; arg[3] = (ULONG) date; rc = sendpkt( task, ACTION_SETDATE_MODE, arg, 4L ); exit1: if ( bstr ) FreeMem( (void *)bstr, 68L ); exit2: if ( rc == DOSTRUE ) return TRUE; else return FALSE; } /*---------------------------------------------------------------------*/ /* getDate: get the datestamp the given file. */ /*---------------------------------------------------------------------*/ BOOL getDate(name, date ) char *name; register struct DateStamp *date; { struct FileInfoBlock *Fib; ULONG FLock; int result; register struct DateStamp *d; if ( (FLock = (ULONG) Lock(name, (long)(ACCESS_READ) )) == NULL) return FALSE; Fib = (struct FileInfoBlock * ) AllocMem( (long)sizeof(struct FileInfoBlock), (long)(MEMF_CHIP)); if (Fib == NULL ) result = FALSE; else { if ( !Examine( FLock, Fib )) result = FALSE; else if ( Fib->fib_DirEntryType > 0 ) result = FALSE; /* It's a directory */ else { d = &Fib->fib_Date; date->ds_Days = d->ds_Days; date->ds_Minute = d->ds_Minute; date->ds_Tick = d->ds_Tick; result = TRUE; } FreeMem( (void *)Fib, (long)sizeof(struct FileInfoBlock) ); } UnLock( FLock ); return result; } ================ cat <wb_parse.c> ================ /* Aztec v3.20a allows you to omit the startup parsing for workbench */ /* by including this module. Since this is a cli utility, we are */ /* going to do just that - well it only saves 232 bytes, but it helps. */ _wb_parse() {} ============== cat <makefile> ============== cp: cp.o PatMatch.o setDate.o wb_parse.o ln cp.o PatMatch.o setDate.o wb_parse.o -lc ============ cat <cp.uue> ============ begin 644 Cp M #\P # ( =/ & $ /I '3T[Z%!Y. M50 2.< ,$ZZ&S F0"1M A@9 P2 "5F7 PJ ', 694( J0K0 (+P O+0 ( M+PM.NALV3^\ #"\M Q.NA?&6$](P"\ +RT #"\+3KH;&D_O P@2E2(+PA. MNA>H6$](P"\ ($I4B"\(+PM.NAKZ3^\ #& &4HI*$F:82A)F'"\M A.NA=^ M6$](P"\ +RT ""\+3KH:TD_O Q,WPP 3EU.=4Y5 O+0 ,+RT "$ZZ_TY0 M3T*G3KH8BEA/3EU.=4Y5 O+0 (2'H +DZZ_S!03R\M A(>@!53KK_(E!/ M2'H <DZZ_QA83TAZ *M.NO\.6$].74YU)7,@5C$N,"!B=69F97)E9"!F:6QE M(&-O<'D@8GD@2F5F9B!,>61I871T+B @57-A9V4Z"@ @("5S(%M&<F]M72!F M:6QE:6X@6U1O72!F:6QE;W5T(%M!;&Q="@ @($%M:6=A1&]S('-T>6QE('!A M='1E<FX@;6%T8VAI;F<@8VAA<F%C=&5R<R!P97)M:71T960@:6X@9FEL96EN M+@H ("!0871T97)N(&UA=&-H:6YG(&-H87)A8W1E<G,@;F]T(&%L;&]W960@ M:6X@1FEL96]U="X*"@ 3E4 "\$&"T "7!AL 1N%+@\ 'IN#A $2("0? @ M*!].74YU$ 1(@&#T3E4 $CG # D;0 ()FT #$H29RI*$V<F$!)(@#\ 8;94 M3S\ $!-(@#\ 8:I43S(?LD!F!E**4HM@ F "8-(0$DB /P!AD%1//P 0$TB M/P!AA%1/,A^R0&8*< !,WPP 3EU.=1 22( _ $ZZ_VI43S\ $!-(@#\ 3KK_ M7%1/,A^R0&\$< %@U'#_8-!.5?_^2.< ,"1M !8,;0 " !1M$DAZ 3 O*@ $ M3KH5'E!/2D!F$"\23KK^$%A/0J=.NA:*6$\@;0 00E [? !__Y3;0 4(&T M"$(0(&T #$(0,"W__K!M !1N #B,"W__DC Y8 F<@@ ,"W__K!M !1L-$AZ M -(O"TZZ_OA03TI 9B12;?_^/SP ?S M__Y(P.6 +S(( "\M A.NA123^\ M"F ) P+?_^L&T %&PR2'H F2\+3KK^NE!/2D!F(E)M__X_/ !_,"W__DC MY8 O,@@ +RT #$ZZ%!1/[P *8%(P+?_^L&T %&8:2'H 8"\+3KK^?E!/2D!F M"B!M ! PO !8"X@;0 (2A!F%#\\ '\O"R\M A.NA/43^\ "F 2/SP ?R\+ M+RT #$ZZ$\!/[P *4FW__F _Q9,WPP 3EU.=3\ 9G)O;0!T;P!A;&P 3E4 M $*L@ 9.74YU3E4 $JL@ 9F!' !8 )P $Y=3G5.50 2.< ,#\\ A.NA1^ M5$\D0$J 9QHO+0 (3KH3ZEA/4D _ $ZZ%&143R9 2H!F$DAZ "I.NOO,6$], MWPP 3EU.=2\M @O"TZZ$ZQ03R2L@ 8E2P $*4J !F#>3F]T(&5N;W5G:"!M M96UO<GD* !.50 +PI.NO]R2D!G"DAZ #9.NOPB6$\D;( &+RH !"\M A. MNA-@4$\O*@ $3KH3_EA/*5* !B\*3KH3\EA/)%].74YU0V%N)W0@:&%P<&5N M.B!S=&%C:R!P;W!P960@=VET:"!N;W1H:6YG('1H97)E"@ 3E7__$CG #!" MK?_\)&T $& 2#!( .F<&#!( +V8$*TK__%**2A)FZB\M !!.N@#L6$]*0&<6 M+RT $"\M A.NA+04$\@;0 ,0A!@5DJM__QF%B\M ! O+0 ,3KH2M%!/(&T M"$(08#HF;0 ()&T $+7M__QD#"!*4HHB2U*+$I!@[@P2 #IF!B!+4HL0DD(3 M(&W__%*(+P@O+0 ,3KH2<E!/("T "$S?# !.74YU3E4 $CG"# D;0 ()FT M#"\++PI.NA),4$\O"DZZ$E183S@ 2D1O+"!M !!*$&<D, 130 PR #H &<8 M,@1300PR "\0 &<,2'H ("\*3KH1N%!/+RT $"\*3KH1K%!/( I,WPP03EU. M=2\ 3E7_]D)M__9(>/_^+RT "$ZZ%0903RM __A*K?_X9UQ(> "2'@!!$ZZ M%F!03RM __Q*K?_\9@I(>@!*3KKZ:%A/+RW__"\M__A.NA284$]*0&<0(&W_ M_$JH 1M!CM\ '_]B\M__A.NA3P6$](> $$+RW__$ZZ%CQ03S M__9.74YU M56YA8FQE('1O(&%L;&]C871E('-P86-E(&9O<B!&:6QE26YF;T)L;V-K(0H M $Y5 O"B1M A@-A 22(!(P& (< $D7TY=3G60O "-G\%6 9^Q5@&?H M4X!GY)"\ %V?<D+P ]9]12BDH29L9P &#,3E7^W"\M ! O+0 (2&W_ M@$ZZ_H9/[P ,(&T #$H09QXO+0 ,3KK^WEA/2D!F$"\M Q(;?\ 3KH0PE!/ M8!0O+0 0+RT #$AM_P!.NOY,3^\ #$AM_X!(>@&P3KKXJE!/2&W_ $AZ :I. MNOB<4$](> /M2&W_@$ZZ$[903RM _NQF%$AM_X!(>@&,3KKX>E!/< %.74YU M2'@#[DAM_P!.NA..4$\K0/[H9AQ(;?\ 2'H!?DZZ^%)03R\M_NQ.NA+F6$]P M 6#,*WP ( _O _+?[R3KH0NE1/*T#^_&82!*T @ _O ,K0 " #^\&[> M#*T @ _O!N)"\M_NQ.NA*D6$\O+?[H3KH2FEA/2'H!.$ZZ]_)83W !8 #_ M=BM\ ?[X2JW^^&]*+RW^\"\M_OPO+?[L3KH3$D_O PK0/[TL*W^\&8L M3KH0HDJ 9PHK?/_____^^& 8+RW^]"\M_OPO+?[H3KH3!$_O PK0/[X8+!* MK?[X;QY*K?[T;Q@O+?[T+RW^_"\M_NA.NA+>3^\ #"M _O@O+?[L3KH2!%A/ M+RW^Z$ZZ$?I83R\M_OQ.N@_N6$]*K?[X;09*K?[T;!Y(;?\ 3KH2 EA/2&W_ M $AZ (A.NO<N4$]P 6 _K)(;?[<2&W_@$ZZ"H!03TI 9PY(;?[<2&W_ $ZZ M"<!03W 8 #^C"5S(#T]/B )7,* $-A;B=T(&]P96X@)7,@9F]R(&EN<'5T M+@H 0V%N)W0@;W!E;B E<R!F;W(@;W5P=70N"@!.;W0@96YO=6=H(&UE;6]R M>2X* " @("5S(%MR96UO=F5D72X* $Y5^GHO"D)L@"8O+0 */RT "$AM^GI( M;?X 2&W^@$ZZ^0!/[P 22&W^@$AM^X!(;?R 3KK[2$_O Q(>@+"2&W^ $ZZ M#AA03TI 9@1"+?X 2&W\@$ZZ_/)83TI 9PY(;?Z 2'H"G$ZZ]M103TAM_@!. MNOS66$]*0&<*2'H"L4ZZ]KQ83TIM^GIF.$AM^X!.NORX6$]*0&8J2&W^@$ZZ M^_A83TI 9AQ(;?N 2&W^ $AM_(!.NOS>3^\ #$*G3KH/'EA/2'@ DAX 01. MNA)44$\D0$AM_@!(;?P 3KH-L%!/2BW\ &8^2'C__DAZ G%.NA"^4$\K0/I\ M2JWZ?&<F+PHO+?I\3KH0=%!/($I0B"\(2&W\ $ZZ#7903R\M^GQ.NA#06$]. MNOE.2'H"-$ZZ^6983THM^X!F#DAZ B5(;?N 3KH-2E!/2&W_ $AM^X!.N@9V M4$]*0&822&W[@$AZ @1.NO4V4$]@ %\3KKY%$I 9@ !<DAM^P!.NOF,6$]( M;?L 2&W\@$AM_8!.NOJ>3^\ #$AM^P!(;?X 2&W] $ZZ^HI/[P ,2FWZ>F=& M2&W] $ZZ^N183TI 9CA(;?T 3KH/AEA/*T#Z?&802&W] $AZ ;=.NO3$4$]@ MD$AM_0!(>@&Y3KKTM%!/+RWZ?$ZZ$ )83TAX__Y(;?V 3KH/LE!/*T#Z?&<0 M+PHO+?I\3KH/;%!/2D!F(DAM_8!(>@&/3KKT>%!/2JWZ?&<*+RWZ?$ZZ#\!8 M3V *XO"B\M^GQ.N@],4$]*0&< (Y*J@ $;SI*;?IZ9S(@2E"(+PA(;?P M3KH+^E!/2D!G'B!*4(@O"$AM^P!(;?J 3KKYL$_O PO $ZZ^!!83V!(($I0 MB"\(2&W_ $AM^X!.N@&$3^\ #$I 9RY.N@S:2H!F&B!*4(@O"$AM_0!(;?V M3KKZUD_O Q*0&<,+RWZ?$ZZ#R183V 28 #_9"\M^GQ.N@\46$]@ /Z(2'@! M!"\*3KH07E!/0J=.N@SH6$\D7TY=3G4N %)E9W5L87(@97AP<F5S<VEO;B!N M;W0@86QL;W=E9"!I;B!P871H.B E<RX* %)E9W5L87(@97AP<F5S<VEO;B!N M;W0@86QL;W=E9"!A<R!O=71P=70@;F%M92X* (S\ 0F%D(')E9W5L87(@ M97AP<F5S<VEO;B!P871T97)N.B E<RX* $-A;B=T(&-R96%T92 E<R * "5S M("XN+B!;8W)E871E9%T* $-A;B=T(&9I;F0@9&ER96-T;W)Y("5S"@!.50 M2.< ,$IM AF"#E\ & (&!")&R &E2*,"R 'DC XX F0-?L@!I@$C 2L&T M"&8(3-\, $Y=3G54BK7+8^I2;( >,"R 'DC XX @;( :,:T " @ 8-I.5?[R M0FW^_D'M_P I2( :0FR 'D)L@" O+0 03KH*8%A/.T#^]#\\ %.NO]Z5$\@ M;0 ,2E!G#"!M P_$$ZZ_V943SM\ '^^F )@P+?[Z2,#C@"!L@!H[< @ M_O8P+?[V4T @;0 (&W /[S,"W^]DC XX @;0 ,.W ( /[X$"W^\TB 2,!@ M.C M_O920#\ 3KK_$%1//RW^^$ZZ_P943V Z,"W^]E) /P!.NO[V5$]*;?[X M9PH_+?[X3KK^YE1/8!J0O "-GOE6 9\A7@&?0D+P !49\A@Q%)M_OHP M+?[ZL&R 'F\ _V P+?[^L&W^]&T(,"R ($Y=3G5*;( >9@1P &#R,"W^_E)M M_OX@;0 0&7 ( *.VR 'O[Z0FR 'D)L@" [? !_OQ@ "8,"W^_$C XX @ M;( :.W ( /[V,"W^]E- (&T "!MP #^\Q M_O-(@$C 8$!@9# M_O8@;0 ( M&W /[S$"R "DB P'P 7Q(M_O-(@<)\ %^P068^,"W^]DC XX @;0 ,/S ( M $ZZ_@I43V FD+P C9[A5@&>T58!GLE. 9ZR0O !=GS)"\ /6>< M8*I2;?[\,"W^_+!M_OIO /]@8 #^:F _R!.50 ,"R %+!L@!9M!D(L@ I@ M$C L@!12;( 4(&R #!EP " "DY=3G5.50 #"P )X *9@)AR&'&3EU.=4Y5 M__XP+0 (2,#C@"!L@! [< @ __XP+0 (2,#C@"!L@! QK0 *" [;?_^ A* M;0 (9M!.74YU3E7__CMM C__DIM AF"# M I.74YU,"T "$C XX @;( 0 M2G ( &<4,"T "$C XX @;( 0.W ( (8-HP+0 (2,#C@"!L@! QK0 *" P M+?_^8+Y.5?_\.VR %/_^&VR "O_]3KK_3! M__U(@$C 8$8Y? !@!@P+?_^ M3EU.=3\M__YASC\ 3KK_/%A/,"W__F#H/RW__F$^5$\[0/_^#"P *8 *9P8Y M? !@!A.NO\","W__F#$2H!GMI"\ (V>\6X!GS%. 9Z:0O %-GGF"B M8*1.5?_\0FW__DZZ_W([0/_\#"P ?( *9PX,+ I@ IG!DHL@ IF0#\M__P_ M+?_^3KK^]EA/.T#__@PL 'R "F<(,"W__DY=3G4P+0 (2,#C@"!L@! QK( 4 M" [;( 4 A.NOYX8 X_+( 4/RW__$ZZ_GY83V"28,Q.5?_^*6T "( ,*6T M#( 00FR %"\L@ Q.N@:\6$\Y0( 60FR &$)M__Y@%# M__Y(P.. (&R $$)P M" !2;?_^,"W__K!L@!9OXDZZ_>Q"9T)G3KK_-%1//P!.NOX:6$]*;( 89@1P M 6 "< !.74YU3E7_[ RM !P 4;P9P $Y=3G5"IT*G3KH)YE!/*T#__$JM M__QF!' 8.1(>0 ! %(> !$3KH*LE!/*T#_^$JM__AF$DAX $0O+?_X3KH* MQ%!/< !@N"!M__@@+?_XT+P 4(4 "B!M__@A;?_X !0@;?_X(6W__ 8 M(&W_^"%M P '" M__C0O "@K0/_L0JW_]& >("W_].6 (&T $"(M__3E M@2)M_^PCL @ & !2K?_T("W_]+"M !1L"@RM !__T;<XO+?_X+RT "$ZZ M"GY03R\M__Q.N@JH6$\O+?_\3KH*2%A/(&W_^"MH "#_\$AX $0O+?_X3KH* M$%!/+RW__$ZZ"7Y83R M__!@ /[X3E7_Y$*M_^1(> !2'@ 1$ZZ";Y03RM M_^AG?B\M A.N@?\6$\K0/_\9UHO+0 ((&W_Z%*(+PA.N@4"4$\O+0 (3KH% M"%A/(&W_Z!" 0JW_[$ZZ!_XK0/_P("W_Z.2(*T#_]"MM S_^$AX 1(;?_L M2'@ (B\M__Q.NOYJ3^\ $"M _^1*K?_H9PY(> !$+RW_Z$ZZ"6103PRM____ M___D9@9P 4Y=3G5P ϧ_]DCG # D;0 ,2'C__B\M A.N@>:4$\K0/_X M9@IP $S?# !.74YU2'@ DAX 01.N@CN4$\K0/_\2JW__&8&0FW_]F!4+RW_ M_"\M__A.N@<J4$]*0&8&0FW_]F N(&W__$JH 1O!D)M__9@'B9M__S7_ M (0DDR5K 0 !"5K @ "#M\ '_]DAX 00O+?_\3KH(M%!/+RW_^$ZZ!U!8 M3S M__9@ /]V3E4 $Y=3G5A<$/L@ 9%[( &M<EF#C(\ !9K"'0 (L)1R?_\ M*4^ *"QX 0I3H L2.> @ @N 0!*6<02_H "$ZN_^)@!D*G\U].<T/Z "!. MKOYH*4" ,&8,+CP X '3J[_E& $3KH &E!/3G5D;W,N;&EB<F%R>0!)^0 M?_Y.=4Y5 O"DAY $ # L@ +!_ &+P!.N@?>4$\I0( T9A1"ITAY $ M $ZZ!KA03RYL@"A.=2!L@#1": $(&R -#%\ $ $")L@#0S? ! H@;( H M("R *)"H 10@"E @#@@;( X(+Q-04Y80J=.N@>66$\D0$JJ *QG+B\M PO M+0 (+PI.N@"R3^\ ##E\ & )B!L@#0 :( 0@;( T &B *8$1(:@!< M3KH'Y%A/2&H 7$ZZ!X183RE @#P@;( \2J@ )&<0(&R /")H "0O$4ZZ!4I8 M3R\L@#PO"DZZ_IA03REL@#R 0$ZZ!7H@;( T((!.N@6L(&R -"% 9G%DAX M ^U(>@ L3KH%A%!/(&R -"% PO+(! /RR 1$ZZ\ZI<3T)G3KH#?E1/)%]. M74YU*@!.50 2.<,,"1M ! @;0 (("@ K.6 * @1" H !#E@"9 $!-(@$C MT*T #%2 .4" 1D*G,"R 1DC +P!.N@9\4$\I0(!(9@A,WPPP3EU.=1 32( _ M "!+4H@O""\L@$A.N@%$3^\ "DAZ 3H0$TB 2,#0K(!(+P!.N@&H4$\_+0 . M+PHO+(!(3KH!1$_O I";(!$)FR 2"1+$!-(@#H L'P (&<8NGP "6<2NGP M#&<,NGP #6<&NGP "F8$4HM@V P3 "!M>@P3 ")F+E*+($M2BQ 02( Z &<> M($I2BA"%NGP (F80#!, (F8$4HM@!D(J__]@ F#68#@@2U*+$!!(@#H 9R:Z M? @9R"Z? )9QJZ? ,9Q2Z? -9PZZ? *9P@@2E**$(5@SB!*4HI"$$I% M9@)3BU)L@$1@ /]:0A)"IS L@$120$C Y8 O $ZZ!6903RE @$!F"$)L@$1@ M /[D>@ F;(!(8!XP!4C Y8 @;(! (8L( "\+3KH LEA/4D!(P-? 4D6Z;(!$ M;=PP!4C Y8 @;(! 0K ( & _J8@ $SO P !" (,B\ #& "$-E7R?_\9P92 M06 "0AA1R?_\3G4P/'__8 0P+P ,(&\ !$H89OQ32")O A30!#95\C__&<" M0A @+P $3G4P/'__8 0P+P ,4T!K%"!O 0B;P (L0EF#%-(2AA7R/_V< !. M=6,$< %.=7#_3G4@;P $( @B;P ($-EF_$YU(&\ !" (2AAF_)' ( A3@$YU M3E4 $CG # D;( B8!0F4B J 10@"\ +PI.N@2$4$\D2R *9NA"K( B3-\, M $Y=3G5.50 +PI!^O_&*4B 3$*G("T "%" +P!.N@0J4$\D0$J 9@AP "1? M3EU.=22L@"(E;0 ( 0I2H B( I0@&#F3E4 ' ,"T ""\ 8;)83TY=3G5. M50 2.< ,)?+)&R (F .(&T "%&(L<IG$B9*)%(@"F;N</],WPP 3EU.=2 + M9P0FDF $*5* (B J 10@"\ +PI.N@/64$]P SE7__$AX$ !"ITZZ!"90 M3RM __P( ,9Q)*;( F9@@@+?_\3EU.=4ZZ 9P &#T3E4 $AX 1(>@ > M3KH"&"\ 3KH"0$_O P_/ !3KH #%1/3EU.=5Y#"@!.50 2JR 7F<&(&R M7DZ0/RT "$ZZ A43TY=3G5.5?_\+P0P+0 (2, K0/_\2JR -&<H> !@"C\$ M3KH T%1/4D2X;( ";? P+( "P?P !B\ +RR -$ZZ QI03TJL@$QG!B!L@$Q. MD$JL@%!G"B\L@%!.N@':6$]*K(!49PHO+(!43KH!REA/2JR 6&<*+RR 6$ZZ M ;I83RQX 0(+@ $ 2EG%"\-2_H "DZN_^(J7V &0J?S7TYS2JR /&8P2JR M2&<H,"R 1DC +P O+(!(3KH"H%!/,"R 1%) 2,#E@"\ +RR 0$ZZ HI03V . M3KH"=B\L@#Q.N@+26$\@+?_\+FR *$YU*!].74YU3E4 $CG#B X+0 (, 3! M_ &)$#5[( T2D1M"KAL@ )L!$J29A Y? "@%QP_TS?!'!.74YU,"H !,!\ M@ !F""\23KH #EA/0I)P &#@3OH B(O 0L;( P3N[_W"(O 0L;( P3N[_ MB"(O 0L;( P3N[_@D[Z (B+P $+&R ,$[N_[@B+P $+&R ,$[N_U).^@ " M3.\ !@ $+&R ,$[N_YI,[P & 0L;( P3N[_E"QL@#!.[O_*3OH BQL@#!. M[O]\3OH DSO 8 !"QL@#!.[O^L3OH DSO 8 !"QL@#!.[O_B3OH BQL M@#!.[O_$3OH DSO X !"QL@#!.[O_63OH B(O 0L;( P3N[_ID[Z ), M[P . 0L;( P3N[_T$CG 01,[R" PL;( L3J[_E$S?((!.=2)O 0L;( L M3N[^8DY5 !(YP@@2'C__TZZ -!83R@ L+S_____9@IP $S?!!!.74YU2'D M 0 !2'@ (DZZ +A03R1 2H!F#"\$3KH Z%A/< !@UB5M @ "A5M \ "15\ M 0 "$(J X51 /0J=.N@"66$\E0 02JT "&<*+PI.N@!:6$]@"DAJ !1. MN@# 6$\@"F"23E4 "\*)&T "$JJ IG""\*3KH Q%A/%7P _P ()7S_____ M !1P ! J \O $ZZ &Q83TAX "(O"DZZ $Q03R1?3EU.=2)O 0L;( L3N[^ MGB O 0L;( L3N[^MD[Z ),[P # 0L;( L3N[_.D[Z (B;P $+&R +$[N M_MHL;( L3N[_?$[Z (B;P $("\ ""QL@"Q.[O\N("\ !"QL@"Q.[OZP3OH M B!O 0L;( L3N[^C"!O 0@B%B00J@ !"%( A.=4SO P !"QL@"Q.[OZ2 M(F\ !"QL@"Q.[OZ8(F\ !"QL@"Q.[OZ&3.\ P $+&R +$[N_LY.^@ "(&\ M!"QL@"Q.[OZ #[ $ ! 4E /R #Z@ $ % 0 #\@ ^L ! #\@$ end
chas@gtss.UUCP (Charles Cleveland) (05/25/87)
In article <741@van-bc.UUCP> jlydiatt@van-bc.UUCP (Jeff Lydiatt) writes: > >Here is a replacement for AmigaDog "copy" program.... >It ... has the added bonus that it retains the date of copied file. This is not a feature, it is a bug :-). Virtually nobody does it this way and for good reason. Kindly include this feature as an option only, and not the default one at that. -- Charles Cleveland EDU: chas@ss.physics.gatech.edu Georgia Tech School of Physics UUCP: ...!{akgua,allegra,amd,hplabs,ihnp4, Atlanta, GA 30332 masscomp,ut-ngp,rlgvax,sb1,uf-cgrl, unmvax,ut-sally}!gatech!gtss!chas
kim@amdahl.amdahl.com (Kim DeVaughn) (05/26/87)
In article <121@gtss.UUCP>, chas@gtss.UUCP (Charles Cleveland) writes: > In article <741@van-bc.UUCP> jlydiatt@van-bc.UUCP (Jeff Lydiatt) writes: > > > >Here is a replacement for AmigaDog "copy" program.... > >It ... has the added bonus that it retains the date of copied file. > > This is not a feature, it is a bug :-). Virtually nobody does it this > way and for good reason. Kindly include this feature as an option only, and > not the default one at that. Well, this is probably one of those "religious issues", but I *strongly* disagree with you, Charles! It is *especially* important on floppy-based systems to retain the "last modified" date of a file when it is copied from one floppy to another, *as the default*. Without such date retention, it can become quite difficult to figure-out just which "incarnation" of a set of files (i.e., directory of files) is really the oldest, newest, etc. And of course, many processing programs (such as "make", and various archiving/backup programs) rely on the modification date to guide their processing. It may interest you to know that the MS-DOS and PC-DOS "copy" command retains the file date [I'd hardly call Microsoft and IBM "virtually nobody"], and many UNIX(R) utilities go to the trouble of preserving/restoring it (e.g., tar, pack, compress, etc.), as do archivers like ARC, PKARC, etc. Maybe I'm overlooking something obvious, but I sure can't come up with the "good reason" you alluded to for not retaining the date on a pure copy operation. If you *do* want the file to have the current date, there is is always "touch" ... :-)! Anyway, thanks to Jeff for posting the new copy, with file-dating working the way it should have in the first place! Now, about the way AmigaDOS (nee' Tripos) does pattern matching ... /kim -- UUCP: kim@amdahl.amdahl.com or: {sun,decwrl,hplabs,pyramid,ihnp4,seismo,oliveb,cbosgd}!amdahl!kim DDD: 408-746-8462 USPS: Amdahl Corp. M/S 249, 1250 E. Arques Av, Sunnyvale, CA 94086 CIS: 76535,25
mwm@eris.UUCP (05/26/87)
In article <7180@amdahl.amdahl.com> kim@amdahl.amdahl.com (Kim DeVaughn) writes: <In article <121@gtss.UUCP>, chas@gtss.UUCP (Charles Cleveland) writes: <> In article <741@van-bc.UUCP> jlydiatt@van-bc.UUCP (Jeff Lydiatt) writes: <> >It ... has the added bonus that it retains the date of copied file. <> <> This is not a feature, it is a bug :-). < <Well, this is probably one of those "religious issues", but I *strongly* <disagree with you, Charles! No, it's not a religious issue. It depends on what you're using copy for. <Without such date retention, it can become quite difficult to figure-out just <which "incarnation" of a set of files (i.e., directory of files) is really the <oldest, newest, etc. And of course, many processing programs (such as "make", <and various archiving/backup programs) rely on the modification date to guide <their processing. Odd, I never run into that problem. Maybe because my habits come from large systems instead of floppy-based systems? Or maybe it's because I make backups with backup utilities, and use copy for making copies. <It may interest you to know that the MS-DOS and PC-DOS "copy" command retains <the file date Given the general quality of software sold by IBM and Microsoft, this strikes me as a good indication that copy preserving the date is wrong 1/2-). <many UNIX(R) utilities go to the trouble of preserving/restoring it <(e.g., tar, pack, compress, etc.), as do archivers like ARC, PKARC, <etc. Ah, but those unix utilities create archives or backups, *not* copies. There jobs is to make it possible to recreate files exactly, which includes the create/modification/access times. On the other hand, Unix cp creates copies. It makes the creation and modification date the current time (didn't check access time, but it hardly matters for this). <Maybe I'm overlooking something obvious, but I sure can't come up with the <"good reason" you alluded to for not retaining the date on a pure copy <operation. You want a good reason for copy (especially "copy all") to preserve dates? How about because after I copy new software from a floppy to my hard disk, I'd like the next incremental backup to pick up all the new stuff. That way, I don't have to rebuild my hard disk from umpteen Fish disks (or whatever). Or how about the following (which I do): copy ttyio.c ttyio.c.save emacs ttyio.c ; want to try out some new changes... make mg ; see how they work copy ttyio.c.save ttyio.c ; they don't make ; gee, nothing happens... Since copy put the wrong date on the new copy of ttyio.c, it wound up as "older" than ttyio.o. Similarly, if I get a new version of mg, and just want to try the ttyio.c, if it was actually edited before I last tweaked mine, the make won't find anything to do. <If you *do* want the file to have the current date, there is is <always "touch" ... :-)! And if you want the date preserved, there's always "setdate". In summary, if you want a command to make backups of a file for you, I suggest you use a backup utility. Don't try and pervert copy into such a utility. I want copy to make new copies of a file for me. <Anyway, thanks to Jeff for posting the new copy, with file-dating working <the way it should have in the first place! Gee, I must have missed that posting. All I've got is one where file-dating is broken :-). <mike -- How many times do you have to fall Mike Meyer While people stand there gawking? mwm@berkeley.edu How many times do you have to fall ucbvax!mwm Before you end up walking? mwm@ucbjade.BITNET
tenny@z.dec.com.UUCP (05/27/87)
Charles Cleveland @ gatech writes: >In article <741@van-bc.UUCP> jlydiatt@van-bc.UUCP (Jeff Lydiatt) writes: >>Here is a replacement for AmigaDog "copy" program.... >>It ... has the added bonus that it retains the date of copied file. >This is not a feature, it is a bug :-). Virtually nobody does it this >way and for good reason. Kindly include this feature as an option only, and >not the default one at that. Since you seem to know that nobody uses date preserving copy programs, would you care to tell the rest of us what the good reason is? I agree the date preservation should be an option, but I find the ability to preserve dates extremely useful in file management. Dave Tenny Lisp Development, Digital Equipment Corp.
scotty@l5comp.UUCP (Scott Turner) (05/27/87)
In article <121@gtss.UUCP> chas@gtss.UUCP (Charles Cleveland) writes: >In article <741@van-bc.UUCP> jlydiatt@van-bc.UUCP (Jeff Lydiatt) writes: >> >>Here is a replacement for AmigaDog "copy" program.... >>It ... has the added bonus that it retains the date of copied file. > >This is not a feature, it is a bug :-). Virtually nobody does it this >way and for good reason. Kindly include this feature as an option only, and >not the default one at that. One man's bug is another man's feature. I for one am ALL in favor of having my datestamps left alone when I move files around. I find it a bloody nuisance having the datestamp changed everytime I move a file from one place to another. And for those that would argue that dates are not a good way of verifying if one file is newer than the other, I submit that in that case why not do away with them all together? And I don't consider and exact copy of another file to be 'newer' than the original. If I need to change the datestamp that's what I've got 'touch' for. If there is some reason for why a copy should be seen as 'newer' I'd love to hear about it. Scott Turner -- L5 Computing, the home of Merlin, Arthur, Excalibur and the CRAM. GEnie: JST | UUCP: stride!l5comp!scotty | 12311 Maplewood Ave; Edmonds WA 98020 If Motorola had wanted us to use BPTR's they'd have built in shifts on A regs [ BCPL? Just say *NO*! ] (I don't smoke, send flames to /dev/null)
mwm@eris.UUCP (05/29/87)
In article <156@l5comp.UUCP> scotty@l5comp.UUCP (Scott Turner) writes:
<I for one am ALL in favor of having my datestamps left alone when I move files
<around. I find it a bloody nuisance having the datestamp changed everytime I
<move a file from one place to another.
You use copy to move a file? That's odd - I use rename. Copy makes a
new copy, rename moves the current one to a new name (or directory).
<If there is some reason for why a copy should be seen as 'newer' I'd love to
<hear about it.
I've already posted a couple; I'm not going to post them again.
A reasonable solution has already been proposed: have two programs,
one called copy creates new copies, and one called cp that creates
copies with preserved dates. "Copy" needs to have behavior identical
to the original DOS copy for script-writers, so the date-mangling one
winds up as "cp" (or "mv", or "backup", or whatever you want to call
it).
While I'm talking to you, let me add to requests that you tone the
excess verbiage (read: flames) in your postings. No matter how good a
tecnical point is, most people will ignore it (or just not bother
reading it) if it's 5% of an article that's 95% flameage.
<mike
--
How many times do you have to fall Mike Meyer
While people stand there gawking? mwm@berkeley.edu
How many times do you have to fall ucbvax!mwm
Before you end up walking? mwm@ucbjade.BITNET
ewhac@well.UUCP (05/29/87)
In article <156@l5comp.UUCP> scotty@l5comp.UUCP (Scott Turner) writes: >In article <121@gtss.UUCP> chas@gtss.UUCP (Charles Cleveland) writes: >>In article <741@van-bc.UUCP> jlydiatt@van-bc.UUCP (Jeff Lydiatt) writes: >>> >>>Here is a replacement for AmigaDog "copy" program.... >>>It ... has the added bonus that it retains the date of copied file. >> >>This is not a feature, it is a bug :-). Virtually nobody does it this >>way and for good reason. Kindly include this feature as an option only, and >>not the default one at that. >One man's bug is another man's feature. > >I for one am ALL in favor of having my datestamps left alone when I move files >around. [ ... ] In the hopes of quelling this argument, I contribute to this flame: My orientation is that copy should "modify" the creation date. The reason I have the word "modify" in quotes is because you aren't really modifying the date at all. When you invoke "Copy", you make a copy of the file in question. It is *NOT* the same file. The only thing similar between them is their contents. By copying the source file, you *create* a totally *new* destination file. When creating a new file, it gets the current date. Thus, you aren't modifying anything. You are creating a new file (with today's date), and filling it with the contents of the source file. People complain about this behavior because, when copying the files to floppy from RAM: (or VD0:), it "changes" the dates, and causes problems with programs like 'make'. However, if you think about it for a while, what you're really doing is *backing up* your data onto floppies. A backup utility is designed to preserve the date when backing up and restoring files. A typical development cycle might be: Create file, make, BACKUP to floppy (preserving dates), test, Guru, reboot (flushing core), RESTORE RAM: drive from floppy (preserving dates), and trying again. By saying "Copy", you're telling the machine that you want to make a duplicate of a file's contents by *creating* a new file to keep it in. By saying "Backup" (or whatever), you're asking the machine to *preserve* your files in their current state. Anyone who might suggest, because the source and destination filenames are the same, or that the destination file already exists, that "Copy" should preserve dates is still wrong. When copying over an existing file, one of two things happens: 1) A *new* file is created, data copied and, if successful, the old version deleted, 2) The destination file is deleted, and a *new* file created and filled with the data. Asserting that the source and destination names are the same doesn't prove anything. Someone earlier was picking on semantics. You should call the backup utility "Backup", or "Preserve", or something along those lines; and the file copier "Copy". That is, if you wanted to be picky :-). 'Nuff said? _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ Leo L. Schwab -- The Guy in The Cape ihnp4!ptsfa -\ \_ -_ Bike shrunk by popular demand, dual ---> !{well,unicom}!ewhac O----^o But it's still the only way to fly. hplabs / (pronounced "AE-wack") "Work FOR? I don't work FOR anybody! I'm just having fun." -- The Doctor
keithd@cadovax.UUCP (06/02/87)
In article <3171@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes: > When you invoke "Copy", you make a copy of the file in question. It >is *NOT* the same file. The only thing similar between them is their >contents. By copying the source file, you *create* a totally *new* >destination file. When creating a new file, it gets the current date. >Thus, you aren't modifying anything. You are creating a new file (with >today's date), and filling it with the contents of the source file. It all depends on what you consider a files 'date' field as, 'last modified date' or 'last copied date'. I'd prefer a filesystem that provides BOTH date fields. 'Last modified date' can be an indication of 'version', while 'last copied date' can be an indication of when the file was backed up. On a backup disk where all of the files were backed up at the same time (the way I usually backup files), EVERY files 'last copied date' is the same, and the same as the disk's last used date. In such a case, and with only one choice of 'date' fields, I prefer using 'last modified date' as an indication of version, as 'last copied date' is more usually redundant information. Keith Doyle # {ucbvax,ihnp4,decvax}!trwrb!cadovax!keithd # cadovax!keithd@ucla-locus.arpa Contel Business Systems 213-323-8170
tenny@z.dec.com.UUCP (06/02/87)
Mike Meyer at berkeley writes: >You use copy to move a file? That's odd - I use rename. Copy makes a >new copy, rename moves the current one to a new name (or directory). Unfortunately this doesn't work across devices. (can't rename df1:xxx ram:xxx) Dave Tenny
scotty@l5comp.UUCP (Scott Turner) (06/04/87)
In article <3762@jade.BERKELEY.EDU> mwm@eris.BERKELEY.EDU (Mike (My watch has windows) Meyer) writes: >You use copy to move a file? That's odd - I use rename. Copy makes a >new copy, rename moves the current one to a new name (or directory). I often move files in ways that rename can't handle. For example: I have a dual hard disk system. I often "Load Manage" it by shifting things from one drive to the other as they move from "active" to "not so active". Or from not so active back to active. And yes when they go "stone cold" I kick 'em off to floppy. >I've already posted a couple; I'm not going to post them again. Great. I got them soon after my posting. This net bounce takes a bit of getting used to. >A reasonable solution has already been proposed: have two programs, >one called copy creates new copies, and one called cp that creates >copies with preserved dates. "Copy" needs to have behavior identical >to the original DOS copy for script-writers, so the date-mangling one >winds up as "cp" (or "mv", or "backup", or whatever you want to call >it). A better solution I think is to use a shell 'alias' command to deal with this. Even before this whole topic came up I had alias'd copy as cp on my system. I have since re-alias'd cp as xcopy. An issue that this raises is what to call the two copy programs so that shell scripts can address both. By using aliases I have allowed myself to use the copy program I find most useful without interfering with shell scripts or make. But while copy is standardized the other copy isn't. I'm all for calling it 'xcopy', :) but I'm sure there's got to be a better name out there. I'm NOT in favor of calling it cp. >While I'm talking to you, let me add to requests that you tone the >excess verbiage (read: flames) in your postings. No matter how good a >tecnical point is, most people will ignore it (or just not bother >reading it) if it's 5% of an article that's 95% flameage. I really appreciate all the time that countless netlanders have taken on my account on this subject. I just hope that some of it will rub off on the countless OTHER netlanders out there with similar problems. I think I've been a lightning rod on this subject, but I am by no means the ONLY sinner amongst those here on the net. I seem to be a natural when it comes to drawing down attention on topics that need it. But we also have to be careful not to focus on me to the exclusion of all else. Scott Turner -- L5 Computing, the home of Merlin, Arthur, Excalibur and the CRAM. GEnie: JST | UUCP: stride!l5comp!scotty | 12311 Maplewood Ave; Edmonds WA 98020 If Motorola had wanted us to use BPTR's they'd have built in shifts on A regs [ BCPL? Just say *NO*! ] (I don't smoke, send flames to /dev/null)
jdg@elmgate.UUCP (06/08/87)
In article <1578@cadovax.UUCP> keithd@cadovax.UUCP (Keith Doyle) writes: >It all depends on what you consider a files 'date' field as, >'last modified date' or 'last copied date'. I'd prefer a filesystem >that provides BOTH date fields. 'Last modified date' can be an indication >of 'version', while 'last copied date' can be an indication of when the >file was backed up. >Keith Doyle This is probably a dumb idea (I gotta million of 'm, ah, cha cha cha cha) but what about a copy program that preserves the old date (or inserts the new date) into the Filenote area (the last 8 characters)? Ok, ok .... It was just an idea..... 8^) -- Jeff Gortatowsky {seismo,allegra}!rochester!kodak!elmgate!jdg Eastman Kodak Company These comments are mine alone and not Eastman Kodak's. How's that for a simple and complete disclaimer?
bryce@COGSCI.BERKELEY.EDU.UUCP (06/09/87)
In article <640@elmgate.UUCP> jdg@aurora.UUCP (Jeff Gortatowsky) writes: > >but what about a copy program that preserves the old date (or inserts >the new date) into the Filenote area (the last 8 characters)? What about a copy command that PRESERVES the FileNote (comment) area!? Some of us actually use it. ( C-A, Metacomco take note. Your COPY does not ) ---------------------------------- | See ClickToFront, coming soon | | to a newsgroup near you. Try | | it, you'll like it. | ---------------------------------- Ack! (NAK,EOT,SOH) |\ /| . {o O} . bryce@cogsci.berkeley.EDU -or- ucbvax!cogsci!bryce ( " ) U
spencer@eris.UUCP (06/10/87)
In article <10166@decwrl.DEC.COM> tenny@z.dec.com writes: >Mike Meyer at berkeley writes: >>You use copy to move a file? That's odd - I use rename. Copy makes a >>new copy, rename moves the current one to a new name (or directory). > >Unfortunately this doesn't work across devices. (can't rename df1:xxx ram:xxx) >Dave Tenny Oh, too true. Matt's Shell has that ability, and I always thought that it shouldn't be that hard to write a program that would allow you to move files around devices like you can around disk structures. It should support wild cards, and it should preserve the date stamp, then we can use copy (or cp) to copy files and use the current time stamp (and wild card here too). Sorry, I was at CES while you all got to have your licks about who gets to datestamp, I appologize for being late. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Randy Spencer P.O. Box 4542 Berkeley CA 94704 (415)284-4740 I N F I N I T Y BBS: (415)283-5469 Now working for |||||||||||::::... . . BUD-LINX But in no way |||||||||||||||::::.. .. . Officially representing ||||||||||||:::::... .. ....ucbvax!mica!spencer s o f t w a r e spencer@mica.berkeley.edu -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-