aboutsummaryrefslogtreecommitdiff
path: root/lib/metadata.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/metadata.c')
-rw-r--r--lib/metadata.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/lib/metadata.c b/lib/metadata.c
new file mode 100644
index 0000000..6861740
--- /dev/null
+++ b/lib/metadata.c
@@ -0,0 +1,166 @@
+#include "spm.h"
+
+extern const char *METADATA_FILES[];
+
+static int verify_filelist(size_t lineno, char **a) {
+ if (lineno == 0) {
+ if (strncmp((*a), SPM_PACKAGE_HEADER_FILELIST, strlen(SPM_PACKAGE_HEADER_FILELIST)) != 0) {
+ fprintf(stderr, "invalid or missing header: line %zu: %s (expected: '%s')\n",
+ lineno, (*a), SPM_PACKAGE_HEADER_FILELIST);
+ return 1;
+ }
+ }
+ return -1;
+}
+
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+static int verify_depends(size_t lineno, char **a) {
+ return -1;
+}
+
+static int verify_descriptor(size_t lineno, char **a) {
+ if (lineno == 0) {
+ if (strncmp((*a), SPM_PACKAGE_HEADER_DESCRIPTOR, strlen(SPM_PACKAGE_HEADER_DESCRIPTOR)) != 0) {
+ fprintf(stderr, "invalid or missing header: line %zu: %s (expected: '%s')\n",
+ lineno, (*a), SPM_PACKAGE_HEADER_DESCRIPTOR);
+ return 1;
+ }
+ }
+ return -1;
+}
+
+static int verify_prefix(size_t lineno, char **a) {
+ size_t parity = lineno % 2;
+ if (parity == 0 && *(*a) == '#') {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+static int verify_no_op(size_t lineno, char **a) {
+ return -1;
+}
+
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+static int reader_metadata(size_t lineno, char **line) {
+ (*line) = strip((*line));
+ if (isempty((*line))) {
+ return 1; // indicate "continue"
+ }
+ return 0; // indicate "ok"
+}
+
+/**
+ * Detect the type of metadata based on file name and execute the appropriate function against each line
+ * in the file. Verification can be disabled by passing a non-zero value as the second argument.
+ * @param filename
+ * @param no_verify SPM_METADATA_VERIFY or SPM_METADATA_NO_VERIFY
+ * @return array of strings (line endings removed)
+ */
+char **spm_metadata_read(const char *_filename, int no_verify) {
+ char *filename = strdup(_filename);
+ char **data = NULL;
+ char **result = NULL;
+ size_t start = 0;
+ ReaderFn *func_verify;
+
+ // Guard
+ if (file_is_metadata(filename) == 0) {
+ free(filename);
+ return NULL;
+ }
+
+ // Setup function pointer and data starting offsets (if any)
+ if (strcmp(basename(filename), SPM_META_FILELIST) == 0) {
+ func_verify = verify_filelist;
+ start = 1;
+ } else if (strcmp(basename(filename), SPM_META_DESCRIPTOR) == 0) {
+ func_verify = verify_descriptor;
+ start = 1;
+ } else if (strcmp(basename(filename), SPM_META_DEPENDS) == 0) {
+ func_verify = verify_depends;
+ } else if (strcmp(basename(filename), SPM_META_PREFIX_BIN) == 0) {
+ func_verify = verify_prefix;
+ } else if (strcmp(basename(filename), SPM_META_PREFIX_TEXT) == 0) {
+ func_verify = verify_prefix;
+ } else {
+ func_verify = verify_no_op;
+ }
+
+ // Get file contents
+ data = file_readlines(filename, 0, 0, reader_metadata);
+
+ // Strip newlines and whitespace
+ for (size_t i = 0; data[i] != NULL; i++) {
+ data[i] = strip(data[i]);
+ }
+
+ // Perform verification
+ if (no_verify == 0) {
+ for (size_t i = 0; data[i] != NULL; i++) {
+ int status = func_verify(i, &data[i]);
+ if (status > 0) {
+ fprintf(stderr, "%s: file verification failed\n", filename);
+ free(filename);
+ return NULL;
+ } else if (status < 0) {
+ // NOT AN ERROR
+ // a negative value indicates the verification function has processed enough information
+ // so we can gracefully
+ break;
+ }
+ }
+ }
+
+ // If there was a header, duplicate the array from the start of the data
+ // Otherwise return the array
+ if (start > 0) {
+ result = strdup_array(&data[start]);
+ for (size_t i = 0; data[i] != NULL; i++) {
+ free(data[i]);
+ }
+ free(data);
+ } else {
+ result = data;
+ }
+
+ free(filename);
+ return result;
+}
+
+/**
+ * SPM packages contain metadata files that are not useful post-install and would amount to a lot of clutter.
+ * This function removes these data files from a directory tree
+ * @param _path
+ * @return success=0, error=-1
+ */
+int spm_metadata_remove(const char *_path) {
+ if (exists(_path) != 0) {
+ perror(_path);
+ fprintf(SYSERROR);
+ return -1;
+ }
+
+ for (int i = 0; METADATA_FILES[i] != NULL; i++) {
+ char path[PATH_MAX];
+ sprintf(path, "%s%c%s", _path, DIRSEP, METADATA_FILES[i]);
+ if (exists(path) != 0) {
+ continue;
+ }
+ if (unlink(path) < 0) {
+ perror(path);
+ fprintf(SYSERROR);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+ConfigItem **spm_descriptor_read(const char *filename) {
+ ConfigItem **result = config_read(filename);
+ return result;
+}
+