aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2020-04-18 15:28:21 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2020-04-19 00:32:26 -0400
commitf70b803e39484a2eba362414545ba8afd027c9da (patch)
tree9fd89a070f272df3e0c47de821f6fbf38c914360
parent59f7d29e2d707373ba1153337dca3279a2e3acc5 (diff)
downloadspmc-f70b803e39484a2eba362414545ba8afd027c9da.tar.gz
Add error handler
-rw-r--r--include/error_handler.h34
-rw-r--r--include/spm.h1
-rw-r--r--lib/error_handler.c27
-rw-r--r--tests/test_error_handler_spm_strerror.c27
4 files changed, 89 insertions, 0 deletions
diff --git a/include/error_handler.h b/include/error_handler.h
new file mode 100644
index 0000000..a731d28
--- /dev/null
+++ b/include/error_handler.h
@@ -0,0 +1,34 @@
+#ifndef SPM_ERROR_HANDLER_H
+#define SPM_ERROR_HANDLER_H
+
+#define _SPM_ERR_BASE 0x8000 // SPM errors begin at 32768
+#define _SPM_ERR_MASK 0x7FFF // Support up to 32768 error strings (zero index)
+#define _SPM_ERR(X) _SPM_ERR_BASE + X // Create an error code
+#define SPM_ERR_CONFIRM(X) (X >= 0x8000) // Is X a SPM error code? (no=0, yes=!0)
+#define SPM_ERR_INDEX(X) (_SPM_ERR_MASK & X) // get index of error string
+
+#define SPM_ERR_SUCCESS _SPM_ERR(0) // no error
+#define SPM_ERR_ROOT_NO_RECORD _SPM_ERR(1) // "root" has no root record
+#define SPM_ERR_ROOT_UNSAFE _SPM_ERR(2) // "root" at root, "/"
+#define SPM_ERR_PKG_NOT_FOUND _SPM_ERR(3) // package not found
+#define SPM_ERR_PKG_INVALID _SPM_ERR(4) // invalid package (wrong structure, missing data, etc)
+#define SPM_ERR_PKG_CHECKSUM _SPM_ERR(5) // bad checksum
+#define SPM_ERR_PKG_FETCH _SPM_ERR(6) // failed to download package
+
+extern int spmerrno;
+
+static const char *SPM_ERR_STRING[] = {
+ "Success",
+ "No root record",
+ "Dangerous root path",
+ "Package not found",
+ "Invalid package",
+ "Bad package checksum",
+ "Failed to fetch package",
+ NULL,
+};
+
+char *spm_strerror(int code);
+void spm_perror(const char *msg);
+
+#endif //SPM_ERROR_HANDLER_H
diff --git a/include/spm.h b/include/spm.h
index 5931a94..b96554a 100644
--- a/include/spm.h
+++ b/include/spm.h
@@ -28,6 +28,7 @@
#endif
#include "compat.h"
+#include "error_handler.h"
#include "package.h"
#include "str.h"
#include "strlist.h"
diff --git a/lib/error_handler.c b/lib/error_handler.c
new file mode 100644
index 0000000..baf56b4
--- /dev/null
+++ b/lib/error_handler.c
@@ -0,0 +1,27 @@
+#include "spm.h"
+
+int spmerrno = 0;
+static char spmerrbuf[255];
+
+/**
+ *
+ * @param code
+ * @return
+ */
+char *spm_strerror(int code) {
+ char *buf = spmerrbuf;
+ int is_spm_error = SPM_ERR_CONFIRM(code);
+
+ memset(buf, '\0', sizeof(spmerrbuf));
+ if (is_spm_error == 0) {
+ strcpy(buf, strerror(code));
+ } else {
+ strcpy(buf, SPM_ERR_STRING[SPM_ERR_INDEX(code)]);
+ }
+ return buf;
+}
+
+void spm_perror(const char *msg) {
+ fprintf(stderr, "%s: %s\n", msg ? msg : "", spm_strerror(spmerrno));
+}
+
diff --git a/tests/test_error_handler_spm_strerror.c b/tests/test_error_handler_spm_strerror.c
new file mode 100644
index 0000000..f373a59
--- /dev/null
+++ b/tests/test_error_handler_spm_strerror.c
@@ -0,0 +1,27 @@
+#include "spm.h"
+#include "framework.h"
+
+const char *testFmt = "translated error code '%d': returned '%s', expected '%s'\n";
+struct TestCase testCase[] = {
+ {.caseValue.signed_integer = 0, .truthValue.sptr = "Success", .arg[0].signed_integer = 0},
+ {.caseValue.signed_integer = SPM_ERR_ROOT_NO_RECORD, .truthValue.sptr = "No root record", .arg[0].signed_integer = 0},
+ {.caseValue.signed_integer = SPM_ERR_ROOT_UNSAFE, .truthValue.sptr = "Dangerous root path", .arg[0].signed_integer = 0},
+ {.caseValue.signed_integer = ENOENT, .truthValue.sptr = "No such file or directory", .arg[0].signed_integer = ENOENT},
+ {.caseValue.signed_integer = EPIPE, .truthValue.sptr = "Broken pipe", .arg[0].signed_integer = EPIPE},
+ {.caseValue.signed_integer = -1, .truthValue.sptr = "Unknown error -1", .arg[0].signed_integer = 0},
+};
+size_t numCases = sizeof(testCase) / sizeof(struct TestCase);
+
+int main(int argc, char *argv[]) {
+ for (size_t i = 0; i < numCases; i++) {
+ // Mock global errno value to the value stored in the test case
+ errno = testCase[i].arg[0].signed_integer;
+
+ // Get SPM error (or system error)
+ char *estr = spm_strerror(testCase[i].caseValue.signed_integer);
+
+ // Assert error string matches error produced
+ myassert(strcmp(estr, testCase[i].truthValue.sptr) == 0, testFmt, testCase[i].caseValue.signed_integer, estr, testCase[i].truthValue.sptr);
+ }
+ return 0;
+} \ No newline at end of file