refactor: Add original .c package files by Jef.
							parent
							
								
									f376aedaee
								
							
						
					
					
						commit
						c2313fe0be
					
				| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
#ifndef VIETER_DYNARRAY
 | 
			
		||||
#define VIETER_DYNARRAY
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
typedef struct dyn_array DynArray;
 | 
			
		||||
 | 
			
		||||
DynArray *dynarray_init(size_t initial_capacity);
 | 
			
		||||
void dynarray_add(DynArray *da, const char * s);
 | 
			
		||||
void dynarray_free(DynArray *da);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Convert a DynArray into an array by freeing all its surrounding components
 | 
			
		||||
 * and returning the underlying array pointer.
 | 
			
		||||
 */
 | 
			
		||||
char **dynarray_convert(DynArray *da);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
#ifndef VIETER_PACKAGE
 | 
			
		||||
#define VIETER_PACKAGE
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include "archive.h"
 | 
			
		||||
#include "archive_entry.h"
 | 
			
		||||
 | 
			
		||||
#include "package_info.h"
 | 
			
		||||
#include "dynarray.h"
 | 
			
		||||
 | 
			
		||||
typedef struct pkg {
 | 
			
		||||
	char *path;
 | 
			
		||||
	PkgInfo *info;
 | 
			
		||||
	DynArray *files;
 | 
			
		||||
	int compression;
 | 
			
		||||
} Pkg;
 | 
			
		||||
 | 
			
		||||
Pkg *package_read_archive(const char *pkg_path);
 | 
			
		||||
void package_free(Pkg ** ptp);
 | 
			
		||||
char *package_to_description(Pkg *pkg);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
#ifndef VIETER_PACKAGE_INFO
 | 
			
		||||
#define VIETER_PACKAGE_INFO
 | 
			
		||||
 | 
			
		||||
#define FREE_STRING(sp) if (sp != NULL) free(sp)
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include "dynarray.h"
 | 
			
		||||
 | 
			
		||||
typedef struct pkg_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;
 | 
			
		||||
 | 
			
		||||
	DynArray *groups;
 | 
			
		||||
	DynArray *licenses;
 | 
			
		||||
	DynArray *replaces;
 | 
			
		||||
	DynArray *depends;
 | 
			
		||||
	DynArray *conflicts;
 | 
			
		||||
	DynArray *provides;
 | 
			
		||||
	DynArray *optdepends;
 | 
			
		||||
	DynArray *makedepends;
 | 
			
		||||
	DynArray *checkdepends;
 | 
			
		||||
} PkgInfo;
 | 
			
		||||
 | 
			
		||||
PkgInfo *package_info_init();
 | 
			
		||||
int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str);
 | 
			
		||||
void package_info_free(PkgInfo *pkg_info);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
#include "dynarray.h"
 | 
			
		||||
 | 
			
		||||
struct dyn_array {
 | 
			
		||||
	char **array;
 | 
			
		||||
	size_t size;
 | 
			
