Ejemplo n.º 1
0
EXPORTED int gzuc_skip(struct gzuncat *gz, size_t len)
{
    if (gzuc_member_eof(gz)) return -1;

    while (len) {
        unsigned char discard[16 * 1024];

        size_t want = len;
        if (want > sizeof(discard)) want = sizeof(discard);

        ssize_t got = gzuc_read(gz, discard, want);
        if (got == 0) return -1;
        if (got < 0) return got;

        len -= got;
    }

    return 0;
}
Ejemplo n.º 2
0
static int verify_chunk_checksums(struct backup *backup, struct backup_chunk *chunk,
                                  struct gzuncat *gzuc, int verbose, FILE *out)
{
    int r;

    if (out && verbose)
        fprintf(out, "checking chunk %d checksums...\n", chunk->id);

    /* validate file-prior-to-this-chunk checksum */
    if (out && verbose > 1)
        fprintf(out, "  checking file checksum...\n");
    char file_sha1[2 * SHA1_DIGEST_LENGTH + 1];
    sha1_file(backup->fd, backup->data_fname, chunk->offset, file_sha1);
    r = strncmp(chunk->file_sha1, file_sha1, sizeof(file_sha1));
    if (r) {
        syslog(LOG_DEBUG, "%s: %s (chunk %d) file checksum mismatch: %s on disk, %s in index\n",
                __func__, backup->data_fname, chunk->id, file_sha1, chunk->file_sha1);
        if (out)
            fprintf(out, "file checksum mismatch for chunk %d: %s on disk, %s in index\n",
                    chunk->id, file_sha1, chunk->file_sha1);
        goto done;
    }

    /* validate data-within-this-chunk checksum */
    // FIXME length and data_sha1 are set at backup_append_end.
    //       detect and correctly report case where this hasn't occurred.
    if (out && verbose > 1)
        fprintf(out, "  checking data length\n");
    char buf[8192]; /* FIXME whatever */
    size_t len = 0;
    SHA_CTX sha_ctx;
    SHA1_Init(&sha_ctx);
    gzuc_member_start_from(gzuc, chunk->offset);
    while (!gzuc_member_eof(gzuc)) {
        ssize_t n = gzuc_read(gzuc, buf, sizeof(buf));
        if (n >= 0) {
            SHA1_Update(&sha_ctx, buf, n);
            len += n;
        }
    }
    gzuc_member_end(gzuc, NULL);
    if (len != chunk->length) {
        syslog(LOG_DEBUG, "%s: %s (chunk %d) data length mismatch: "
                        SIZE_T_FMT " on disk,"
                        SIZE_T_FMT " in index\n",
                __func__, backup->data_fname, chunk->id, len, chunk->length);
        if (out)
            fprintf(out, "data length mismatch for chunk %d: "
                         SIZE_T_FMT " on disk,"
                         SIZE_T_FMT " in index\n",
                    chunk->id, len, chunk->length);
        r = -1;
        goto done;
    }

    if (out && verbose > 1)
        fprintf(out, "  checking data checksum...\n");
    unsigned char sha1_raw[SHA1_DIGEST_LENGTH];
    char data_sha1[2 * SHA1_DIGEST_LENGTH + 1];
    SHA1_Final(sha1_raw, &sha_ctx);
    r = bin_to_hex(sha1_raw, SHA1_DIGEST_LENGTH, data_sha1, BH_LOWER);
    assert(r == 2 * SHA1_DIGEST_LENGTH);
    r = strncmp(chunk->data_sha1, data_sha1, sizeof(data_sha1));
    if (r) {
        syslog(LOG_DEBUG, "%s: %s (chunk %d) data checksum mismatch: %s on disk, %s in index\n",
                __func__, backup->data_fname, chunk->id, data_sha1, chunk->data_sha1);
        if (out)
            fprintf(out, "data checksum mismatch for chunk %d: %s on disk, %s in index\n",
                    chunk->id, data_sha1, chunk->data_sha1);
        goto done;
    }

done:
    syslog(LOG_DEBUG, "%s: checksum %s!\n", __func__, r ? "failed" : "passed");
    if (out && verbose)
        fprintf(out, "%s\n", r ? "error" : "ok");
    return r;
}