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