		||||
	size_t capacity;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
DynArray *dynarray_init(size_t initial_capacity) {
 | 
			
		||||
	DynArray *da = malloc(sizeof(DynArray));
 | 
			
		||||
	da->size = 0;
 | 
			
		||||
	da->capacity = initial_capacity;
 | 
			
		||||
 | 
			
		||||
	return da;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dynarray_add(DynArray *da, const char *s) {
 | 
			
		||||
	// An empty dynarray does not have an allocated internal array yet
 | 
			
		||||
	if (da->size == 0) {
 | 
			
		||||
		da->array = malloc(sizeof(char*) * da->capacity);
 | 
			
		||||
	}
 | 
			
		||||
	// Double array size if it's full
 | 
			
		||||
	else if (da->size == da->capacity) {
 | 
			
		||||
		da->array = realloc(da->array, da->capacity * 2);
 | 
			
		||||
		da->capacity *= 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	da->array[da->size] = strdup(s);
 | 
			
		||||
	da->size++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dynarray_free(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 **dynarray_convert(DynArray *da) {
 | 
			
		||||
	char **array = da->array;
 | 
			
		||||
 | 
			
		||||
	da->array = NULL;
 | 
			
		||||
	dynarray_free(da);
 | 
			
		||||
 | 
			
		||||
	return array;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,98 @@
 | 
			
		|||
#include "package.h"
 | 
			
		||||
 | 
			
		||||
static char *ignored_names[5] = {
 | 
			
		||||
	".BUILDINFO",
 | 
			
		||||
	".INSTALL",
 | 
			
		||||
	".MTREE",
 | 
			
		||||
	".PKGINFO",
 | 
			
		||||
	".CHANGELOG"
 | 
			
		||||
};
 | 
			
		||||
static int ignored_words_len = sizeof(ignored_names) / sizeof(char *);
 | 
			
		||||
 | 
			
		||||
Pkg *package_init() {
 | 
			
		||||
	return calloc(sizeof(PkgInfo), 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Pkg *package_read_archive(const char *pkg_path) {
 | 
			
		||||
	struct archive *a = archive_read_new();
 | 
			
		||||
	struct archive_entry *entry = archive_entry_new();
 | 
			
		||||
 | 
			
		||||
	// 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) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int compression_code = archive_filter_code(a, 0);
 | 
			
		||||
	const char *path_name;
 | 
			
		||||
 | 
			
		||||
	PkgInfo *pkg_info;
 | 
			
		||||
	DynArray *files = dynarray_init(16);
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
			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);
 | 
			
		||||
			archive_read_data(a, buf, size);
 | 
			
		||||
 | 
			
		||||
			// Parse package info string into a struct
 | 
			
		||||
			pkg_info = package_info_init();
 | 
			
		||||
			package_info_parse(pkg_info, buf);
 | 
			
		||||
 | 
			
		||||
			free(buf);
 | 
			
		||||
		} else {
 | 
			
		||||
			archive_read_data_skip(a);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get size of file
 | 
			
		||||
	struct stat stats;
 | 
			
		||||
 | 
			
		||||
	if (stat(pkg_path, &stats) != 0) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pkg_info->csize = stats.st_size;
 | 
			
		||||
 | 
			
		||||
	archive_read_free(a);
 | 
			
		||||
	archive_entry_free(entry);
 | 
			
		||||
 | 
			
		||||
	// Create final return value
 | 
			
		||||
	Pkg *pkg = package_init();
 | 
			
		||||
	pkg->path = strdup(pkg_path);
 | 
			
		||||
	pkg->info = pkg_info;
 | 
			
		||||
	pkg->files = files;
 | 
			
		||||
	pkg->compression = compression_code;
 | 
			
		||||
 | 
			
		||||
	return pkg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *package_to_description(Pkg *pkg) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,139 @@
 | 
			
		|||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#include "package_info.h"
 | 
			
		||||
 | 
			
		||||
PkgInfo *package_info_init() {
 | 
			
		||||
	return calloc(1, sizeof(PkgInfo));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void package_info_free(PkgInfo *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);
 | 
			
		||||
 | 
			
		||||
	dynarray_free(pkg_info->groups);
 | 
			
		||||
	dynarray_free(pkg_info->licenses);
 | 
			
		||||
	dynarray_free(pkg_info->replaces);
 | 
			
		||||
	dynarray_free(pkg_info->depends);
 | 
			
		||||
	dynarray_free(pkg_info->conflicts);
 | 
			
		||||
	dynarray_free(pkg_info->provides);
 | 
			
		||||
	dynarray_free(pkg_info->optdepends);
 | 
			
		||||
	dynarray_free(pkg_info->makedepends);
 | 
			
		||||
	dynarray_free(pkg_info->checkdepends);
 | 
			
		||||
 | 
			
		||||
	free(pkg_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Advance the pointer until all spaces are skipped.
 | 
			
		||||
 */
 | 
			
		||||
static inline char *trim_spaces_front(char *ptr) {
 | 
			
		||||
	while (ptr[0] == ' ') {
 | 
			
		||||
		ptr++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Given a string pointer in the middle of a string, move over all spaces in the
 | 
			
		||||
 * given direction. The final space is replaced with a NULL-byte.
 | 
			
		||||
 */
 | 
			
		||||
static inline void trim_spaces_back(char *ptr) {
 | 
			
		||||
	if (ptr[0] != ' ') {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (ptr[-1] == ' ') {
 | 
			
		||||
		ptr--;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ptr[0] = '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define PKG_INFO_STRING(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = strdup(value_ptr); goto advance; }
 | 
			
		||||
#define PKG_INFO_INT(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = atoi(value_ptr); goto advance; }
 | 
			
		||||
#define PKG_INFO_ARRAY(key, field) if (strcmp(key_ptr, key) == 0) { \
 | 
			
		||||
	if (pkg_info->field == NULL) { pkg_info->field = dynarray_init(4); } \
 | 
			
		||||
	dynarray_add(pkg_info->field, value_ptr); goto advance; \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) {
 | 
			
		||||
	char *offset_ptr, *equals_ptr, *key_ptr, *value_ptr;
 | 
			
		||||
 | 
			
		||||
	bool end = false;
 | 
			
		||||
 | 
			
		||||
	// Iterate over all lines in file
 | 
			
		||||
	while (!end) {
 | 
			
		||||
		// This pointer will always point to the final character of the
 | 
			
		||||
		// current line, be it the position of a newline or the NULL byte at
 | 
			
		||||
		// the end of the entire string
 | 
			
		||||
		offset_ptr = strchr(pkg_info_str, '\n');
 | 
			
		||||
 | 
			
		||||
		// We replace the newline with a NULL byte. Now we know the line runs
 | 
			
		||||
		// until the next NULL byte.
 | 
			
		||||
		if (offset_ptr != NULL) {
 | 
			
		||||
			offset_ptr[0] = '\0';
 | 
			
		||||
		} else {
 | 
			
		||||
			// Advance pointer to the NULL byte of the string
 | 
			
		||||
			offset_ptr = pkg_info_str + 1;
 | 
			
		||||
 | 
			
		||||
			while (*offset_ptr != '\0') {
 | 
			
		||||
				offset_ptr++;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			end = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Skip comment lines
 | 
			
		||||
		if (pkg_info_str[0] == '#') {
 | 
			
		||||
			goto advance;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		equals_ptr = strchr(pkg_info_str, '=');
 | 
			
		||||
 | 
			
		||||
		// If a line doesn't contain an equals sign, the file is invalid
 | 
			
		||||
		if (equals_ptr == NULL) {
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Trim whitespace from key
 | 
			
		||||
		key_ptr = trim_spaces_front(pkg_info_str);
 | 
			
		||||
		trim_spaces_back(equals_ptr - 1);
 | 
			
		||||
 | 
			
		||||
		// Trim spaces from value
 | 
			
		||||
		value_ptr = trim_spaces_front(equals_ptr + 1);
 | 
			
		||||
		trim_spaces_back(offset_ptr - 1);
 | 
			
		||||
 | 
			
		||||
		// Match key
 | 
			
		||||
		PKG_INFO_STRING("pkgname", name);
 | 
			
		||||
		PKG_INFO_STRING("pkgbase", base);
 | 
			
		||||
		PKG_INFO_STRING("pkgver", version);
 | 
			
		||||
		PKG_INFO_STRING("pkgdesc", description);
 | 
			
		||||
		PKG_INFO_INT("size", size);
 | 
			
		||||
		PKG_INFO_STRING("url", url);
 | 
			
		||||
		PKG_INFO_STRING("arch", arch);
 | 
			
		||||
		PKG_INFO_INT("builddate", build_date);
 | 
			
		||||
		PKG_INFO_STRING("packager", packager);
 | 
			
		||||
		PKG_INFO_STRING("pgpsig", pgpsig);
 | 
			
		||||
		PKG_INFO_INT("pgpsigsize", pgpsigsize);
 | 
			
		||||
		PKG_INFO_ARRAY("group", groups);
 | 
			
		||||
		PKG_INFO_ARRAY("license", licenses);
 | 
			
		||||
		PKG_INFO_ARRAY("replaces", replaces);
 | 
			
		||||
		PKG_INFO_ARRAY("depend", depends);
 | 
			
		||||
		PKG_INFO_ARRAY("optdepend", optdepends);
 | 
			
		||||
		PKG_INFO_ARRAY("makedepend", makedepends);
 | 
			
		||||
		PKG_INFO_ARRAY("checkdepend", checkdepends);
 | 
			
		||||
 | 
			
		||||
advance:
 | 
			
		||||
		pkg_info_str = offset_ptr + 1;
 | 
			
		||||
		continue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue