Compare commits

..

No commits in common. "031e28ed33e63c695ac1bfb5d65df57120469026" and "4cacb1534fa6a7fa3d7603182fa6eb96635700ae" have entirely different histories.

4 changed files with 54 additions and 76 deletions

View File

@ -1,23 +1,21 @@
#ifndef VIETER_PACKAGE #ifndef VIETER_PACKAGE
#define VIETER_PACKAGE #define VIETER_PACKAGE
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <archive.h>
#include <archive_entry.h>
typedef struct vieter_package vieter_package; typedef struct vieter_package vieter_package;
typedef enum vieter_package_error {
vieter_package_ok = 0,
vieter_package_unarchive_error = 1,
vieter_package_stat_error = 2
} vieter_package_error;
/*
* Allocate an empty package
*/
vieter_package *vieter_package_init();
/* /*
* Parse package file into something usable by libvieter. * Parse package file into something usable by libvieter.
* The pointer returned by this function will need to freed at a later point.
*/ */
vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path); vieter_package *vieter_package_read_archive(const char *pkg_path);
/* /*
* Deallocate a package. * Deallocate a package.

View File

@ -1,29 +1,30 @@
#include <stdlib.h>
#include <stdbool.h>
#include <archive.h>
#include <archive_entry.h>
#include "vieter_package_internal.h" #include "vieter_package_internal.h"
#include "sha256.h" #include "sha256.h"
#define SMALL_BUFF_SIZE 128
#define ADD_STRING(section, field) if (pkg_info->field != 0) { \ #define ADD_STRING(section, field) if (pkg_info->field != 0) { \
size_to_be_written = snprintf(aux, small_buff_size, section, pkg_info->field); \ snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \
if (size_to_be_written > small_buff_size) { \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \
aux = realloc(aux, size_to_be_written + 1); \
small_buff_size = size_to_be_written + 1; \
snprintf(aux, small_buff_size, section, pkg_info->field); \
} \
if (buff_size < strlen(description) + small_buff_size + 1) { \
description = realloc(description, buff_size * 2); \ description = realloc(description, buff_size * 2); \
buff_size *= 2; \ buff_size *= 2; \
} \ } \
strcat(description, aux); \ strcat(description, aux); \
} }
#define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ #define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \
ADD_STRING(section, field->array[i]); i++; \ snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \
description = realloc(description, buff_size * 2); \
buff_size *= 2; \
} \
strcat(description, aux); \
while (pkg_info->field->array[i] != NULL) { \ while (pkg_info->field->array[i] != NULL) { \
ADD_STRING("\n%s", field->array[i]); i++; \ snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \
description = realloc(description, buff_size * 2); \
buff_size *= 2; \
} \
strcat(description, aux); \
} \ } \
} }
@ -40,7 +41,7 @@ vieter_package *vieter_package_init() {
return calloc(sizeof(vieter_package_info), 1); return calloc(sizeof(vieter_package_info), 1);
} }
vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path) { vieter_package *vieter_package_read_archive(const char *pkg_path) {
struct archive *a = archive_read_new(); struct archive *a = archive_read_new();
struct archive_entry *entry = archive_entry_new(); struct archive_entry *entry = archive_entry_new();
@ -57,7 +58,7 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char
// Exit early if we weren't able to successfully open the archive for reading // Exit early if we weren't able to successfully open the archive for reading
if (r != ARCHIVE_OK) { if (r != ARCHIVE_OK) {
return vieter_package_unarchive_error; return NULL;
} }
int compression_code = archive_filter_code(a, 0); int compression_code = archive_filter_code(a, 0);
@ -103,9 +104,7 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char
struct stat stats; struct stat stats;
if (stat(pkg_path, &stats) != 0) { if (stat(pkg_path, &stats) != 0) {
// errno is set if stat() fails; the calling function should check return NULL;
// the value of errno in case vieter_package_stat_error is returned
return vieter_package_stat_error;
} }
pkg_info->csize = stats.st_size; pkg_info->csize = stats.st_size;
@ -113,31 +112,31 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char
archive_read_free(a); archive_read_free(a);
// Create final return value // Create final return value
vieter_package *pkg = vieter_package_init();
pkg->path = strdup(pkg_path); pkg->path = strdup(pkg_path);
pkg->info = pkg_info; pkg->info = pkg_info;
pkg->files = files; pkg->files = files;
pkg->compression = compression_code; pkg->compression = compression_code;
return vieter_package_ok; return pkg;
} }
void vieter_package_sha256sum(vieter_package *pkg, char *res) { void vieter_package_sha256sum(vieter_package *pkg, char *res) {
FILE *f = fopen(pkg->path, "r"); FILE *f = fopen(pkg->path, "r");
// Try to read 100KiB at a time fseek(f, 0, SEEK_END);
unsigned char *in = malloc(102400); size_t size = ftell(f);
// Actual number of bytes read rewind(f);
size_t read_size; unsigned char *in = malloc(size);
fread(in, 1, size, f);
fclose(f);
unsigned char hash[32];
SHA256_CTX *ctx = malloc(sizeof(SHA256_CTX)); SHA256_CTX *ctx = malloc(sizeof(SHA256_CTX));
sha256_init(ctx);
while ((read_size = fread(in, 1, 102400, f)) != 0) {
sha256_update(ctx, in, read_size);
}
unsigned char hash[SHA256_BLOCK_SIZE];
sha256_init(ctx);
sha256_update(ctx, in, size);
sha256_final(ctx, hash); sha256_final(ctx, hash);
fclose(f);
free(in); free(in);
free(ctx); free(ctx);
@ -148,8 +147,8 @@ void vieter_package_sha256sum(vieter_package *pkg, char *res) {
unsigned int half_byte = 0; unsigned int half_byte = 0;
int j = 0; int j = 0;
// We advance 2 bytes in the string for every one byte of the hash // We advance in the string 2 bytes for every one byte of the hash
for (int i = 0; i < SHA256_BLOCK_SIZE; i++) { for (int i = 0; i < 32; i++) {
// We transform the first half byte into the second character to keep // We transform the first half byte into the second character to keep
// each byte from becoming reversed in the final string // each byte from becoming reversed in the final string
half_byte = hash[i] & 0b1111; half_byte = hash[i] & 0b1111;
@ -171,32 +170,19 @@ void vieter_package_sha256sum(vieter_package *pkg, char *res) {
res[j] = '\0'; res[j] = '\0';
} }
char *vieter_package_to_description(vieter_package *pkg) { char *vieter_package_to_description(vieter_package *pkg) {
vieter_package_info *pkg_info = pkg->info; vieter_package_info *pkg_info = pkg->info;
size_t buff_size = 1024; size_t buff_size = 1024;
int small_buff_size = 128; char aux[SMALL_BUFF_SIZE];
int size_to_be_written;
char *aux = malloc(sizeof(char) * small_buff_size);
char *description = malloc(sizeof(char) * buff_size); char *description = malloc(sizeof(char) * buff_size);
// Helper variable for ADD_ARRAY macro // Helper variable for ADD_ARRAY macro
int i; int i;
// special case for FILENAME // special case for FILENAME
// assuming .pkg.tar.zst; other formats are valid, this should account for that // assuming .pkg.tar.zst; other formats are valid, this should account for that
size_to_be_written = snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name,
pkg_info->version, pkg_info->arch); pkg_info->version, pkg_info->arch);
// We neither want to let an arbritrarily long input to overflow the buffer
// nor to truncate perfectly valid inputs
if (size_to_be_written > small_buff_size) {
aux = realloc(aux, size_to_be_written + 1);
small_buff_size = size_to_be_written + 1;
snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name,
pkg_info->version, pkg_info->arch);
}
strcpy(description, aux); strcpy(description, aux);
ADD_STRING("\n\n%%NAME%%\n%s", name); ADD_STRING("\n\n%%NAME%%\n%s", name);
@ -207,11 +193,11 @@ char *vieter_package_to_description(vieter_package *pkg) {
ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); ADD_STRING("\n\n%%CSIZE%%\n%ld", csize);
ADD_STRING("\n\n%%ISIZE%%\n%ld", size); ADD_STRING("\n\n%%ISIZE%%\n%ld", size);
char checksum[SHA256_BLOCK_SIZE * 2 + 1]; char checksum[65];
vieter_package_sha256sum(pkg, checksum); vieter_package_sha256sum(pkg, checksum);
snprintf(aux, small_buff_size, "\n\n%%SHA256SUM%%\n%s", checksum); snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", checksum);
if (buff_size < strlen(description) + small_buff_size + 1) { if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) {
description = realloc(description, buff_size * 2); description = realloc(description, buff_size * 2);
buff_size *= 2; buff_size *= 2;
} }
@ -230,7 +216,8 @@ char *vieter_package_to_description(vieter_package *pkg) {
ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends); ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends);
ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends); ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends);
strcat(description, "\n\n"); snprintf(aux, SMALL_BUFF_SIZE, "\n\n");
strcat(description, aux);
return description; return description;
} }

View File

@ -12,18 +12,12 @@ void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) {
// An empty vieter_package_dynarray does not have an allocated internal array yet // An empty vieter_package_dynarray does not have an allocated internal array yet
if (da->size == 0) { if (da->size == 0) {
da->array = malloc(sizeof(char*) * da->capacity); da->array = malloc(sizeof(char*) * da->capacity);
// Initialise all char*'s to 0 so array[i] == NULL can be used to see if field is empty
memset(da->array, 0, sizeof(char*) * da->capacity);
} }
// Double array size if it's full // Double array size if it's full
else if (da->size == da->capacity) { else if (da->size == da->capacity) {
// if the realloc fails, access to memory in da->array is lost // if the realloc fails, access to memory in da->array is lost
da->array = realloc(da->array, sizeof(char*) * da->capacity * 2); da->array = realloc(da->array, sizeof(char*) * da->capacity * 2);
da->capacity *= 2; da->capacity *= 2;
// Same as the previous memset, but only for newly allocated pointers
memset(da->array + da->size, 0, sizeof(char*) * da->capacity / 2);
} }
da->array[da->size] = strdup(s); da->array[da->size] = strdup(s);

View File

@ -39,9 +39,8 @@ void test_info_parse() {
} }
void test_pkg_read_archive_files() { void test_pkg_read_archive_files() {
vieter_package *pkg = vieter_package_init(); vieter_package *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst");
vieter_package_error e = vieter_package_read_archive(pkg, "./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive");
TEST_ASSERT_(e == vieter_package_ok, "failure parsing pkg archive");
FILE *f = fopen("./test/package/files", "r"); FILE *f = fopen("./test/package/files", "r");
TEST_ASSERT_(f != NULL, "could not find test files file in ./test/package"); TEST_ASSERT_(f != NULL, "could not find test files file in ./test/package");
@ -59,12 +58,12 @@ void test_pkg_read_archive_files() {
TEST_CHECK(pkg->compression = 14); TEST_CHECK(pkg->compression = 14);
vieter_package_free(&pkg); vieter_package_free(&pkg);
} }
void test_pkg_read_archive_desc() { void test_pkg_read_archive_desc() {
vieter_package *pkg = vieter_package_init(); vieter_package *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst");
vieter_package_error e = vieter_package_read_archive(pkg, "./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive");
TEST_ASSERT_(e == vieter_package_ok, "failure parsing pkg archive");
char *description = vieter_package_to_description(pkg); char *description = vieter_package_to_description(pkg);