void maint(void) { int i; ulong l,m,n,f,flagged=0; time_t now; smbmsg_t msg; idxrec_t *idx; printf("Maintaining %s\r\n",smb.file); now=time(NULL); i=smb_locksmbhdr(&smb); if(i) { fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n" ,beep,i,smb.last_error); return; } i=smb_getstatus(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n" ,beep,i,smb.last_error); return; } if(smb_open_hash(&smb) == SMB_SUCCESS) { ulong max_hashes=0; printf("Maintaining %s hash file\r\n", smb.file); if((smb.status.attr&(SMB_EMAIL|SMB_NOHASH)) == 0) { max_hashes = smb.status.max_msgs; if(smb.status.max_crcs > max_hashes) max_hashes = smb.status.max_crcs; } if(!max_hashes) { CHSIZE_FP(smb.hash_fp,0); } else if(filelength(fileno(smb.hash_fp)) > (long)(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t))) { if(fseek(smb.hash_fp, -((long)(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t))), SEEK_END) == 0) { hash_t* hashes = malloc(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t)); if(hashes != NULL) { if(fread(hashes, sizeof(hash_t), max_hashes * SMB_HASH_SOURCE_TYPES, smb.hash_fp) == max_hashes * SMB_HASH_SOURCE_TYPES) { CHSIZE_FP(smb.hash_fp,0); rewind(smb.hash_fp); fwrite(hashes, sizeof(hash_t), max_hashes * SMB_HASH_SOURCE_TYPES, smb.hash_fp); } free(hashes); } } } smb_close_hash(&smb); } if(!smb.status.total_msgs) { smb_unlocksmbhdr(&smb); printf("Empty\n"); return; } printf("Loading index...\n"); if((idx=(idxrec_t *)malloc(sizeof(idxrec_t)*smb.status.total_msgs)) ==NULL) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!Error allocating %u bytes of memory\n" ,beep,sizeof(idxrec_t)*smb.status.total_msgs); return; } fseek(smb.sid_fp,0L,SEEK_SET); for(l=0;l<smb.status.total_msgs;l++) { printf("%lu of %"PRIu32"\r" ,l+1,smb.status.total_msgs); if(!fread(&idx[l],1,sizeof(idxrec_t),smb.sid_fp)) break; } printf("\nDone.\n\n"); printf("Scanning for pre-flagged messages...\n"); for(m=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&MSG_DELETE) flagged++; } printf("\r100%% (%lu pre-flagged for deletion)\n",flagged); if(smb.status.max_age) { printf("Scanning for messages more than %u days old...\n" ,smb.status.max_age); for(m=f=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; if((ulong)now>idx[m].time && (now-idx[m].time)/(24L*60L*60L) >smb.status.max_age) { f++; flagged++; idx[m].attr|=MSG_DELETE; } } /* mark for deletion */ printf("\r100%% (%lu flagged for deletion due to age)\n",f); } printf("Scanning for read messages to be killed...\n"); for(m=f=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) { f++; flagged++; idx[m].attr|=MSG_DELETE; } } printf("\r100%% (%lu flagged for deletion due to read status)\n",f); if(smb.status.max_msgs && l-flagged>smb.status.max_msgs) { printf("Flagging excess messages for deletion...\n"); for(m=n=0,f=flagged;l-flagged>smb.status.max_msgs && m<l;m++) { if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; printf("%lu of %lu\r",++n,(l-f)-smb.status.max_msgs); flagged++; idx[m].attr|=MSG_DELETE; } /* mark for deletion */ printf("\nDone.\n\n"); } if(!flagged) { /* No messages to delete */ free(idx); smb_unlocksmbhdr(&smb); return; } if(!(mode&NOANALYSIS)) { printf("Freeing allocated header and data blocks for deleted messages...\n"); if(!(smb.status.attr&SMB_HYPERALLOC)) { i=smb_open_da(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_open_da returned %d: %s\n" ,beep,i,smb.last_error); bail(1); } i=smb_open_ha(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_open_ha returned %d: %s\n" ,beep,i,smb.last_error); bail(1); } } for(m=n=0;m<l;m++) { if(idx[m].attr&MSG_DELETE) { printf("%lu of %lu\r",++n,flagged); msg.idx=idx[m]; msg.hdr.number=msg.idx.number; if((i=smb_getmsgidx(&smb,&msg))!=0) { fprintf(errfp,"\n%s!smb_getmsgidx returned %d: %s\n" ,beep,i,smb.last_error); continue; } i=smb_lockmsghdr(&smb,&msg); if(i) { fprintf(errfp,"\n%s!smb_lockmsghdr returned %d: %s\n" ,beep,i,smb.last_error); break; } if((i=smb_getmsghdr(&smb,&msg))!=0) { smb_unlockmsghdr(&smb,&msg); fprintf(errfp,"\n%s!smb_getmsghdr returned %d: %s\n" ,beep,i,smb.last_error); break; } msg.hdr.attr|=MSG_DELETE; /* mark header as deleted */ if((i=smb_putmsg(&smb,&msg))!=0) { smb_freemsgmem(&msg); smb_unlockmsghdr(&smb,&msg); fprintf(errfp,"\n%s!smb_putmsg returned %d: %s\n" ,beep,i,smb.last_error); break; } smb_unlockmsghdr(&smb,&msg); if((i=smb_freemsg(&smb,&msg))!=0) { smb_freemsgmem(&msg); fprintf(errfp,"\n%s!smb_freemsg returned %d: %s\n" ,beep,i,smb.last_error); break; } smb_freemsgmem(&msg); } } if(!(smb.status.attr&SMB_HYPERALLOC)) { smb_close_ha(&smb); smb_close_da(&smb); } printf("\nDone.\n\n"); } printf("Re-writing index...\n"); rewind(smb.sid_fp); CHSIZE_FP(smb.sid_fp,0); for(m=n=0;m<l;m++) { if(idx[m].attr&MSG_DELETE) continue; printf("%lu of %lu\r",++n,l-flagged); fwrite(&idx[m],sizeof(idxrec_t),1,smb.sid_fp); } printf("\nDone.\n\n"); fflush(smb.sid_fp); free(idx); smb.status.total_msgs-=flagged; smb_putstatus(&smb); smb_unlocksmbhdr(&smb); }
int sbbs_t::delmail(uint usernumber, int which) { ulong i,l; time_t now; idxrec_t *idxbuf; smbmsg_t msg; now=time(NULL); if((i=smb_getstatus(&smb))!=0) { errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error); return(2); } if(!smb.status.total_msgs) return(0); if((idxbuf=(idxrec_t *)malloc(smb.status.total_msgs*sizeof(idxrec_t)))==NULL) { errormsg(WHERE,ERR_ALLOC,smb.file,smb.status.total_msgs*sizeof(idxrec_t)); return(-1); } if((i=smb_open_da(&smb))!=0) { errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); free(idxbuf); return(i); } if((i=smb_open_ha(&smb))!=0) { smb_close_da(&smb); errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); free(idxbuf); return(i); } smb_rewind(smb.sid_fp); for(l=0;l<smb.status.total_msgs;) { if(smb_fread(&smb,&msg.idx,sizeof(idxrec_t),smb.sid_fp)!=sizeof(idxrec_t)) break; if(!(msg.idx.attr&MSG_PERMANENT) && ((which==MAIL_SENT && usernumber==msg.idx.from) || (which==MAIL_YOUR && usernumber==msg.idx.to) || (which==MAIL_ANY && (usernumber==msg.idx.to || usernumber==msg.idx.from)) || which==MAIL_ALL)) { if(smb.status.max_age && (now<0?0:(uintmax_t)now)>msg.idx.time && (now-msg.idx.time)/(24L*60L*60L)>smb.status.max_age) msg.idx.attr|=MSG_DELETE; else if(msg.idx.attr&MSG_KILLREAD && msg.idx.attr&MSG_READ) msg.idx.attr|=MSG_DELETE; if(msg.idx.attr&MSG_DELETE) { /* Don't need to lock message because base is locked */ if((i=smb_getmsghdr(&smb,&msg))!=0) errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error); else { if(msg.hdr.attr!=msg.idx.attr) { msg.hdr.attr=msg.idx.attr; if((i=smb_putmsghdr(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error); } if((i=smb_freemsg(&smb,&msg))!=0) errormsg(WHERE,ERR_REMOVE,smb.file,i,smb.last_error); if(msg.hdr.auxattr&MSG_FILEATTACH) delfattach(&cfg,&msg); smb_freemsgmem(&msg); } continue; } } idxbuf[l]=msg.idx; l++; } smb_rewind(smb.sid_fp); smb_fsetlength(smb.sid_fp,0); for(i=0;i<l;i++) smb_fwrite(&smb,&idxbuf[i],sizeof(idxrec_t),smb.sid_fp); free(idxbuf); smb.status.total_msgs=l; smb_putstatus(&smb); smb_fflush(smb.sid_fp); smb_close_ha(&smb); smb_close_da(&smb); return(0); }