|
|
1.1 root 1: /* chksmb.c */
2:
3: /* Synchronet message base (SMB) validity checker */
4:
5: /* $Id: chksmb.c,v 1.43 2005/10/02 23:00:45 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: /* ANSI */
39: #include <stdio.h>
40: #include <stdlib.h> /* exit */
41: #include <string.h> /* strrchr */
42: #include <time.h> /* ctime */
43: #include <ctype.h> /* toupper */
44:
45: /* SMB-specific */
46: #include "genwrap.h"
47: #include "conwrap.h" /* getch */
48: #include "dirwrap.h" /* fexist */
49: #include "filewrap.h" /* filelength */
50: #include "smblib.h"
51:
52: /****************************************************************************/
53: /* Returns in 'string' a character representation of the number in l with */
54: /* commas. */
55: /****************************************************************************/
56: char *ultoac(ulong l, char *string)
57: {
58: char str[256];
59: signed char i,j,k;
60:
61: sprintf(str,"%lu",l);
62: i=strlen(str)-1;
63: j=i/3+1+i;
64: string[j--]=0;
65: for(k=1;i>-1;k++) {
66: string[j--]=str[i--];
67: if(j>0 && !(k%3))
68: string[j--]=',';
69: }
70: return(string);
71: }
72:
73: /****************************************************************************/
74: /* Returns an ASCII string for FidoNet address 'addr' */
75: /****************************************************************************/
76: char *faddrtoa(fidoaddr_t addr)
77: {
78: static char str[25];
79: char point[25];
80:
81: sprintf(str,"%hu:%hu/%hu",addr.zone,addr.net,addr.node);
82: if(addr.point) {
83: sprintf(point,".%u",addr.point);
84: strcat(str,point);
85: }
86: return(str);
87: }
88:
89: char* DLLCALL strip_ctrl(char *str)
90: {
91: char tmp[1024];
92: int i,j;
93:
94: for(i=j=0;str[i] && j<sizeof(tmp)-1;i++) {
95: if(str[i]==CTRL_A && str[i+1]!=0)
96: i++;
97: else if((uchar)str[i]>=' ')
98: tmp[j++]=str[i];
99: }
100: if(i!=j) {
101: tmp[j]=0;
102: strcpy(str,tmp);
103: }
104: return(str);
105: }
106:
107: char *usage="\nusage: chksmb [-opts] <filespec.SHD>\n"
108: "\n"
109: " opts:\n"
110: " b - beep on error\n"
111: " s - stop after errored message base\n"
112: " p - pause after errored messsage base\n"
113: " h - don't check hash file\n"
114: " a - don't check allocation files\n"
115: " t - don't check translation strings\n"
116: " e - display extended info on corrupted msgs\n";
117:
118: int main(int argc, char **argv)
119: {
120: char str[128],*p,*s,*beep="";
121: char* body;
122: char* tail;
123: int h,i,j,x,y,lzh,errors,errlast;
124: BOOL stop_on_error=FALSE,pause_on_error=FALSE,chkxlat=TRUE,chkalloc=TRUE,chkhash=TRUE
125: ,lzhmsg,extinfo=FALSE,msgerr;
126: ushort xlat;
127: ulong l,m,n,length,size,total=0,orphan,deleted,headers
128: ,*offset,*number,xlaterr
129: ,delidx
130: ,delhdrblocks,deldatblocks,hdrerr,lockerr,hdrnumerr,hdrlenerr
131: ,getbodyerr,gettailerr
132: ,hasherr
133: ,acthdrblocks,actdatblocks
134: ,dfieldlength,dfieldoffset
135: ,dupenum,dupenumhdr,dupeoff,attr,actalloc
136: ,datactalloc,misnumbered,timeerr,idxofferr,idxerr
137: ,subjcrc,fromcrc,tocrc
138: ,intransit,unvalidated
139: ,zeronum,idxzeronum,idxnumerr,packable=0L,totallzhsaved=0L
140: ,totalmsgs=0,totallzhmsgs=0,totaldelmsgs=0,totalmsgbytes=0L
141: ,lzhblocks,lzhsaved;
142: smb_t smb;
143: idxrec_t idx;
144: smbmsg_t msg;
145: hash_t** hashes;
146: char revision[16];
147:
148: sscanf("$Revision: 1.43 $", "%*s %s", revision);
149:
150: fprintf(stderr,"\nCHKSMB v2.20-%s (rev %s) SMBLIB %s - Check Synchronet Message Base\n"
151: ,PLATFORM_DESC,revision,smb_lib_ver());
152:
153: if(argc<2) {
154: printf("%s",usage);
155: exit(1);
156: }
157:
158: errlast=errors=0;
159: for(x=1;x<argc;x++) {
160: if(stop_on_error && errors)
161: break;
162: if(pause_on_error && errlast!=errors) {
163: fprintf(stderr,"\7\nHit any key to continue...");
164: if(!getch())
165: getch();
166: printf("\n");
167: }
168: errlast=errors;
169: if(argv[x][0]=='-'
170: #if !defined(__unix__) /* just for backwards compatibility */
171: || argv[x][0]=='/'
172: #endif
173: ) {
174: for(y=1;argv[x][y];y++)
175: switch(toupper(argv[x][y])) {
176: case 'Q':
177: beep="";
178: break;
179: case 'B':
180: beep="\a";
181: break;
182: case 'P':
183: pause_on_error=TRUE;
184: break;
185: case 'S':
186: stop_on_error=TRUE;
187: break;
188: case 'T':
189: chkxlat=FALSE;
190: break;
191: case 'A':
192: chkalloc=FALSE;
193: break;
194: case 'H':
195: chkhash=FALSE;
196: break;
197: case 'E':
198: extinfo=TRUE;
199: break;
200: default:
201: printf("%s",usage);
202: exit(1);
203: }
204: continue;
205: }
206:
207: SAFECOPY(smb.file,argv[x]);
208: p=strrchr(smb.file,'.');
209: s=strrchr(smb.file,'\\');
210: if(p>s) *p=0;
211:
212: sprintf(str,"%s.shd",smb.file);
213: if(!fexist(str)) {
214: printf("\n%s doesn't exist.\n",smb.file);
215: continue;
216: }
217:
218: fprintf(stderr,"\nChecking %s Headers\n\n",smb.file);
219:
220: smb.retry_time=30;
221: if((i=smb_open(&smb))!=0) {
222: printf("smb_open returned %d: %s\n",i,smb.last_error);
223: errors++;
224: continue;
225: }
226:
227: length=filelength(fileno(smb.shd_fp));
228: if(length<sizeof(smbhdr_t)) {
229: printf("Empty\n");
230: smb_close(&smb);
231: continue;
232: }
233:
234: if((i=smb_locksmbhdr(&smb))!=0) {
235: smb_close(&smb);
236: printf("smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
237: errors++;
238: continue;
239: }
240:
241: if((length/SHD_BLOCK_LEN)*sizeof(ulong)) {
242: if((number=(ulong *)malloc(((length/SHD_BLOCK_LEN)+2)*sizeof(ulong)))
243: ==NULL) {
244: printf("Error allocating %lu bytes of memory\n"
245: ,(length/SHD_BLOCK_LEN)*sizeof(ulong));
246: return(++errors);
247: }
248: }
249: else
250: number=NULL;
251:
252: if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
253: if((i=smb_open_ha(&smb))!=0) {
254: printf("smb_open_ha returned %d: %s\n",i,smb.last_error);
255: return(++errors);
256: }
257:
258: if((i=smb_open_da(&smb))!=0) {
259: printf("smb_open_da returned %d: %s\n",i,smb.last_error);
260: return(++errors);
261: }
262: }
263:
264: headers=deleted=orphan=dupenumhdr=attr=zeronum=timeerr=lockerr=hdrerr=0;
265: subjcrc=fromcrc=tocrc=0;
266: hdrnumerr=hdrlenerr=0;
267: actalloc=datactalloc=deldatblocks=delhdrblocks=xlaterr=0;
268: lzhblocks=lzhsaved=acthdrblocks=actdatblocks=0;
269: getbodyerr=gettailerr=0;
270: hasherr=0;
271: unvalidated=0;
272: intransit=0;
273: acthdrblocks=actdatblocks=0;
274: dfieldlength=dfieldoffset=0;
275:
276: for(l=smb.status.header_offset;l<length;l+=size) {
277: size=SHD_BLOCK_LEN;
278: fprintf(stderr,"\r%2lu%% ",(long)(100.0/((float)length/l)));
279: memset(&msg,0,sizeof(msg));
280: msg.idx.offset=l;
281: msgerr=FALSE;
282: if((i=smb_lockmsghdr(&smb,&msg))!=0) {
283: printf("\n(%06lX) smb_lockmsghdr returned %d: %s\n",l,i,smb.last_error);
284: lockerr++;
285: headers++;
286: continue;
287: }
288: if((i=smb_getmsghdr(&smb,&msg))!=0) {
289: smb_unlockmsghdr(&smb,&msg);
290: if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
291: fseek(smb.sha_fp
292: ,(l-smb.status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
293: j=fgetc(smb.sha_fp);
294: if(j) { /* Allocated block or at EOF */
295: printf("%s\n(%06lX) smb_getmsghdr returned %d: %s\n",beep,l,i,smb.last_error);
296: hdrerr++;
297: }
298: else
299: delhdrblocks++;
300: }
301: else {
302: /* printf("%s\n(%06lX) smb_getmsghdr returned %d\n",beep,l,i); */
303: delhdrblocks++;
304: }
305: continue;
306: }
307: smb_unlockmsghdr(&smb,&msg);
308: size=smb_hdrblocks(smb_getmsghdrlen(&msg))*SHD_BLOCK_LEN;
309:
310: truncsp(msg.from);
311: strip_ctrl(msg.from);
312: fprintf(stderr,"#%-5lu (%06lX) %-25.25s ",msg.hdr.number,l,msg.from);
313:
314: if(msg.hdr.length!=smb_getmsghdrlen(&msg)) {
315: fprintf(stderr,"%sHeader length mismatch\n",beep);
316: msgerr=TRUE;
317: if(extinfo)
318: printf("MSGERR: Header length (%hu) does not match calculcated length (%lu)\n"
319: ,msg.hdr.length,smb_getmsghdrlen(&msg));
320: hdrlenerr++;
321: }
322:
323: /* Test reading of the message text (body and tails) */
324: if(msg.hdr.attr&MSG_DELETE)
325: body=tail=NULL;
326: else {
327: if((body=smb_getmsgtxt(&smb,&msg,GETMSGTXT_BODY_ONLY))==NULL) {
328: fprintf(stderr,"%sGet text body failure\n",beep);
329: msgerr=TRUE;
330: if(extinfo)
331: printf("MSGERR: %s\n", smb.last_error);
332: getbodyerr++;
333: }
334: if((tail=smb_getmsgtxt(&smb,&msg,GETMSGTXT_TAIL_ONLY))==NULL) {
335: fprintf(stderr,"%sGet text tail failure\n",beep);
336: msgerr=TRUE;
337: if(extinfo)
338: printf("MSGERR: %s\n", smb.last_error);
339: gettailerr++;
340: }
341: }
342:
343: if(!(smb.status.attr&SMB_EMAIL) && chkhash) {
344: /* Look-up the message hashes */
345: hashes=smb_msghashes(&msg,body);
346: if(hashes!=NULL
347: && hashes[0]!=NULL
348: && (i=smb_findhash(&smb,hashes,NULL,SMB_HASH_SOURCE_ALL,/* mark */TRUE ))
349: !=SMB_SUCCESS) {
350: for(h=0;hashes[h]!=NULL;h++) {
351: if(hashes[h]->flags&SMB_HASH_MARKED)
352: continue;
353: fprintf(stderr,"%sFailed to find %s hash\n"
354: ,beep,smb_hashsourcetype(hashes[h]->source));
355: msgerr=TRUE;
356: if(extinfo) {
357: printf("MSGERR: %d searching for %s: %s\n"
358: ,i
359: ,smb_hashsourcetype(hashes[h]->source)
360: ,smb_hashsource(&msg,hashes[h]->source));
361: #ifdef _DEBUG
362: printf("\n");
363: printf("%-10s: %s\n", "Source", smb_hashsourcetype(hashes[h]->source));
364: printf("%-10s: %lu\n", "Length", hashes[h]->length);
365: printf("%-10s: %x\n", "Flags", hashes[h]->flags);
366: if(hashes[h]->flags&SMB_HASH_CRC16)
367: printf("%-10s: %04x\n", "CRC-16", hashes[h]->crc16);
368: if(hashes[h]->flags&SMB_HASH_CRC32)
369: printf("%-10s: %08lx\n","CRC-32", hashes[h]->crc32);
370: if(hashes[h]->flags&SMB_HASH_MD5)
371: printf("%-10s: %s\n", "MD5", MD5_hex(str,hashes[h]->md5));
372:
373: #endif
374: }
375: hasherr++;
376: }
377: }
378:
379: smb_close_hash(&smb); /* just incase */
380:
381: FREE_LIST(hashes,i);
382: }
383: FREE_AND_NULL(body);
384: FREE_AND_NULL(tail);
385:
386: lzhmsg=FALSE;
387: if(msg.hdr.attr&MSG_DELETE) {
388: deleted++;
389: if(number)
390: number[headers]=0;
391: if(smb.status.attr&SMB_HYPERALLOC)
392: deldatblocks+=smb_datblocks(smb_getmsgdatlen(&msg));
393: }
394: else {
395: actdatblocks+=smb_datblocks(smb_getmsgdatlen(&msg));
396: if(msg.hdr.number>smb.status.last_msg) {
397: fprintf(stderr,"%sOut-Of-Range message number\n",beep);
398: msgerr=TRUE;
399: if(extinfo)
400: printf("MSGERR: Header number (%lu) greater than last (%lu)\n"
401: ,msg.hdr.number,smb.status.last_msg);
402: hdrnumerr++;
403: }
404: if(smb_getmsgidx(&smb,&msg)) {
405: fprintf(stderr,"%sNot found in index\n",beep);
406: msgerr=TRUE;
407: if(extinfo)
408: printf("MSGERR: Header number (%lu) not found in index\n"
409: ,msg.hdr.number);
410: orphan++;
411: }
412: else {
413: if(msg.hdr.attr!=msg.idx.attr) {
414: fprintf(stderr,"%sAttributes mismatch\n",beep);
415: msgerr=TRUE;
416: if(extinfo)
417: printf("MSGERR: Header attributes (%04X) do not match index "
418: "attributes (%04X)\n"
419: ,msg.hdr.attr,msg.idx.attr);
420: attr++;
421: }
422: if(msg.hdr.when_imported.time!=msg.idx.time) {
423: fprintf(stderr,"%sImport date/time mismatch\n",beep);
424: msgerr=TRUE;
425: if(extinfo)
426: printf("MSGERR: Header import date/time does not match "
427: "index import date/time\n");
428: timeerr++;
429: }
430: if(msg.idx.subj!=smb_subject_crc(msg.subj)) {
431: fprintf(stderr,"%sSubject CRC mismatch\n",beep);
432: msgerr=TRUE;
433: if(extinfo)
434: printf("MSGERR: Subject (%04X) does not match index "
435: "CRC (%04X)\n"
436: ,smb_subject_crc(msg.subj),msg.idx.subj);
437: subjcrc++;
438: }
439: if(smb.status.attr&SMB_EMAIL
440: && (msg.from_ext!=NULL || msg.idx.from)
441: && (msg.from_ext==NULL || msg.idx.from!=atoi(msg.from_ext))) {
442: fprintf(stderr,"%sFrom extension mismatch\n",beep);
443: msgerr=TRUE;
444: if(extinfo)
445: printf("MSGERR: From extension (%s) does not match index "
446: "(%u)\n"
447: ,msg.from_ext,msg.idx.from);
448: fromcrc++;
449: }
450: if(!(smb.status.attr&SMB_EMAIL)
451: && msg.idx.from!=smb_name_crc(msg.from)) {
452: fprintf(stderr,"%sFrom CRC mismatch\n",beep);
453: msgerr=TRUE;
454: if(extinfo)
455: printf("MSGERR: From (%04X) does not match index "
456: "CRC (%04X)\n"
457: ,smb_name_crc(msg.from),msg.idx.from);
458: fromcrc++;
459: }
460: if(smb.status.attr&SMB_EMAIL
461: && (msg.to_ext!=NULL || msg.idx.to)
462: && (msg.to_ext==NULL || msg.idx.to!=atoi(msg.to_ext))) {
463: fprintf(stderr,"%sTo extension mismatch\n",beep);
464: msgerr=TRUE;
465: if(extinfo)
466: printf("MSGERR: To extension (%s) does not match index "
467: "(%u)\n"
468: ,msg.to_ext,msg.idx.to);
469: tocrc++;
470: }
471: if(!(smb.status.attr&SMB_EMAIL)
472: && msg.to_ext==NULL && msg.idx.to!=smb_name_crc(msg.to)) {
473: fprintf(stderr,"%sTo CRC mismatch\n",beep);
474: msgerr=TRUE;
475: if(extinfo)
476: printf("MSGERR: To (%04X) does not match index "
477: "CRC (%04X)\n"
478: ,smb_name_crc(msg.to),msg.idx.to);
479: tocrc++;
480: }
481: if(msg.hdr.netattr&MSG_INTRANSIT) {
482: fprintf(stderr,"%sIn transit\n",beep);
483: msgerr=TRUE;
484: if(extinfo)
485: printf("MSGERR: Flagged 'in transit'\n");
486: intransit++;
487: }
488: if((msg.hdr.attr&(MSG_MODERATED|MSG_VALIDATED)) == MSG_MODERATED) {
489: fprintf(stderr,"%sUnvalidated\n",beep);
490: msgerr=TRUE;
491: if(extinfo)
492: printf("MSGERR: Flagged 'moderated', but not yet 'validated'\n");
493: unvalidated++;
494: }
495: }
496: if(msg.hdr.number==0) {
497: fprintf(stderr,"%sZero message number\n",beep);
498: msgerr=TRUE;
499: if(extinfo)
500: printf("MSGERR: Header number is zero (invalid)\n");
501: zeronum++;
502: }
503: if(number) {
504: for(m=0;m<headers;m++)
505: if(number[m] && msg.hdr.number==number[m]) {
506: fprintf(stderr,"%sDuplicate message number\n",beep);
507: msgerr=TRUE;
508: if(extinfo)
509: printf("MSGERR: Header number (%lu) duplicated\n"
510: ,msg.hdr.number);
511: dupenumhdr++;
512: break;
513: }
514: number[headers]=msg.hdr.number;
515: }
516: if(chkxlat) { /* Check translation strings */
517: for(i=0;i<msg.hdr.total_dfields;i++) {
518: fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset,SEEK_SET);
519: if(!fread(&xlat,2,1,smb.sdt_fp))
520: xlat=0xffff;
521: lzh=0;
522: if(xlat==XLAT_LZH) {
523: lzh=1;
524: if(!fread(&xlat,2,1,smb.sdt_fp))
525: xlat=0xffff;
526: }
527: if(xlat!=XLAT_NONE) {
528: fprintf(stderr,"%sUnsupported Xlat %04X dfield[%u]\n"
529: ,beep,xlat,i);
530: msgerr=TRUE;
531: if(extinfo)
532: printf("MSGERR: Unsupported translation type (%04X) "
533: "in dfield[%u] (offset %ld)\n"
534: ,xlat,i,msg.dfield[i].offset);
535: xlaterr++;
536: }
537: else {
538: if(lzh) {
539: lzhmsg=TRUE;
540: if(fread(&m,4,1,smb.sdt_fp)) { /* Get uncompressed len */
541: lzhsaved+=(smb_datblocks(m+2)
542: -smb_datblocks(msg.dfield[i].length))
543: *SDT_BLOCK_LEN;
544: lzhblocks+=smb_datblocks(msg.dfield[i].length);
545: }
546: }
547: }
548: }
549: }
550: }
551:
552: if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
553: fseek(smb.sha_fp,(l-smb.status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
554: for(m=0;m<size;m+=SHD_BLOCK_LEN) {
555: /***
556: if(msg.hdr.attr&MSG_DELETE && (i=fgetc(smb.sha_fp))!=0) {
557: fprintf(stderr,"%sDeleted Header Block %lu marked %02X\n"
558: ,beep,m/SHD_BLOCK_LEN,i);
559: msgerr=TRUE;
560: delalloc++;
561: }
562: ***/
563: if(!(msg.hdr.attr&MSG_DELETE) && (i=fgetc(smb.sha_fp))!=1) {
564: fprintf(stderr,"%sActive Header Block %lu marked %02X\n"
565: ,beep,m/SHD_BLOCK_LEN,i);
566: msgerr=TRUE;
567: if(extinfo)
568: printf("MSGERR: Active header block %lu marked %02X "
569: "instead of 01\n"
570: ,m/SHD_BLOCK_LEN,i);
571: actalloc++;
572: }
573: }
574:
575: if(!(msg.hdr.attr&MSG_DELETE)) {
576: acthdrblocks+=(size/SHD_BLOCK_LEN);
577: for(n=0;n<msg.hdr.total_dfields;n++) {
578: if(msg.dfield[n].offset&0x80000000UL) {
579: msgerr=TRUE;
580: if(extinfo)
581: printf("MSGERR: Invalid Data Field [%lu] Offset: %lu\n"
582: ,n,msg.dfield[n].offset);
583: dfieldoffset++;
584: }
585: if(msg.dfield[n].length&0x80000000UL) {
586: msgerr=TRUE;
587: if(extinfo)
588: printf("MSGERR: Invalid Data Field [%lu] Length: %lu\n"
589: ,n,msg.dfield[n].length);
590: dfieldlength++;
591: }
592: fseek(smb.sda_fp
593: ,((msg.hdr.offset+msg.dfield[n].offset)/SDT_BLOCK_LEN)*2
594: ,SEEK_SET);
595: for(m=0;m<msg.dfield[n].length;m+=SDT_BLOCK_LEN) {
596: if(!fread(&i,2,1,smb.sda_fp) || !i) {
597: fprintf(stderr
598: ,"%sActive Data Block %lu.%lu marked free\n"
599: ,beep,n,m/SHD_BLOCK_LEN);
600: msgerr=TRUE;
601: if(extinfo)
602: printf("MSGERR: Active Data Block %lu.%lu "
603: "marked free\n"
604: ,n,m/SHD_BLOCK_LEN);
605: datactalloc++;
606: }
607: }
608: }
609: }
610: else
611: delhdrblocks+=(size/SHD_BLOCK_LEN);
612: }
613:
614: else { /* Hyper Alloc */
615: if(msg.hdr.attr&MSG_DELETE)
616: delhdrblocks+=(size/SHD_BLOCK_LEN);
617: else
618: acthdrblocks+=(size/SHD_BLOCK_LEN);
619: }
620:
621: totallzhmsgs+=lzhmsg;
622: headers++;
623: if(msgerr && extinfo) {
624: printf("\n");
625: printf("%-20s %s\n","message base",smb.file);
626: smb_dump_msghdr(stdout,&msg);
627: printf("\n");
628: }
629:
630: smb_freemsgmem(&msg);
631: }
632:
633: FREE_AND_NULL(number);
634:
635: fprintf(stderr,"\r%79s\r100%%\n","");
636:
637: if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
638:
639: fprintf(stderr,"\nChecking %s Data Blocks\n\n",smb.file);
640:
641: length=filelength(fileno(smb.sda_fp));
642:
643: fseek(smb.sda_fp,0L,SEEK_SET);
644: for(l=0;l<length;l+=2) {
645: if((l%10)==0)
646: fprintf(stderr,"\r%2lu%% ",l ? (long)(100.0/((float)length/l)) : 0);
647: i=0;
648: if(!fread(&i,2,1,smb.sda_fp))
649: break;
650: if(!i)
651: deldatblocks++;
652: }
653:
654: smb_close_ha(&smb);
655: smb_close_da(&smb);
656:
657: fprintf(stderr,"\r%79s\r100%%\n","");
658: }
659:
660: total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
661:
662: dupenum=dupeoff=misnumbered=idxzeronum=idxnumerr=idxofferr=idxerr=delidx=0;
663:
664: if(total) {
665:
666: fprintf(stderr,"\nChecking %s Index\n\n",smb.file);
667:
668: if((offset=(ulong *)malloc(total*sizeof(ulong)))==NULL) {
669: printf("Error allocating %lu bytes of memory\n",total*sizeof(ulong));
670: return(++errors);
671: }
672: if((number=(ulong *)malloc(total*sizeof(ulong)))==NULL) {
673: printf("Error allocating %lu bytes of memory\n",total*sizeof(ulong));
674: return(++errors);
675: }
676: fseek(smb.sid_fp,0L,SEEK_SET);
677:
678: for(l=0;l<total;l++) {
679: fprintf(stderr,"\r%2lu%% %5lu ",l ? (long)(100.0/((float)total/l)) : 0,l);
680: if(!fread(&idx,sizeof(idxrec_t),1,smb.sid_fp))
681: break;
682: fprintf(stderr,"#%-5lu (%06lX) 1st Pass ",idx.number,idx.offset);
683: if(idx.attr&MSG_DELETE) {
684: /* Message Disabled... why? ToDo */
685: /* fprintf(stderr,"%sMarked for deletion\n",beep); */
686: delidx++;
687: }
688: for(m=0;m<l;m++)
689: if(number[m]==idx.number) {
690: fprintf(stderr,"%sDuplicate message number\n",beep);
691: dupenum++;
692: break;
693: }
694: for(m=0;m<l;m++)
695: if(offset[m]==idx.offset) {
696: fprintf(stderr,"%sDuplicate offset: %lu\n",beep,idx.offset);
697: dupeoff++;
698: break;
699: }
700: if(idx.offset<smb.status.header_offset) {
701: fprintf(stderr,"%sInvalid offset\n",beep);
702: idxofferr++;
703: break;
704: }
705: if(idx.number==0) {
706: fprintf(stderr,"%sZero message number\n",beep);
707: idxzeronum++;
708: break;
709: }
710: if(idx.number>smb.status.last_msg) {
711: fprintf(stderr,"%sOut-Of-Range message number\n",beep);
712: idxnumerr++;
713: break;
714: }
715: number[l]=idx.number;
716: offset[l]=idx.offset;
717: }
718:
719: if(l<total) {
720: fprintf(stderr,"%sError reading index record\n",beep);
721: idxerr=1;
722: }
723: else {
724: fprintf(stderr,"\r%79s\r","");
725: for(m=0;m<total;m++) {
726: fprintf(stderr,"\r%2lu%% %5lu ",m ? (long)(100.0/((float)total/m)) : 0,m);
727: fprintf(stderr,"#%-5lu (%06lX) 2nd Pass ",number[m],offset[m]);
728: for(n=0;n<m;n++)
729: if(number[m] && number[n] && number[m]<number[n]) {
730: fprintf(stderr,"%sMisordered message number\n",beep);
731: misnumbered++;
732: number[n]=0;
733: break;
734: }
735: }
736: fprintf(stderr,"\r%79s\r100%%\n","");
737: }
738: FREE_AND_NULL(number);
739: FREE_AND_NULL(offset);
740:
741: } /* if(total) */
742:
743: totalmsgs+=smb.status.total_msgs;
744: totalmsgbytes+=(acthdrblocks*SHD_BLOCK_LEN)+(actdatblocks*SDT_BLOCK_LEN);
745: totaldelmsgs+=deleted;
746: totallzhsaved+=lzhsaved;
747: printf("\n");
748: printf("%-35.35s (=): %lu\n"
749: ,"Status Total"
750: ,smb.status.total_msgs);
751: printf("%-35.35s (=): %lu\n"
752: ,"Total Indexes"
753: ,total);
754: printf("%-35.35s (=): %lu\n"
755: ,"Active Indexes"
756: ,total-delidx);
757: printf("%-35.35s (=): %lu\n"
758: ,"Active Headers"
759: ,headers-deleted);
760: printf("%-35.35s ( ): %-8lu %13s bytes used\n"
761: ,"Active Header Blocks"
762: ,acthdrblocks,ultoac(acthdrblocks*SHD_BLOCK_LEN,str));
763: printf("%-35.35s ( ): %-8lu %13s bytes used\n"
764: ,"Active Data Blocks"
765: ,actdatblocks,ultoac(actdatblocks*SDT_BLOCK_LEN,str));
766: if(lzhblocks)
767: printf("%-35.35s ( ): %-8lu %13s bytes saved\n"
768: ,"Active LZH Compressed Data Blocks"
769: ,lzhblocks,ultoac(lzhsaved,str));
770: printf("%-35.35s ( ): %lu\n"
771: ,"Header Records"
772: ,headers);
773: printf("%-35.35s ( ): %lu\n"
774: ,"Deleted Indexes"
775: ,delidx);
776: printf("%-35.35s ( ): %lu\n"
777: ,"Deleted Headers"
778: ,deleted);
779: printf("%-35.35s ( ): %-8lu %13s bytes used\n"
780: ,"Deleted Header Blocks"
781: ,delhdrblocks,ultoac(delhdrblocks*SHD_BLOCK_LEN,str));
782: packable+=(delhdrblocks*SHD_BLOCK_LEN);
783: printf("%-35.35s ( ): %-8lu %13s bytes used\n"
784: ,"Deleted Data Blocks"
785: ,deldatblocks,ultoac(deldatblocks*SDT_BLOCK_LEN,str));
786: packable+=(deldatblocks*SDT_BLOCK_LEN);
787:
788: if(orphan)
789: printf("%-35.35s (!): %lu\n"
790: ,"Orphaned Headers"
791: ,orphan);
792: if(idxzeronum)
793: printf("%-35.35s (!): %lu\n"
794: ,"Zeroed Index Numbers"
795: ,idxzeronum);
796: if(zeronum)
797: printf("%-35.35s (!): %lu\n"
798: ,"Zeroed Header Numbers"
799: ,zeronum);
800: if(idxofferr)
801: printf("%-35.35s (!): %lu\n"
802: ,"Invalid Index Offsets"
803: ,idxofferr);
804: if(dupenum)
805: printf("%-35.35s (!): %lu\n"
806: ,"Duplicate Index Numbers"
807: ,dupenum);
808: if(dupeoff)
809: printf("%-35.35s (!): %lu\n"
810: ,"Duplicate Index Offsets"
811: ,dupeoff);
812: if(dupenumhdr)
813: printf("%-35.35s (!): %lu\n"
814: ,"Duplicate Header Numbers"
815: ,dupenumhdr);
816: if(misnumbered)
817: printf("%-35.35s (!): %lu\n"
818: ,"Misordered Index Numbers"
819: ,misnumbered);
820: if(lockerr)
821: printf("%-35.35s (!): %lu\n"
822: ,"Unlockable Header Records"
823: ,lockerr);
824: if(hdrerr)
825: printf("%-35.35s (!): %lu\n"
826: ,"Unreadable Header Records"
827: ,hdrerr);
828: if(idxnumerr)
829: printf("%-35.35s (!): %lu\n"
830: ,"Out-Of-Range Index Numbers"
831: ,idxnumerr);
832: if(hdrnumerr)
833: printf("%-35.35s (!): %lu\n"
834: ,"Out-Of-Range Header Numbers"
835: ,hdrnumerr);
836: if(hdrlenerr)
837: printf("%-35.35s (!): %lu\n"
838: ,"Mismatched Header Lengths"
839: ,hdrlenerr);
840: #define INDXERR "Index/Header Mismatch: "
841: if(attr)
842: printf("%-35.35s (!): %lu\n"
843: ,INDXERR "Attributes"
844: ,attr);
845: if(timeerr)
846: printf("%-35.35s (!): %lu\n"
847: ,INDXERR "Import Time"
848: ,timeerr);
849: if(subjcrc)
850: printf("%-35.35s (!): %lu\n"
851: ,INDXERR "Subject CRCs"
852: ,subjcrc);
853: if(fromcrc)
854: printf("%-35.35s (!): %lu\n"
855: ,smb.status.attr&SMB_EMAIL ? INDXERR "From Ext" : INDXERR "From CRCs"
856: ,fromcrc);
857: if(tocrc)
858: printf("%-35.35s (!): %lu\n"
859: ,smb.status.attr&SMB_EMAIL ? INDXERR "To Ext" : INDXERR "To CRCs"
860: ,tocrc);
861: if(intransit)
862: printf("%-35.35s (?): %lu\n"
863: ,"Message flagged as 'In Transit'"
864: ,intransit);
865: if(unvalidated)
866: printf("%-35.35s (?): %lu\n"
867: ,"Moderated message not yet validated"
868: ,unvalidated);
869: if(getbodyerr)
870: printf("%-35.35s (!): %lu\n"
871: ,"Message Body Text Read Failures"
872: ,getbodyerr);
873: if(gettailerr)
874: printf("%-35.35s (!): %lu\n"
875: ,"Message Tail Text Read Failures"
876: ,gettailerr);
877: if(xlaterr)
878: printf("%-35.35s (!): %lu\n"
879: ,"Unsupported Translation Types"
880: ,xlaterr);
881: if(hasherr)
882: printf("%-35.35s (!): %lu\n"
883: ,"Missing Hash Records"
884: ,hasherr);
885: if(datactalloc)
886: printf("%-35.35s (!): %lu\n"
887: ,"Misallocated Active Data Blocks"
888: ,datactalloc);
889: if(actalloc)
890: printf("%-35.35s (!): %lu\n"
891: ,"Misallocated Active Header Blocks"
892: ,actalloc);
893: /***
894: if(delalloc)
895: printf("%-35.35s (!): %lu\n"
896: ,"Misallocated Deleted Header Blocks"
897: ,delalloc);
898: ***/
899:
900: if(dfieldoffset)
901: printf("%-35.35s (!): %lu\n"
902: ,"Invalid Data Field Offsets"
903: ,dfieldoffset);
904:
905: if(dfieldlength)
906: printf("%-35.35s (!): %lu\n"
907: ,"Invalid Data Field Lengths"
908: ,dfieldlength);
909:
910:
911: printf("\n%s Message Base ",smb.file);
912: if(/* (headers-deleted)!=smb.status.total_msgs || */
913: total!=smb.status.total_msgs
914: || (headers-deleted)!=total-delidx
915: || idxzeronum || zeronum
916: || hdrlenerr || hasherr
917: || getbodyerr || gettailerr
918: || orphan || dupenumhdr || dupenum || dupeoff || attr
919: || lockerr || hdrerr || hdrnumerr || idxnumerr || idxofferr
920: || actalloc || datactalloc || misnumbered || timeerr
921: || intransit || unvalidated
922: || subjcrc || fromcrc || tocrc
923: || dfieldoffset || dfieldlength || xlaterr || idxerr) {
924: printf("%shas Errors!\n",beep);
925: errors++;
926: }
927: else
928: printf("is OK\n");
929:
930: smb_unlocksmbhdr(&smb);
931: smb_close(&smb);
932: }
933:
934: if((totalmsgs && (totalmsgs!=smb.status.total_msgs || totallzhmsgs))
935: || packable)
936: printf("\n");
937: if(totalmsgs && totalmsgs!=smb.status.total_msgs)
938: printf("%-39.39s: %-8lu %13s bytes used\n"
939: ,"Total Active Messages"
940: ,totalmsgs,ultoac(totalmsgbytes,str));
941: if(totallzhmsgs && totalmsgs!=smb.status.total_msgs)
942: printf("%-39.39s: %-8lu %13s bytes saved\n"
943: ,"Total LZH Compressed Messages"
944: ,totallzhmsgs,ultoac(totallzhsaved,str));
945: if(packable)
946: printf("%-39.39s: %-8lu %13s bytes used\n"
947: ,"Total Deleted Messages"
948: ,totaldelmsgs,ultoac(packable,str));
949:
950: if(pause_on_error && errlast!=errors) {
951: fprintf(stderr,"\7\nHit any key to continue...");
952: if(!getch())
953: getch();
954: fprintf(stderr,"\n");
955: }
956:
957: if(errors)
958: printf("\n'fixsmb' can be used to repair most message base problems.\n");
959:
960: return(errors);
961: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.