Factor out code to read mailboxes, and make read more robust

New tel_read_header(), tel_read_body().  Use them in rea(),
show_first_tel(), copy_and_expire().

rea() now stops when it encounters a corrupt telegram, and logs the
problem.  Before, error detection was incomplete, and errors were not
logged.  Corrupt mailboxes could make it crash.

show_first_tel() and copy_and_expire() can now cope with telegrams of
arbitrary length, like rea(), and sanity-check the header fields they
don't actually use.
This commit is contained in:
Markus Armbruster 2009-02-08 11:13:25 +01:00
parent 6f1e669bea
commit 4238323d63
5 changed files with 114 additions and 76 deletions

View file

@ -46,6 +46,7 @@
static int copy_and_expire(FILE *annfp, FILE *tmpfp,
char *tmp_filename, time_t expiry_time);
static int copy_sink(char *, size_t, void *);
void
delete_old_announcements(void)
@ -110,32 +111,18 @@ copy_and_expire(FILE *annfp, FILE *tmpfp, char *tmp_filename,
time_t expiry_time)
{
struct telstr tgm;
int writeit;
char message[MAXTELSIZE]; /* UTF-8 */
int res, writeit;
int deleted = 0;
int saved = 0;
int first = 1;
while (fread(&tgm, sizeof(tgm), 1, annfp) == 1) {
writeit = 1;
if (tgm.tel_length > MAXTELSIZE) {
logerror("bad telegram file header (length=%d)",
tgm.tel_length);
return 0;
}
if (tgm.tel_type > TEL_LAST) {
logerror("bad telegram file header (type=%d)", tgm.tel_type);
return 0;
}
while ((res = tel_read_header(annfp, annfil, &tgm)) > 0) {
writeit = tgm.tel_date >= expiry_time;
if (first) {
first = 0;
if (tgm.tel_date >= expiry_time)
if (writeit)
return 0;
}
if (tgm.tel_date < expiry_time)
writeit = 0;
if (writeit) {
if (fwrite(&tgm, sizeof(tgm), 1, tmpfp) != 1) {
logerror("error writing header to temporary "
@ -145,21 +132,25 @@ copy_and_expire(FILE *annfp, FILE *tmpfp, char *tmp_filename,
++saved;
} else
++deleted;
if (fread(message, 1, tgm.tel_length, annfp) != tgm.tel_length) {
logerror("error reading body from telegram file %s",
annfil);
res = tel_read_body(annfp, annfil, &tgm,
writeit ? copy_sink : NULL, tmpfp);
if (res < 0)
return 0;
}
if (writeit) {
if (fwrite(message, 1, tgm.tel_length, tmpfp)
!= tgm.tel_length) {
logerror("error writing body to temporary telegram "
"file %s", tmp_filename);
return 0;
}
}
}
if (res < 0)
return 0;
logerror("%d announcements deleted; %d announcements saved",
deleted, saved);
return 1;
}
static int
copy_sink(char *chunk, size_t sz, void *fp)
{
if (fwrite(chunk, 1, sz, fp) != sz) {
logerror("error writing to %s.tmp", annfil);
return -1;
}
return 0;
}