OSDN Git Service

efivar: add an api to inspect errors that occurred in more detail.
authorPeter Jones <pjones@redhat.com>
Thu, 4 Aug 2016 17:48:34 +0000 (13:48 -0400)
committerPeter Jones <pjones@redhat.com>
Wed, 10 Aug 2016 13:30:48 +0000 (09:30 -0400)
I'm tired of manually debugging everything in the world, so add this API
that gives our callers more detail and verbosity about errors that
occur.

Signed-off-by: Peter Jones <pjones@redhat.com>
gcc.specs
src/Makefile
src/error.c [new file with mode: 0644]
src/include/efivar/efivar.h
src/libefivar.map.in

index 0d4bbda..a9c3ce5 100644 (file)
--- a/gcc.specs
+++ b/gcc.specs
@@ -2,7 +2,7 @@
 + -D_GNU_SOURCE
 
 *efivar_cpp_options:
- -Werror -Wall -std=gnu11 -Wextra
+ -Werror -Wall -std=gnu11 -Wextra -Wno-nonnull-compare
 
 *cpp_options:
 + %(efivar_cpp_options)
index 826266a..5216602 100644 (file)
@@ -14,7 +14,7 @@ TARGETS=$(LIBTARGETS) $(STATICLIBTARGETS) $(BINTARGETS) $(PCTARGETS)
 LIBEFIBOOT_SOURCES = crc32.c creator.c disk.c gpt.c linux.c loadopt.c
 LIBEFIBOOT_OBJECTS = $(patsubst %.c,%.o,$(LIBEFIBOOT_SOURCES))
 LIBEFIVAR_SOURCES = dp.c dp-acpi.c dp-hw.c dp-media.c dp-message.c \
-       efivarfs.c export.c guid.c guids.S guid-symbols.c \
+       efivarfs.c error.c export.c guid.c guids.S guid-symbols.c \
        lib.c vars.c
 LIBEFIVAR_OBJECTS = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(LIBEFIVAR_SOURCES)))
 EFIVAR_SOURCES = efivar.c
diff --git a/src/error.c b/src/error.c
new file mode 100644 (file)
index 0000000..e8e3004
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * libefiboot - library for the manipulation of EFI boot variables
+ * Copyright 2012-2015 Red Hat, Inc.
+ * Copyright (C) 2000-2001 Dell Computer Corporation <Matt_Domsch@dell.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+typedef struct {
+       int error;
+       char *filename;
+       char *function;
+       int line;
+       char *message;
+} error_table_entry;
+
+static error_table_entry *error_table;
+static unsigned int current;
+
+int
+__attribute__((__visibility__ ("default")))
+__attribute__((__nonnull__ (2, 3, 4, 5, 6)))
+efi_error_get(unsigned int n,
+             char ** const filename,
+             char ** const function,
+             int *line,
+             char ** const message,
+             int *error
+             )
+{
+       if (!filename || !function || !line || !message || !error) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (n >= current)
+               return 0;
+
+       *filename = error_table[n].filename;
+       *function = error_table[n].function;
+       *line = error_table[n].line;
+       *message = error_table[n].message;
+       *error = error_table[n].error;
+
+       return 1;
+}
+
+int
+__attribute__((__visibility__ ("default")))
+__attribute__((__nonnull__ (1, 2, 5)))
+__attribute__((__format__ (printf, 5, 6)))
+efi_error_set(const char *filename,
+             const char *function,
+             int line,
+             int error,
+             const char *fmt, ...)
+{
+       error_table_entry et = { 0, };
+       error_table_entry *table;
+       char *tmp;
+
+       table = realloc(error_table, sizeof(et) * (current +1));
+       if (!table)
+               goto err;
+       error_table = table;
+
+       et.error = error;
+       et.line = line;
+       tmp = filename ? strdup(filename) : NULL;
+       if (!tmp)
+               goto err;
+       et.filename = tmp;
+
+       tmp = function ? strdup(function) : NULL;
+       if (!tmp)
+               goto err;
+       et.function = tmp;
+
+       if (fmt) {
+               int rc;
+               int saved_errno;
+               va_list ap;
+
+               tmp = NULL;
+               va_start(ap, fmt);
+               rc = vasprintf(&tmp, fmt, ap);
+               saved_errno = errno;
+               va_end(ap);
+               errno = saved_errno;
+               if (rc < 0)
+                       goto err;
+               et.message = tmp;
+       }
+
+       memcpy(&error_table[current], &et, sizeof(et));
+       current += 1;
+       return current;
+err:
+       if (et.filename)
+               free(et.filename);
+       if (et.function)
+               free(et.function);
+       if (et.message)
+               free(et.message);
+       errno = ENOMEM;
+       return -1;
+}
+
+void
+__attribute__((__visibility__ ("default")))
+__attribute__((destructor))
+efi_error_clear(void)
+{
+       if (error_table) {
+               for (unsigned int i = 0; i < current; i++) {
+                       error_table_entry *et = &error_table[i];
+
+                       if (et->filename)
+                               free(et->filename);
+                       if (et->function)
+                               free(et->function);
+                       if (et->message)
+                               free(et->message);
+
+                       memset(et, '\0', sizeof(*et));
+               }
+               free(error_table);
+       }
+       error_table = NULL;
+       current = 0;
+}
index 21f6b46..27dc34e 100644 (file)
@@ -151,6 +151,64 @@ extern int efi_variable_get_attributes(efi_variable_t *var, uint64_t *attrs)
 extern int efi_variable_realize(efi_variable_t *var)
                        __attribute__((__nonnull__ (1)));
 
