portable: initial Linux compilation
[got-portable.git] / lib / error.c
blob4ad6d22aa77f19cf6105fcd6bc22a98e92d55ef7
1 /*
2 * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <errno.h>
19 #include <limits.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sha1.h>
25 #include <zlib.h>
26 #include <uuid.h>
28 #include "got_compat.h"
30 #include "got_error.h"
31 #include "got_object.h"
33 #include "got_lib_delta.h"
34 #include "got_lib_inflate.h"
35 #include "got_lib_object.h"
36 #include "got_lib_sha1.h"
38 #ifndef nitems
39 #define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
40 #endif
42 static struct got_custom_error {
43 struct got_error err;
44 char msg[4080];
45 } custom_errors[16];
47 static struct got_custom_error *
48 get_custom_err(void)
50 static unsigned int idx;
51 return &custom_errors[(idx++) % nitems(custom_errors)];
54 const struct got_error *
55 got_error(int code)
57 size_t i;
59 for (i = 0; i < nitems(got_errors); i++) {
60 if (code == got_errors[i].code)
61 return &got_errors[i];
64 abort();
67 const struct got_error *
68 got_error_msg(int code, const char *msg)
70 struct got_custom_error *cerr = get_custom_err();
71 struct got_error *err = &cerr->err;
72 size_t i;
74 for (i = 0; i < nitems(got_errors); i++) {
75 if (code == got_errors[i].code) {
76 err->code = code;
77 strlcpy(cerr->msg, msg, sizeof(cerr->msg));
78 err->msg = cerr->msg;
79 return err;
83 abort();
86 const struct got_error *
87 got_error_from_errno(const char *prefix)
89 struct got_custom_error *cerr = get_custom_err();
90 struct got_error *err = &cerr->err;
91 char strerr[128];
93 strerror_r(errno, strerr, sizeof(strerr));
94 snprintf(cerr->msg, sizeof(cerr->msg), "%s: %s", prefix, strerr);
96 err->code = GOT_ERR_ERRNO;
97 err->msg = cerr->msg;
98 return err;
101 const struct got_error *
102 got_error_from_errno2(const char *prefix, const char *prefix2)
104 struct got_custom_error *cerr = get_custom_err();
105 struct got_error *err = &cerr->err;
106 char strerr[128];
108 strerror_r(errno, strerr, sizeof(strerr));
109 snprintf(cerr->msg, sizeof(cerr->msg), "%s: %s: %s", prefix, prefix2,
110 strerr);
112 err->code = GOT_ERR_ERRNO;
113 err->msg = cerr->msg;
114 return err;
117 const struct got_error *
118 got_error_from_errno3(const char *prefix, const char *prefix2,
119 const char *prefix3)
121 struct got_custom_error *cerr = get_custom_err();
122 struct got_error *err = &cerr->err;
123 char strerr[128];
125 strerror_r(errno, strerr, sizeof(strerr));
126 snprintf(cerr->msg, sizeof(cerr->msg), "%s: %s: %s: %s", prefix,
127 prefix2, prefix3, strerr);
129 err->code = GOT_ERR_ERRNO;
130 err->msg = cerr->msg;
131 return err;
134 const struct got_error *
135 got_error_from_errno_fmt(const char *fmt, ...)
137 struct got_custom_error *cerr = get_custom_err();
138 struct got_error *err = &cerr->err;
139 char buf[PATH_MAX * 4];
140 char strerr[128];
141 va_list ap;
143 va_start(ap, fmt);
144 vsnprintf(buf, sizeof(buf), fmt, ap);
145 va_end(ap);
147 strerror_r(errno, strerr, sizeof(strerr));
148 snprintf(cerr->msg, sizeof(cerr->msg), "%s: %s", buf, strerr);
150 err->code = GOT_ERR_ERRNO;
151 err->msg = cerr->msg;
152 return err;
155 const struct got_error *
156 got_error_set_errno(int code, const char *prefix)
158 errno = code;
159 return got_error_from_errno(prefix);
162 const struct got_error *
163 got_ferror(FILE *f, int code)
165 if (ferror(f))
166 return got_error_from_errno("");
167 return got_error(code);
170 const struct got_error *
171 got_error_no_obj(struct got_object_id *id)
173 char msg[sizeof("object not found") + SHA1_DIGEST_STRING_LENGTH];
174 char id_str[SHA1_DIGEST_STRING_LENGTH];
175 int ret;
177 if (!got_sha1_digest_to_str(id->sha1, id_str, sizeof(id_str)))
178 return got_error(GOT_ERR_NO_OBJ);
180 ret = snprintf(msg, sizeof(msg), "object %s not found", id_str);
181 if (ret == -1 || ret >= sizeof(msg))
182 return got_error(GOT_ERR_NO_OBJ);
184 return got_error_msg(GOT_ERR_NO_OBJ, msg);
187 const struct got_error *
188 got_error_not_ref(const char *refname)
190 char msg[sizeof("reference not found") + 1004];
191 int ret;
193 ret = snprintf(msg, sizeof(msg), "reference %s not found", refname);
194 if (ret == -1 || ret >= sizeof(msg))
195 return got_error(GOT_ERR_NOT_REF);
197 return got_error_msg(GOT_ERR_NOT_REF, msg);
200 const struct got_error *
201 got_error_uuid(uint32_t uuid_status, const char *prefix)
203 switch (uuid_status) {
204 case uuid_s_ok:
205 return NULL;
206 case uuid_s_bad_version:
207 return got_error(GOT_ERR_UUID_VERSION);
208 case uuid_s_invalid_string_uuid:
209 return got_error(GOT_ERR_UUID_INVALID);
210 case uuid_s_no_memory:
211 return got_error_set_errno(ENOMEM, prefix);
212 default:
213 return got_error(GOT_ERR_UUID);
217 const struct got_error *
218 got_error_path(const char *path, int code)
220 struct got_custom_error *cerr = get_custom_err();
221 struct got_error *err = &cerr->err;
222 size_t i;
224 for (i = 0; i < nitems(got_errors); i++) {
225 if (code == got_errors[i].code) {
226 err->code = code;
227 snprintf(cerr->msg, sizeof(cerr->msg), "%s: %s", path,
228 got_errors[i].msg);
229 err->msg = cerr->msg;
230 return err;
234 abort();
237 const struct got_error *
238 got_error_fmt(int code, const char *fmt, ...)
240 struct got_custom_error *cerr = get_custom_err();
241 struct got_error *err = &cerr->err;
242 char buf[PATH_MAX * 4];
243 va_list ap;
244 size_t i;
246 va_start(ap, fmt);
247 vsnprintf(buf, sizeof(buf), fmt, ap);
248 va_end(ap);
250 for (i = 0; i < nitems(got_errors); i++) {
251 if (code == got_errors[i].code) {
252 err->code = code;
253 snprintf(cerr->msg, sizeof(cerr->msg), "%s: %s", buf,
254 got_errors[i].msg);
255 err->msg = cerr->msg;
256 return err;
260 abort();