home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
back2roots/padua
/
padua.7z
/
padua
/
ftp.vapor.com
/
microdot-1
/
md1_src_02.lzx
/
crunch.c
< prev
next >
Wrap
C/C++ Source or Header
|
2014-05-19
|
36KB
|
1,629 lines
#include "microdot.h"
#include "asyncio.h"
#include "ogre.h"
#include "ogre_protos.h"
extern BOOL do_autoreorg, do_autocrunch;
void calcmcount_mb( struct mindex *mix, struct mbrett *mb )
{
struct mmail *mm=(struct mmail*)mix->maillist.lh_Head;
long newcount=0/*,delcount=0*/,mailcount=0,/*foldcount=0,*/unreadcount=0;
while( mm->n.mln_Succ )
{
if( ! ( mm->m.flags & MMF_KILL ) )
{
mailcount++;
/*if(mm->m.flags & MMF_DEL ) delcount++;
if(mm->m.flags & MMF_FOLD) foldcount++;*/
if(mm->m.flags & (MMF_UNSEEN|MMF_SHOW)) newcount++;
if(!(mm->m.flags & MMF_READ)) unreadcount++;
}
mm=(struct mmail*)mm->n.mln_Succ;
}
mb->b.mails = mailcount;
mb->b.newmails = newcount;
mb->b.unreadmails = unreadcount;
}
#define CGID_CRUNCH_DAT 9
#define CGID_CRUNCH_NEW 1
#define CGID_CRUNCH_READ 2
#define CGID_START 3
#define CGID_END 4
#define CGID_FG 5
#define CGID_FG2 10
#define CGID_FG3 11
#define CGID_FG3T 12
#define CGID_DUPEKILL 13
#define CGID_L0 6
#define CGID_L1 7
#define CGID_L2 8
static int Done,datedel,newdel,readdel,dupedel;
static struct ogwin *ogw;
static int abscount,delcount,remcount;
static void removemsgs(struct mbrett *mb,struct mindex *mix)
{
struct mmail *m=(struct mmail*)mix->maillist.lh_Head,*nm;
int currentcount = 0,
ptr = 0,
mmcount;
mmcount = mix->mailcount;
ogreSetMaxVal( ogw, CGID_FG, mmcount + 1 );
ogreSetValue( ogw, CGID_FG, 0 );
while((nm=(struct mmail*)m->n.mln_Succ))
{
ptr++;
ogreSetValue( ogw, CGID_FG, ptr );
/* Nachricht erhalten */
if( ( !newdel && ( m->m.flags & MMF_UNSEEN ) ) ||
( m->m.flags & ( MMF_ARCHIVE | MMF_SHOW ) ) ||
( !( m->m.flags & ( MMF_KILL | MMF_DEL ) ) ) )
{
currentcount++;
}
else
{
mix->changed=1;
remcount++;
Remove((struct Node*)m); /* Nachricht wech! */
}
m=nm;
}
mix->mailcount = currentcount;
}
static void crunchkillfile( void )
{
char buffer[1024];
long t, cmpt;
FILE *midin, *midout;
int count = 0, delcount = 0;
int maxlen, currentpos;
int kftimeout;
int rc;
kftimeout = ( prefs.killfile_hold ) ? prefs.killfile_hold : 30;
kftimeout *= 3600 * 24;
maxlen = getfilelen( "microdot.kill" );
if( maxlen < 1 )
return;
midin = fopen( "microdot.kill", "r" );
if( !midin )
return;
midout = fopen( "microdot.newkill", "w" );
if( !midout )
{
displaybeep();
fclose( midin );
return;
}
time( &cmpt );
ogreSetMaxVal( ogw, CGID_FG, maxlen );
for( ;; )
{
currentpos = ftell( midin );
ogreSetValue( ogw, CGID_FG, currentpos );
sprintf( buffer, "%lD EintrΣge, %lD gel÷scht",
count++, delcount );
ogreSetStringValue( ogw, CGID_L1, buffer );
if( fread( &t, 4, 1, midin ) != 1 )
break;
fgets( buffer, 1024, midin );
/* Alter prⁿfen */
if( t + kftimeout < cmpt )
{
delcount ++;
continue;
}
/* Rest Kopieren */
fwrite( &t, 4, 1, midout );
fwrite( buffer, strlen( buffer ), 1, midout );
while( ( rc = fread( buffer, 1, 1024, midin ) ) > 0 )
fwrite( buffer, rc, 1, midout );
break;
}
fclose( midin );
fclose( midout );
DeleteFile( "microdot.kill.bak" );
Rename( "microdot.kill", "microdot.kill.bak" );
Rename( "microdot.newkill", "microdot.kill" );
}
void docrunchkillfile( void )
{
struct Window *iw;
struct IntuiMessage *im;
int Done = FALSE;
int l;
char buffer[á64 ];
Done = FALSE;
ogw = ogreInitWindow( scr, WFLG_RMBTRAP, NULL, "Killfile aufrΣumen..." );
ogreAddGroup( ogw, 0, OGFRAME_NONE, NULL );
ogreAddText( ogw, 0, "Status:", CGID_L1, "", 46, 1 );
ogreAddFuelGauge( ogw, 1, CGID_FG, 100 );
ogreAddInteger( ogw, 2, 'h', "_Haltezeit in Tagen:", CGID_L0, prefs.killfile_hold ? prefs.killfile_hold : 30, 1, 2000, 10, 10 );
ogreAddGroup( ogw, 1, OGFRAME_NONE, NULL );
ogreAddButton( ogw, 0 | OGB_ONENTER, 's', "_Start", CGID_START );
ogreAddHelp( ogw, 0 );
ogreAddButton( ogw, 0 | OGB_ONESC, 'a', "_Abbruch", CGID_END );
iw = ogreOpenWindow( ogw );
if( !iw )
return;
pushhomedir();
l = getfilelen( "microdot.kill" );
if( l < 0 )
l = 0;
sprintf( buffer, "KillfilelΣnge %lD Bytes", l );
ogreSetStringValue( ogw, CGID_L1, buffer );
while( !Done )
{
im = ogreWaitIM( ogw );
if( im->Class == IDCMP_GADGETHELP)
showguidenum( "crunchkill_gads", im->Code );
else if( im->Class == IDCMP_GADGETUP )
{
if( im->Code == CGID_START )
Done = 2;
else if( im->Code == CGID_END )
Done = 1;
}
ogreIMReply( ogw, im );
}
prefs.killfile_hold = ogreValue( ogw, CGID_L0 );
if( Done == 2 )
{
ogreEnable( ogw, FALSE, CGID_START, CGID_END, CGID_L0, 0 );
crunchkillfile();
}
popdir();
ogreExitWindow( ogw );
}
static struct mmail * testdupe( struct mmail *cm )
{
struct mmail *ml = ( struct mmail * ) cm->n.mln_Succ;
while( ml && ml->n.mln_Succ )
{
if( cm->m.midcrc == ml->m.midcrc )
{
return( ml );
}
ml = ( struct mmail * ) ml->n.mln_Succ;
}
return( NULL );
}
static void crunchbrett(struct mbrett *mb)
{
struct mindex *mix;
struct mmail *m, *dupe;
char tmp[128];
long t,timeout;
ogreSetValue( ogw, CGID_FG, 0 );
ogreSetStringValue( ogw, CGID_L0,mb->b.name);
ogreSetStringValue( ogw, CGID_L2, "Lade Brettindex..." );
mix=loadbrettixquiet(mb);
if(!mix)
{
mb->b.unreadmails = 0;
mb->b.mails = 0;
mb->b.newmails = 0;
return;
}
/* mb->nextfreemsg=0;*/
time( &t );
timeout = mb->b.days * ( 3600 * 24 );
m=(struct mmail*)mix->maillist.lh_Head;
ogreSetStringValue( ogw, CGID_L2,"L÷sche Nachrichten...");
while(m->n.mln_Succ)
{
abscount++;
if( !( mb->b.flags & BFLAG_NOCRUNCH ) )
{
if( !( m->m.flags & MMF_DEL ) )
{
if( datedel )
{
if( ( t - ( m->m.incomtime ) > timeout ) && !( m->m.flags & ( MMF_SHOW | MMF_ARCHIVE ) ) )
{
if( newdel || !( m->m.flags & MMF_UNSEEN ) )
{
mix->changed = 1;
m->m.flags |= MMF_DEL;
delcount++;
}
}
}
}
if( !( m->m.flags & MMF_DEL ) )
{
if( readdel )
{
if( ( m->m.flags & MMF_READ ) && ( !( m->m.flags & ( MMF_SHOW | MMF_ARCHIVE ) ) ) )
{
if( newdel || !( m->m.flags & MMF_UNSEEN ) )
{
mix->changed = 1;
m->m.flags |= MMF_DEL;
delcount++;
}
}
}
}
}
if( !( m->m.flags & MMF_DEL ) )
{
/* gegen Killfile testen */
if((!(m->m.flags&MMF_DEL)) && testcrcidmke(m->m.midcrc))
{
struct header *hl;
struct msghandle *msg;
struct hlist *hlist;
msg = msg_open( m->m.pufferID, m->m.mailID );
if( msg )
{
hlist = msg_loadheader( msg );
hl = hl_findheader( hlist, "MID" );
if(hl && testidmke(hl->data)) { mix->changed=1; delcount++; m->m.flags|=MMF_DEL; }
hl_freeheader( hlist );
msg_close( msg );
}
}
}
/* Dupe? */
if( dupedel )
{
//Printf( "testing for %lx\n", m );
if( dupe = testdupe( m ) )
{
//Printf( "found dupe %lx\n", dupe );
if( !( dupe->m.flags & MMF_DEL ) )
{
mix->changed = 1;
dupe->m.flags = MMF_DEL;
delcount++;
}
}
}
m=(struct mmail*)m->n.mln_Succ;
}
ogreSetStringValue( ogw, CGID_L2, "Entferne Nachrichten..." );
removemsgs( mb, mix );
sprintf( tmp, "%lD insgesamt, %lD gel÷scht, %lD entfernt", abscount, delcount, remcount );
ogreSetStringValue( ogw, CGID_L1, tmp );
ogreSetStringValue( ogw, CGID_L2, "Speichere Brettindex..." );
calcmcount_mb( mix, mb );
savebrettix( mix, mb );
freebrettix( mix );
ogreSetStringValue( ogw, CGID_L2, "" );
closeallixfiles();
flushbrettix();
/* mb->nextfreemsg = 0;*/
}
static void startcrunch( struct mbrett *cmb )
{
struct IntuiMessage *im;
long class, code;
datedel = ogreValue( ogw, CGID_CRUNCH_DAT );
newdel = ogreValue( ogw, CGID_CRUNCH_NEW );
readdel = ogreValue( ogw, CGID_CRUNCH_READ );
dupedel = ogreValue( ogw, CGID_DUPEKILL );
ogreEnable( ogw, FALSE, CGID_CRUNCH_DAT, CGID_CRUNCH_NEW, CGID_CRUNCH_READ, CGID_START, CGID_DUPEKILL, OGID_HELP, 0 );
delcount=0;
remcount=0;
abscount=0;
if( !cmb )
{
crunchkillfile();
doinfofg();
}
ogreSetStringValue( ogw, CGID_L1, "" );
ogreSetStringValue( ogw, CGID_L2, "Lade Killfile..." );
loadmke();
if( cmb ) crunchbrett( cmb );
else
{
int bc = 0;
cmb=(struct mbrett*)brettlist.lh_Head;
while(cmb->n.ln_Succ)
{
if( stricmp( cmb->b.name, "/╗SPOOL" ) )
crunchbrett( cmb );
ogreSetValue( ogw, CGID_FG2, bc++ );
cmb=(struct mbrett*)cmb->n.ln_Succ;
if((im=(struct IntuiMessage*)ogreIM(ogw)))
{
class=im->Class; code=im->Code;
ogreIMReply(ogw, im);
if(class==GADGETUP)
break;
}
doinfofg();
}
}
doinfofg();
freemke();
savebretter();
}
void docrunch( struct mbrett *mb )
{
struct Window *iw;
struct IntuiMessage *im;
Done = FALSE;
if( mb == (struct mbrett*)-1 )
{
mb = NULL;
Done = 2;
}
if( mb && !stricmp( mb->b.name, "/╗SPOOL" ) )
{
askreq( "Das /╗SPOOL-Brett wird automatisch nach dem\nNetcall aufgerΣumt. Gel÷schte Nachrichten werden grundsΣtzlich\nnicht verschickt.", "OK" );
return;
}
ogw = ogreInitWindow( scr, WFLG_RMBTRAP, NULL, "AufrΣumen" );
ogreAddGroup( ogw, 0, OGFRAME_OUTLINE, " Parameter " );
ogreAddCheckbox( ogw, 0, 'd', "nach _Datum l÷schen", CGID_CRUNCH_DAT, prefs.flags2 & MDF2_CRUNCH_DAT );
ogreAddCheckbox( ogw, 0, 'n', " auch _Neue", CGID_CRUNCH_NEW, prefs.flags2 & MDF2_CRUNCH_NEW );
ogreAddCheckbox( ogw, 1, 'g', " Alle _Gelesenen", CGID_CRUNCH_READ, prefs.flags2 & MDF2_CRUNCH_ALLREAD );
ogreAddCheckbox( ogw, 1, 'p', "Alle Do_ppelten", CGID_DUPEKILL, prefs.flags2 & MDF2_CRUNCH_DUPES );
ogreAddGroup( ogw, 1, OGFRAME_OUTLINE, " Status " );
ogreAddText( ogw, 0, " Brett:", CGID_L0, "", 46, 1 );
ogreAddText( ogw, 1, " Mails:", CGID_L1, "", 46, 1 );
ogreAddText( ogw, 2, "Status:", CGID_L2, "", 46, 1 );
ogreAddFuelGauge( ogw, 3, CGID_FG, 100 );
if( !mb )
{
ogreAddFuelGauge( ogw, 4, CGID_FG2, GetNumEntries( &brettlist ) );
ogreAddText( ogw, 5, "Belegter Festplattenplatz:", CGID_FG3T, "", 1, 0 );
ogreAddFuelGauge( ogw, 5, CGID_FG3, 100 );
}
ogreAddGroup( ogw, 2, OGFRAME_NONE, NULL );
ogreAddButton( ogw, 0 | OGB_ONENTER, 's', "_Start", CGID_START );
ogreAddHelp( ogw, 0 );
ogreAddButton( ogw, 0 | OGB_ONESC, 'a', "_Abbruch", CGID_END );
iw = ogreOpenWindow( ogw );
if( !iw )
return;
if( mb && ( mb->b.flags & BFLAG_NOCRUNCH ) )
{
ogreSetValue( ogw, CGID_CRUNCH_DAT, FALSE );
ogreSetValue( ogw, CGID_CRUNCH_READ, FALSE );
//ogreSetValue( ogw, CGID_CRUNCH_NEW, FALSE );
ogreEnable( ogw, FALSE, CGID_CRUNCH_DAT, CGID_CRUNCH_READ, 0 );
}
setupinfofg( prefs.datadir, ogw, CGID_FG3 );
doinfofg();
while( !Done )
{
im = ogreWaitIM( ogw );
if( im->Class == IDCMP_GADGETHELP)
showguidenum( "crunch_gads", im->Code );
else if( im->Class == IDCMP_GADGETUP )
{
if( im->Code == CGID_START )
Done = 2;
else if( im->Code == CGID_END )
Done = 1;
}
ogreIMReply( ogw, im );
}
if( ogreValue( ogw, CGID_CRUNCH_DAT ) )
prefs.flags2 |= MDF2_CRUNCH_DAT;
else
prefs.flags2 &= ~MDF2_CRUNCH_DAT;
if( ogreValue( ogw, CGID_CRUNCH_NEW ) )
prefs.flags2 |= MDF2_CRUNCH_NEW;
else
prefs.flags2 &= ~MDF2_CRUNCH_NEW;
if( ogreValue( ogw, CGID_CRUNCH_READ ) )
prefs.flags2 |= MDF2_CRUNCH_ALLREAD;
else
prefs.flags2 &= ~MDF2_CRUNCH_ALLREAD;
if( ogreValue( ogw, CGID_DUPEKILL ) )
prefs.flags2 |= MDF2_CRUNCH_DUPES;
else
prefs.flags2 &= ~MDF2_CRUNCH_DUPES;
if( Done == 2 )
startcrunch( mb );
freeinfofg();
ogreExitWindow( ogw );
}
#define IX_T 1
#define IX_F 2
#define IX_X 3
void setallold( void )
{
struct Window *iw;
struct IntuiMessage *im;
struct mbrett *mb = (struct mbrett *) brettlist.lh_Head;
struct mindex *mix;
int bcount = 0;
int Abort = FALSE;
struct mmail *mm;
if( !askreq( "Wirklich ALLE Nachrichten auf 'Alt' setzen?", "Ja|Abbruch" ) )
return;
ogw = ogreInitWindow( scr, 0, NULL, "Alle Nachrichten auf 'Alt' setzen..." );
ogreAddGroup( ogw, 0, OGFRAME_NONE, NULL );
ogreAddText( ogw, 0, "Brett:", IX_T, "", 46, 1 );
ogreAddFuelGauge( ogw, 1, IX_F, GetNumEntries( &brettlist ) );
ogreAddButton( ogw, 2 | OGB_ONESC, 'a', "_Abbruch", IX_X );
iw = ogreOpenWindow( ogw );
if( !iw )
return;
sortbrettlist();
while( mb->n.ln_Succ && !Abort )
{
ogreSetStringValue( ogw, IX_T, mb->b.name );
mix = loadbrettixquiet( mb );
if( !mix )
break;
calcmcount_mb( mix, mb );
mm = ( struct mmail * ) mix->maillist.lh_Head;
while( mm->n.mln_Succ )
{
mm->m.flags &= ~ MMF_UNSEEN;
mm = ( struct mmail * ) mm->n.mln_Succ;
}
mix->changed = 1;
savebrettix( mix, mb );
freebrettix( mix );
mb->b.flags &= ~ BFLAG_TOUCHED;
ogreSetValue( ogw, IX_F, bcount++ );
im = ogreIM( ogw );
if( im )
{
if( im->Class == GADGETUP )
Abort = TRUE;
ogreIMReply( ogw, im );
}
mb = ( struct mbrett * ) mb->n.ln_Succ;
}
ogreExitWindow( ogw );
}
#define RID_ABBRUCH 1
#define RID_I1 2
#define RID_I2 3
#define RID_FG 4
#define RID_GFG 5
#define RID_GFGTXT 6
static struct msgmove
{
struct msgmove *n;
ULONG spID;
ULONG smID;
ULONG dpID;
ULONG dmID;
} *msgmovelist;
struct ixinfo
{
struct MinNode n;
ULONG pID;
ULONG count;
UBYTE *mark;
ULONG newlen;
};
static struct MinList ixlist;
static int ixignoreall;
static int markix( struct mmail *mm, struct mindex *mix )
{
struct ixinfo *ix = ( struct ixinfo * ) ixlist.mlh_Head;
int dowhat = 0;
ULONG mID = mm->m.mailID, pID = mm->m.pufferID;
while( ix->n.mln_Succ )
{
if( ix->pID == pID )
{
if( mID >= ix->count )
{
if( !ixignoreall )
{
dowhat = askreq( "Fehler bei der Reorganisation:\nNachricht %lD im Puffer %lx (max %lD) existiert nicht!",
"Diese Nachricht entfernen|Alle Defekten entfernen|Ignorieren",
mID, pID, ix->count
);
}
else
dowhat = 1;
switch( dowhat )
{
case 2:
ixignoreall = TRUE;
// Fallthrough
case 1:
mm->m.flags |= MMF_KILL;
mix->changed = TRUE;
break;
}
}
else
setbit( ix->mark, mID );
return( 0 );
}
ix = ( struct ixinfo * ) ix->n.mln_Succ;
}
if( !ixignoreall )
dowhat = askreq( "Fehler bei der Reorganisation:\nPuffer %lx existiert nicht!",
"Diese Nachricht entfernen|Alle Defekten entfernen|Ignorieren",
pID
);
else
dowhat = 1;
switch( dowhat )
{
case 2:
ixignoreall = TRUE;
// Fallthrough
case 1:
mm->m.flags |= MMF_KILL;
mix->changed = TRUE;
break;
}
return( 0 );
}
static void copyfh2async( BPTR from, struct AsyncFile *to, int size )
{
void *bufmem;
int rc;
int bs;
if( size < 1 )
return;
bufmem = allocbuffmem( size, &bs );
while( size )
{
rc = Read( from, bufmem, bs );
if( rc > 0 )
WriteAsync( to, bufmem, rc );
else
break;
size -= rc;
}
freebuffmem();
}
static int procmsgmovelist( struct mmail *m )
{
ULONG pID = m->m.pufferID, mID = m->m.mailID;
struct msgmove *mm = msgmovelist;
while( mm )
{
if( ( mm->spID == pID ) && ( mm->smID == mID ) )
{
m->m.pufferID = mm->dpID;
m->m.mailID = mm->dmID;
return( TRUE );
}
mm = mm->n;
}
return( FALSE );
}
//
// HΣngt einen Puffer an einen anderen an
// und erzeugt msgmove-Nodes
//
static void moveerr( ULONG fid, ULONG tid, char *filename )
{
askreq( "Fehler beim Verschieben von ID %lx nach %lx:\nDatei %s lΣ▀t sich nicht ÷ffnen!\n(DOS-Fehler %ld)",
"Abbruch",
fid, tid, filename, IoErr()
);
}
static int movepuffer( APTR pool, ULONG fpID, ULONG tpID )
{
struct pindex *pix, *scan;
struct msgmove *newmm;
char oixname[á32 ], sixname[á32 ];
char odname[á32 ], sdname[á32 ];
struct AsyncFile *oldix, *olddata;
BPTR six, sd;
ULONG sixsize;
ULONG poffset, midoffset;
int ixcount, c, maillen;
sprintf( sixname, "MD_%lx.Index", fpID );
sprintf( sdname, "MD_%lx.Data", fpID );
sprintf( oixname, "MD_%lx.Index", tpID );
sprintf( odname, "MD_%lx.Data", tpID );
sixsize = getfilelen( sixname );
ixcount = sixsize / sizeof( struct pindex );
poffset = getfilelen( odname );
midoffset = getfilelen( oixname ) / sizeof( struct pindex );
oldix = OpenAsync( oixname, MODE_APPEND, sizeof( struct pindex ) * 64 );
if( !oldix )
{
moveerr( fpID, tpID, oixname );
return( 1 );
}
pix = LibAllocPooled( miscmempool, sixsize );
if( !pix )
return( 1 );
olddata = OpenAsync( odname, MODE_APPEND, 32768 );
if( !olddata )
{
CloseAsync( oldix );
moveerr( fpID, tpID, odname );
return( 1 );
}
six = Open( sixname, MODE_OLDFILE );
if( !six )
{
CloseAsync( oldix );
CloseAsync( olddata );
moveerr( fpID, tpID, sixname );
return( 1 );
}
Read( six, pix, sixsize );
Close( six );
sd = Open( sdname, MODE_OLDFILE );
if( !sd )
{
CloseAsync( oldix );
CloseAsync( olddata );
moveerr( fpID, tpID, sdname );
return( 1 );
}
for( c = 0, scan = pix; c < ixcount; scan++, c++ )
{
if( scan->flags & PIF_KILLED )
continue;
maillen = scan->headersize + scan->commentsize + scan->datasize;
// Data kopieren
Seek( sd, scan->offset, OFFSET_BEGINNING );
copyfh2async( sd, olddata, maillen );
// Index korrigieren
scan->offset = poffset;
poffset += maillen;
WriteAsync( oldix, scan, sizeof( *scan ) );
newmm = LibAllocPooled( pool, sizeof( *newmm ) );
if( !newmm )
{
LibFreePooled( miscmempool, pix, sixsize );
askreq( "Fehler: Kein Speicher fⁿr Nachrichtenverschiebetabelle!", "Abbruch" );
Close( sd );
DeleteFile( sixname );
DeleteFile( sdname );
CloseAsync( oldix );
CloseAsync( olddata );
return( 1 );
}
newmm->n = msgmovelist;
msgmovelist = newmm;
newmm->spID = fpID;
newmm->smID = c;
newmm->dpID = tpID;
newmm->dmID = midoffset++;
}
LibFreePooled( miscmempool, pix, sixsize );
Close( sd );
DeleteFile( sixname );
DeleteFile( sdname );
CloseAsync( oldix );
CloseAsync( olddata );
return( 0 );
}
static void reworkpuffer( struct ogwin *ogw, struct ixinfo *ix )
{
char f1[ 128 ];
char f2[á128 ];
char fo1[ 128 ];
BPTR oldp;
struct AsyncFile *newp;
struct pindex *pix, *pixp;
LONG pixsize = ix->count * sizeof( struct pindex );
LONG curoffs = 0, maillen = 0;
int changed = 0;
int c;
sprintf( fo1, "MD_%lx.Data", ix->pID );
sprintf( f1, "MD_%lx.Data.New", ix->pID );
sprintf( f2, "MD_%lx.Index", ix->pID );
/* Entgⁿltige Entsorgung... */
if( !ix->count || !tstbitfield( ix->mark, ix->count ) )
{
prefs.nextfreepuf = 0;
DeleteFile( fo1 );
DeleteFile( f2 );
return;
}
ogreSetMaxVal( ogw, RID_FG, ix->count );
pix = LibAllocPooled( miscmempool, pixsize );
if( !pix )
{
askreq( "Fehler beim Reorganisieren:\nKein Speicher fⁿr Index.", "Abbruch" );
return;
}
/* Indizies einlesen */
oldp = Open( f2, MODE_OLDFILE );
Read( oldp, pix, pixsize );
Close( oldp );
/* Prⁿfen, ob gⁿltiger Eintrag entfernt wurde */
for( pixp = pix, c = 0; c < ix->count; c++, pixp++ )
{
if( !tstbit( ix->mark, cá)á&& ( ! ( pixp->flags & PIF_KILLED ) ) )
{
pixp->flags |= PIF_KILLED;
pixp->offset = ~0;
changed = 1;
}
}
/* Keine ─nderungen */
if( !changed )
{
exnodo:
LibFreePooled( miscmempool, pix, pixsize );
return;
}
oldp = Open( fo1, MODE_OLDFILE );
newp = OpenAsync( f1, MODE_WRITE, 65536 );
if( !oldp )
{
askreq( "Fehler bei der Reorganisation:\nDatei %s lΣ▀t sich nicht ÷ffnen (%ld)",
"Abbruch",
fo1,
IoErr()
);
goto exnodo;
}
if( !newp )
{
Close( oldp );
askreq( "Fehler bei der Reorganisation:\nDatei %s lΣ▀t sich nicht beschreiben (%ld)",
"Abbruch",
f1,
IoErr()
);
goto exnodo;
}
/* Nun verbleibende Daten umkopieren */
for( pixp = pix, c = 0; c < ix->count; c++, pixp++ )
{
ogreSetValue( ogw, RID_FG, c );
if( ! ( pixp->flags & PIF_KILLED ) )
{
maillen = pixp->headersize + pixp->commentsize + pixp->datasize;
reseek:
if( Seek( oldp, pixp->offset, OFFSET_BEGINNING ) < 0 )
{
if( askreq( "Fehler bei der Reorganisation:\nDos-Fehler %ld bei Seek() zu Offset %ld\nin Datei \"%s\"",
"Wiederholen|Abbruch",
IoErr(),
pixp->offset,
fo1
) )
goto reseek;
Close( oldp );
CloseAsync( newp );
LibFreePooled( miscmempool, pix, pixsize );
return;
}
pixp->offset = curoffs;
curoffs += maillen;
copyfh2async( oldp, newp, maillen );
}
}
Close( oldp );
CloseAsync( newp );
/* Indizies zurⁿckschreiben */
oldp = Open( f2, MODE_NEWFILE );
if( !oldp )
{
askreq( "Fehler bei der Reorganisation:\nBrettindex \"%s\" konnte nicht neu\ngeschrieben werden (%ld)",
"Abbruch",
f2, IoErr()
);
}
else
{
Write( oldp, pix, pixsize );
Close( oldp );
/* Puffer umkopieren */
DeleteFile( fo1 );
Rename( f1, fo1 );
}
LibFreePooled( miscmempool, pix, pixsize );
}
static int abortreorg( void )
{
return( ( int ) askreq( "Reorganisation abbrechen?", "Reorganisation abbrechen|Fortsetzen" ) );
}
static int abortrestore( void )
{
return( ( int ) askreq( "Wiederherstellung des Brettindex abbrechen?", "Wiederherstellung abbrechen|Fortsetzen" ) );
}
static struct direntry {
struct direntry *next;
char name[ 256 ];
} *first;
static void adddir( struct ogwin *ogw, APTR pool, char *dir )
{
struct FileInfoBlock *fib;
BPTR lock, oldcd;
struct direntry *new;
char path[ 256 ];
ogreSetStringValue( ogw, RID_I1, dir );
lock = Lock( dir, SHARED_LOCK );
if( !lock )
return;
new = LibAllocPooled( pool, sizeof( *new ) );
if( !new )
{
UnLock( lock );
return;
}
strcpy( new->name, dir );
new->next = first;
first = new;
oldcd = CurrentDir( lock );
fib = allocfib();
Examine( lock, fib );
while( ExNext( lock, fib ) )
{
if( fib->fib_DirEntryType > 0 )
{
strcpy( path, dir );
addpart( path, fib->fib_FileName );
adddir( ogw, pool, path );
}
}
freefib( fib );
UnLock( CurrentDir( oldcd ) );
}
static void doremovedirs( struct ogwin *ogw )
{
APTR pool;
first = NULL;
pool = LibCreatePool( 0, sizeof( struct direntry ) * 16, sizeof( struct direntry ) * 8 );
ogreSetStringValue( ogw, RID_I2, "Suche ⁿberflⁿssige Verzeichnisse..." );
adddir( ogw, pool, prefs.datadir );
ogreSetStringValue( ogw, RID_I2, "Entferne ⁿberflⁿssige Verzeichnisse..." );
ogreSetStringValue( ogw, RID_I1, "-" );
while( first )
{
DeleteFile( first->name );
first = first->next;
}
LibDeletePool( pool );
}
void doreorg2( int merge )
{
struct Window *iw;
struct IntuiMessage *im;
struct mbrett *mb = (struct mbrett *) brettlist.lh_Head;
struct mindex *mix;
int bcount = 5;
int Abort = FALSE;
struct mmail *mm;
struct FileInfoBlock *fib;
BPTR lock;
struct ixinfo *new;
APTR pool;
char tmp[á128 ], tmp2[ 128 ];
int c, d;
ULONG olddbsize = 0, newdbsize = 0;
int dbfilecount;
struct MinList mergelist;
ixignoreall = FALSE;
NewList( ( struct List * ) &ixlist );
NewList( ( struct List * ) &mergelist );
ogw = ogreInitWindow( scr, 0, NULL, "Reorganisation..." );
ogreAddGroup( ogw, 0, OGFRAME_NONE, NULL );
ogreAddText( ogw, 0, "Aktion:", RID_I2, "", 46, 1 );
ogreAddText( ogw, 1, "Status:", RID_I1, "", 46, 1 );
ogreAddFuelGauge( ogw, 2, RID_FG, GetNumEntries( &brettlist ) );
ogreAddFuelGauge( ogw, 3, RID_GFG, 100 );
ogreAddText( ogw, 4, "Belegter Festplattenplatz:", RID_GFGTXT, "", 1, 0 );
ogreAddFuelGauge( ogw, 4, CGID_FG3, 100 );
ogreAddButton( ogw, 5 | OGB_ONESC, 'a', "_Abbruch", RID_ABBRUCH );
iw = ogreOpenWindow( ogw );
if( !iw )
return;
setupinfofg( prefs.datadir, ogw, CGID_FG3 );
doinfofg();
ixc_flush();
closeallixfiles();
sortbrettlist();
fib = allocfib();
pool = LibCreatePool( MEMF_CLEAR, 8192, 4096 );
ogreSetStringValue( ogw, RID_I2, "Untersuche Datenfiles..." );
lock = Lock( prefs.datadir, SHARED_LOCK );
Examine( lock, fib );
openlogmsg( "Reorganisations-Protokoll" );
while( ExNext( lock, fib ) && !Abort )
{
if( !astcsma( fib->fib_FileName, "MD_#?.Index" ) )
continue;
ogreSetStringValue( ogw, RID_I1, fib->fib_FileName );
new = LibAllocPooled( pool, sizeof( *new ) );
if( !new )
continue;
new->count = fib->fib_Size / sizeof( struct pindex );
if( fib->fib_Size % sizeof( struct pindex ) )
{
Abort = !askreq( "Warnung: Indexdatei %s hat\nungⁿltige LΣnge %lD (~%lD/%lD)",
"Weiter|Abbruch",
fib->fib_FileName,
fib->fib_Size,
new->count * sizeof( struct pindex ),
new->count
);
}
if( new->count )
{
new->mark = LibAllocPooled( pool, ( new->count + 31 ) / 8 );
if( !new->mark )
{
askreq( "Fehler bei der Reorganisation:\nKein Speicher fⁿr Tabellen.", "Abbruch" );
Abort = TRUE;
}
}
stch_l( &fib->fib_FileName[3], ( LONG * ) &new->pID );
AddTail( ( struct List * ) &ixlist, ( struct Node * ) new );
im = ogreIM( ogw );
if( im )
{
if( im->Class == GADGETUP )
Abort = abortreorg();
ogreIMReply( ogw, im );
}
}
freefib( fib );
UnLock( lock );
ogreSetStringValue( ogw, RID_I2, "Untersuche Bretter..." );
ogreSetMaxVal( ogw, RID_GFG, GetNumEntries( &brettlist ) + ( GetNumEntries( ( struct List * ) &ixlist ) * 10 ) + 5 );
ogreSetValue( ogw, RID_GFG, bcount );
while( mb->n.ln_Succ && !Abort )
{
ogreSetStringValue( ogw, RID_I1, mb->b.name );
mix = loadbrettixquiet( mb );
if( !mix )
{
Abort = TRUE;
break;
}
calcmcount_mb( mix, mb );
mm = ( struct mmail * ) mix->maillist.lh_Head;
while( mm->n.mln_Succ )
{
markix( mm, mix );
mm = ( struct mmail * ) mm->n.mln_Succ;
}
savebrettix( mix, mb );
freebrettix( mix );
closeallixfiles();
flushbrettix();
ogreSetValue( ogw, RID_GFG, bcount++ );
im = ogreIM( ogw );
if( im )
{
if( im->Class == GADGETUP )
Abort = abortreorg();
ogreIMReply( ogw, im );
}
mb = ( struct mbrett * ) mb->n.ln_Succ;
}
closeallixfiles();
ixc_flush();
ogreSetStringValue( ogw, RID_I2, "Bearbeite Datenfiles..." );
pushdir( prefs.datadir );
printlog( "▄berarbeiten der Datenfiles:\n---------------------------------------------------\n" );
dbfilecount = GetNumEntries( ( struct List * ) &ixlist );
while( !Abort && ( new = ( struct ixinfo * ) RemHead( ( struct List * ) &ixlist ) ) )
{
sprintf( tmp, "MD_%lx.Data", new->pID );
sprintf( tmp2, "%s, %lD Bytes", tmp, d = getfilelen( tmp ) );
ogreSetStringValue( ogw, RID_I1, tmp2 );
reworkpuffer( ogw, new );
doinfofg();
olddbsize += d;
c = getfilelen( tmp );
if( c < 1 )
strcat( tmp2,": gel÷scht!" );
else
{
asprintf( tmp2, "-> %lD Bytes", c );
newdbsize += c;
}
ogreSetStringValue( ogw, RID_I1, tmp2 );
new->newlen = c;
printlog( "%-16.16s: %10lD -> %10lD Bytes (%ld%%)\n",
tmp,
d,
( c > 1 ) ? c : 0,
( c > 1 && d ) ? ( ( c * 100 ) / d ) : 0
);
ogreSetValue( ogw, RID_GFG, bcount );
bcount += 10;
ogreSetValue( ogw, RID_FG, 0 );
im = ogreIM( ogw );
if( im )
{
if( im->Class == GADGETUP )
Abort = abortreorg();
ogreIMReply( ogw, im );
}
if( c > 0 )
AddTail( ( struct List *) &mergelist, new );
}
if( !Abort )
printlog( "-------------------\n%10lD Files, %10lD -> %10lD Bytes (%ld%%)\n\n",
dbfilecount,
olddbsize,
newdbsize,
( olddbsize > 100 ) ? ( newdbsize ) / ( olddbsize / 100 ) : 0
);
else
printlog( "\n*** Reorganisation abgebrochen!\n\n" );
// Eventuell mergen?
if( merge )
{
int destsize = prefs.reorg_destsize * 1024;
msgmovelist = NULL;
printlog( "\nZusammenfassen kleiner Datenfiles:\n---------------------------------------------------\n" );
ogreSetStringValue( ogw, RID_I2, "Zusammenfassung kleiner Datenfiles..." );
while( !Abort && ( new = ( struct ixinfo * ) RemHead( ( struct List * ) &mergelist ) ) )
{
while( new->newlen < destsize )
{
struct ixinfo *from = ( struct ixinfo * ) mergelist.mlh_Head;
while( from->n.mln_Succ )
{
if( ( from->newlen + new->newlen ) < ( destsize + ( destsize / 5 ) ) )
{
sprintf( tmp, "MD_%lx an MD_%lx", from->pID, new->pID );
ogreSetStringValue( ogw, RID_I1, tmp );
printlog( "MD_%lx (%lD) an MD_%lx (%lD); neue LΣnge %lD Bytes\n",
from->pID, from->newlen,
new->pID, new->newlen,
from->newlen + new->newlen
);
if( movepuffer( pool, from->pID, new->pID ) )
Abort = TRUE;
new->newlen += from->newlen;
Remove( from );
break;
}
from = ( struct ixinfo * ) from->n.mln_Succ;
}
if( !from->n.mln_Succ )
break;
}
im = ogreIM( ogw );
if( im )
{
if( im->Class == GADGETUP )
Abort = abortreorg();
ogreIMReply( ogw, im );
}
}
if( msgmovelist )
{
ogreSetStringValue( ogw, RID_I2, "Korrigiere Brettindizes..." );
mb = (struct mbrett *) brettlist.lh_Head;
while( mb->n.ln_Succ && !Abort )
{
ogreSetStringValue( ogw, RID_I1, mb->b.name );
mix = loadbrettixquiet( mb );
if( !mix )
{
Abort = TRUE;
break;
}
mm = ( struct mmail * ) mix->maillist.lh_Head;
while( mm->n.mln_Succ )
{
if( procmsgmovelist( mm ) )
mix->changed = TRUE;
mm = ( struct mmail * ) mm->n.mln_Succ;
}
savebrettix( mix, mb );
freebrettix( mix );
closeallixfiles();
flushbrettix();
mb = ( struct mbrett * ) mb->n.ln_Succ;
}
}
}
if( !Abort )
{
doremovedirs( ogw );
}
closelogmsg();
popdir();
freeinfofg();
LibDeletePool( pool );
ogreExitWindow( ogw );
}
#define REOID_START 1
#define REOID_CANCEL 2
#define REOID_L1 3
#define REOID_L2 4
#define REOID_MERGE 5
#define REOID_MAX 6
static long nummsgs(void)
{
struct mbrett *n=(struct mbrett*)brettlist.lh_Head;
long count = 0;
while(n->n.ln_Succ)
{
count += n->b.mails;
n=(struct mbrett*)n->n.ln_Succ;
}
return( count );
}
void doreorg( void )
{
struct Window *iw;
struct IntuiMessage *im;
int v;
char buffer[ 40 ];
int num = nummsgs();
Done = FALSE;
if( !prefs.reorg_destsize )
prefs.reorg_destsize = 256;
ogw = ogreInitWindow( scr, WFLG_RMBTRAP, NULL, "Reorganisation der Nachrichtendatenbank" );
ogreAddGroup( ogw, 0, OGFRAME_OUTLINE, " Parameter " );
ogreAddText( ogw, 0, "", REOID_L1, "Die Reorganisation kann lΣngere Zeit in Anspruch nehmen!", 56, 0 );
ogreAddText( ogw, 1, "UngefΣhrer Speicherbedarf:", REOID_L2, "", 20, 0 );
ogreAddCheckbox( ogw, 2, 'z', "_Zusammenfassen kleiner Puffer:", REOID_MERGE, prefs.reorg_merge );
ogreAddInteger( ogw, 3, 'g', "Ziel_gr÷▀e KByte:", REOID_MAX, prefs.reorg_destsize, 8, MAXINT, 10, 10 );
ogreAddGroup( ogw, 1, OGFRAME_NONE, NULL );
ogreAddButton( ogw, 0 | OGB_ONENTER, 's', "_Start", REOID_START );
ogreAddHelp( ogw, 0 );
ogreAddButton( ogw, 0 | OGB_ONESC, 'a', "_Abbruch", REOID_CANCEL );
iw = ogreOpenWindow( ogw );
if( !iw )
return;
while( !Done )
{
v = ogreValue( ogw, REOID_MERGE );
ogreEnable( ogw, v, REOID_MAX, 0 );
sprintf( buffer, "%lD Bytes", 160749 + ( ( num + 7 ) / 8 ) + ( v ? num * 20 : 0 ) );
ogreSetStringValue( ogw, REOID_L2, buffer );
im = ogreWaitIM( ogw );
if( im->Class == IDCMP_GADGETHELP )
showguidenum( "reorgprefs_gads", im->Code );
else if( im->Class == IDCMP_GADGETUP )
{
if( im->Code == REOID_START )
Done = 2;
else if( im->Code == REOID_CANCEL )
Done = 1;
}
ogreIMReply( ogw, im );
}
if( Done == 1 )
{
ogreExitWindow( ogw );
return;
}
prefs.reorg_destsize = ogreValue( ogw, REOID_MAX );
prefs.reorg_merge = ogreValue( ogw, REOID_MERGE );
ogreExitWindow( ogw );
doreorg2( v );
}
#define RGID_L0 1
#define RGID_L1 2
#define RGID_L2 3
#define RGID_FG 4
#define RGID_START 5
#define RGID_END 6
void restoremindex( struct mbrett *mb )
{
struct Window *iw;
struct IntuiMessage *im;
char buffer[ 128 ], buffer2[á128 ];
BPTR lock;
struct AsyncFile *newmindex;
struct FileInfoBlock *fib;
int Abort = FALSE;
int mailcount = 0;
ULONG pID, mID;
struct msghandle *msg;
struct hlist *hlist;
struct header *hl;
struct mail mail;
int pmc;
struct mindex *mix;
int ispm;
Done = FALSE;
ispm = mb->b.name[á0 ]á!= '/';
if( !stricmp( mb->b.name, "/╗SPOOL" ) )
{
askreq( "Wiederherstellung des /╗SPOOL-Brettes\nist nicht m÷glich.", "Abbruch" );
return;
}
if( !stricmp( mb->b.name, "/╗ARCHIV" ) )
{
askreq( "Wiederherstellung des /╗ARCHIV-Brettes\nist nicht m÷glich.", "Abbruch" );
return;
}
ogw = ogreInitWindow( scr, WFLG_RMBTRAP, NULL, "Brettindex wiederherstellen" );
ogreAddGroup( ogw, 0, OGFRAME_OUTLINE, " Status " );
ogreAddText( ogw, 0, " Brett:", RGID_L0, mb->b.name, 46, 1 );
ogreAddText( ogw, 1, " Mails:", RGID_L1, "", 46, 1 );
ogreAddText( ogw, 2, "Status:", RGID_L2, "", 46, 1 );
ogreAddFuelGauge( ogw, 3, RGID_FG, 100 );
ogreAddGroup( ogw, 1, OGFRAME_NONE, NULL );
ogreAddButton( ogw, 0 | OGB_ONENTER, 's', "_Start", RGID_START );
ogreAddHelp( ogw, 0 );
ogreAddButton( ogw, 0 | OGB_ONESC, 'a', "_Abbruch", RGID_END );
iw = ogreOpenWindow( ogw );
if( !iw )
return;
while( !Done )
{
im = ogreWaitIM( ogw );
if( im->Class == IDCMP_GADGETHELP)
showguidenum( "restoremindex_gads", im->Code );
else if( im->Class == IDCMP_GADGETUP )
{
if( im->Code == RGID_START )
Done = 2;
else if( im->Code == RGID_END )
Done = 1;
}
ogreIMReply( ogw, im );
}
if( Done == 1 )
{
ogreExitWindow( ogw );
return;
}
if( !askreq( "Wollen Sie wirklich den Index von\nBrett %s\nrestaurieren?\n\n*** ACHTUNG!\n*** SΣmtliche Flags bestehender Nachrichten gehen verloren!", "Wiederherstellen|Abbruch", mb->b.name ) )
{
ogreExitWindow( ogw );
return;
}
ogreEnable( ogw, FALSE, RGID_START, OGID_HELP, NULL );
/* Es geht los */
flushbrettix();
closeallixfiles();
brettpfad( buffer, mb );
addpart( buffer, ".Mindex-new" );
newmindex = OpenAsync( buffer, MODE_WRITE, sizeof( struct mail ) * 32 );
if( !newmindex )
{
askreq( "Fehler bei der Wiederherstellung:\nDatei \"%s\" lΣ▀t sich nicht beschreiben (%ld).",
"Abbruch",
buffer,
IoErr()
);
ogreExitWindow( ogw );
return;
}
fib = allocfib();
lock = Lock( prefs.datadir, SHARED_LOCK );
Examine( lock, fib );
while( ExNext( lock, fib ) && !Abort )
{
if( !astcsma( fib->fib_FileName, "MD_#?.Index" ) )
continue;
sprintf( buffer, "Untersuche %s...", fib->fib_FileName );
ogreSetStringValue( ogw, RGID_L2, buffer );
stch_l( &fib->fib_FileName[á3 ], &pID );
pmc = fib->fib_Size / sizeof( struct pindex );
ogreSetMaxVal( ogw, RGID_FG, pmc );
for( mID = 0; mID < pmc && !Abort; mID++ )
{
ogreSetValue( ogw, RGID_FG, mID );
msg = msg_open( pID, mID );
if( !msg )
break;
if( msg->pix.flags & PIF_KILLED )
{
msg_close( msg );
continue;
}
hlist = msg_loadheader( msg );
if( !hlist )
{
askreq( "Fehler bei der Wiederherstellung:\nHeader von Nachricht %lx:%lx konnte\nnicht geladen werden.", "Abbruch", pID, mID );
msg_close( msg );
break;
}
/* In hlist steht die Headerliste */
hl = hl_findheader( hlist, "EMP" );
while( hl )
{
/* Gefunden! */
if( ( ispm && hl->data[ 0 ]á!= '/' ) || !stricmp( hl->data, mb->b.name ) )
{
memset( &mail, 0, sizeof( mail ) );
mail.pufferID = pID;
mail.mailID = mID;
header2mail( hlist, &mail );
if( !mail.maillen )
mail.maillen = msg_getsize( msg, MC_HEADER ) + msg_getsize( msg, MC_COMMENT ) + msg_getsize( msg, MC_DATA );
WriteAsync( newmindex, &mail, sizeof( mail ) );
mailcount++;
break;
}
hl = hl_findnextheader( hl );
}
hl_freeheader( hlist );
msg_close( msg );
sprintf( buffer, "%lD Nachricht%s gefunden", mailcount, mailcount == 1 ? "en" : "" );
ogreSetStringValue( ogw, RGID_L1, buffer );
}
im = ogreIM( ogw );
if( im )
{
if( im->Class == GADGETUP )
Abort = abortrestore();
ogreIMReply( ogw, im );
}
}
freefib( fib );
UnLock( lock );
CloseAsync( newmindex );
brettpfad( buffer, mb );
addpart( buffer, ".Mindex-new" );
if( !Abort )
{
brettpfad( buffer2, mb );
addpart( buffer2, ".Mindex" );
DeleteFile( buffer2 );
Rename( buffer, buffer2 );
}
else
DeleteFile( buffer );
ogreExitWindow( ogw );
mix = loadbrettixquiet( mb );
if( mix )
{
calcmcount_mb( mix, mb );
freebrettix( mix );
}
}