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