|
|
38ab4d |
From 50296303d8066a327c17cbd10c55a02e0b69b6ba Mon Sep 17 00:00:00 2001
|
|
|
c9eda1 |
From: Peter Jones <pjones@redhat.com>
|
|
|
c9eda1 |
Date: Mon, 20 Oct 2014 12:04:34 -0400
|
|
|
38ab4d |
Subject: [PATCH 23/31] Make -o's behavior actually match the documented
|
|
|
c9eda1 |
behavior.
|
|
|
c9eda1 |
|
|
|
c9eda1 |
Also make it a bit better and reporting errors.
|
|
|
c9eda1 |
|
|
|
c9eda1 |
This should actually resolve
|
|
|
c9eda1 |
https://github.com/vathpela/efibootmgr/issues/12 .
|
|
|
c9eda1 |
|
|
|
c9eda1 |
Signed-off-by: Peter Jones <pjones@redhat.com>
|
|
|
c9eda1 |
---
|
|
|
c9eda1 |
src/efibootmgr/efibootmgr.c | 94 +++++++++++++++++++++++++++++++--------------
|
|
|
c9eda1 |
1 file changed, 66 insertions(+), 28 deletions(-)
|
|
|
c9eda1 |
|
|
|
c9eda1 |
diff --git a/src/efibootmgr/efibootmgr.c b/src/efibootmgr/efibootmgr.c
|
|
|
38ab4d |
index b5d4147..ec083af 100644
|
|
|
c9eda1 |
--- a/src/efibootmgr/efibootmgr.c
|
|
|
c9eda1 |
+++ b/src/efibootmgr/efibootmgr.c
|
|
|
c9eda1 |
@@ -34,10 +34,11 @@
|
|
|
c9eda1 |
|
|
|
c9eda1 |
#include <ctype.h>
|
|
|
c9eda1 |
#include <err.h>
|
|
|
c9eda1 |
+#include <errno.h>
|
|
|
c9eda1 |
+#include <limits.h>
|
|
|
c9eda1 |
#include <stdio.h>
|
|
|
c9eda1 |
#include <stdlib.h>
|
|
|
c9eda1 |
#include <string.h>
|
|
|
c9eda1 |
-#include <errno.h>
|
|
|
c9eda1 |
#include <stdint.h>
|
|
|
c9eda1 |
#include <sys/stat.h>
|
|
|
c9eda1 |
#include <fcntl.h>
|
|
|
38ab4d |
@@ -596,52 +597,89 @@ is_current_boot_entry(int b)
|
|
|
c9eda1 |
return 0;
|
|
|
c9eda1 |
}
|
|
|
c9eda1 |
|
|
|
c9eda1 |
+static void
|
|
|
c9eda1 |
+print_error_arrow(char *message, char *buffer, off_t offset)
|
|
|
c9eda1 |
+{
|
|
|
c9eda1 |
+ unsigned int i;
|
|
|
c9eda1 |
+ fprintf(stderr, "%s: %s\n", message, buffer);
|
|
|
c9eda1 |
+ for (i = 0; i < strlen(message) + 2; i++)
|
|
|
c9eda1 |
+ fprintf(stderr, " ");
|
|
|
c9eda1 |
+ for (i = 0; i < offset; i++)
|
|
|
c9eda1 |
+ fprintf(stderr, " ");
|
|
|
c9eda1 |
+ fprintf(stderr, "^\n");
|
|
|
c9eda1 |
+}
|
|
|
c9eda1 |
|
|
|
c9eda1 |
static int
|
|
|
c9eda1 |
parse_boot_order(char *buffer, uint16_t **order, size_t *length)
|
|
|
c9eda1 |
{
|
|
|
c9eda1 |
- int i, len;
|
|
|
c9eda1 |
- int num, rc;
|
|
|
c9eda1 |
-
|
|
|
c9eda1 |
uint16_t *data;
|
|
|
c9eda1 |
size_t data_size;
|
|
|
c9eda1 |
-
|
|
|
c9eda1 |
- len = strlen(buffer);
|
|
|
c9eda1 |
- if (len % 5 != 4) {
|
|
|
c9eda1 |
- fprintf(stderr, "\nInvalid boot order: %s\n\n", buffer);
|
|
|
c9eda1 |
- return -1;
|
|
|
c9eda1 |
+ size_t len = strlen(buffer);
|
|
|
c9eda1 |
+ intptr_t end = (intptr_t)buffer + len + 1;
|
|
|
c9eda1 |
+
|
|
|
c9eda1 |
+ int num = 0;
|
|
|
c9eda1 |
+ char *buf = buffer;
|
|
|
c9eda1 |
+ while ((intptr_t)buf < end) {
|
|
|
c9eda1 |
+ size_t comma = strcspn(buf, ",");
|
|
|
c9eda1 |
+ if (comma == 0) {
|
|
|
c9eda1 |
+ off_t offset = (intptr_t)buf - (intptr_t)buffer;
|
|
|
c9eda1 |
+ print_error_arrow("Malformed boot order",buffer,offset);
|
|
|
c9eda1 |
+ exit(8);
|
|
|
c9eda1 |
+ } else {
|
|
|
c9eda1 |
+ num++;
|
|
|
c9eda1 |
+ }
|
|
|
c9eda1 |
+ buf += comma + 1;
|
|
|
c9eda1 |
}
|
|
|
c9eda1 |
- len = (len / 5) + 1;
|
|
|
c9eda1 |
|
|
|
c9eda1 |
- data_size = len * sizeof (*data);
|
|
|
c9eda1 |
- data = malloc(data_size);
|
|
|
c9eda1 |
+ data = calloc(num, sizeof (*data));
|
|
|
c9eda1 |
if (!data)
|
|
|
c9eda1 |
return -1;
|
|
|
c9eda1 |
-
|
|
|
c9eda1 |
- for (i=0; i < len && *buffer; i++) {
|
|
|
c9eda1 |
- rc = sscanf(buffer, "%x", &num);
|
|
|
c9eda1 |
- if (rc == 1) {
|
|
|
c9eda1 |
- data[i] = num & 0xFFFF;
|
|
|
c9eda1 |
- } else {
|
|
|
c9eda1 |
- fprintf(stderr,"\nInvalid hex characters in boot order: %s\n\n",buffer);
|
|
|
c9eda1 |
+ data_size = num * sizeof (*data);
|
|
|
c9eda1 |
+
|
|
|
c9eda1 |
+ int i = 0;
|
|
|
c9eda1 |
+ buf = buffer;
|
|
|
c9eda1 |
+ while ((intptr_t)buf < end) {
|
|
|
c9eda1 |
+ unsigned long result = 0;
|
|
|
c9eda1 |
+ size_t comma = strcspn(buf, ",");
|
|
|
c9eda1 |
+
|
|
|
c9eda1 |
+ buf[comma] = '\0';
|
|
|
c9eda1 |
+ char *endptr = NULL;
|
|
|
c9eda1 |
+ result = strtoul(buf, &endptr, 16);
|
|
|
c9eda1 |
+ if ((result == ULONG_MAX && errno == ERANGE) ||
|
|
|
c9eda1 |
+ (endptr && *endptr != '\0')) {
|
|
|
c9eda1 |
+ print_error_arrow("Invalid boot order", buffer,
|
|
|
c9eda1 |
+ (intptr_t)endptr - (intptr_t)buffer);
|
|
|
c9eda1 |
free(data);
|
|
|
c9eda1 |
- return -1;
|
|
|
c9eda1 |
+ exit(8);
|
|
|
c9eda1 |
}
|
|
|
c9eda1 |
+ if (result > 0xffff) {
|
|
|
c9eda1 |
+ fprintf(stderr, "Invalid boot order entry value: %lX\n",
|
|
|
c9eda1 |
+ result);
|
|
|
c9eda1 |
+ print_error_arrow("Invalid boot order", buffer,
|
|
|
c9eda1 |
+ (intptr_t)buf - (intptr_t)buffer);
|
|
|
c9eda1 |
+ free(data);
|
|
|
c9eda1 |
+ exit(8);
|
|
|
c9eda1 |
+ }
|
|
|
c9eda1 |
+
|
|
|
c9eda1 |
/* make sure this is an existing boot entry */
|
|
|
c9eda1 |
- if (!is_current_boot_entry(data[i])) {
|
|
|
c9eda1 |
- fprintf (stderr,"\nboot entry %X does not exist\n\n",data[i]);
|
|
|
c9eda1 |
+ if (!is_current_boot_entry(result)) {
|
|
|
c9eda1 |
+ print_error_arrow("Invalid boot order entry value",
|
|
|
c9eda1 |
+ buffer,
|
|
|
c9eda1 |
+ (intptr_t)buf - (intptr_t)buffer);
|
|
|
c9eda1 |
+ fprintf(stderr,"Boot entry %04lX does not exist\n",
|
|
|
c9eda1 |
+ result);
|
|
|
c9eda1 |
free(data);
|
|
|
c9eda1 |
- return -1;
|
|
|
c9eda1 |
+ exit(8);
|
|
|
c9eda1 |
}
|
|
|
c9eda1 |
|
|
|
c9eda1 |
- /* Advance to the comma */
|
|
|
c9eda1 |
- while (*buffer && *buffer != ',') buffer++;
|
|
|
c9eda1 |
- /* Advance through the comma(s) */
|
|
|
c9eda1 |
- while (*buffer && *buffer == ',') buffer++;
|
|
|
c9eda1 |
+ data[i++] = result;
|
|
|
c9eda1 |
+ buf[comma] = ',';
|
|
|
c9eda1 |
+ buf += comma + 1;
|
|
|
c9eda1 |
}
|
|
|
c9eda1 |
+
|
|
|
c9eda1 |
*order = data;
|
|
|
c9eda1 |
*length = data_size;
|
|
|
c9eda1 |
- return i;
|
|
|
c9eda1 |
+ return num;
|
|
|
c9eda1 |
}
|
|
|
c9eda1 |
|
|
|
c9eda1 |
static int
|
|
|
c9eda1 |
--
|
|
|
38ab4d |
2.7.4
|
|
|
c9eda1 |
|