OSDN Git Service

linux-pci-root: remove an unused assignment
[android-x86/external-efivar.git] / src / error.c
1 /*
2  * libefiboot - library for the manipulation of EFI boot variables
3  * Copyright 2012-2015 Red Hat, Inc.
4  * Copyright (C) 2000-2001 Dell Computer Corporation <Matt_Domsch@dell.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of the
9  * License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see
18  * <http://www.gnu.org/licenses/>.
19  *
20  */
21
22 #include "fix_coverity.h"
23
24 #include <errno.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
30
31 #include "efiboot.h"
32
33 /*
34  * GCC/Clang complains that we check for null if we have a nonnull attribute,
35  * even though older or other compilers might just ignore that attribute if
36  * they don't support it.  Ugh.
37  */
38 #if defined(__clang__)
39 #pragma clang diagnostic ignored "-Wpointer-bool-conversion"
40 #elif defined(__GNUC__) && __GNUC__ >= 6
41 #pragma GCC diagnostic ignored "-Wnonnull-compare"
42 #endif
43
44 typedef struct {
45         int error;
46         char *filename;
47         char *function;
48         int line;
49         char *message;
50 } error_table_entry;
51
52 static error_table_entry *error_table;
53 static unsigned int current;
54
55 int PUBLIC NONNULL(2, 3, 4, 5, 6)
56 efi_error_get(unsigned int n,
57               char ** const filename,
58               char ** const function,
59               int *line,
60               char ** const message,
61               int *error
62               )
63 {
64         if (!filename || !function || !line || !message || !error) {
65                 errno = EINVAL;
66                 return -1;
67         }
68
69         if (n >= current)
70                 return 0;
71
72         *filename = error_table[n].filename;
73         *function = error_table[n].function;
74         *line = error_table[n].line;
75         *message = error_table[n].message;
76         *error = error_table[n].error;
77
78         return 1;
79 }
80
81 int PUBLIC NONNULL(1, 2, 5) PRINTF(5, 6)
82 efi_error_set(const char *filename,
83               const char *function,
84               int line,
85               int error,
86               const char *fmt, ...)
87 {
88         error_table_entry et = { 0, };
89         error_table_entry *table;
90         char *tmp;
91
92         table = realloc(error_table, sizeof(et) * (current +1));
93         if (!table)
94                 goto err;
95         error_table = table;
96
97         et.error = error;
98         et.line = line;
99         tmp = filename ? strdup(filename) : NULL;
100         if (!tmp)
101                 goto err;
102         et.filename = tmp;
103
104         tmp = function ? strdup(function) : NULL;
105         if (!tmp)
106                 goto err;
107         et.function = tmp;
108
109         if (fmt) {
110                 int rc;
111                 int saved_errno;
112                 va_list ap;
113
114                 tmp = NULL;
115                 va_start(ap, fmt);
116                 rc = vasprintf(&tmp, fmt, ap);
117                 saved_errno = errno;
118                 va_end(ap);
119                 errno = saved_errno;
120                 if (rc < 0)
121                         goto err;
122                 et.message = tmp;
123         }
124
125         memcpy(&error_table[current], &et, sizeof(et));
126         current += 1;
127         return current;
128 err:
129         if (et.filename)
130                 free(et.filename);
131         if (et.function)
132                 free(et.function);
133         if (et.message)
134                 free(et.message);
135         errno = ENOMEM;
136         return -1;
137 }
138
139 void PUBLIC DESTRUCTOR
140 efi_error_clear(void)
141 {
142         if (error_table) {
143                 for (unsigned int i = 0; i < current; i++) {
144                         error_table_entry *et = &error_table[i];
145
146                         if (et->filename)
147                                 free(et->filename);
148                         if (et->function)
149                                 free(et->function);
150                         if (et->message)
151                                 free(et->message);
152
153                         memset(et, '\0', sizeof(*et));
154                 }
155                 free(error_table);
156         }
157         error_table = NULL;
158         current = 0;
159 }
160
161 static int efi_verbose;
162 static FILE *efi_errlog;
163
164 FILE PUBLIC *
165 efi_get_logfile(void)
166 {
167         if (efi_errlog)
168                 return efi_errlog;
169         return stderr;
170 }
171
172 void PUBLIC
173 efi_set_verbose(int verbosity, FILE *errlog)
174 {
175         efi_verbose = verbosity;
176         if (errlog)
177                 efi_errlog = errlog;
178 }
179
180 int PUBLIC
181 efi_get_verbose(void)
182 {
183         return efi_verbose;
184 }