aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/error_handler.c5
-rw-r--r--lib/fs.c98
-rw-r--r--lib/install.c16
-rw-r--r--lib/mirrors.c81
-rw-r--r--lib/strlist.c115
5 files changed, 218 insertions, 97 deletions
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);
+}
diff --git a/lib/fs.c b/lib/fs.c
index 20a5999..e75c6a0 100644
--- a/lib/fs.c
+++ b/lib/fs.c
@@ -641,3 +641,101 @@ 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;
+ int use_stdin = 0;
+
+ 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;
+ }
+
+ // Allocate buffer
+ if ((buffer = calloc(BUFSIZ, sizeof(char))) == NULL) {
+ perror("line buffer");
+ fprintf(SYSERROR);
+ if (!use_stdin) {
+ fclose(fp);
+ }
+ return NULL;
+ }
+
+ // count number the of lines in the file
+ while ((fgets(buffer, BUFSIZ - 1, fp)) != NULL) {
+ lines++;
+ }
+
+ if (!lines) {
+ free(buffer);
+ if (!use_stdin) {
+ 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);
+ if (!use_stdin) {
+ fclose(fp);
+ }
+ return result;
+} \ No newline at end of file
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");
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
diff --git a/lib/strlist.c b/lib/strlist.c
index aac2755..f90cce4 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,98 @@ 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=no data, -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 retval = 0;
+ int is_remote = 0;
+ char *path = NULL;
+ char *filename = NULL;
+ char *from_file_tmpdir = NULL;
+ char **data = 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));
+ path = strdup(_path);
+ if (path == NULL) {
+ spmerrno = errno;
+ retval = -1;
+ goto fatal;
}
- return result;
+
+ 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");
+ retval = -1;
+ goto fatal;
+ }
+
+ 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);
+ retval = -1;
+ goto fatal;
+ }
+
+ filename = strdup(fetched);
+ free(fetched);
+ } else {
+ filename = expandpath(path);
+ }
+
+ if (filename == NULL) {
+ spmerrno = errno;
+ retval = -1;
+ goto fatal;
+ }
+
+ data = file_readlines(filename, 0, 0, readerFn);
+ if (data == NULL) {
+ retval = 1;
+ goto fatal;
+ }
+
+ for (size_t record = 0; data[record] != NULL; record++) {
+ strlist_append(pStrList, data[record]);
+ free(data[record]);
+ }
+ free(data);
+
+fatal:
+ if (from_file_tmpdir != NULL) {
+ rmdirs(from_file_tmpdir);
+ free(from_file_tmpdir);
+ }
+ if (filename != NULL) {
+ free(filename);
+ }
+ if (path != NULL) {
+ free(path);
+ }
+
+ return retval;
}
/**
@@ -83,6 +161,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
* @param index