예제 #1
0
int
cr_repomd_record_compress_and_fill(cr_RepomdRecord *record,
                                   cr_RepomdRecord *crecord,
                                   cr_ChecksumType checksum_type,
                                   cr_CompressionType record_compression,
                                   GError **err)
{
    const char *suffix;
    gchar *path, *cpath;
    gchar *clocation_real, *clocation_href;
    gchar *checksum, *cchecksum;
    int readed;
    char buf[BUFFER_SIZE];
    CR_FILE *cw_plain;
    CR_FILE *cw_compressed;
    gint64 gf_size = -1, cgf_size = -1;
    gint64 gf_time = -1, cgf_time = -1;
    struct stat gf_stat, cgf_stat;
    const char *checksum_str = cr_checksum_name_str(checksum_type);
    GError *tmp_err = NULL;

    assert(record);
    assert(crecord);
    assert(!err || *err == NULL);

    if (!(record->location_real) || !strlen(record->location_real)) {
        g_set_error(err, CR_REPOMD_RECORD_ERROR, CRE_BADARG,
                    "Empty locations in repomd record object");
        return CRE_BADARG;
    }

    if (!g_file_test(record->location_real, G_FILE_TEST_IS_REGULAR)) {
        // File doesn't exists
        g_warning("%s: File %s doesn't exists", __func__, record->location_real);
        g_set_error(err, CR_REPOMD_RECORD_ERROR, CRE_NOFILE,
                    "File %s doesn't exists or not a regular file",
                    record->location_real);
        return CRE_NOFILE;;
    }

    // Paths

    suffix = cr_compression_suffix(record_compression);

    clocation_real = g_strconcat(record->location_real, suffix, NULL);
    clocation_href = g_strconcat(record->location_href, suffix, NULL);
    crecord->location_real = g_string_chunk_insert(crecord->chunk,
                                                   clocation_real);
    crecord->location_href = g_string_chunk_insert(crecord->chunk,
                                                   clocation_href);
    g_free(clocation_real);
    g_free(clocation_href);

    path  = record->location_real;
    cpath = crecord->location_real;


    // Compress file + get size of non compressed file

    cw_plain = cr_open(path,
                       CR_CW_MODE_READ,
                       CR_CW_NO_COMPRESSION,
                       &tmp_err);
    if (!cw_plain) {
        int code = tmp_err->code;
        g_propagate_prefixed_error(err, tmp_err, "Cannot open %s: ", path);
        return code;
    }

    cw_compressed = cr_open(cpath,
                            CR_CW_MODE_WRITE,
                            record_compression,
                            &tmp_err);
    if (!cw_compressed) {
        int code = tmp_err->code;
        g_propagate_prefixed_error(err, tmp_err, "Cannot open %s: ", cpath);
        return code;
    }

    while ((readed = cr_read(cw_plain, buf, BUFFER_SIZE, &tmp_err)) > 0) {
        cr_write(cw_compressed, buf, (unsigned int) readed, &tmp_err);
        if (tmp_err)
            break;
    }

    cr_close(cw_plain, NULL);

    if (tmp_err) {
        int code = tmp_err->code;
        cr_close(cw_compressed, NULL);
        g_debug("%s: Error while repomd record compression: %s", __func__,
                tmp_err->message);
        g_propagate_prefixed_error(err, tmp_err,
                "Error while compression %s -> %s:", path, cpath);
        return code;
    }

    cr_close(cw_compressed, &tmp_err);
    if (tmp_err) {
        int code = tmp_err->code;
        g_propagate_prefixed_error(err, tmp_err,
                "Error while closing %s: ", path);
        return code;
    }


    // Compute checksums

    checksum  = cr_checksum_file(path, checksum_type, &tmp_err);
    if (tmp_err) {
        int code = tmp_err->code;
        g_propagate_prefixed_error(err, tmp_err,
                                   "Error while checksum calculation:");
        return code;
    }

    cchecksum = cr_checksum_file(cpath, checksum_type, &tmp_err);
    if (tmp_err) {
        int code = tmp_err->code;
        g_propagate_prefixed_error(err, tmp_err,
                                   "Error while checksum calculation:");
        return code;
    }


    // Get stats

    if (stat(path, &gf_stat)) {
        g_debug("%s: Error while stat() on %s", __func__, path);
        g_set_error(err, CR_REPOMD_RECORD_ERROR, CRE_IO,
                    "Cannot stat %s", path);
        return CRE_IO;
    } else {
        gf_size = gf_stat.st_size;
        gf_time = gf_stat.st_mtime;
    }

    if (stat(cpath, &cgf_stat)) {
        g_debug("%s: Error while stat() on %s", __func__, cpath);
        g_set_error(err, CR_REPOMD_RECORD_ERROR, CRE_IO,
                    "Cannot stat %s", cpath);
        return CRE_IO;
    } else {
        cgf_size = cgf_stat.st_size;
        cgf_time = cgf_stat.st_mtime;
    }


    // Results

    record->checksum = g_string_chunk_insert(record->chunk, checksum);
    record->checksum_type = g_string_chunk_insert(record->chunk, checksum_str);
    record->checksum_open = NULL;
    record->checksum_open_type = NULL;
    record->timestamp = gf_time;
    record->size = gf_size;
    record->size_open = -1;

    crecord->checksum = g_string_chunk_insert(crecord->chunk, cchecksum);
    crecord->checksum_type = g_string_chunk_insert(crecord->chunk, checksum_str);
    crecord->checksum_open = g_string_chunk_insert(record->chunk, checksum);
    crecord->checksum_open_type = g_string_chunk_insert(record->chunk, checksum_str);
    crecord->timestamp = cgf_time;
    crecord->size = cgf_size;
    crecord->size_open = gf_size;

    g_free(checksum);
    g_free(cchecksum);

    return CRE_OK;
}
예제 #2
0
static char *
get_checksum(const char *filename,
             cr_ChecksumType type,
             cr_Package *pkg,
             const char *cachedir,
             GError **err)
{
    GError *tmp_err = NULL;
    char *checksum = NULL;
    char *cachefn = NULL;

    if (cachedir) {
        // Prepare cache fn
        char *key;
        cr_ChecksumCtx *ctx = cr_checksum_new(type, err);
        if (!ctx) return NULL;

        if (pkg->siggpg)
            cr_checksum_update(ctx, pkg->siggpg->data, pkg->siggpg->size, NULL);
        if (pkg->sigpgp)
            cr_checksum_update(ctx, pkg->sigpgp->data, pkg->sigpgp->size, NULL);
        if (pkg->hdrid)
            cr_checksum_update(ctx, pkg->hdrid, strlen(pkg->hdrid), NULL);

        key = cr_checksum_final(ctx, err);
        if (!key) return NULL;

        cachefn = g_strdup_printf("%s%s-%s-%"G_GINT64_FORMAT"-%"G_GINT64_FORMAT,
                                  cachedir,
                                  cr_get_filename(pkg->location_href),
                                  key, pkg->size_installed, pkg->time_file);
        free(key);

        // Try to load checksum
        FILE *f = fopen(cachefn, "r");
        if (f) {
            char buf[CACHEDCHKSUM_BUFFER_LEN];
            size_t readed = fread(buf, 1, CACHEDCHKSUM_BUFFER_LEN, f);
            if (!ferror(f) && readed > 0) {
                checksum = g_strndup(buf, readed);
            }
            fclose(f);
        }

        if (checksum) {
            g_debug("Cached checksum used: %s: \"%s\"", cachefn, checksum);
            goto exit;
        }
    }

    // Calculate checksum
    checksum = cr_checksum_file(filename, type, &tmp_err);
    if (!checksum) {
        g_propagate_prefixed_error(err, tmp_err,
                                   "Error while checksum calculation: ");
        goto exit;
    }

    // Cache the checksum value
    if (cachefn && !g_file_test(cachefn, G_FILE_TEST_EXISTS)) {
        gchar *template = g_strconcat(cachefn, "-XXXXXX", NULL);
예제 #3
0
int
cr_repomd_record_fill(cr_RepomdRecord *md,
                      cr_ChecksumType checksum_type,
                      GError **err)
{
    const char *checksum_str;
    cr_ChecksumType checksum_t;
    gchar *path;
    GError *tmp_err = NULL;

    assert(md);
    assert(!err || *err == NULL);

    if (!(md->location_real) || !strlen(md->location_real)) {
        g_set_error(err, CR_REPOMD_RECORD_ERROR, CRE_BADARG,
                    "Empty locations in repomd record object.");
        return CRE_BADARG;
    }

    path = md->location_real;

    checksum_str = cr_checksum_name_str(checksum_type);
    checksum_t = checksum_type;

    if (!g_file_test(path, G_FILE_TEST_IS_REGULAR)) {
        // File doesn't exists
        g_warning("%s: File %s doesn't exists", __func__, path);
        g_set_error(err, CR_REPOMD_RECORD_ERROR, CRE_NOFILE,
                    "File %s doesn't exists or not a regular file", path);
        return CRE_NOFILE;
    }


    // Compute checksum of compressed file

    if (!md->checksum_type || !md->checksum) {
        gchar *chksum;

        chksum = cr_checksum_file(path, checksum_t, &tmp_err);
        if (tmp_err) {
            int code = tmp_err->code;
            g_propagate_prefixed_error(err, tmp_err,
                "Error while checksum calculation of %s:", path);
            return code;
        }

        md->checksum_type = g_string_chunk_insert(md->chunk, checksum_str);
        md->checksum = g_string_chunk_insert(md->chunk, chksum);
        g_free(chksum);
    }


    // Compute checksum of non compressed content and its size

    if (!md->checksum_open_type || !md->checksum_open || !md->size_open) {
        cr_CompressionType com_type = cr_detect_compression(path, &tmp_err);
        if (tmp_err) {
            int code = tmp_err->code;
            g_propagate_prefixed_error(err, tmp_err,
                    "Cannot detect compression type of %s: ", path);
            return code;
        }

        if (com_type != CR_CW_UNKNOWN_COMPRESSION &&
            com_type != CR_CW_NO_COMPRESSION)
        {
            // File compressed by supported algorithm
            contentStat *open_stat = NULL;

            open_stat = cr_get_compressed_content_stat(path, checksum_t, &tmp_err);
            if (tmp_err) {
                int code = tmp_err->code;
                g_propagate_prefixed_error(err, tmp_err,
                    "Error while computing stat of compressed content of %s:",
                    path);
                return code;
            }

            md->checksum_open_type = g_string_chunk_insert(md->chunk, checksum_str);
            md->checksum_open = g_string_chunk_insert(md->chunk, open_stat->checksum);
            if (!md->size_open)
                md->size_open = open_stat->size;
            g_free(open_stat->checksum);
            g_free(open_stat);
        } else {
            if (com_type != CR_CW_NO_COMPRESSION) {
                // Unknown compression
                g_warning("%s: File \"%s\" compressed by an unsupported type"
                          " of compression", __func__, path);
            }
            md->checksum_open_type = NULL;
            md->checksum_open = NULL;
            md->size_open = -1;
        }
    }


    // Get timestamp and size of compressed file

    if (!md->timestamp || !md->size) {
        struct stat buf;
        if (!stat(path, &buf)) {
            if (!md->timestamp) {
                md->timestamp = buf.st_mtime;
            }
            if (!md->size) {
                md->size = buf.st_size;
            }
        } else {
            g_warning("%s: Stat on file \"%s\" failed", __func__, path);
            g_set_error(err, CR_REPOMD_RECORD_ERROR, CRE_STAT,
                        "Stat() on %s failed: %s", path, strerror(errno));
            return CRE_STAT;
        }
    }


    // Set db version

    if (!md->db_ver)
        md->db_ver = DEFAULT_DATABASE_VERSION;

    return CRE_OK;
}