(delete_old_announcements, copy_and_expire): Split off

copy_and_expire() to simplify cleanup.  Previously, cleanup was
missing or incomplete on many less common code paths, which leaked
file descriptors and memory, and could corrupt the anno file.  Use
stdio instead of POSIX I/O for writing.  Check for I/O errors
properly.  Treat bad telegram type just like bad telegram length (give
up).  Closes #1013234.
This commit is contained in:
Ron Koenderink 2004-08-21 00:44:20 +00:00
parent 739a695241
commit 7cba668c39

View file

@ -45,97 +45,118 @@
#include "optlist.h" #include "optlist.h"
#include "common.h" #include "common.h"
static int copy_and_expire(FILE *annfp, FILE *tmpfp,
char *tmp_filename, time_t expiry_time);
void void
delete_old_announcements(void) delete_old_announcements(void)
{ {
time_t now; time_t now;
time_t old; time_t old;
struct telstr tgm; FILE *annfp;
FILE *oldfp; FILE *tmpfp;
int tmpfd; char tmp_filename[1024];
s_char tmp_filename[1024]; int copy_file;
int writeit;
s_char message[MAXTELSIZE];
int deleted = 0;
int saved = 0;
int length;
int nbytes;
int first = 1;
time(&now); time(&now);
old = now - days(ANNO_KEEP_DAYS); old = now - days(ANNO_KEEP_DAYS);
logerror("Deleting annos older than %s", ctime(&old)); logerror("Deleting annos older than %s", ctime(&old));
#if !defined(_WIN32) if ((annfp = fopen(annfil, "rb")) == NULL) {
if ((oldfp = fopen(annfil, "r+")) == 0) { logerror("can't open telegram file %s for reading", annfil);
#else
if ((oldfp = fopen(annfil, "r+b")) == 0) {
#endif
logerror("can't read telegram file %s", annfil);
return; return;
} }
sprintf(tmp_filename, "%s.tmp", annfil); sprintf(tmp_filename, "%s.tmp", annfil);
#if !defined(_WIN32) if ((tmpfp = fopen(tmp_filename, "wb")) == NULL) {
if ((tmpfd = logerror("can't open telegram file %s for writing",
open(tmp_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { tmp_filename);
#else if (fclose(annfp) != 0)
if ((tmpfd = logerror("can't close telegram file %s", annfil);
open(tmp_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0666)) < 0) {
#endif
logerror("can't write telegram file %s", tmp_filename);
return; return;
} }
while (fread((s_char *)&tgm, sizeof(tgm), 1, oldfp) == 1) { copy_file = copy_and_expire(annfp, tmpfp, tmp_filename, old);
if (fclose(annfp) != 0) {
logerror("can't close telegram file %s", annfil);
copy_file = 0;
}
if (fclose(tmpfp) != 0) {
logerror("can't close temporary telegram file %s",
tmp_filename);
copy_file = 0;
}
#if defined(_WIN32)
if (copy_file) {
if (unlink(annfil) != 0) {
logerror("can't delete telegram file %s", annfil);
copy_file = 0;
}
}
#endif
if (copy_file) {
if (rename(tmp_filename, annfil) != 0)
logerror("can't move temporary telegram file %s "
"to telegram file %s", tmp_filename, annfil);
}
}
static int
copy_and_expire(FILE *annfp, FILE *tmpfp, char *tmp_filename,
time_t expiry_time)
{
struct telstr tgm;
int writeit;
char message[MAXTELSIZE];
int deleted = 0;
int saved = 0;
int first = 1;
while (fread((void *)&tgm, sizeof(tgm), 1, annfp) == 1) {
writeit = 1; writeit = 1;
if (tgm.tel_length < 0) { if (tgm.tel_length < 0 || tgm.tel_length > MAXTELSIZE) {
logerror("bad telegram file header (length)"); logerror("bad telegram file header (length=%ld)",
return; tgm.tel_length);
return 0;
} }
if (tgm.tel_type < 0 || tgm.tel_type > TEL_LAST) { if (tgm.tel_type < 0 || tgm.tel_type > TEL_LAST) {
logerror("bad telegram file header (type)"); logerror("bad telegram file header (type=%d)",
writeit = 0; tgm.tel_type);
return 0;
} }
if (first) { if (first) {
first = 0; first = 0;
if (tgm.tel_date >= old) { if (tgm.tel_date >= expiry_time)
fclose(oldfp); return 0;
return;
}
} }
if (tgm.tel_date < expiry_time)
if (tgm.tel_date < old) {
writeit = 0; writeit = 0;
}
if (writeit) { if (writeit) {
if (write(tmpfd, &tgm, sizeof(tgm)) < (int)sizeof(tgm)) { if (fwrite((void *)&tgm, sizeof(tgm), 1, tmpfp) != 1) {
logerror("error writing to ann.tmp"); logerror("error writing header to temporary "
return; "telegram file %s", tmp_filename);
return 0;
} }
++saved; ++saved;
} else { } else
++deleted; ++deleted;
if (fread(message, sizeof(char), tgm.tel_length, annfp) !=
(size_t)tgm.tel_length) {
logerror("error reading body from telegram file %s",
annfil);
return 0;
} }
length = tgm.tel_length; if (writeit) {
while (length > 0) { if (fwrite(message, sizeof(char), tgm.tel_length, tmpfp) !=
nbytes = length; (size_t)tgm.tel_length) {
if (nbytes > (int)sizeof(message)) logerror("error writing body to temporary telegram "
nbytes = sizeof(message); "file %s", tmp_filename);
(void)fread(message, sizeof(s_char), nbytes, oldfp); return 0;
if (writeit) {
if (write(tmpfd, message, nbytes) < nbytes) {
logerror("Error writing to ann.tmp");
return;
}
} }
length -= nbytes;
} }
} }
logerror("%d announcements deleted; %d announcements saved", logerror("%d announcements deleted; %d announcements saved",
deleted, saved); deleted, saved);
fclose(oldfp); return 1;
close(tmpfd);
unlink(annfil);
rename(tmp_filename, annfil);
} }