Newer
Older
/* chksmb.c */
/* Synchronet message base (SMB) validity checker */
/* $Id$ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/

rswindell
committed
#include <string.h> /* strrchr */
#include <time.h> /* ctime */

rswindell
committed
#include "conwrap.h" /* getch */
#include "dirwrap.h" /* fexist */
#include "filewrap.h" /* filelength */
#include "smblib.h"
/****************************************************************************/
/* Returns in 'string' a character representation of the number in l with */
/* commas. */
/****************************************************************************/
char *ultoac(ulong l, char *string)
{
char str[256];
signed char i,j,k;
i=strlen(str)-1;
j=i/3+1+i;
string[j--]=0;
for(k=1;i>-1;k++) {
string[j--]=str[i--];
if(j>0 && !(k%3))
}
/****************************************************************************/
/* Returns an ASCII string for FidoNet address 'addr' */
/****************************************************************************/
char *faddrtoa(fidoaddr_t addr)
{
static char str[25];
char point[25];
sprintf(str,"%hu:%hu/%hu",addr.zone,addr.net,addr.node);
if(addr.point) {
sprintf(point,".%u",addr.point);
char* DLLCALL strip_ctrl(char *str)
{
char tmp[1024];
int i,j;
if(str[i]==CTRL_A && str[i+1]!=0)
i++;
else if((uchar)str[i]>=' ')
}
if(i!=j) {
tmp[j]=0;
strcpy(str,tmp);
}
return(str);
}
char *usage="\nusage: chksmb [-opts] <filespec.SHD>\n"
" b - beep on error\n"
" s - stop after errored message base\n"
" p - pause after errored messsage base\n"
" a - don't check allocation files\n"
" t - don't check translation strings\n"
" e - display extended info on corrupted msgs\n";
int main(int argc, char **argv)
{
char str[128],*p,*s,*beep="";
char* body;
char* tail;
int h,i,j,x,y,lzh,errors,errlast;
BOOL stop_on_error=FALSE,pause_on_error=FALSE,chkxlat=TRUE,chkalloc=TRUE,chkhash=TRUE
,lzhmsg,extinfo=FALSE,msgerr;
ulong l,m,n,length,size,total=0,orphan,deleted,headers
,*offset,*number,xlaterr
,delidx
,delhdrblocks,deldatblocks,hdrerr,lockerr,hdrnumerr,hdrlenerr
,getbodyerr,gettailerr
,hasherr
,dfieldlength,dfieldoffset
,dupenum,dupenumhdr,dupeoff,attr,actalloc
,datactalloc,misnumbered,timeerr,idxofferr,idxerr
,subjcrc,fromcrc,tocrc
,zeronum,idxzeronum,idxnumerr,packable=0L,totallzhsaved=0L
,totalmsgs=0,totallzhmsgs=0,totaldelmsgs=0,totalmsgbytes=0L
,lzhblocks,lzhsaved;
smb_t smb;
idxrec_t idx;
smbmsg_t msg;
hash_t** hashes;
fprintf(stderr,"\nCHKSMB v2.20 - Check Synchronet Message Base - "
"Copyright 2004 Rob Swindell\n");
if(argc<2) {
printf("%s",usage);
errlast=errors=0;
for(x=1;x<argc;x++) {
if(stop_on_error && errors)
break;
if(pause_on_error && errlast!=errors) {
fprintf(stderr,"\7\nHit any key to continue...");
if(!getch())
getch();
if(argv[x][0]=='-'
#if !defined(__unix__) /* just for backwards compatibility */
|| argv[x][0]=='/'
#endif
) {
for(y=1;argv[x][y];y++)
switch(toupper(argv[x][y])) {
case 'Q':
beep="";
break;
case 'B':
beep="\a";
break;
chkalloc=FALSE;
break;
case 'H':
chkhash=FALSE;
break;
default:
printf("%s",usage);
SAFECOPY(smb.file,argv[x]);
p=strrchr(smb.file,'.');
s=strrchr(smb.file,'\\');
if(p>s) *p=0;

rswindell
committed
sprintf(str,"%s.shd",smb.file);
if(!fexist(str)) {
printf("\n%s doesn't exist.\n",smb.file);
fprintf(stderr,"\nChecking %s Headers\n\n",smb.file);
smb.retry_time=30;
if((i=smb_open(&smb))!=0) {
printf("smb_open returned %d: %s\n",i,smb.last_error);
length=filelength(fileno(smb.shd_fp));
if(length<sizeof(smbhdr_t)) {
printf("Empty\n");
smb_close(&smb);
if((i=smb_locksmbhdr(&smb))!=0) {
smb_close(&smb);
printf("smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
if((length/SHD_BLOCK_LEN)*sizeof(ulong)) {
if((number=(ulong *)MALLOC(((length/SHD_BLOCK_LEN)+2)*sizeof(ulong)))
==NULL) {
printf("Error allocating %lu bytes of memory\n"
,(length/SHD_BLOCK_LEN)*sizeof(ulong));
if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
if((i=smb_open_ha(&smb))!=0) {
printf("smb_open_ha returned %d: %s\n",i,smb.last_error);
if((i=smb_open_da(&smb))!=0) {
printf("smb_open_da returned %d: %s\n",i,smb.last_error);
headers=deleted=orphan=dupenumhdr=attr=zeronum=timeerr=lockerr=hdrerr=0;
subjcrc=fromcrc=tocrc=0;
hdrnumerr=hdrlenerr=0;
actalloc=datactalloc=deldatblocks=delhdrblocks=xlaterr=0;
lzhblocks=lzhsaved=acthdrblocks=actdatblocks=0;
getbodyerr=gettailerr=0;
hasherr=0;
acthdrblocks=actdatblocks=0;
dfieldlength=dfieldoffset=0;
for(l=smb.status.header_offset;l<length;l+=size) {
fprintf(stderr,"\r%2lu%% ",(long)(100.0/((float)length/l)));
memset(&msg,0,sizeof(msg));
if((i=smb_lockmsghdr(&smb,&msg))!=0) {
printf("\n(%06lX) smb_lockmsghdr returned %d: %s\n",l,i,smb.last_error);
lockerr++;
headers++;
if((i=smb_getmsghdr(&smb,&msg))!=0) {
smb_unlockmsghdr(&smb,&msg);
if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
fseek(smb.sha_fp
,(l-smb.status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
j=fgetc(smb.sha_fp);
if(j) { /* Allocated block or at EOF */
printf("%s\n(%06lX) smb_getmsghdr returned %d: %s\n",beep,l,i,smb.last_error);
else {
/* printf("%s\n(%06lX) smb_getmsghdr returned %d\n",beep,l,i); */
smb_unlockmsghdr(&smb,&msg);
size=smb_hdrblocks(smb_getmsghdrlen(&msg))*SHD_BLOCK_LEN;
truncsp(msg.from);
strip_ctrl(msg.from);
fprintf(stderr,"#%-5lu (%06lX) %-25.25s ",msg.hdr.number,l,msg.from);
if(msg.hdr.length!=smb_getmsghdrlen(&msg)) {
fprintf(stderr,"%sHeader length mismatch\n",beep);
printf("MSGERR: Header length (%hu) does not match calculcated length (%lu)\n"
,msg.hdr.length,smb_getmsghdrlen(&msg));
hdrlenerr++;
}
/* Test reading of the message text (body and tails) */
if(msg.hdr.attr&MSG_DELETE)
body=tail=NULL;
else {
if((body=smb_getmsgtxt(&smb,&msg,GETMSGTXT_BODY_ONLY))==NULL) {
fprintf(stderr,"%sGet text body failure\n",beep);
if(extinfo)
printf("MSGERR: %s\n", smb.last_error);
getbodyerr++;
}
if((tail=smb_getmsgtxt(&smb,&msg,GETMSGTXT_TAIL_ONLY))==NULL) {
fprintf(stderr,"%sGet text tail failure\n",beep);
if(extinfo)
printf("MSGERR: %s\n", smb.last_error);
gettailerr++;
}
}
if(chkhash) {
/* Look-up the message hashes */
hashes=smb_msghashes(&msg,body);
if(hashes[0]!=NULL
&& (i=smb_findhash(&smb,hashes,NULL,SMB_HASH_SOURCE_ALL,/* mark */TRUE ))
!=SMB_SUCCESS) {
for(h=0;hashes[h]!=NULL;h++) {
if(hashes[h]->flags&SMB_HASH_MARKED)
continue;
fprintf(stderr,"%sFailed to find %s hash\n"
,beep,smb_hashsourcetype(hashes[h]->source));
msgerr=TRUE;
printf("MSGERR: %d searching for %s: %s\n"
,i
,smb_hashsourcetype(hashes[h]->source)
,smb_hashsource(&msg,hashes[h]->source));
#ifdef _DEBUG
printf("\n");
printf("%-10s: %s\n", "Source", smb_hashsourcetype(hashes[h]->source));
printf("%-10s: %lu\n", "Length", hashes[h]->length);
printf("%-10s: %x\n", "Flags", hashes[h]->flags);
if(hashes[h]->flags&SMB_HASH_CRC16)
printf("%-10s: %04x\n", "CRC-16", hashes[h]->crc16);
if(hashes[h]->flags&SMB_HASH_CRC32)
printf("%-10s: %08lx\n","CRC-32", hashes[h]->crc32);
if(hashes[h]->flags&SMB_HASH_MD5)
printf("%-10s: %s\n", "MD5", MD5_hex(str,hashes[h]->md5));
#endif
}
hasherr++;
}
}
smb_close_hash(&smb); /* just incase */
FREE_AND_NULL(body);
FREE_AND_NULL(tail);
if(msg.hdr.attr&MSG_DELETE) {
deleted++;
if(number)
number[headers]=0;
if(smb.status.attr&SMB_HYPERALLOC)
deldatblocks+=smb_datblocks(smb_getmsgdatlen(&msg));
}
actdatblocks+=smb_datblocks(smb_getmsgdatlen(&msg));
if(msg.hdr.number>smb.status.last_msg) {
fprintf(stderr,"%sOut-Of-Range message number\n",beep);
if(extinfo)
printf("MSGERR: Header number (%lu) greater than last (%lu)\n"
,msg.hdr.number,smb.status.last_msg);
if(smb_getmsgidx(&smb,&msg)) {
fprintf(stderr,"%sNot found in index\n",beep);
if(extinfo)
printf("MSGERR: Header number (%lu) not found in index\n"
,msg.hdr.number);
else if(msg.hdr.attr!=msg.idx.attr) {
fprintf(stderr,"%sAttributes mismatch index\n",beep);
if(extinfo)
printf("MSGERR: Header attributes (%04X) do not match index "
"attributes (%04X)\n"
,msg.hdr.attr,msg.idx.attr);
else if(msg.hdr.when_imported.time!=msg.idx.time) {
fprintf(stderr,"%sImport date/time mismatch index\n",beep);
printf("MSGERR: Header import date/time does not match "
"index import date/time\n");
else if(msg.idx.subj!=smb_subject_crc(msg.subj)) {
fprintf(stderr,"%sSubject CRC mismatch index\n",beep);
msgerr=TRUE;
if(extinfo)
printf("MSGERR: Subject (%04X) does not match index "
"CRC (%04X)\n"
,smb_subject_crc(msg.subj),msg.idx.subj);
subjcrc++;
}
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
else if(smb.status.attr&SMB_EMAIL
&& msg.from_ext && msg.idx.from!=atoi(msg.from_ext)) {
fprintf(stderr,"%sFrom extension mismatch index\n",beep);
msgerr=TRUE;
if(extinfo)
printf("MSGERR: From extension (%s) does not match index "
"(%u)\n"
,msg.from_ext,msg.idx.from);
fromcrc++;
}
else if(!(smb.status.attr&SMB_EMAIL)
&& msg.idx.from!=smb_name_crc(msg.from)) {
fprintf(stderr,"%sFrom CRC mismatch index\n",beep);
msgerr=TRUE;
if(extinfo)
printf("MSGERR: From (%04X) does not match index "
"CRC (%04X)\n"
,smb_name_crc(msg.from),msg.idx.from);
fromcrc++;
}
else if(smb.status.attr&SMB_EMAIL
&& msg.to_ext && msg.idx.from!=atoi(msg.to_ext)) {
fprintf(stderr,"%sTo extension mismatch index\n",beep);
msgerr=TRUE;
if(extinfo)
printf("MSGERR: To extension (%s) does not match index "
"(%u)\n"
,msg.to_ext,msg.idx.to);
tocrc++;
}
else if(!(smb.status.attr&SMB_EMAIL)
&& msg.to_ext==NULL && msg.idx.to!=smb_name_crc(msg.to)) {
fprintf(stderr,"%sTo CRC mismatch index\n",beep);
msgerr=TRUE;
if(extinfo)
printf("MSGERR: To (%04X) does not match index "
"CRC (%04X)\n"
,smb_name_crc(msg.to),msg.idx.to);
tocrc++;
}
if(msg.hdr.number==0) {
fprintf(stderr,"%sZero message number\n",beep);
if(extinfo)
printf("MSGERR: Header number is zero (invalid)\n");
if(number) {
for(m=0;m<headers;m++)
if(number[m] && msg.hdr.number==number[m]) {
fprintf(stderr,"%sDuplicate message number\n",beep);
if(extinfo)
printf("MSGERR: Header number (%lu) duplicated\n"
,msg.hdr.number);
dupenumhdr++;
if(chkxlat) { /* Check translation strings */
for(i=0;i<msg.hdr.total_dfields;i++) {
fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset,SEEK_SET);
if(!fread(&xlat,2,1,smb.sdt_fp))
xlat=0xffff;
lzh=0;
if(xlat==XLAT_LZH) {
lzh=1;
if(!fread(&xlat,2,1,smb.sdt_fp))
if(xlat!=XLAT_NONE) {
fprintf(stderr,"%sUnsupported Xlat %04X dfield[%u]\n"
,beep,xlat,i);
if(extinfo)
printf("MSGERR: Unsupported translation type (%04X) "
"in dfield[%u] (offset %ld)\n"
,xlat,i,msg.dfield[i].offset);
if(fread(&m,4,1,smb.sdt_fp)) { /* Get uncompressed len */
lzhsaved+=(smb_datblocks(m+2)
-smb_datblocks(msg.dfield[i].length))
*SDT_BLOCK_LEN;
lzhblocks+=smb_datblocks(msg.dfield[i].length);
if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
fseek(smb.sha_fp,(l-smb.status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
for(m=0;m<size;m+=SHD_BLOCK_LEN) {
/***
if(msg.hdr.attr&MSG_DELETE && (i=fgetc(smb.sha_fp))!=0) {
fprintf(stderr,"%sDeleted Header Block %lu marked %02X\n"
,beep,m/SHD_BLOCK_LEN,i);
***/
if(!(msg.hdr.attr&MSG_DELETE) && (i=fgetc(smb.sha_fp))!=1) {
fprintf(stderr,"%sActive Header Block %lu marked %02X\n"
,beep,m/SHD_BLOCK_LEN,i);
printf("MSGERR: Active header block %lu marked %02X "
"instead of 01\n"
,m/SHD_BLOCK_LEN,i);
if(!(msg.hdr.attr&MSG_DELETE)) {
acthdrblocks+=(size/SHD_BLOCK_LEN);
for(n=0;n<msg.hdr.total_dfields;n++) {
if(msg.dfield[n].offset&0x80000000UL) {
printf("MSGERR: Invalid Data Field [%lu] Offset: %lu\n"
,n,msg.dfield[n].offset);
if(msg.dfield[n].length&0x80000000UL) {
printf("MSGERR: Invalid Data Field [%lu] Length: %lu\n"
,n,msg.dfield[n].length);
fseek(smb.sda_fp
,((msg.hdr.offset+msg.dfield[n].offset)/SDT_BLOCK_LEN)*2
,SEEK_SET);
for(m=0;m<msg.dfield[n].length;m+=SDT_BLOCK_LEN) {
if(!fread(&i,2,1,smb.sda_fp) || !i) {
fprintf(stderr
,"%sActive Data Block %lu.%lu marked free\n"
,beep,n,m/SHD_BLOCK_LEN);
if(extinfo)
printf("MSGERR: Active Data Block %lu.%lu "
"marked free\n"
,n,m/SHD_BLOCK_LEN);
else { /* Hyper Alloc */
if(msg.hdr.attr&MSG_DELETE)
delhdrblocks+=(size/SHD_BLOCK_LEN);
else
totallzhmsgs+=lzhmsg;
headers++;
if(msgerr && extinfo) {
printf("\n");
printf("%-20s %s\n","message base",smb.file);
smb_dump_msghdr(stdout,&msg);
FREE_AND_NULL(number);
fprintf(stderr,"\r%79s\r100%%\n","");
if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
fprintf(stderr,"\nChecking %s Data Blocks\n\n",smb.file);
length=filelength(fileno(smb.sda_fp));
fseek(smb.sda_fp,0L,SEEK_SET);
for(l=0;l<length;l+=2) {
fprintf(stderr,"\r%2lu%% ",l ? (long)(100.0/((float)length/l)) : 0);
i=0;
if(!fread(&i,2,1,smb.sda_fp))
break;
if(!i)
smb_close_ha(&smb);
smb_close_da(&smb);
total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
dupenum=dupeoff=misnumbered=idxzeronum=idxnumerr=idxofferr=idxerr=delidx=0;
if(total) {
fprintf(stderr,"\nChecking %s Index\n\n",smb.file);
if((offset=(ulong *)MALLOC(total*sizeof(ulong)))==NULL) {
printf("Error allocating %lu bytes of memory\n",total*sizeof(ulong));
if((number=(ulong *)MALLOC(total*sizeof(ulong)))==NULL) {
printf("Error allocating %lu bytes of memory\n",total*sizeof(ulong));
fseek(smb.sid_fp,0L,SEEK_SET);
for(l=0;l<total;l++) {
fprintf(stderr,"\r%2lu%% %5lu ",l ? (long)(100.0/((float)total/l)) : 0,l);
if(!fread(&idx,sizeof(idxrec_t),1,smb.sid_fp))
fprintf(stderr,"#%-5lu (%06lX) 1st Pass ",idx.number,idx.offset);
if(idx.attr&MSG_DELETE) {
// fprintf(stderr,"%sMarked for deletion\n",beep);
for(m=0;m<l;m++)
if(number[m]==idx.number) {
fprintf(stderr,"%sDuplicate message number\n",beep);
dupenum++;
for(m=0;m<l;m++)
if(offset[m]==idx.offset) {
fprintf(stderr,"%sDuplicate offset: %lu\n",beep,idx.offset);
if(idx.offset<smb.status.header_offset) {
fprintf(stderr,"%sInvalid offset\n",beep);
idxofferr++;
if(idx.number==0) {
fprintf(stderr,"%sZero message number\n",beep);
idxzeronum++;
if(idx.number>smb.status.last_msg) {
fprintf(stderr,"%sOut-Of-Range message number\n",beep);
idxnumerr++;
if(l<total) {
fprintf(stderr,"%sError reading index record\n",beep);
else {
fprintf(stderr,"\r%79s\r","");
for(m=0;m<total;m++) {
fprintf(stderr,"\r%2lu%% %5lu ",m ? (long)(100.0/((float)total/m)) : 0,m);
fprintf(stderr,"#%-5lu (%06lX) 2nd Pass ",number[m],offset[m]);
for(n=0;n<m;n++)
if(number[m] && number[n] && number[m]<number[n]) {
fprintf(stderr,"%sMisordered message number\n",beep);
misnumbered++;
number[n]=0;
break;
}
}
fprintf(stderr,"\r%79s\r100%%\n","");
}
FREE_AND_NULL(number);
FREE_AND_NULL(offset);
} /* if(total) */
totalmsgs+=smb.status.total_msgs;
totalmsgbytes+=(acthdrblocks*SHD_BLOCK_LEN)+(actdatblocks*SDT_BLOCK_LEN);
totaldelmsgs+=deleted;
totallzhsaved+=lzhsaved;
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
printf("%-35.35s (=): %lu\n"
,"Status Total"
,smb.status.total_msgs);
printf("%-35.35s (=): %lu\n"
,"Total Indexes"
,total);
printf("%-35.35s (=): %lu\n"
,"Active Indexes"
,total-delidx);
printf("%-35.35s (=): %lu\n"
,"Active Headers"
,headers-deleted);
printf("%-35.35s ( ): %-8lu %13s bytes used\n"
,"Active Header Blocks"
,acthdrblocks,ultoac(acthdrblocks*SHD_BLOCK_LEN,str));
printf("%-35.35s ( ): %-8lu %13s bytes used\n"
,"Active Data Blocks"
,actdatblocks,ultoac(actdatblocks*SDT_BLOCK_LEN,str));
if(lzhblocks)
printf("%-35.35s ( ): %-8lu %13s bytes saved\n"
,"Active LZH Compressed Data Blocks"
,lzhblocks,ultoac(lzhsaved,str));
printf("%-35.35s ( ): %lu\n"
,"Header Records"
,headers);
printf("%-35.35s ( ): %lu\n"
,"Deleted Indexes"
,delidx);
printf("%-35.35s ( ): %lu\n"
,"Deleted Headers"
,deleted);
printf("%-35.35s ( ): %-8lu %13s bytes used\n"
,"Deleted Header Blocks"
,delhdrblocks,ultoac(delhdrblocks*SHD_BLOCK_LEN,str));
packable+=(delhdrblocks*SHD_BLOCK_LEN);
printf("%-35.35s ( ): %-8lu %13s bytes used\n"
,"Deleted Data Blocks"
,deldatblocks,ultoac(deldatblocks*SDT_BLOCK_LEN,str));
packable+=(deldatblocks*SDT_BLOCK_LEN);
if(orphan)
printf("%-35.35s (!): %lu\n"
,"Orphaned Headers"
,orphan);
if(idxzeronum)
printf("%-35.35s (!): %lu\n"
,"Zeroed Index Numbers"
,idxzeronum);
if(zeronum)
printf("%-35.35s (!): %lu\n"
,"Zeroed Header Numbers"
,zeronum);
if(idxofferr)
printf("%-35.35s (!): %lu\n"
,"Invalid Index Offsets"
,idxofferr);
if(dupenum)
printf("%-35.35s (!): %lu\n"
,"Duplicate Index Numbers"
,dupenum);
if(dupeoff)
printf("%-35.35s (!): %lu\n"
,"Duplicate Index Offsets"
,dupeoff);
if(dupenumhdr)
printf("%-35.35s (!): %lu\n"
,"Duplicate Header Numbers"
,dupenumhdr);
if(misnumbered)
printf("%-35.35s (!): %lu\n"
,"Misordered Index Numbers"
,misnumbered);
if(lockerr)
printf("%-35.35s (!): %lu\n"
,"Unlockable Header Records"
,lockerr);
if(hdrerr)
printf("%-35.35s (!): %lu\n"
,"Unreadable Header Records"
,hdrerr);
if(idxnumerr)
printf("%-35.35s (!): %lu\n"
,"Out-Of-Range Index Numbers"
,idxnumerr);
if(hdrnumerr)
printf("%-35.35s (!): %lu\n"
,"Out-Of-Range Header Numbers"
,hdrnumerr);
if(hdrlenerr)
printf("%-35.35s (!): %lu\n"
,"Mismatched Header Lengths"
,hdrlenerr);
if(attr)
printf("%-35.35s (!): %lu\n"
,"Mismatched Header Attributes"
,attr);
if(timeerr)
printf("%-35.35s (!): %lu\n"
,"Mismatched Header Import Time"
,timeerr);
if(subjcrc)
printf("%-35.35s (!): %lu\n"
,"Mismatched Subject CRCs"
,subjcrc);
if(fromcrc)
printf("%-35.35s (!): %lu\n"
,smb.status.attr&SMB_EMAIL ? "Mismatched From Extensions" : "Mismatched From CRCs"
,fromcrc);
if(tocrc)
printf("%-35.35s (!): %lu\n"
,smb.status.attr&SMB_EMAIL ? "Mismatched To Extensions" : "Mismatched To CRCs"
,tocrc);
if(getbodyerr)
printf("%-35.35s (!): %lu\n"
,"Message Body Text Read Failures"
,getbodyerr);
if(gettailerr)
printf("%-35.35s (!): %lu\n"
,"Message Tail Text Read Failures"
,gettailerr);
if(xlaterr)
printf("%-35.35s (!): %lu\n"
,"Unsupported Translation Types"
,xlaterr);
if(hasherr)
printf("%-35.35s (!): %lu\n"
,"Missing Hash Records"
,hasherr);
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
if(datactalloc)
printf("%-35.35s (!): %lu\n"
,"Misallocated Active Data Blocks"
,datactalloc);
if(actalloc)
printf("%-35.35s (!): %lu\n"
,"Misallocated Active Header Blocks"
,actalloc);
/***
if(delalloc)
printf("%-35.35s (!): %lu\n"
,"Misallocated Deleted Header Blocks"
,delalloc);
***/
if(dfieldoffset)
printf("%-35.35s (!): %lu\n"
,"Invalid Data Field Offsets"
,dfieldoffset);
if(dfieldlength)
printf("%-35.35s (!): %lu\n"
,"Invalid Data Field Lengths"
,dfieldlength);
printf("\n%s Message Base ",smb.file);
if(/* (headers-deleted)!=smb.status.total_msgs || */
total!=smb.status.total_msgs
|| (headers-deleted)!=total-delidx
|| idxzeronum || zeronum
|| hdrlenerr || hasherr
|| getbodyerr || gettailerr
|| orphan || dupenumhdr || dupenum || dupeoff || attr
|| lockerr || hdrerr || hdrnumerr || idxnumerr || idxofferr
|| actalloc || datactalloc || misnumbered || timeerr
|| subjcrc || fromcrc || tocrc
|| dfieldoffset || dfieldlength || xlaterr || idxerr) {
printf("%shas Errors!\n",beep);
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
else
printf("is OK\n");
smb_unlocksmbhdr(&smb);
smb_close(&smb);
}
if((totalmsgs && (totalmsgs!=smb.status.total_msgs || totallzhmsgs))
|| packable)
printf("\n");
if(totalmsgs && totalmsgs!=smb.status.total_msgs)
printf("%-39.39s: %-8lu %13s bytes used\n"
,"Total Active Messages"
,totalmsgs,ultoac(totalmsgbytes,str));
if(totallzhmsgs && totalmsgs!=smb.status.total_msgs)
printf("%-39.39s: %-8lu %13s bytes saved\n"
,"Total LZH Compressed Messages"
,totallzhmsgs,ultoac(totallzhsaved,str));
if(packable)
printf("%-39.39s: %-8lu %13s bytes used\n"
,"Total Deleted Messages"
,totaldelmsgs,ultoac(packable,str));
if(pause_on_error && errlast!=errors) {
fprintf(stderr,"\7\nHit any key to continue...");
if(!getch())
getch();
if(errors)
printf("\n'fixsmb' can be used to repair most message base problems.\n");