/* Boolean operations on file sets based on MD5 digests. * Jerzy Tarasiuk 22-Jul-2000 */ #include #include #include const char usage[]="Boolean operations on file sets " "based on MD5 digests. Jerzy Tarasiuk\n\n" "Usage: %s [-p] {-a|-b}[number] " "additional_input_files < input > output\n\n" "-p\tprints path only (w/o MD5 digest),\n" "-a/-b\trequire at least or below number " "of additional_input_files\n" "\tto contain same MD5 digests, " "for the line to be passed.\n\n" "All input files (STDIN and additional) " "must be sorted by MD5 digest value.\n"; /* Boolean operations on file sets based on MD5 digests. * - works on files sorted by MD5 digest values in ascending * order, containing in every line: md5_digest and file_path, * separted by two blanks (such a files can be produced by * 'md5sum' on Linux or by MD5TREE (mine) on DOS * - works as filter with additional input files, passing from * STDIN to STDOUT lines which match criteria defined by * filtering options and additional input files * - names of additional input files cannot start from '-' * - option: -a[number] or -b[number] (default number is 1) * defines filtering rule: -a means at least number, -b less * than number of additional input files contains MD5 digest * same as in input line for the line to pass through filter * - option: -p means passing file_path only to STDOUT */ #define OPT_P 1 #define OPT_A 2 #define OPT_B 4 typedef char aibf_t[300]; /* seems may need 32+2+256+1 */ int optflg=0,count=1; FILE **aifd; aibf_t buf,*aibf; int compare_md5(int fi) { int c; char *fbf=aibf[fi]; do { if((c=strncmp(buf,fbf,33))<=0) return c==0; } while(fgets(fbf,sizeof(*aibf),aifd[fi])!=NULL); if(ferror(aifd[fi])) { sprintf(fbf,"input %u",fi+1); perror(fbf); } for(fbf[c=sizeof(*aibf)-1]=0; c-->0; fbf[c]=0x7f); return 0; } main(int ac, char **av) { int ai,nf,v,c; char *cp; for(nf=ai=0; ++ainf) { cp="%s: too less input files"; goto badarg; } if((aifd=malloc(nf*sizeof(*aifd)))==NULL || (aibf=malloc(nf*sizeof(*aibf)))==NULL) { perror("malloc"); return -1; } for(nf=ai=0; ++ai=count) continue; cp=buf; if((optflg & OPT_P) && (cp=strchr(buf,' '))!=NULL && *cp==' ' && *++cp==' ') cp++; if(cp!=NULL) fputs(cp,stdout); } if(ferror(stdin)) perror("STDIN"); if(fclose(stdout)!=0) perror("STDOUT"); return 0; badopt: cp=usage; badarg: { char pn[10],*ap; for(ap=*av,v=0; (c=*ap++)!=0; ) switch(c) { case':':case'/':case'\\': v=0; break; case'.':pn[v]=0; v=9; break; default:if(v<9) pn[v++]=c; } pn[v]=0; fprintf(stderr,cp,pn); return -1; } }