+#ifndef EFIVAR_BUILD_ENVIRONMENT
+extern int efi_error_get(unsigned int n,
+                        char ** const filename,
+                        char ** const function,
+                        int *line,
+                        char ** const message,
+                        int *error)
+                       __attribute__((__nonnull__ (2, 3, 4, 5, 6)));
+extern int efi_error_set(const char *filename,
+                        const char *function,
+                        int line,
+                        int error,
+                        const char *fmt, ...)
+                       __attribute__((__visibility__ ("default")))
+                       __attribute__((__nonnull__ (1, 2, 5)))
+                       __attribute__((__format__ (printf, 5, 6)));
+extern void efi_error_clear(void);
+#else
+static inline int
+__attribute__((__nonnull__ (2, 3, 4, 5, 6)))
+efi_error_get(unsigned int n __attribute__((__unused__)),
+             char ** const filename __attribute__((__unused__)),
+             char ** const function __attribute__((__unused__)),
+             int *line __attribute__((__unused__)),
+             char ** const message __attribute__((__unused__)),
+             int *error __attribute__((__unused__)))
+{
+       return 0;
+}
+
+static inline int
+__attribute__((__nonnull__ (1, 2, 5)))
+__attribute__((__format__ (printf, 5, 6)))
+efi_error_set(const char *filename __attribute__((__unused__)),
+             const char *function __attribute__((__unused__)),
+             int line __attribute__((__unused__)),
+             int error __attribute__((__unused__)),
+             const char *fmt __attribute__((__unused__)),
+             ...)
+{
+       return 0;
+}
+
+static inline void
+efi_error_clear(void)
+{
+       return;
+}
+#endif
+
+#define efi_error_real__(errval, file, function, line, fmt, args...) \
+       efi_error_set(file, function, line, errval, (fmt), ## args)
+
+#define efi_error(fmt, args...) \
+       efi_error_real__(errno, __FILE__, __func__, __LINE__, (fmt), ## args)
+#define efi_error_val(errval, msg, args...) \
+       efi_error_real__(errval, __FILE__, __func__, __LINE__, (fmt), ## args)
+
 #include <efivar-dp.h>
 
 #endif /* EFIVAR_H */
index ce627c8..145eb75 100644 (file)
@@ -100,4 +100,7 @@ LIBEFIVAR_0.24 {
 } LIBEFIVAR_0.0;
 
 LIBEFIVAR_@@VERSION@@ {
+       global: efi_error_set;
+               efi_error_get;
+               efi_error_clear;
 };