From 2d981c10be5f902442c885fb7e2cafa6154145c7 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 25 May 2020 01:17:40 -0400 Subject: Move file_readlines function out of mirrors.c --- lib/fs.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/mirrors.c | 81 --------------------------------------------------------- 2 files changed, 83 insertions(+), 81 deletions(-) (limited to 'lib') diff --git a/lib/fs.c b/lib/fs.c index 20a5999..cacaf6d 100644 --- a/lib/fs.c +++ b/lib/fs.c @@ -641,3 +641,86 @@ char *spm_mkdtemp(const char *base, const char *name, const char *extended_path) return 0; } + +char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn *readerFn) { + FILE *fp = NULL; + char **result = NULL; + char *buffer = NULL; + size_t lines = 0; + + if ((fp = fopen(filename, "r")) == NULL) { + perror(filename); + fprintf(SYSERROR); + return NULL; + } + + // Allocate buffer + if ((buffer = calloc(BUFSIZ, sizeof(char))) == NULL) { + perror("line buffer"); + fprintf(SYSERROR); + fclose(fp); + return NULL; + } + + // count number the of lines in the file + while ((fgets(buffer, BUFSIZ - 1, fp)) != NULL) { + lines++; + } + + if (!lines) { + free(buffer); + fclose(fp); + result = calloc(2, sizeof(char *)); + result[0] = strdup(""); + return result; + } + + rewind(fp); + + // Handle invalid start offset + if (start > lines) { + start = 0; + } + + // Adjust line count when start offset is non-zero + if (start != 0 && start < lines) { + lines -= start; + } + + + // Handle minimum and maximum limits + if (limit == 0 || limit > lines) { + limit = lines; + } + + // Populate results array + result = calloc(limit + 1, sizeof(char *)); + for (size_t i = start; i < limit; i++) { + if (i < start) { + continue; + } + + if (fgets(buffer, BUFSIZ - 1, fp) == NULL) { + break; + } + + if (readerFn != NULL) { + int status = readerFn(i - start, &buffer); + // A status greater than zero indicates we should ignore this line entirely and "continue" + // A status less than zero indicates we should "break" + // A zero status proceeds normally + if (status > 0) { + i--; + continue; + } else if (status < 0) { + break; + } + } + result[i] = strdup(buffer); + memset(buffer, '\0', BUFSIZ); + } + + free(buffer); + fclose(fp); + return result; +} \ No newline at end of file diff --git a/lib/mirrors.c b/lib/mirrors.c index 6bc7aed..1c51845 100644 --- a/lib/mirrors.c +++ b/lib/mirrors.c @@ -1,87 +1,6 @@ #include "spm.h" #include "url.h" -char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn *readerFn) { - FILE *fp = NULL; - char **result = NULL; - char *buffer = NULL; - size_t lines = 0; - - if ((fp = fopen(filename, "r")) == NULL) { - perror(filename); - fprintf(SYSERROR); - return NULL; - } - - // Allocate buffer - if ((buffer = calloc(BUFSIZ, sizeof(char))) == NULL) { - perror("line buffer"); - fprintf(SYSERROR); - fclose(fp); - return NULL; - } - - // count number the of lines in the file - while ((fgets(buffer, BUFSIZ - 1, fp)) != NULL) { - lines++; - } - - if (!lines) { - free(buffer); - fclose(fp); - return NULL; - } - - rewind(fp); - - // Handle invalid start offset - if (start > lines) { - start = 0; - } - - // Adjust line count when start offset is non-zero - if (start != 0 && start < lines) { - lines -= start; - } - - - // Handle minimum and maximum limits - if (limit == 0 || limit > lines) { - limit = lines; - } - - // Populate results array - result = calloc(limit + 1, sizeof(char *)); - for (size_t i = start; i < limit; i++) { - if (i < start) { - continue; - } - - if (fgets(buffer, BUFSIZ - 1, fp) == NULL) { - break; - } - - if (readerFn != NULL) { - int status = readerFn(i - start, &buffer); - // A status greater than zero indicates we should ignore this line entirely and "continue" - // A status less than zero indicates we should "break" - // A zero status proceeds normally - if (status > 0) { - i--; - continue; - } else if (status < 0) { - break; - } - } - result[i] = strdup(buffer); - memset(buffer, '\0', BUFSIZ); - } - - free(buffer); - fclose(fp); - return result; -} - /** * * @param filename -- cgit From bb88ad38aacb40a9a3debcdcbeb21fef2e537dcd Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 25 May 2020 01:18:05 -0400 Subject: Implement -F|--from-file argument --- lib/install.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/install.c b/lib/install.c index 9fb80c2..282c662 100644 --- a/lib/install.c +++ b/lib/install.c @@ -201,16 +201,24 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) { ManifestPackage **requirements = NULL; char source[PATH_MAX]; char *tmpdir = NULL; + size_t package_count; + + package_count = strlist_count(packages); + if (package_count == 0) { + spmerrno = SPM_ERR_PKG_NOT_FOUND; + spmerrno_cause("EMPTY PACKAGE LIST"); + return -1; + } // Produce a dependency tree from requested package(s) - for (size_t i = 0; i < strlist_count(packages); i++) { + for (size_t i = 0; i < package_count; i++) { char *item = strlist_item(packages, i); // Does the package exist in the manifest? if (manifestlist_search(mf, item) == NULL) { spmerrno = SPM_ERR_PKG_NOT_FOUND; spmerrno_cause(item); - break; + return -1; } requirements = resolve_dependencies(mf, item); @@ -221,10 +229,6 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) { } } - if (spmerrno) { - return -1; - } - tmpdir = spm_mkdtemp(TMP_DIR, "spm_destroot", NULL); if (tmpdir == NULL) { perror("Could not create temporary destination root"); -- cgit From 5cce499107951ca06574b7dde6ff2bb6e25370c3 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 25 May 2020 23:54:52 -0400 Subject: Error handler: * Add spm_die() * Add SPM_ERR_FETCH to handle non-package download failures --- lib/error_handler.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/error_handler.c b/lib/error_handler.c index 2ccb4e7..5130f3a 100644 --- a/lib/error_handler.c +++ b/lib/error_handler.c @@ -15,6 +15,7 @@ const char *SPM_ERR_STRING[] = { "Manifest has no data", "Parsing error", "Not implemented", + "Failed to fetch data", NULL, }; @@ -55,3 +56,7 @@ void spm_perror(const char *msg) { fprintf(stderr, "%s: %s\n", msg ? msg : "", spm_strerror(spmerrno)); } +void spm_die(void) { + spm_perror("FATAL"); + exit(1); +} -- cgit From 737729afb8d2b248105d8301066479092ac6c4c7 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 25 May 2020 23:56:17 -0400 Subject: readlines() return NULL array instead of array with a blank string. --- lib/fs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/fs.c b/lib/fs.c index cacaf6d..3d9cc9f 100644 --- a/lib/fs.c +++ b/lib/fs.c @@ -671,7 +671,6 @@ char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn free(buffer); fclose(fp); result = calloc(2, sizeof(char *)); - result[0] = strdup(""); return result; } -- cgit From ef427fa2c16139b2d6790b8867d5bdb6307fd14d Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 25 May 2020 23:57:24 -0400 Subject: Add strlist_append_file() * Add reader_strlist_append_file() as default reader function --- lib/strlist.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/strlist.c b/lib/strlist.c index aac2755..c2cff09 100644 --- a/lib/strlist.c +++ b/lib/strlist.c @@ -4,6 +4,7 @@ */ #include "spm.h" #include "strlist.h" +#include "url.h" /** * @@ -46,21 +47,87 @@ void strlist_append(StrList *pStrList, char *str) { pStrList->num_alloc++; } +static int reader_strlist_append_file(size_t lineno, char **line) { + (void)(lineno); // unused parameter + (void)(line); // unused parameter + return 0; +} + /** - * Produce a new copy of a `StrList` - * @param pStrList `StrList` - * @return `StrList` copy + * Append lines from a local file or remote URL (HTTP/s only) + * @param pStrList + * @param path file path or HTTP/s address + * @param readerFn pointer to a reader function (use NULL to retrieve all data) + * @return 0=success -1=error (spmerrno set) */ -StrList *strlist_copy(StrList *pStrList) { - StrList *result = strlist_init(); - if (pStrList == NULL || result == NULL) { - return NULL; +int strlist_append_file(StrList *pStrList, char *path, ReaderFn *readerFn) { + int is_remote = 0; + char *filename = NULL; + char *from_file_tmpdir = NULL; + char **from_file = NULL; + char *fetched = NULL; + + if (readerFn == NULL) { + readerFn = reader_strlist_append_file; } - for (size_t i = 0; i < strlist_count(pStrList); i++) { - strlist_append(result, strlist_item(pStrList, i)); + filename = calloc(PATH_MAX, sizeof(char)); + if (filename == NULL) { + spmerrno = errno; + return -1; } - return result; + + filename = expandpath(path); + + is_remote = (startswith(path, "http") || startswith(path, "https")); + if (is_remote) { + long response = 0; + from_file_tmpdir = spm_mkdtemp(TMP_DIR, __FUNCTION__, NULL); + + if (from_file_tmpdir == NULL) { + spmerrno = errno; + spmerrno_cause("file_from temp directory"); + return -1; + } + + fetched = join((char *[]){from_file_tmpdir, basename(path), NULL}, DIRSEPS); + if ((response = fetch(path, fetched)) >= 400) { + spmerrno = SPM_ERR_FETCH; + char cause[PATH_MAX]; + sprintf(cause, "HTTP(%ld): %s: %s", response, http_response_str(response), path); + spmerrno_cause(cause); + return -1; + } + + strcpy(filename, fetched); + } + + if (exists(filename) != 0) { + spmerrno = errno; + spmerrno_cause(filename); + return -1; + } + + from_file = file_readlines(filename, 0, 0, readerFn); + if (from_file == NULL) { + spmerrno = errno; + spmerrno_cause(filename); + return -1; + } + + for (size_t record = 0; from_file[record] != NULL; record++) { + strlist_append(pStrList, from_file[record]); + free(from_file[record]); + } + free(from_file); + + if (from_file_tmpdir) { + rmdirs(from_file_tmpdir); + } + free(from_file_tmpdir); + free(filename); + + return 0; } /** @@ -82,6 +149,23 @@ void strlist_append_strlist(StrList *pStrList1, StrList *pStrList2) { } } +/** + * Produce a new copy of a `StrList` + * @param pStrList `StrList` + * @return `StrList` copy + */ +StrList *strlist_copy(StrList *pStrList) { + StrList *result = strlist_init(); + if (pStrList == NULL || result == NULL) { + return NULL; + } + + for (size_t i = 0; i < strlist_count(pStrList); i++) { + strlist_append(result, strlist_item(pStrList, i)); + } + return result; +} + /** * Remove a record by index from a `StrList` * @param pStrList -- cgit From 629ab111362a361729a8c2281c7168eb13729a77 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Tue, 26 May 2020 00:19:06 -0400 Subject: Make a copy of the path --- lib/strlist.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/strlist.c b/lib/strlist.c index c2cff09..0de0d2a 100644 --- a/lib/strlist.c +++ b/lib/strlist.c @@ -60,8 +60,9 @@ static int reader_strlist_append_file(size_t lineno, char **line) { * @param readerFn pointer to a reader function (use NULL to retrieve all data) * @return 0=success -1=error (spmerrno set) */ -int strlist_append_file(StrList *pStrList, char *path, ReaderFn *readerFn) { +int strlist_append_file(StrList *pStrList, char *_path, ReaderFn *readerFn) { int is_remote = 0; + char *path = NULL; char *filename = NULL; char *from_file_tmpdir = NULL; char **from_file = NULL; @@ -71,6 +72,12 @@ int strlist_append_file(StrList *pStrList, char *path, ReaderFn *readerFn) { readerFn = reader_strlist_append_file; } + path = strdup(_path); + if (path == NULL) { + spmerrno = errno; + return -1; + } + filename = calloc(PATH_MAX, sizeof(char)); if (filename == NULL) { spmerrno = errno; @@ -99,7 +106,7 @@ int strlist_append_file(StrList *pStrList, char *path, ReaderFn *readerFn) { return -1; } - strcpy(filename, fetched); + strncpy(filename, fetched, PATH_MAX - 1); } if (exists(filename) != 0) { -- cgit From c34dc1f1dfe74ded5b71bb0bb10f61f3610bc987 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Tue, 26 May 2020 00:20:26 -0400 Subject: Nevermind --- lib/fs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/fs.c b/lib/fs.c index 3d9cc9f..cacaf6d 100644 --- a/lib/fs.c +++ b/lib/fs.c @@ -671,6 +671,7 @@ char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn free(buffer); fclose(fp); result = calloc(2, sizeof(char *)); + result[0] = strdup(""); return result; } -- cgit From 9bc167d23a3f738057185dc8a6412132c7c47c3e Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Tue, 26 May 2020 13:53:44 -0400 Subject: Errors set return value and jump to end of function --- lib/strlist.c | 66 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 31 deletions(-) (limited to 'lib') diff --git a/lib/strlist.c b/lib/strlist.c index 0de0d2a..f90cce4 100644 --- a/lib/strlist.c +++ b/lib/strlist.c @@ -58,15 +58,15 @@ static int reader_strlist_append_file(size_t lineno, char **line) { * @param pStrList * @param path file path or HTTP/s address * @param readerFn pointer to a reader function (use NULL to retrieve all data) - * @return 0=success -1=error (spmerrno set) + * @return 0=success 1=no data, -1=error (spmerrno set) */ int strlist_append_file(StrList *pStrList, char *_path, ReaderFn *readerFn) { + int retval = 0; int is_remote = 0; char *path = NULL; char *filename = NULL; char *from_file_tmpdir = NULL; - char **from_file = NULL; - char *fetched = NULL; + char **data = NULL; if (readerFn == NULL) { readerFn = reader_strlist_append_file; @@ -75,26 +75,21 @@ int strlist_append_file(StrList *pStrList, char *_path, ReaderFn *readerFn) { path = strdup(_path); if (path == NULL) { spmerrno = errno; - return -1; - } - - filename = calloc(PATH_MAX, sizeof(char)); - if (filename == NULL) { - spmerrno = errno; - return -1; + retval = -1; + goto fatal; } - filename = expandpath(path); - is_remote = (startswith(path, "http") || startswith(path, "https")); if (is_remote) { long response = 0; + char *fetched = NULL; from_file_tmpdir = spm_mkdtemp(TMP_DIR, __FUNCTION__, NULL); if (from_file_tmpdir == NULL) { spmerrno = errno; spmerrno_cause("file_from temp directory"); - return -1; + retval = -1; + goto fatal; } fetched = join((char *[]){from_file_tmpdir, basename(path), NULL}, DIRSEPS); @@ -103,38 +98,47 @@ int strlist_append_file(StrList *pStrList, char *_path, ReaderFn *readerFn) { char cause[PATH_MAX]; sprintf(cause, "HTTP(%ld): %s: %s", response, http_response_str(response), path); spmerrno_cause(cause); - return -1; + retval = -1; + goto fatal; } - strncpy(filename, fetched, PATH_MAX - 1); + filename = strdup(fetched); + free(fetched); + } else { + filename = expandpath(path); } - if (exists(filename) != 0) { + if (filename == NULL) { spmerrno = errno; - spmerrno_cause(filename); - return -1; + retval = -1; + goto fatal; } - from_file = file_readlines(filename, 0, 0, readerFn); - if (from_file == NULL) { - spmerrno = errno; - spmerrno_cause(filename); - return -1; + data = file_readlines(filename, 0, 0, readerFn); + if (data == NULL) { + retval = 1; + goto fatal; } - for (size_t record = 0; from_file[record] != NULL; record++) { - strlist_append(pStrList, from_file[record]); - free(from_file[record]); + for (size_t record = 0; data[record] != NULL; record++) { + strlist_append(pStrList, data[record]); + free(data[record]); } - free(from_file); + free(data); - if (from_file_tmpdir) { +fatal: + if (from_file_tmpdir != NULL) { rmdirs(from_file_tmpdir); + free(from_file_tmpdir); + } + if (filename != NULL) { + free(filename); + } + if (path != NULL) { + free(path); } - free(from_file_tmpdir); - free(filename); - return 0; + return retval; } /** -- cgit From 73e15115a66ab0b45acbbd9f45f4622f19a32187 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Tue, 26 May 2020 13:57:25 -0400 Subject: file_readlines now accepts STDIN (filename = "-") --- lib/fs.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/fs.c b/lib/fs.c index cacaf6d..e75c6a0 100644 --- a/lib/fs.c +++ b/lib/fs.c @@ -647,8 +647,19 @@ char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn char **result = NULL; char *buffer = NULL; size_t lines = 0; + int use_stdin = 0; - if ((fp = fopen(filename, "r")) == NULL) { + if (strcmp(filename, "-") == 0) { + use_stdin = 1; + } + + if (use_stdin) { + fp = stdin; + } else { + fp = fopen(filename, "r"); + } + + if (fp == NULL) { perror(filename); fprintf(SYSERROR); return NULL; @@ -658,7 +669,9 @@ char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn if ((buffer = calloc(BUFSIZ, sizeof(char))) == NULL) { perror("line buffer"); fprintf(SYSERROR); - fclose(fp); + if (!use_stdin) { + fclose(fp); + } return NULL; } @@ -669,10 +682,10 @@ char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn if (!lines) { free(buffer); - fclose(fp); - result = calloc(2, sizeof(char *)); - result[0] = strdup(""); - return result; + if (!use_stdin) { + fclose(fp); + } + return NULL; } rewind(fp); @@ -721,6 +734,8 @@ char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn } free(buffer); - fclose(fp); + if (!use_stdin) { + fclose(fp); + } return result; } \ No newline at end of file -- cgit