From 3b4687cb028b6f89a9f183a9c29f0f5f6e59c2e9 Mon Sep 17 00:00:00 2001 From: Tomas Mlcoch Date: Wed, 11 Jan 2012 15:15:51 +0100 Subject: [PATCH] Add compute_file_checksum and get_header_byte_range functions. --- misc.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ misc.h | 10 +++++- 2 files changed, 122 insertions(+), 1 deletion(-) diff --git a/misc.c b/misc.c index cd09a9d..732f388 100644 --- a/misc.c +++ b/misc.c @@ -1,8 +1,13 @@ #include +#include #include #include +#include +#include "constants.h" #include "misc.h" +#define BUFFER_SIZE 4096 + const char *flag_to_string(gint64 flags) { @@ -141,3 +146,111 @@ int is_primary(const char *filename) return 0; } + + +char *compute_file_checksum(const char *filename, ChecksumType type) +{ + GChecksumType gchecksumtype; + + // Check if file exists and if it is a regular file (not a directory) + + if (!g_file_test(filename, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) { + return NULL; + } + + // Convert our checksum type into glib type + + switch (type) { + case PKG_CHECKSUM_MD5: + gchecksumtype = G_CHECKSUM_MD5; + break; + case PKG_CHECKSUM_SHA1: + gchecksumtype = G_CHECKSUM_SHA1; + break; + case PKG_CHECKSUM_SHA256: + gchecksumtype = G_CHECKSUM_SHA256; + break; + }; + + // Open file and initialize checksum structure + + FILE *fp = fopen(filename, "rb"); + if (!fp) { + return NULL; + } + + // Calculate checksum + + GChecksum *checksum = g_checksum_new(gchecksumtype); + unsigned char buffer[BUFFER_SIZE]; + + while (1) { + size_t input_len; + input_len = fread((void *) buffer, sizeof(unsigned char), BUFFER_SIZE, fp); + g_checksum_update(checksum, (const guchar *) buffer, input_len); + if (input_len < BUFFER_SIZE) { + break; + } + } + + fclose(fp); + + // Malloc space and get checksum + + const char *checksum_tmp_str = g_checksum_get_string(checksum); + size_t checksum_len = strlen(checksum_tmp_str); + char *checksum_str = (char *) malloc(sizeof(char) * (checksum_len + 1)); + if (!checksum_str) { + g_checksum_free(checksum); + return NULL; + } + strcpy(checksum_str, checksum_tmp_str); + + // Clean up + + g_checksum_free(checksum); + + return checksum_str; +} + + +#define VAL_LEN 4 // Len of numeric values in rpm + +struct HeaderRangeStruct get_header_byte_range(const char *filename) +{ + /* Values readed by fread are 4 bytes long and stored as big-endian. + * So there is htonl function to convert this big-endian number into host byte order. + */ + FILE *fp = fopen(filename, "rb"); + fseek(fp, 104, SEEK_SET); + unsigned int sigindex = 0; + unsigned int sigdata = 0; + fread(&sigindex, VAL_LEN, 1, fp); + sigindex = htonl(sigindex); + fread(&sigdata, VAL_LEN, 1, fp); + sigdata = htonl(sigdata); + unsigned int sigindexsize = sigindex * 16; + unsigned int sigsize = sigdata + sigindexsize; + unsigned int disttoboundary = sigsize % 8; + if (disttoboundary) { + disttoboundary = 8 - disttoboundary; + } + unsigned int hdrstart = 112 + sigsize + disttoboundary; + + fseek(fp, hdrstart, SEEK_SET); + fseek(fp, 8, SEEK_CUR); + + unsigned int hdrindex = 0; + unsigned int hdrdata = 0; + fread(&hdrindex, VAL_LEN, 1, fp); + hdrindex = htonl(hdrindex); + fread(&hdrdata, VAL_LEN, 1, fp); + hdrdata = htonl(hdrdata); + unsigned int hdrindexsize = hdrindex * 16; + unsigned int hdrsize = hdrdata + hdrindexsize + 16; + unsigned int hdrend = hdrstart + hdrsize; + + fclose(fp); + + return (struct HeaderRangeStruct) {hdrstart, hdrend}; +} diff --git a/misc.h b/misc.h index 9f3254e..92aee65 100644 --- a/misc.h +++ b/misc.h @@ -2,10 +2,10 @@ #define __MISC__ #include +#include "constants.h" const char *flag_to_string(gint64 flags); - struct VersionStruct { char *epoch; char *version; @@ -18,5 +18,13 @@ struct VersionStruct { */ struct VersionStruct string_to_version(const char *string, GStringChunk *chunk); int is_primary(const char *filename); +char *compute_file_checksum(const char *filename, ChecksumType type); + +struct HeaderRangeStruct { + unsigned int start; + unsigned int end; +}; +struct HeaderRangeStruct get_header_byte_range(const char *filename); + #endif /* __MISC__ */ -- 2.7.4