diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-03-18 22:25:27 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-03-18 22:25:27 -0400 |
commit | ccaeb7092b5ad40b1b3833c987ba3ec4d47f0bb8 (patch) | |
tree | ae167772a9a2343aa77bf8944b56abe853f6a2ec /lib/metadata.c | |
parent | 3731bb4679ee8716d4f579d5744c36a2d1b4a257 (diff) | |
download | spmc-ccaeb7092b5ad40b1b3833c987ba3ec4d47f0bb8.tar.gz |
Refactor project: build/install libspm[_static.a].so to make unit testing possible
Diffstat (limited to 'lib/metadata.c')
-rw-r--r-- | lib/metadata.c | 166 |
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; +} + |