static int want_append_message(struct dlist *dlist, struct sync_msgid_list *keep_message_guids) { struct dlist *di, *next; for (di = dlist->head; di; di = next) { struct message_guid *guid = NULL; /* save next pointer now in case we need to unstitch */ next = di->next; if (!dlist_tofile(di, NULL, &guid, NULL, NULL)) continue; if (!sync_msgid_lookup(keep_message_guids, guid)) { syslog(LOG_DEBUG, "%s: MESSAGE no longer needed: %s", __func__, message_guid_encode(guid)); dlist_unstitch(dlist, di); dlist_unlink_files(di); dlist_free(&di); } } if (dlist->head) { syslog(LOG_DEBUG, "%s: keeping MESSAGE line", __func__); return 1; } syslog(LOG_DEBUG, "%s: MESSAGE line has no more messages", __func__); return 0; }
int dlist_getfile(struct dlist *parent, const char *name, const char **partp, struct message_guid **guidp, unsigned long *sizep, const char **fnamep) { struct dlist *child = dlist_getchild(parent, name); return dlist_tofile(child, partp, guidp, sizep, fnamep); }
static int _verify_message_cb(const struct backup_message *message, void *rock) { struct verify_message_rock *vmrock = (struct verify_message_rock *) rock; struct dlist *dl = NULL; struct dlist *di = NULL; FILE *out = vmrock->out; int r; /* cache the dlist so that multiple reads from the same offset don't * cause expensive reverse seeks in decompression stream */ if (!vmrock->cached_dlist || vmrock->cached_offset != message->offset) { if (vmrock->cached_dlist) { dlist_unlink_files(vmrock->cached_dlist); dlist_free(&vmrock->cached_dlist); } r = gzuc_seekto(vmrock->gzuc, message->offset); if (r) return r; struct protstream *ps = prot_readcb(_prot_fill_cb, vmrock->gzuc); prot_setisclient(ps, 1); /* don't sync literals */ r = parse_backup_line(ps, NULL, NULL, &dl); prot_free(ps); if (r == EOF) { const char *error = prot_error(ps); if (error && 0 != strcmp(error, PROT_EOF_STRING)) { syslog(LOG_ERR, "%s: error reading message %i at offset %jd, byte %i: %s", __func__, message->id, message->offset, prot_bytes_in(ps), error); if (out) fprintf(out, "error reading message %i at offset %jd, byte %i: %s", message->id, message->offset, prot_bytes_in(ps), error); } return r; } vmrock->cached_dlist = dl; vmrock->cached_offset = message->offset; } else { dl = vmrock->cached_dlist; } r = strcmp(dl->name, "MESSAGE"); if (r) return r; r = -1; for (di = dl->head; di; di = di->next) { struct message_guid *guid = NULL; const char *fname = NULL; if (!dlist_tofile(di, NULL, &guid, NULL, &fname)) continue; r = message_guid_cmp(guid, message->guid); if (!r) { if (vmrock->verify_guid) { const char *msg_base = NULL; size_t msg_len = 0; struct message_guid computed_guid; int fd; fd = open(fname, O_RDWR); if (fd != -1) { map_refresh(fd, 1, &msg_base, &msg_len, MAP_UNKNOWN_LEN, fname, NULL); message_guid_generate(&computed_guid, msg_base, msg_len); r = message_guid_cmp(&computed_guid, message->guid); if (r && out) fprintf(out, "guid mismatch for message %i\n", message->id); map_free(&msg_base, &msg_len); close(fd); } else { syslog(LOG_ERR, "IOERROR: %s open %s: %m", __func__, fname); if (out) fprintf(out, "error reading staging file for message %i\n", message->id); r = -1; } } break; } } return r; }