github.com/anonymouse64/snapd@v0.0.0-20210824153203-04c4c42d842d/cmd/libsnap-confine-private/error.c (about) 1 /* 2 * Copyright (C) 2016 Canonical Ltd 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 3 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 * 16 */ 17 #include "error.h" 18 19 // To get vasprintf 20 #define _GNU_SOURCE 21 22 #include "utils.h" 23 24 #include <errno.h> 25 #include <stdarg.h> 26 #include <stdio.h> 27 #include <string.h> 28 29 static sc_error *sc_error_initv(const char *domain, int code, 30 const char *msgfmt, va_list ap) 31 { 32 // Set errno in case we die. 33 errno = 0; 34 sc_error *err = calloc(1, sizeof *err); 35 if (err == NULL) { 36 die("cannot allocate memory for error object"); 37 } 38 err->domain = domain; 39 err->code = code; 40 if (vasprintf(&err->msg, msgfmt, ap) == -1) { 41 die("cannot format error message"); 42 } 43 return err; 44 } 45 46 sc_error *sc_error_init(const char *domain, int code, const char *msgfmt, ...) 47 { 48 va_list ap; 49 va_start(ap, msgfmt); 50 sc_error *err = sc_error_initv(domain, code, msgfmt, ap); 51 va_end(ap); 52 return err; 53 } 54 55 sc_error *sc_error_init_from_errno(int errno_copy, const char *msgfmt, ...) 56 { 57 va_list ap; 58 va_start(ap, msgfmt); 59 sc_error *err = sc_error_initv(SC_ERRNO_DOMAIN, errno_copy, msgfmt, ap); 60 va_end(ap); 61 return err; 62 } 63 64 sc_error *sc_error_init_simple(const char *msgfmt, ...) 65 { 66 va_list ap; 67 va_start(ap, msgfmt); 68 sc_error *err = sc_error_initv(SC_LIBSNAP_DOMAIN, 69 SC_UNSPECIFIED_ERROR, msgfmt, ap); 70 va_end(ap); 71 return err; 72 } 73 74 sc_error *sc_error_init_api_misuse(const char *msgfmt, ...) 75 { 76 va_list ap; 77 va_start(ap, msgfmt); 78 sc_error *err = sc_error_initv(SC_LIBSNAP_DOMAIN, 79 SC_API_MISUSE, msgfmt, ap); 80 va_end(ap); 81 return err; 82 } 83 84 const char *sc_error_domain(sc_error * err) 85 { 86 // Set errno in case we die. 87 errno = 0; 88 if (err == NULL) { 89 die("cannot obtain error domain from NULL error"); 90 } 91 return err->domain; 92 } 93 94 int sc_error_code(sc_error * err) 95 { 96 // Set errno in case we die. 97 errno = 0; 98 if (err == NULL) { 99 die("cannot obtain error code from NULL error"); 100 } 101 return err->code; 102 } 103 104 const char *sc_error_msg(sc_error * err) 105 { 106 // Set errno in case we die. 107 errno = 0; 108 if (err == NULL) { 109 die("cannot obtain error message from NULL error"); 110 } 111 return err->msg; 112 } 113 114 void sc_error_free(sc_error * err) 115 { 116 if (err != NULL) { 117 free(err->msg); 118 err->msg = NULL; 119 free(err); 120 } 121 } 122 123 void sc_cleanup_error(sc_error ** ptr) 124 { 125 sc_error_free(*ptr); 126 *ptr = NULL; 127 } 128 129 void sc_die_on_error(sc_error * error) 130 { 131 if (error != NULL) { 132 if (strcmp(sc_error_domain(error), SC_ERRNO_DOMAIN) == 0) { 133 fprintf(stderr, "%s: %s\n", sc_error_msg(error), strerror(sc_error_code(error))); 134 } else { 135 fprintf(stderr, "%s\n", sc_error_msg(error)); 136 } 137 sc_error_free(error); 138 exit(1); 139 } 140 } 141 142 int sc_error_forward(sc_error ** recipient, sc_error * error) 143 { 144 if (recipient != NULL) { 145 *recipient = error; 146 } else { 147 sc_die_on_error(error); 148 } 149 return error != NULL ? -1 : 0; 150 } 151 152 bool sc_error_match(sc_error * error, const char *domain, int code) 153 { 154 // Set errno in case we die. 155 errno = 0; 156 if (domain == NULL) { 157 die("cannot match error to a NULL domain"); 158 } 159 if (error == NULL) { 160 return false; 161 } 162 return strcmp(sc_error_domain(error), domain) == 0 163 && sc_error_code(error) == code; 164 }