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; }
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);
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; }