/* compare output of crc from two systems * command line options * -i "incremental" write updated checksum file, not commands; * * Here is the script run nightly at AT&T's netlib... * #!/bin/sh * DIR=$HOME/lib/netlib * netlib mkmaster * cd $DIR/master * sites=`echo *` * cd /netlib * for i in $sites;do * lsr -t `cat $DIR/master/$i` | $DIR/exclude | sort > /tmp/crc$$ * netlib masterslave -i /tmp/crc$$ /netlib/crc/res/$i > /tmp/$i * cp /tmp/$i /netlib/crc/res/$i * rm /tmp/crc$$ /tmp/$i * done * * Eric Grosse 3 Jan 93 first version * 29 Mar 93 added -i option * 13 Jun 95 cope with blanks in filenames; better handling sum=0 * 12 Jul 95 added -v option * 5 Jul 96 added -t9 option to tolerate small clock skew * * The author of this software is Eric Grosse. Copyright (c) 1993 by AT&T. * Permission to use, copy, modify, and distribute this software for any * purpose without fee is hereby granted, provided that this entire notice * is included in all copies of any software which is or includes a copy * or modification of this software and in all copies of the supporting * documentation for such software. * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */ /* for internationalization... */ #define MESS_OPEN "can't open %s\n" #define MESS_SUM "can't sum %s\n" #define MESS_TIM "%s: same time, different contents?!!\n" #define MESS_SORT "input should be sorted:\n\t%s\n\t%s\n" #define MESS_BAD "%i bad input: %s\n" #define _POSIX_SOURCE #include #include #include #include #include #include extern FILE *zopen(char*); /* like fopen, but for compressed files */ extern int crc(int,unsigned long*,unsigned long*); int incremental = 0; int verbose = 0; char *progname; typedef struct Fsum{ unsigned long tim, len, sum; char name[2001]; char ok; /* other fields are valid if this is nonzero */ } Fsum; FILE* Fopen(char *path, char *mode) { FILE *f; if( strcmp(mode,"r")==0 && ( strcmp(path+strlen(path)-2,".Z")==0 || strcmp(path+strlen(path)-3,".gz")==0 ) ) f = zopen(path); else f = fopen(path,mode); if(!f){ fprintf(stderr,MESS_OPEN,path); perror(""); exit(1); } return f; } void bad(int i,char*b) { fprintf(stderr,MESS_BAD,i,b); exit(1); } void next_Fsum(FILE *f, Fsum *s) { /* Parse right-to-left to cope with blanks in filenames. */ Fsum old; int n; char *b = s->name, *p; s->ok = 0; strcpy(old.name,b); if(fgets(b,sizeof(s->name),f)==NULL) return; /* EOF or read error */ n = strlen(b); p = b+n-1; /* p=='\n' */ for(*p-- = '\0'; *p!=' '; p--) if(p<=b || !strchr("0123456789abcdef",*p)) bad(801,b); n = sscanf(p+1,"%lx",&s->sum); if(n!=1) bad(802,b); for(*p-- = '\0'; *p!=' '; p--) if(p<=b || !strchr("0123456789",*p)) bad(803,b); n = sscanf(p+1,"%lu",&s->len); if(n!=1) bad(804,b); for(*p-- = '\0'; *p!=' '; p--) if(p<=b || !strchr("0123456789",*p)) bad(805,b); n = sscanf(p+1,"%lu",&s->tim); if(n!=1) bad(806,b); *p-- = '\0'; if(strcmp(old.name,b)>=0 ){ fprintf(stderr,MESS_SORT,old.name,s->name); exit(1); } s->ok = 1; } void cmd(char *c, struct Fsum *s) { int fd; if(incremental){ switch(*c){ case 'g': /* "get" */ if(verbose) fprintf(stderr,"crc %s\n",s->name); fd = open(s->name,O_RDONLY); if(crc(fd,&s->sum,&s->len)) fprintf(stderr,MESS_SUM,s->name); close(fd); case 'o': /* "ok" or fall-through from "get" */ printf("%s %lu %lu %lx\n", s->name,s->tim,s->len,s->sum); /* "time" can't happen; if "rm", do nothing */ } }else{ /* normal case */ if(*c!='o') /* skip if "ok" */ printf("%s %s %lu %lu %lx\n", c,s->name,s->tim,s->len,s->sum); } } int main(int argc, char **argv) { int cmp; FILE *master, *slave; Fsum m, s; long toler = 0; progname = argv[0]; if(argc>=4 && strcmp(argv[1],"-v")==0){ verbose = 1; argv++; argc--; } if(argc>=4 && strncmp(argv[1],"-t",2)==0){ toler = atol(argv[1]+2);argv++; argc--; } if(argc==4 && strcmp(argv[1],"-i")==0){ incremental = 1; argv++; argc--; } if(argc!=3) exit(3); master = Fopen(argv[1],"r"); slave = Fopen(argv[2],"r"); m.name[0] = '\0'; /* for benefit of sort check in next_Fsum */ s.name[0] = '\0'; next_Fsum(master,&m); next_Fsum(slave,&s); while(m.ok||s.ok){ if( !m.ok ) cmp = 1; else if ( !s.ok ) cmp = -1; else cmp = strcmp(m.name,s.name); if( cmp < 0 ){ cmd("get",&m); next_Fsum(master,&m); }else if( cmp > 0 ){ cmd("rm",&s); next_Fsum(slave,&s); }else{ /* cmp==0 */ if( labs(m.tim-s.tim)>toler ){ if(m.len==s.len && m.sum==s.sum) cmd("time",&m); else cmd("get",&m); }else if( m.len!=s.len ){ fprintf(stderr,MESS_TIM,m.name); cmd("get",&m); }else if( m.sum!=s.sum ){ if(incremental && m.sum==0){ m.sum = s.sum; cmd("ok",&m); }else if(incremental && s.sum==0){ cmd("ok",&m); }else{ fprintf(stderr,MESS_TIM,m.name); cmd("get",&m); } }else{ cmd("ok",&m); } next_Fsum(master,&m); next_Fsum(slave,&s); } } exit(0); }