Refactor package module into C #6
15
Makefile
|
@ -6,15 +6,20 @@ LIB_FILENAME ?= libvieter.a
|
||||||
BUILD_DIR ?= build
|
BUILD_DIR ?= build
|
||||||
SRC_DIR ?= src
|
SRC_DIR ?= src
|
||||||
TEST_DIR ?= test
|
TEST_DIR ?= test
|
||||||
INC_DIRS ?= include
|
3RDPARTY_DIR ?= thirdparty
|
||||||
|
INCLUDE_DIR ?= include
|
||||||
|
|
||||||
|
INC_DIRS ?= $(INCLUDE_DIR) $(3RDPARTY_DIR)/include
|
||||||
LIB := $(BUILD_DIR)/$(LIB_FILENAME)
|
LIB := $(BUILD_DIR)/$(LIB_FILENAME)
|
||||||
|
|
||||||
SRCS != find '$(SRC_DIR)' -iname '*.c'
|
SRCS != find '$(SRC_DIR)' -iname '*.c'
|
||||||
SRCS_H != find $(INC_DIRS) '$(SRC_DIR)' -iname '*.h'
|
SRCS_H != find $(INC_DIRS) '$(SRC_DIR)' -iname '*.h'
|
||||||
SRCS_TEST != find '$(TEST_DIR)' -iname '*.c'
|
SRCS_TEST != find '$(TEST_DIR)' -iname '*.c'
|
||||||
|
SRCS_3RDPARTY != find '$(3RDPARTY_DIR)/src' -iname '*.c'
|
||||||
|
|
||||||
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
|
$(info ${SRCS})
|
||||||
|
|
||||||
|
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) $(SRCS_3RDPARTY:%=$(BUILD_DIR)/%.o)
|
||||||
OBJS_TEST := $(SRCS_TEST:%=$(BUILD_DIR)/%.o)
|
OBJS_TEST := $(SRCS_TEST:%=$(BUILD_DIR)/%.o)
|
||||||
DEPS := $(SRCS:%=$(BUILD_DIR)/%.d) $(SRCS_TEST:%=$(BUILD_DIR)/%.d)
|
DEPS := $(SRCS:%=$(BUILD_DIR)/%.d) $(SRCS_TEST:%=$(BUILD_DIR)/%.d)
|
||||||
|
|
||||||
|
@ -22,6 +27,7 @@ BINS_TEST := $(OBJS_TEST:%.c.o=%)
|
||||||
TARGETS_TEST := $(BINS_TEST:%=test-%)
|
TARGETS_TEST := $(BINS_TEST:%=test-%)
|
||||||
TARGETS_MEM_TEST := $(BINS_TEST:%=test-mem-%)
|
TARGETS_MEM_TEST := $(BINS_TEST:%=test-mem-%)
|
||||||
|
|
||||||
|
LIBFLAGS := -larchive
|
||||||
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
|
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
|
||||||
|
|
||||||
# -MMD: generate a .d file for every source file. This file can be imported by
|
# -MMD: generate a .d file for every source file. This file can be imported by
|
||||||
|
@ -50,6 +56,9 @@ $(BUILD_DIR)/$(SRC_DIR)/%.c.o: $(SRC_DIR)/%.c
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
$(CC) $(VIETERCFLAGS) -c $< -o $@
|
$(CC) $(VIETERCFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(BUILD_DIR)/$(3RDPARTY_DIR)/src/%.c.o: $(3RDPARTY_DIR)/src/%.c
|
||||||
|
mkdir -p $(dir $@)
|
||||||
|
$(CC) $(VIETERCFLAGS) -c $< -o $@
|
||||||
|
|
||||||
# =====TESTING=====
|
# =====TESTING=====
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
|
@ -71,7 +80,7 @@ build-test: $(BINS_TEST)
|
||||||
|
|
||||||
$(BINS_TEST): %: %.c.o $(LIB)
|
$(BINS_TEST): %: %.c.o $(LIB)
|
||||||
$(CC) \
|
$(CC) \
|
||||||
$^ -o $@
|
$^ $(LIBFLAGS) -o $@
|
||||||
|
|
||||||
# Along with the include directory, each test includes $(TEST_DIR) (which
|
# Along with the include directory, each test includes $(TEST_DIR) (which
|
||||||
# contains the acutest.h header file), and the src directory of the module it's
|
# contains the acutest.h header file), and the src directory of the module it's
|
||||||
|
|
|
@ -15,6 +15,10 @@ See the [source code](src) for the list of modules.
|
||||||
Everything is handled by the provided Makefile. To compile the static library,
|
Everything is handled by the provided Makefile. To compile the static library,
|
||||||
simply run `make`.
|
simply run `make`.
|
||||||
|
|
||||||
|
### Required libraries
|
||||||
|
|
||||||
|
Libvieter requires libarchive.
|
||||||
|
|
||||||
### Project structure
|
### Project structure
|
||||||
|
|
||||||
Each module has its own subdirectory inside `src`, e.g. `src/cron`. This
|
Each module has its own subdirectory inside `src`, e.g. `src/cron`. This
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef VIETER_DYNARRAY
|
||||||
|
#define VIETER_DYNARRAY
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct vieter_dynarray {
|
||||||
|
char **array;
|
||||||
|
size_t capacity;
|
||||||
|
size_t size;
|
||||||
|
} vieter_dynarray;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a dynamic array.
|
||||||
|
*/
|
||||||
|
vieter_dynarray *vieter_dynarray_init(size_t initial_capacity);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise array (if it's not already initialised) and insert a string.
|
||||||
|
*/
|
||||||
|
void vieter_dynarray_add(vieter_dynarray *da, const char *s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deallocate dynamic array.
|
||||||
|
*/
|
||||||
|
void vieter_dynarray_free(vieter_dynarray *da);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a vieter_dynarray into an array by freeing all its surrounding
|
||||||
|
* components and returning the underlying array pointer.
|
||||||
|
*/
|
||||||
|
char **vieter_dynarray_convert(vieter_dynarray *da);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef VIETER_PACKAGE
|
||||||
|
#define 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.
|
||||||
|
*/
|
||||||
|
vieter_package_error vieter_package_read_archive(vieter_package *pkg,
|
||||||
|
const char *pkg_path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|||||||
|
* Deallocate a package.
|
||||||
|
*/
|
||||||
|
void vieter_package_free(vieter_package **ptp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create string that will become the package's desc file.
|
||||||
|
*/
|
||||||
|
char *vieter_package_to_description(vieter_package *pkg);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,58 @@
|
||||||
|
#include "vieter_dynarray.h"
|
||||||
|
|
||||||
|
vieter_dynarray *vieter_dynarray_init(size_t initial_capacity) {
|
||||||
|
vieter_dynarray *da = malloc(sizeof(vieter_dynarray));
|
||||||
|
da->size = 0;
|
||||||
|
da->capacity = initial_capacity;
|
||||||
|
|
||||||
|
return da;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vieter_dynarray_add(vieter_dynarray *da, const char *s) {
|
||||||
|
// An empty vieter_dynarray does not have an allocated internal array
|
||||||
|
// yet
|
||||||
|
if (da->size == 0) {
|
||||||
|
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
|
||||||
|
else if (da->size == da->capacity) {
|
||||||
|
// if the realloc fails, access to memory in da->array is lost
|
||||||
|
da->array = realloc(da->array, sizeof(char *) * 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->size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vieter_dynarray_free(vieter_dynarray *da) {
|
||||||
|
if (da == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (da->array != NULL) {
|
||||||
|
for (size_t i = 0; i < da->size; i++) {
|
||||||
|
free(da->array[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(da->array);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(da);
|
||||||
|
}
|
||||||
|
|
||||||
|
char **vieter_dynarray_convert(vieter_dynarray *da) {
|
||||||
|
char **array = da->array;
|
||||||
|
|
||||||
|
da->array = NULL;
|
||||||
|
vieter_dynarray_free(da);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
# package
|
||||||
|
|
||||||
|
This module handles both parsing the published Arch tarballs & the contents of
|
||||||
|
their `.PKGINFO` files, as well as generating the contents of the database
|
||||||
|
archives' `desc` & `files` files.
|
|
@ -0,0 +1,263 @@
|
||||||
|
#include <archive.h>
|
||||||
|
#include <archive_entry.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "sha256.h"
|
||||||
|
#include "vieter_package_internal.h"
|
||||||
Jef Roosens
commented
Outdated
Review
General note for General note for `snprintf` usage: what happens if the value is larger than the buffer? Is it simply cut off? Cuz if so, we shouldn't be making assumptions about the length of the input.
GreekStapler
commented
Outdated
Review
I used I used `snprintf` because I didn't want to risk any buffer overflows, but it can truncate perfectly valid inputs if they are long enough (e.g. very long url). I'll turn `aux` into a malloc'd string and use the return value of `snprintf` to reallocate memory as is necessary without any overflows.
|
|||||||
|
|
||||||
|
#define ADD_STRING(section, field) \
|
||||||
|
if (pkg_info->field != 0) { \
|
||||||
|
size_to_be_written = \
|
||||||
|
snprintf(aux, small_buff_size, section, pkg_info->field); \
|
||||||
|
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, section, pkg_info->field); \
|
||||||
|
} \
|
||||||
|
if (buff_size < strlen(description) + small_buff_size + 1) { \
|
||||||
|
description = realloc(description, buff_size * 2); \
|
||||||
|
buff_size *= 2; \
|
||||||
|
} \
|
||||||
Jef Roosens
commented
Outdated
Review
This check is not safe, the dynarray code doesn't make any guarantees about empty fields being NULL, they're simply malloc'ed and not initialised. This check is not safe, the dynarray code doesn't make any guarantees about empty fields being NULL, they're simply malloc'ed and not initialised.
|
|||||||
|
strcat(description, aux); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADD_ARRAY(section, field) \
|
||||||
|
i = 0; \
|
||||||
|
if (pkg_info->field != NULL) { \
|
||||||
|
ADD_STRING(section, field->array[i]); \
|
||||||
|
i++; \
|
||||||
|
while (pkg_info->field->array[i] != NULL) { \
|
||||||
|
ADD_STRING("\n%s", field->array[i]); \
|
||||||
|
i++; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *ignored_names[5] = {".BUILDINFO", ".INSTALL", ".MTREE", ".PKGINFO",
|
||||||
|
".CHANGELOG"};
|
||||||
|
static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *);
|
||||||
|
|
||||||
|
vieter_package *vieter_package_init() {
|
||||||
|
return calloc(sizeof(vieter_package_info), 1);
|
||||||
GreekStapler marked this conversation as resolved
Outdated
Jef Roosens
commented
Outdated
Review
Shouldn't this be Shouldn't this be `sizeof(a package)`?
|
|||||||
|
}
|
||||||
|
|
||||||
|
vieter_package_error vieter_package_read_archive(vieter_package *pkg,
|
||||||
|
const char *pkg_path) {
|
||||||
|
struct archive *a = archive_read_new();
|
||||||
|
struct archive_entry *entry;
|
||||||
|
|
||||||
|
// These three are the most commonly used compression methods
|
||||||
|
archive_read_support_filter_zstd(a);
|
||||||
|
archive_read_support_filter_gzip(a);
|
||||||
|
archive_read_support_filter_xz(a);
|
||||||
|
|
||||||
|
// Contents should always be a tarball
|
||||||
|
archive_read_support_format_tar(a);
|
||||||
|
|
||||||
|
// TODO where does this 10240 come from?
|
||||||
|
int r = archive_read_open_filename(a, pkg_path, 10240);
|
||||||
|
|
||||||
|
// Exit early if we weren't able to successfully open the archive for reading
|
||||||
|
if (r != ARCHIVE_OK) {
|
||||||
Jef Roosens
commented
Outdated
Review
Returning See the heap module for an example. Returning `NULL` when a function fails doesn't say anything about why the function failed. A better API imo (which I also use in the heap module) is for the function to return an enum value intead, indicating the success of the function. The output is written to a pointer-to-pointer that is passed as the first argument of the function.
See the heap module for an example.
|
|||||||
|
return vieter_package_unarchive_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compression_code = archive_filter_code(a, 0);
|
||||||
|
const char *path_name;
|
||||||
|
|
||||||
|
vieter_package_info *pkg_info = NULL;
|
||||||
|
vieter_dynarray *files = vieter_dynarray_init(16);
|
||||||
|
vieter_dynarray_add(files, "%FILES%");
|
||||||
|
|
||||||
|
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||||
|
path_name = archive_entry_pathname(entry);
|
||||||
|
|
||||||
|
bool ignore = false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ignored_words_len; i++) {
|
||||||
|
if (strcmp(path_name, ignored_names[i]) == 0) {
|
||||||
|
ignore = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ignore) {
|
||||||
|
vieter_dynarray_add(files, path_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(path_name, ".PKGINFO") == 0) {
|
||||||
|
// Read data of file into memory buffer
|
||||||
|
int size = archive_entry_size(entry);
|
||||||
|
char *buf = malloc(size + 1);
|
||||||
|
archive_read_data(a, buf, size);
|
||||||
|
buf[size] = '\0';
|
||||||
|
|
||||||
|
// Parse package vieter_package_info string into a struct
|
||||||
|
pkg_info = vieter_package_info_init();
|
||||||
|
vieter_package_info_parse(pkg_info, buf);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
} else {
|
||||||
|
archive_read_data_skip(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get size of file
|
||||||
|
struct stat stats;
|
||||||
Jef Roosens
commented
Outdated
Review
Same here Same here
|
|||||||
|
|
||||||
|
if (stat(pkg_path, &stats) != 0) {
|
||||||
|
// errno is set if stat() fails; the calling function should check
|
||||||
|
// the value of errno in case vieter_package_stat_error is returned
|
||||||
|
return vieter_package_stat_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg_info->csize = stats.st_size;
|
||||||
|
|
||||||
|
archive_read_free(a);
|
||||||
|
|
||||||
|
// Create final return value
|
||||||
|
pkg->path = strdup(pkg_path);
|
||||||
|
pkg->info = pkg_info;
|
||||||
|
pkg->files = files;
|
||||||
|
pkg->compression = compression_code;
|
||||||
|
|
||||||
|
return vieter_package_ok;
|
||||||
Jef Roosens
commented
Outdated
Review
As mentioned on matrix, this function should become a streaming one. As mentioned on matrix, this function should become a streaming one.
|
|||||||
|
}
|
||||||
|
|
||||||
|
void vieter_package_sha256sum(vieter_package *pkg, char *res) {
|
||||||
|
FILE *f = fopen(pkg->path, "r");
|
||||||
|
// Try to read 100KiB at a time
|
||||||
|
unsigned char *in = malloc(102400);
|
||||||
|
// Actual number of bytes read
|
||||||
|
size_t read_size;
|
||||||
|
|
||||||
|
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_final(ctx, hash);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
free(in);
|
||||||
|
free(ctx);
|
||||||
|
|
||||||
|
// We need to convert the bytes in the hash to get a string representation of
|
||||||
|
// its hex values i.e. turn 1001 1111 into the string "9f" Each byte of the
|
||||||
|
// hash is going to turn into two bytes in the final string so we are going to
|
||||||
|
// convert each half byte into a char
|
||||||
|
unsigned int half_byte = 0;
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
// We advance 2 bytes in the string for every one byte of the hash
|
||||||
|
for (int i = 0; i < SHA256_BLOCK_SIZE; i++) {
|
||||||
Jef Roosens
commented
Outdated
Review
Oh smart, no array indexing required, didn't even think of that ;p Oh smart, no array indexing required, didn't even think of that ;p
|
|||||||
|
// We transform the first half byte into the second character to keep
|
||||||
|
// each byte from becoming reversed in the final string
|
||||||
|
half_byte = hash[i] & 0b1111;
|
||||||
|
if (half_byte < 10) {
|
||||||
|
res[j + 1] = half_byte + 48;
|
||||||
|
} else {
|
||||||
|
res[j + 1] = half_byte + 87;
|
||||||
|
}
|
||||||
|
hash[i] = hash[i] >> 4;
|
||||||
|
half_byte = hash[i] & 0b1111;
|
||||||
|
if (half_byte < 10) {
|
||||||
|
res[j] = half_byte + 48;
|
||||||
|
} else {
|
||||||
|
res[j] = half_byte + 87;
|
||||||
|
}
|
||||||
|
|
||||||
|
j += 2;
|
||||||
|
}
|
||||||
|
res[j] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
Jef Roosens
commented
Outdated
Review
This should also use This should also use `SMALL_BUFF_SIZE` I think, just for consistency.
|
|||||||
|
char *vieter_package_to_description(vieter_package *pkg) {
|
||||||
|
vieter_package_info *pkg_info = pkg->info;
|
||||||
|
|
||||||
|
size_t buff_size = 1024;
|
||||||
|
int small_buff_size = 128;
|
||||||
|
int size_to_be_written;
|
||||||
|
char *aux = malloc(sizeof(char) * small_buff_size);
|
||||||
|
char *description = malloc(sizeof(char) * buff_size);
|
||||||
Jef Roosens
commented
Outdated
Review
Vieter doesn't only supports zstd-compressed archives. Currently it also accepts xz- or gzip-compressed archives, so this should be accounted for. This choice was made noteably because Archlinux ARM uses xz-compressed archives instead of zstd. Vieter doesn't only supports zstd-compressed archives. Currently it also accepts xz- or gzip-compressed archives, so this should be accounted for.
This choice was made noteably because Archlinux ARM uses xz-compressed archives instead of zstd.
|
|||||||
|
// Helper variable for ADD_ARRAY macro
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// special case for FILENAME
|
||||||
|
char *ext = NULL;
|
||||||
|
switch (pkg->compression) {
|
||||||
|
case 0:
|
||||||
|
ext = ".tar";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ext = ".tar.gz";
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
ext = ".tar.xz";
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
ext = ".tar.zst";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_to_be_written =
|
||||||
|
snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg%s",
|
||||||
|
pkg_info->name, pkg_info->version, pkg_info->arch, ext);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
ADD_STRING("\n\n%%NAME%%\n%s", name);
|
||||||
|
ADD_STRING("\n\n%%BASE%%\n%s", base);
|
||||||
|
ADD_STRING("\n\n%%VERSION%%\n%s", version);
|
||||||
|
ADD_STRING("\n\n%%DESC%%\n%s", description);
|
||||||
|
ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups);
|
||||||
|
ADD_STRING("\n\n%%CSIZE%%\n%ld", csize);
|
||||||
|
ADD_STRING("\n\n%%ISIZE%%\n%ld", size);
|
||||||
|
|
||||||
|
char checksum[SHA256_BLOCK_SIZE * 2 + 1];
|
||||||
|
vieter_package_sha256sum(pkg, checksum);
|
||||||
|
|
||||||
|
snprintf(aux, small_buff_size, "\n\n%%SHA256SUM%%\n%s", checksum);
|
||||||
|
if (buff_size < strlen(description) + small_buff_size + 1) {
|
||||||
|
description = realloc(description, buff_size * 2);
|
||||||
|
buff_size *= 2;
|
||||||
|
}
|
||||||
|
strcat(description, aux);
|
||||||
|
|
||||||
|
ADD_STRING("\n\n%%URL%%\n%s", url);
|
||||||
|
ADD_ARRAY("\n\n%%LICENSE%%\n%s", licenses);
|
||||||
|
ADD_STRING("\n\n%%ARCH%%\n%s", arch);
|
||||||
|
ADD_STRING("\n\n%%BUILDDATE%%\n%ld", build_date);
|
||||||
|
ADD_STRING("\n\n%%PACKAGER%%\n%s", packager);
|
||||||
|
ADD_ARRAY("\n\n%%REPLACES%%\n%s", replaces);
|
||||||
|
ADD_ARRAY("\n\n%%CONFLICTS%%\n%s", conflicts);
|
||||||
|
ADD_ARRAY("\n\n%%PROVIDES%%\n%s", provides);
|
||||||
|
ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends);
|
||||||
|
ADD_ARRAY("\n\n%%OPTDEPENDS%%\n%s", optdepends);
|
||||||
|
ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends);
|
||||||
|
ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends);
|
||||||
|
|
||||||
|
strcat(description, "\n\n");
|
||||||
|
|
||||||
|
free(aux);
|
||||||
|
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vieter_package_free(vieter_package **ptp) {
|
||||||
|
FREE_STRING((*ptp)->path);
|
||||||
|
vieter_package_info_free((*ptp)->info);
|
||||||
|
vieter_dynarray_free((*ptp)->files);
|
||||||
|
free(*ptp);
|
||||||
|
*ptp = NULL;
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "vieter_package_info.h"
|
||||||
|
|
||||||
|
#define PKG_INFO_STRING(key_ptr, field) \
|
||||||
|
if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \
|
||||||
Jef Roosens
commented
Outdated
Review
How does this work? How does this work? `strstr` doens't write any terminating NULL bytes for the substring or anything, so won't this `strlen` call return the entire remaining size of the pkginfo string?
GreekStapler
commented
Outdated
Review
The The pkginfo string in here is The `strlen` is called on `key_ptr` which is just a small self contained string (e.g. "\ngroup = ") that is null terminated.
The pkginfo string in here is `value_ptr`.
|
|||||||
|
value_ptr += strlen(key_ptr); \
|
||||||
|
tail_ptr = strchr(value_ptr, '\n'); \
|
||||||
|
tail_ptr[0] = '\0'; \
|
||||||
|
pkg_info->field = strdup(value_ptr); \
|
||||||
|
tail_ptr[0] = '\n'; \
|
||||||
|
} \
|
||||||
|
value_ptr = tail_ptr;
|
||||||
|
|
||||||
|
#define PKG_INFO_INT(key_ptr, field) \
|
||||||
|
value_ptr = strstr(value_ptr, key_ptr) + strlen(key_ptr); \
|
||||||
|
tail_ptr = strchr(value_ptr, '\n'); \
|
||||||
|
tail_ptr[0] = '\0'; \
|
||||||
|
pkg_info->field = atoi(value_ptr); \
|
||||||
|
tail_ptr[0] = '\n'; \
|
||||||
|
value_ptr = tail_ptr;
|
||||||
|
|
||||||
|
#define PKG_INFO_ARRAY(key_ptr, field) \
|
||||||
|
while ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \
|
||||||
|
value_ptr = value_ptr + strlen(key_ptr); \
|
||||||
|
tail_ptr = strchr(value_ptr, '\n'); \
|
||||||
|
tail_ptr[0] = '\0'; \
|
||||||
|
if (pkg_info->field == NULL) { \
|
||||||
|
pkg_info->field = vieter_dynarray_init(4); \
|
||||||
|
} \
|
||||||
|
vieter_dynarray_add(pkg_info->field, value_ptr); \
|
||||||
|
tail_ptr[0] = '\n'; \
|
||||||
|
value_ptr = tail_ptr; \
|
||||||
|
} \
|
||||||
|
value_ptr = tail_ptr;
|
||||||
|
|
||||||
|
vieter_package_info *vieter_package_info_init() {
|
||||||
|
return calloc(1, sizeof(vieter_package_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
void vieter_package_info_free(vieter_package_info *pkg_info) {
|
||||||
|
FREE_STRING(pkg_info->name);
|
||||||
|
FREE_STRING(pkg_info->base);
|
||||||
|
FREE_STRING(pkg_info->version);
|
||||||
|
FREE_STRING(pkg_info->description);
|
||||||
|
FREE_STRING(pkg_info->url);
|
||||||
|
FREE_STRING(pkg_info->arch);
|
||||||
|
FREE_STRING(pkg_info->packager);
|
||||||
|
FREE_STRING(pkg_info->pgpsig);
|
||||||
|
|
||||||
|
vieter_dynarray_free(pkg_info->groups);
|
||||||
|
vieter_dynarray_free(pkg_info->licenses);
|
||||||
|
vieter_dynarray_free(pkg_info->replaces);
|
||||||
|
vieter_dynarray_free(pkg_info->depends);
|
||||||
|
vieter_dynarray_free(pkg_info->conflicts);
|
||||||
|
vieter_dynarray_free(pkg_info->provides);
|
||||||
|
vieter_dynarray_free(pkg_info->optdepends);
|
||||||
|
vieter_dynarray_free(pkg_info->makedepends);
|
||||||
|
vieter_dynarray_free(pkg_info->checkdepends);
|
||||||
|
|
||||||
|
free(pkg_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vieter_package_info_parse(vieter_package_info *pkg_info,
|
||||||
|
char *pkg_info_str) {
|
||||||
|
char *value_ptr = pkg_info_str, *tail_ptr = NULL;
|
||||||
|
|
||||||
|
PKG_INFO_STRING("\npkgname = ", name);
|
||||||
|
PKG_INFO_STRING("\npkgbase = ", base);
|
||||||
|
PKG_INFO_STRING("\npkgver = ", version);
|
||||||
|
PKG_INFO_STRING("\npkgdesc = ", description);
|
||||||
|
PKG_INFO_STRING("\nurl = ", url);
|
||||||
|
PKG_INFO_INT("\nbuilddate = ", build_date);
|
||||||
|
PKG_INFO_STRING("\npackager = ", packager);
|
||||||
|
PKG_INFO_INT("\nsize = ", size);
|
||||||
|
PKG_INFO_STRING("\narch = ", arch);
|
||||||
|
PKG_INFO_ARRAY("\nlicense = ", licenses);
|
||||||
|
PKG_INFO_ARRAY("\nreplaces = ", replaces);
|
||||||
|
PKG_INFO_ARRAY("\ngroup = ", groups);
|
||||||
|
PKG_INFO_ARRAY("\nconflict = ", conflicts);
|
||||||
|
PKG_INFO_ARRAY("\nprovides = ", provides);
|
||||||
|
PKG_INFO_ARRAY("\ndepend = ", depends);
|
||||||
|
PKG_INFO_ARRAY("\noptdepend = ", optdepends);
|
||||||
|
PKG_INFO_ARRAY("\nmakedepend = ", makedepends);
|
||||||
|
PKG_INFO_ARRAY("\ncheckdepend = ", checkdepends);
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef VIETER_PACKAGE_INFO
|
||||||
|
#define VIETER_PACKAGE_INFO
|
||||||
|
|
||||||
|
#define FREE_STRING(sp) if (sp != NULL) free(sp)
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "vieter_package.h"
|
||||||
|
#include "vieter_dynarray.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct vieter_package_info {
|
||||||
|
char *name;
|
||||||
|
char *base;
|
||||||
|
char *version;
|
||||||
|
char *description;
|
||||||
|
int64_t size;
|
||||||
|
int64_t csize;
|
||||||
|
char *url;
|
||||||
|
char *arch;
|
||||||
|
int64_t build_date;
|
||||||
|
char *packager;
|
||||||
|
char *pgpsig;
|
||||||
|
int64_t pgpsigsize;
|
||||||
|
|
||||||
|
vieter_dynarray *groups;
|
||||||
|
vieter_dynarray *licenses;
|
||||||
|
vieter_dynarray *replaces;
|
||||||
|
vieter_dynarray *depends;
|
||||||
|
vieter_dynarray *conflicts;
|
||||||
|
vieter_dynarray *provides;
|
||||||
|
vieter_dynarray *optdepends;
|
||||||
|
vieter_dynarray *makedepends;
|
||||||
|
vieter_dynarray *checkdepends;
|
||||||
|
} vieter_package_info;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate and initialise a pkg_info pointer to hold .PKGINFO.
|
||||||
|
*/
|
||||||
|
vieter_package_info *vieter_package_info_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse .PKGINFO file into something usable by libvieter.
|
||||||
|
*/
|
||||||
|
void vieter_package_info_parse(vieter_package_info *pkg_info, char *pkg_info_str);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deallocate a pkg_info pointer.
|
||||||
|
*/
|
||||||
|
void vieter_package_info_free(vieter_package_info *pkg_info);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include "vieter_package.h"
|
||||||
|
#include "vieter_package_info.h"
|
||||||
|
#include "vieter_dynarray.h"
|
||||||
|
|
||||||
|
struct vieter_package {
|
||||||
|
char *path;
|
||||||
|
vieter_package_info *info;
|
||||||
|
vieter_dynarray *files;
|
||||||
|
int compression;
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by makepkg 6.0.2
|
||||||
|
# using fakeroot version 1.30.1
|
||||||
|
pkgname = xcursor-dmz
|
||||||
|
pkgbase = xcursor-dmz
|
||||||
|
pkgver = 0.4.5-2
|
||||||
|
pkgdesc = Style neutral, scalable cursor theme
|
||||||
|
url = https://packages.debian.org/sid/dmz-cursor-theme
|
||||||
|
builddate = 1673751613
|
||||||
|
packager = Unknown Packager
|
||||||
|
size = 3469584
|
||||||
|
arch = any
|
||||||
|
license = MIT
|
||||||
|
replaces = test1
|
||||||
|
group = x11
|
||||||
|
conflict = test2
|
||||||
|
conflict = test3
|
||||||
|
provides = test4
|
||||||
|
depend = test5
|
||||||
|
depend = test6
|
||||||
|
optdepend = test7
|
||||||
|
makedepend = xorg-xcursorgen
|
||||||
|
checkdepend = test8
|
|
@ -0,0 +1,45 @@
|
||||||
|
%FILENAME%
|
||||||
|
xcursor-dmz-0.4.5-2-any.pkg.tar.zst
|
||||||
|
|
||||||
|
%NAME%
|
||||||
|
xcursor-dmz
|
||||||
|
|
||||||
|
%BASE%
|
||||||
|
xcursor-dmz
|
||||||
|
|
||||||
|
%VERSION%
|
||||||
|
0.4.5-2
|
||||||
|
|
||||||
|
%DESC%
|
||||||
|
Style neutral, scalable cursor theme
|
||||||
|
|
||||||
|
%GROUPS%
|
||||||
|
x11
|
||||||
|
|
||||||
|
%CSIZE%
|
||||||
|
328282
|
||||||
|
|
||||||
|
%ISIZE%
|
||||||
|
3469584
|
||||||
|
|
||||||
|
%SHA256SUM%
|
||||||
|
4f4bce9e975334ed7775ff4ddf4d2e82e411d599802f6179a122f89149f53bfb
|
||||||
|
|
||||||
|
%URL%
|
||||||
|
https://packages.debian.org/sid/dmz-cursor-theme
|
||||||
|
|
||||||
|
%LICENSE%
|
||||||
|
MIT
|
||||||
|
|
||||||
|
%ARCH%
|
||||||
|
any
|
||||||
|
|
||||||
|
%BUILDDATE%
|
||||||
|
1673751613
|
||||||
|
|
||||||
|
%PACKAGER%
|
||||||
|
Unknown Packager
|
||||||
|
|
||||||
|
%MAKEDEPENDS%
|
||||||
|
xorg-xcursorgen
|
||||||
|
|
|
@ -0,0 +1,243 @@
|
||||||
|
%FILES%
|
||||||
|
usr/
|
||||||
|
usr/share/
|
||||||
|
usr/share/icons/
|
||||||
|
usr/share/icons/DMZ-Black/
|
||||||
|
usr/share/icons/DMZ-Black/cursor.theme
|
||||||
|
usr/share/icons/DMZ-Black/cursors/
|
||||||
|
usr/share/icons/DMZ-Black/cursors/00008160000006810000408080010102
|
||||||
|
usr/share/icons/DMZ-Black/cursors/028006030e0e7ebffc7f7070c0600140
|
||||||
|
usr/share/icons/DMZ-Black/cursors/03b6e0fcb3499374a867c041f52298f0
|
||||||
|
usr/share/icons/DMZ-Black/cursors/08e8e1c95fe2fc01f976f1e063a24ccd
|
||||||
|
usr/share/icons/DMZ-Black/cursors/1081e37283d90000800003c07f3ef6bf
|
||||||
|
usr/share/icons/DMZ-Black/cursors/14fef782d02440884392942c11205230
|
||||||
|
usr/share/icons/DMZ-Black/cursors/2870a09082c103050810ffdffffe0204
|
||||||
|
usr/share/icons/DMZ-Black/cursors/3085a0e285430894940527032f8b26df
|
||||||
|
usr/share/icons/DMZ-Black/cursors/3ecb610c1bf2410f44200f48c40d3599
|
||||||
|
usr/share/icons/DMZ-Black/cursors/4498f0e0c1937ffe01fd06f973665830
|
||||||
|
usr/share/icons/DMZ-Black/cursors/5c6cd98b3f3ebcb1f9c7f1c204630408
|
||||||
|
usr/share/icons/DMZ-Black/cursors/6407b0e94181790501fd1e167b474872
|
||||||
|
usr/share/icons/DMZ-Black/cursors/640fb0e74195791501fd1ed57b41487f
|
||||||
|
usr/share/icons/DMZ-Black/cursors/9081237383d90e509aa00f00170e968f
|
||||||
|
usr/share/icons/DMZ-Black/cursors/9d800788f1b08800ae810202380a0822
|
||||||
|
usr/share/icons/DMZ-Black/cursors/X_cursor
|
||||||
|
usr/share/icons/DMZ-Black/cursors/alias
|
||||||
|
usr/share/icons/DMZ-Black/cursors/arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/bd_double_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/bottom_left_corner
|
||||||
|
usr/share/icons/DMZ-Black/cursors/bottom_right_corner
|
||||||
|
usr/share/icons/DMZ-Black/cursors/bottom_side
|
||||||
|
usr/share/icons/DMZ-Black/cursors/bottom_tee
|
||||||
|
usr/share/icons/DMZ-Black/cursors/c7088f0f3e6c8088236ef8e1e3e70000
|
||||||
|
usr/share/icons/DMZ-Black/cursors/circle
|
||||||
|
usr/share/icons/DMZ-Black/cursors/col-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/color-picker
|
||||||
|
usr/share/icons/DMZ-Black/cursors/copy
|
||||||
|
usr/share/icons/DMZ-Black/cursors/cross
|
||||||
|
usr/share/icons/DMZ-Black/cursors/cross_reverse
|
||||||
|
usr/share/icons/DMZ-Black/cursors/crossed_circle
|
||||||
|
usr/share/icons/DMZ-Black/cursors/crosshair
|
||||||
|
usr/share/icons/DMZ-Black/cursors/d9ce0ab605698f320427677b458ad60b
|
||||||
|
usr/share/icons/DMZ-Black/cursors/default
|
||||||
|
usr/share/icons/DMZ-Black/cursors/diamond_cross
|
||||||
|
usr/share/icons/DMZ-Black/cursors/dnd-ask
|
||||||
|
usr/share/icons/DMZ-Black/cursors/dnd-copy
|
||||||
|
usr/share/icons/DMZ-Black/cursors/dnd-link
|
||||||
|
usr/share/icons/DMZ-Black/cursors/dnd-move
|
||||||
|
usr/share/icons/DMZ-Black/cursors/dnd-none
|
||||||
|
usr/share/icons/DMZ-Black/cursors/dot_box_mask
|
||||||
|
usr/share/icons/DMZ-Black/cursors/dotbox
|
||||||
|
usr/share/icons/DMZ-Black/cursors/double_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/draft_large
|
||||||
|
usr/share/icons/DMZ-Black/cursors/draft_small
|
||||||
|
usr/share/icons/DMZ-Black/cursors/draped_box
|
||||||
|
usr/share/icons/DMZ-Black/cursors/e-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/e29285e634086352946a0e7090d73106
|
||||||
|
usr/share/icons/DMZ-Black/cursors/ew-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/fcf1c3c7cd4491d801f1e1c78f100000
|
||||||
|
usr/share/icons/DMZ-Black/cursors/fd_double_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/fleur
|
||||||
|
usr/share/icons/DMZ-Black/cursors/grab
|
||||||
|
usr/share/icons/DMZ-Black/cursors/grabbing
|
||||||
|
usr/share/icons/DMZ-Black/cursors/h_double_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/hand
|
||||||
|
usr/share/icons/DMZ-Black/cursors/hand1
|
||||||
|
usr/share/icons/DMZ-Black/cursors/hand2
|
||||||
|
usr/share/icons/DMZ-Black/cursors/help
|
||||||
|
usr/share/icons/DMZ-Black/cursors/icon
|
||||||
|
usr/share/icons/DMZ-Black/cursors/left_ptr
|
||||||
|
usr/share/icons/DMZ-Black/cursors/left_ptr_help
|
||||||
|
usr/share/icons/DMZ-Black/cursors/left_ptr_watch
|
||||||
|
usr/share/icons/DMZ-Black/cursors/left_side
|
||||||
|
usr/share/icons/DMZ-Black/cursors/left_tee
|
||||||
|
usr/share/icons/DMZ-Black/cursors/link
|
||||||
|
usr/share/icons/DMZ-Black/cursors/ll_angle
|
||||||
|
usr/share/icons/DMZ-Black/cursors/lr_angle
|
||||||
|
usr/share/icons/DMZ-Black/cursors/move
|
||||||
|
usr/share/icons/DMZ-Black/cursors/n-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/ne-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/nesw-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/not-allowed
|
||||||
|
usr/share/icons/DMZ-Black/cursors/ns-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/nw-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/nwse-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/openhand
|
||||||
|
usr/share/icons/DMZ-Black/cursors/pencil
|
||||||
|
usr/share/icons/DMZ-Black/cursors/pirate
|
||||||
|
usr/share/icons/DMZ-Black/cursors/plus
|
||||||
|
usr/share/icons/DMZ-Black/cursors/pointer
|
||||||
|
usr/share/icons/DMZ-Black/cursors/progress
|
||||||
|
usr/share/icons/DMZ-Black/cursors/question_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/right_ptr
|
||||||
|
usr/share/icons/DMZ-Black/cursors/right_side
|
||||||
|
usr/share/icons/DMZ-Black/cursors/right_tee
|
||||||
|
usr/share/icons/DMZ-Black/cursors/row-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/s-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/sb_down_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/sb_h_double_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/sb_left_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/sb_right_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/sb_up_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/sb_v_double_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/se-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/size_bdiag
|
||||||
|
usr/share/icons/DMZ-Black/cursors/size_fdiag
|
||||||
|
usr/share/icons/DMZ-Black/cursors/size_hor
|
||||||
|
usr/share/icons/DMZ-Black/cursors/size_ver
|
||||||
|
usr/share/icons/DMZ-Black/cursors/sw-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/target
|
||||||
|
usr/share/icons/DMZ-Black/cursors/tcross
|
||||||
|
usr/share/icons/DMZ-Black/cursors/text
|
||||||
|
usr/share/icons/DMZ-Black/cursors/top_left_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/top_left_corner
|
||||||
|
usr/share/icons/DMZ-Black/cursors/top_right_corner
|
||||||
|
usr/share/icons/DMZ-Black/cursors/top_side
|
||||||
|
usr/share/icons/DMZ-Black/cursors/top_tee
|
||||||
|
usr/share/icons/DMZ-Black/cursors/ul_angle
|
||||||
|
usr/share/icons/DMZ-Black/cursors/ur_angle
|
||||||
|
usr/share/icons/DMZ-Black/cursors/v_double_arrow
|
||||||
|
usr/share/icons/DMZ-Black/cursors/w-resize
|
||||||
|
usr/share/icons/DMZ-Black/cursors/wait
|
||||||
|
usr/share/icons/DMZ-Black/cursors/watch
|
||||||
|
usr/share/icons/DMZ-Black/cursors/xterm
|
||||||
|
usr/share/icons/DMZ-White/
|
||||||
|
usr/share/icons/DMZ-White/cursor.theme
|
||||||
|
usr/share/icons/DMZ-White/cursors/
|
||||||
|
usr/share/icons/DMZ-White/cursors/00008160000006810000408080010102
|
||||||
|
usr/share/icons/DMZ-White/cursors/028006030e0e7ebffc7f7070c0600140
|
||||||
|
usr/share/icons/DMZ-White/cursors/03b6e0fcb3499374a867c041f52298f0
|
||||||
|
usr/share/icons/DMZ-White/cursors/08e8e1c95fe2fc01f976f1e063a24ccd
|
||||||
|
usr/share/icons/DMZ-White/cursors/1081e37283d90000800003c07f3ef6bf
|
||||||
|
usr/share/icons/DMZ-White/cursors/14fef782d02440884392942c11205230
|
||||||
|
usr/share/icons/DMZ-White/cursors/2870a09082c103050810ffdffffe0204
|
||||||
|
usr/share/icons/DMZ-White/cursors/3085a0e285430894940527032f8b26df
|
||||||
|
usr/share/icons/DMZ-White/cursors/3ecb610c1bf2410f44200f48c40d3599
|
||||||
|
usr/share/icons/DMZ-White/cursors/4498f0e0c1937ffe01fd06f973665830
|
||||||
|
usr/share/icons/DMZ-White/cursors/5c6cd98b3f3ebcb1f9c7f1c204630408
|
||||||
|
usr/share/icons/DMZ-White/cursors/6407b0e94181790501fd1e167b474872
|
||||||
|
usr/share/icons/DMZ-White/cursors/640fb0e74195791501fd1ed57b41487f
|
||||||
|
usr/share/icons/DMZ-White/cursors/9081237383d90e509aa00f00170e968f
|
||||||
|
usr/share/icons/DMZ-White/cursors/9d800788f1b08800ae810202380a0822
|
||||||
|
usr/share/icons/DMZ-White/cursors/X_cursor
|
||||||
|
usr/share/icons/DMZ-White/cursors/alias
|
||||||
|
usr/share/icons/DMZ-White/cursors/arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/bd_double_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/bottom_left_corner
|
||||||
|
usr/share/icons/DMZ-White/cursors/bottom_right_corner
|
||||||
|
usr/share/icons/DMZ-White/cursors/bottom_side
|
||||||
|
usr/share/icons/DMZ-White/cursors/bottom_tee
|
||||||
|
usr/share/icons/DMZ-White/cursors/c7088f0f3e6c8088236ef8e1e3e70000
|
||||||
|
usr/share/icons/DMZ-White/cursors/circle
|
||||||
|
usr/share/icons/DMZ-White/cursors/col-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/color-picker
|
||||||
|
usr/share/icons/DMZ-White/cursors/copy
|
||||||
|
usr/share/icons/DMZ-White/cursors/cross
|
||||||
|
usr/share/icons/DMZ-White/cursors/cross_reverse
|
||||||
|
usr/share/icons/DMZ-White/cursors/crossed_circle
|
||||||
|
usr/share/icons/DMZ-White/cursors/crosshair
|
||||||
|
usr/share/icons/DMZ-White/cursors/d9ce0ab605698f320427677b458ad60b
|
||||||
|
usr/share/icons/DMZ-White/cursors/default
|
||||||
|
usr/share/icons/DMZ-White/cursors/diamond_cross
|
||||||
|
usr/share/icons/DMZ-White/cursors/dnd-ask
|
||||||
|
usr/share/icons/DMZ-White/cursors/dnd-copy
|
||||||
|
usr/share/icons/DMZ-White/cursors/dnd-link
|
||||||
|
usr/share/icons/DMZ-White/cursors/dnd-move
|
||||||
|
usr/share/icons/DMZ-White/cursors/dnd-none
|
||||||
|
usr/share/icons/DMZ-White/cursors/dot_box_mask
|
||||||
|
usr/share/icons/DMZ-White/cursors/dotbox
|
||||||
|
usr/share/icons/DMZ-White/cursors/double_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/draft_large
|
||||||
|
usr/share/icons/DMZ-White/cursors/draft_small
|
||||||
|
usr/share/icons/DMZ-White/cursors/draped_box
|
||||||
|
usr/share/icons/DMZ-White/cursors/e-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/e29285e634086352946a0e7090d73106
|
||||||
|
usr/share/icons/DMZ-White/cursors/ew-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/fcf1c3c7cd4491d801f1e1c78f100000
|
||||||
|
usr/share/icons/DMZ-White/cursors/fd_double_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/fleur
|
||||||
|
usr/share/icons/DMZ-White/cursors/grab
|
||||||
|
usr/share/icons/DMZ-White/cursors/grabbing
|
||||||
|
usr/share/icons/DMZ-White/cursors/h_double_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/hand
|
||||||
|
usr/share/icons/DMZ-White/cursors/hand1
|
||||||
|
usr/share/icons/DMZ-White/cursors/hand2
|
||||||
|
usr/share/icons/DMZ-White/cursors/help
|
||||||
|
usr/share/icons/DMZ-White/cursors/icon
|
||||||
|
usr/share/icons/DMZ-White/cursors/left_ptr
|
||||||
|
usr/share/icons/DMZ-White/cursors/left_ptr_help
|
||||||
|
usr/share/icons/DMZ-White/cursors/left_ptr_watch
|
||||||
|
usr/share/icons/DMZ-White/cursors/left_side
|
||||||
|
usr/share/icons/DMZ-White/cursors/left_tee
|
||||||
|
usr/share/icons/DMZ-White/cursors/link
|
||||||
|
usr/share/icons/DMZ-White/cursors/ll_angle
|
||||||
|
usr/share/icons/DMZ-White/cursors/lr_angle
|
||||||
|
usr/share/icons/DMZ-White/cursors/move
|
||||||
|
usr/share/icons/DMZ-White/cursors/n-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/ne-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/nesw-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/not-allowed
|
||||||
|
usr/share/icons/DMZ-White/cursors/ns-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/nw-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/nwse-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/openhand
|
||||||
|
usr/share/icons/DMZ-White/cursors/pencil
|
||||||
|
usr/share/icons/DMZ-White/cursors/pirate
|
||||||
|
usr/share/icons/DMZ-White/cursors/plus
|
||||||
|
usr/share/icons/DMZ-White/cursors/pointer
|
||||||
|
usr/share/icons/DMZ-White/cursors/progress
|
||||||
|
usr/share/icons/DMZ-White/cursors/question_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/right_ptr
|
||||||
|
usr/share/icons/DMZ-White/cursors/right_side
|
||||||
|
usr/share/icons/DMZ-White/cursors/right_tee
|
||||||
|
usr/share/icons/DMZ-White/cursors/row-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/s-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/sb_down_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/sb_h_double_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/sb_left_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/sb_right_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/sb_up_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/sb_v_double_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/se-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/size_bdiag
|
||||||
|
usr/share/icons/DMZ-White/cursors/size_fdiag
|
||||||
|
usr/share/icons/DMZ-White/cursors/size_hor
|
||||||
|
usr/share/icons/DMZ-White/cursors/size_ver
|
||||||
|
usr/share/icons/DMZ-White/cursors/sw-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/target
|
||||||
|
usr/share/icons/DMZ-White/cursors/tcross
|
||||||
|
usr/share/icons/DMZ-White/cursors/text
|
||||||
|
usr/share/icons/DMZ-White/cursors/top_left_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/top_left_corner
|
||||||
|
usr/share/icons/DMZ-White/cursors/top_right_corner
|
||||||
|
usr/share/icons/DMZ-White/cursors/top_side
|
||||||
|
usr/share/icons/DMZ-White/cursors/top_tee
|
||||||
|
usr/share/icons/DMZ-White/cursors/ul_angle
|
||||||
|
usr/share/icons/DMZ-White/cursors/ur_angle
|
||||||
|
usr/share/icons/DMZ-White/cursors/v_double_arrow
|
||||||
|
usr/share/icons/DMZ-White/cursors/w-resize
|
||||||
|
usr/share/icons/DMZ-White/cursors/wait
|
||||||
|
usr/share/icons/DMZ-White/cursors/watch
|
||||||
|
usr/share/icons/DMZ-White/cursors/xterm
|
||||||
|
usr/share/licenses/
|
||||||
|
usr/share/licenses/xcursor-dmz/
|
||||||
|
usr/share/licenses/xcursor-dmz/LICENSE
|
|
@ -0,0 +1,97 @@
|
||||||
|
#include "acutest.h"
|
||||||
|
#include "vieter_package_internal.h"
|
||||||
|
|
||||||
|
void test_info_parse() {
|
||||||
|
FILE *f = fopen("./test/package/.PKGINFO", "r");
|
||||||
|
TEST_ASSERT_(f != NULL, "could not find test .PKGINFO file in ./test/package ");
|
||||||
|
fseek(f, 0L, SEEK_END);
|
||||||
|
size_t size = ftell(f);
|
||||||
|
fflush(stdout);
|
||||||
|
rewind(f);
|
||||||
|
char *pkg_info_str = malloc(size + 1);
|
||||||
|
fread(pkg_info_str, 1, size, f);
|
||||||
|
pkg_info_str[size] = '\0';
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
vieter_package_info *pkg_info = vieter_package_info_init();
|
||||||
|
vieter_package_info_parse(pkg_info, pkg_info_str);
|
||||||
|
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->name, "xcursor-dmz"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->version, "0.4.5-2"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->description, "Style neutral, scalable cursor theme"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->url, "https://packages.debian.org/sid/dmz-cursor-theme"));
|
||||||
|
TEST_CHECK(pkg_info->build_date == 1673751613);
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->packager, "Unknown Packager"));
|
||||||
|
TEST_CHECK(pkg_info->size == 3469584);
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->arch, "any"));
|
||||||
|
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->licenses->array[0], "MIT"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen"));
|
||||||
|
TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8"));
|
||||||
|
|
||||||
|
free(pkg_info_str);
|
||||||
|
vieter_package_info_free(pkg_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_pkg_read_archive_files() {
|
||||||
|
vieter_package *pkg = vieter_package_init();
|
||||||
|
vieter_package_error e = vieter_package_read_archive(pkg, "./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst");
|
||||||
|
TEST_ASSERT_(e == vieter_package_ok, "failure parsing pkg archive");
|
||||||
|
|
||||||
|
FILE *f = fopen("./test/package/files", "r");
|
||||||
|
TEST_ASSERT_(f != NULL, "could not find test files file in ./test/package");
|
||||||
|
char buff[128];
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
while ((fgets(buff, 128, f)) != NULL || i < pkg->files->size) {
|
||||||
|
if (buff[strlen(buff) - 1] == '\n') {
|
||||||
|
buff[strlen(buff) - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CHECK_(!strcmp(pkg->files->array[i], buff), "%s != %s", pkg->files->array[i], buff);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
TEST_CHECK(pkg->compression = 14);
|
||||||
|
|
||||||
|
vieter_package_free(&pkg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_pkg_read_archive_desc() {
|
||||||
|
vieter_package *pkg = vieter_package_init();
|
||||||
|
vieter_package_error e = vieter_package_read_archive(pkg, "./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst");
|
||||||
|
TEST_ASSERT_(e == vieter_package_ok, "failure parsing pkg archive");
|
||||||
|
|
||||||
|
char *description = vieter_package_to_description(pkg);
|
||||||
|
|
||||||
|
FILE *f = fopen("./test/package/desc", "r");
|
||||||
|
TEST_ASSERT_(f != NULL, "could not find test desc file in ./test/package");
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
size_t size = ftell(f);
|
||||||
|
rewind(f);
|
||||||
|
char *desc = malloc(size + 1);
|
||||||
|
fread(desc, 1, size, f);
|
||||||
|
desc[size] = '\0';
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
TEST_CHECK(!strcmp(description, desc));
|
||||||
|
|
||||||
|
vieter_package_free(&pkg);
|
||||||
|
free(description);
|
||||||
|
free(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_LIST = {
|
||||||
|
{".PKGINFO parse", test_info_parse},
|
||||||
|
{"files array creation", test_pkg_read_archive_files},
|
||||||
|
{"desc file creation", test_pkg_read_archive_desc},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*********************************************************************
|
||||||
|
* Filename: sha256.h
|
||||||
|
* Author: Brad Conte (brad AT bradconte.com)
|
||||||
|
* Copyright:
|
||||||
|
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||||
|
* Details: Defines the API for the corresponding SHA1 implementation.
|
||||||
|
*********************************************************************/
|
||||||
|
|
||||||
|
#ifndef SHA256_H
|
||||||
|
#define SHA256_H
|
||||||
|
|
||||||
|
/*************************** HEADER FILES ***************************/
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/****************************** MACROS ******************************/
|
||||||
|
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
|
||||||
|
|
||||||
|
/**************************** DATA TYPES ****************************/
|
||||||
|
typedef unsigned char BYTE; // 8-bit byte
|
||||||
|
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BYTE data[64];
|
||||||
|
WORD datalen;
|
||||||
|
unsigned long long bitlen;
|
||||||
|
WORD state[8];
|
||||||
|
} SHA256_CTX;
|
||||||
|
|
||||||
|
/*********************** FUNCTION DECLARATIONS **********************/
|
||||||
|
void sha256_init(SHA256_CTX *ctx);
|
||||||
|
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len);
|
||||||
|
void sha256_final(SHA256_CTX *ctx, BYTE hash[]);
|
||||||
|
|
||||||
|
#endif // SHA256_H
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*********************************************************************
|
||||||
|
* Filename: sha256.c
|
||||||
|
* Author: Brad Conte (brad AT bradconte.com)
|
||||||
|
* Copyright:
|
||||||
|
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||||
|
* Details: Implementation of the SHA-256 hashing algorithm.
|
||||||
|
SHA-256 is one of the three algorithms in the SHA2
|
||||||
|
specification. The others, SHA-384 and SHA-512, are not
|
||||||
|
offered in this implementation.
|
||||||
|
Algorithm specification can be found here:
|
||||||
|
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
|
||||||
|
This implementation uses little endian byte order.
|
||||||
|
*********************************************************************/
|
||||||
|
|
||||||
|
/*************************** HEADER FILES ***************************/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include "sha256.h"
|
||||||
|
|
||||||
|
/****************************** MACROS ******************************/
|
||||||
|
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
|
||||||
|
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
|
||||||
|
|
||||||
|
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
|
||||||
|
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||||
|
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
|
||||||
|
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
|
||||||
|
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
|
||||||
|
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
|
||||||
|
|
||||||
|
/**************************** VARIABLES *****************************/
|
||||||
|
static const WORD k[64] = {
|
||||||
|
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
|
||||||
|
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
|
||||||
|
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
|
||||||
|
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
|
||||||
|
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
|
||||||
|
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
|
||||||
|
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
|
||||||
|
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
|
||||||
|
};
|
||||||
|
|
||||||
|
/*********************** FUNCTION DEFINITIONS ***********************/
|
||||||
|
void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
|
||||||
|
{
|
||||||
|
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
|
||||||
|
|
||||||
|
for (i = 0, j = 0; i < 16; ++i, j += 4)
|
||||||
|
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
|
||||||
|
for ( ; i < 64; ++i)
|
||||||
|
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
|
||||||
|
|
||||||
|
a = ctx->state[0];
|
||||||
|
b = ctx->state[1];
|
||||||
|
c = ctx->state[2];
|
||||||
|
d = ctx->state[3];
|
||||||
|
e = ctx->state[4];
|
||||||
|
f = ctx->state[5];
|
||||||
|
g = ctx->state[6];
|
||||||
|
h = ctx->state[7];
|
||||||
|
|
||||||
|
for (i = 0; i < 64; ++i) {
|
||||||
|
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
|
||||||
|
t2 = EP0(a) + MAJ(a,b,c);
|
||||||
|
h = g;
|
||||||
|
g = f;
|
||||||
|
f = e;
|
||||||
|
e = d + t1;
|
||||||
|
d = c;
|
||||||
|
c = b;
|
||||||
|
b = a;
|
||||||
|
a = t1 + t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->state[0] += a;
|
||||||
|
ctx->state[1] += b;
|
||||||
|
ctx->state[2] += c;
|
||||||
|
ctx->state[3] += d;
|
||||||
|
ctx->state[4] += e;
|
||||||
|
ctx->state[5] += f;
|
||||||
|
ctx->state[6] += g;
|
||||||
|
ctx->state[7] += h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha256_init(SHA256_CTX *ctx)
|
||||||
|
{
|
||||||
|
ctx->datalen = 0;
|
||||||
|
ctx->bitlen = 0;
|
||||||
|
ctx->state[0] = 0x6a09e667;
|
||||||
|
ctx->state[1] = 0xbb67ae85;
|
||||||
|
ctx->state[2] = 0x3c6ef372;
|
||||||
|
ctx->state[3] = 0xa54ff53a;
|
||||||
|
ctx->state[4] = 0x510e527f;
|
||||||
|
ctx->state[5] = 0x9b05688c;
|
||||||
|
ctx->state[6] = 0x1f83d9ab;
|
||||||
|
ctx->state[7] = 0x5be0cd19;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
|
||||||
|
{
|
||||||
|
WORD i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; ++i) {
|
||||||
|
ctx->data[ctx->datalen] = data[i];
|
||||||
|
ctx->datalen++;
|
||||||
|
if (ctx->datalen == 64) {
|
||||||
|
sha256_transform(ctx, ctx->data);
|
||||||
|
ctx->bitlen += 512;
|
||||||
|
ctx->datalen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha256_final(SHA256_CTX *ctx, BYTE hash[])
|
||||||
|
{
|
||||||
|
WORD i;
|
||||||
|
|
||||||
|
i = ctx->datalen;
|
||||||
|
|
||||||
|
// Pad whatever data is left in the buffer.
|
||||||
|
if (ctx->datalen < 56) {
|
||||||
|
ctx->data[i++] = 0x80;
|
||||||
|
while (i < 56)
|
||||||
|
ctx->data[i++] = 0x00;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx->data[i++] = 0x80;
|
||||||
|
while (i < 64)
|
||||||
|
ctx->data[i++] = 0x00;
|
||||||
|
sha256_transform(ctx, ctx->data);
|
||||||
|
memset(ctx->data, 0, 56);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append to the padding the total message's length in bits and transform.
|
||||||
|
ctx->bitlen += ctx->datalen * 8;
|
||||||
|
ctx->data[63] = ctx->bitlen;
|
||||||
|
ctx->data[62] = ctx->bitlen >> 8;
|
||||||
|
ctx->data[61] = ctx->bitlen >> 16;
|
||||||
|
ctx->data[60] = ctx->bitlen >> 24;
|
||||||
|
ctx->data[59] = ctx->bitlen >> 32;
|
||||||
|
ctx->data[58] = ctx->bitlen >> 40;
|
||||||
|
ctx->data[57] = ctx->bitlen >> 48;
|
||||||
|
ctx->data[56] = ctx->bitlen >> 56;
|
||||||
|
sha256_transform(ctx, ctx->data);
|
||||||
|
|
||||||
|
// Since this implementation uses little endian byte ordering and SHA uses big endian,
|
||||||
|
// reverse all the bytes when copying the final state to the output hash.
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
|
||||||
|
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
|
||||||
|
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
|
||||||
|
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
|
||||||
|
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
|
||||||
|
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
|
||||||
|
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
|
||||||
|
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
|
||||||
|
}
|
||||||
|
}
|
I don't personally use this style of free function right now, but it might be interesting to migrate all free functions to this style indeed. I'm assuming the pointer-to-pointer is so you can set the variable containing the pointer to NULL as well?
Yeah, dangling pointers can cause some real headaches, so I prefer to have free functions set the pointer to NULL themselves to make it less error prone.