예제 #1
0
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;
}
예제 #2
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);
}
예제 #3
0
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;
}