From a10345813c38b020dc29a8409f82f3f42398fe0c Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Wed, 20 Feb 2013 11:04:16 -0500 Subject: [PATCH] Add --debug style logging (for both success and failures) to /var/log/grubby Signed-off-by: Peter Jones --- 0001-Add-logging-when-things-fail.patch | 414 ++++++++++++++++++++++++ grubby.spec | 7 +- 2 files changed, 420 insertions(+), 1 deletion(-) create mode 100644 0001-Add-logging-when-things-fail.patch diff --git a/0001-Add-logging-when-things-fail.patch b/0001-Add-logging-when-things-fail.patch new file mode 100644 index 0000000..6b00d16 --- /dev/null +++ b/0001-Add-logging-when-things-fail.patch @@ -0,0 +1,414 @@ +From bfb7c70e7eaa1311cadc716c303ca694163f9e2f Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 19 Feb 2013 18:00:36 -0500 +Subject: [PATCH] Add logging when things fail. + +Actually also logs when things succeed. + +Signed-off-by: Peter Jones +--- + Makefile | 2 +- + grubby.c | 92 ++++++++++++++++++++++++++++---------- + log.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++ + log.h | 27 ++++++++++++ + test/results/debug/g2.1 | 1 + + 5 files changed, 212 insertions(+), 24 deletions(-) + create mode 100644 log.c + create mode 100644 log.h + +diff --git a/Makefile b/Makefile +index fcf2dd2..325ffd8 100644 +--- a/Makefile ++++ b/Makefile +@@ -20,7 +20,7 @@ + VERSION=8.22 + + TARGETS = grubby +-OBJECTS = grubby.o ++OBJECTS = grubby.o log.o + + CC = gcc + RPM_OPT_FLAGS := -O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector +diff --git a/grubby.c b/grubby.c +index edbeb64..408e3ca 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -36,6 +36,8 @@ + #include + #include + ++#include "log.h" ++ + #ifndef DEBUG + #define DEBUG 0 + #endif +@@ -58,6 +60,8 @@ int debug = 0; /* Currently just for template debugging */ + + int isEfi = 0; + ++char *saved_command_line = NULL; ++ + /* comments get lumped in with indention */ + struct lineElement { + char * item; +@@ -1533,43 +1537,67 @@ static char *findDiskForRoot() + return NULL; + } + +-void printEntry(struct singleEntry * entry) { ++void printEntry(struct singleEntry * entry, FILE *f) { + int i; + struct singleLine * line; + + for (line = entry->lines; line; line = line->next) { +- fprintf(stderr, "DBG: %s", line->indent); ++ log_message(f, "DBG: %s", line->indent); + for (i = 0; i < line->numElements; i++) { + /* Need to handle this, because we strip the quotes from + * menuentry when read it. */ + if (line->type == LT_MENUENTRY && i == 1) { + if(!isquote(*line->elements[i].item)) +- fprintf(stderr, "\'%s\'", line->elements[i].item); ++ log_message(f, "\'%s\'", line->elements[i].item); + else +- fprintf(stderr, "%s", line->elements[i].item); +- fprintf(stderr, "%s", line->elements[i].indent); ++ log_message(f, "%s", line->elements[i].item); ++ log_message(f, "%s", line->elements[i].indent); + + continue; + } + +- fprintf(stderr, "%s%s", ++ log_message(f, "%s%s", + line->elements[i].item, line->elements[i].indent); + } +- fprintf(stderr, "\n"); ++ log_message(f, "\n"); + } + } + +-void notSuitablePrintf(struct singleEntry * entry, const char *fmt, ...) ++void notSuitablePrintf(struct singleEntry * entry, int okay, const char *fmt, ...) + { +- va_list argp; ++ static int once; ++ va_list argp, argq; + +- if (!debug) ++ va_start(argp, fmt); ++ ++ va_copy(argq, argp); ++ if (!once) { ++ log_time(NULL); ++ log_message(NULL, "command line: %s\n", saved_command_line); ++ } ++ log_message(NULL, "DBG: Image entry %s: ", okay ? "succeeded" : "failed"); ++ log_vmessage(NULL, fmt, argq); ++ ++ printEntry(entry, NULL); ++ va_end(argq); ++ ++ if (!debug) { ++ once = 1; ++ va_end(argp); + return; ++ } + +- va_start(argp, fmt); ++ if (okay) { ++ va_end(argp); ++ return; ++ } ++ ++ if (!once) ++ log_message(stderr, "DBG: command line: %s\n", saved_command_line); ++ once = 1; + fprintf(stderr, "DBG: Image entry failed: "); + vfprintf(stderr, fmt, argp); +- printEntry(entry); ++ printEntry(entry, stderr); + va_end(argp); + } + +@@ -1596,22 +1624,25 @@ int suitableImage(struct singleEntry * entry, const char * bootPrefix, + char * rootdev; + + if (skipRemoved && entry->skip) { +- notSuitablePrintf(entry, "marked to skip\n"); ++ notSuitablePrintf(entry, 0, "marked to skip\n"); + return 0; + } + + line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines); + if (!line) { +- notSuitablePrintf(entry, "no line found\n"); ++ notSuitablePrintf(entry, 0, "no line found\n"); + return 0; + } + if (line->numElements < 2) { +- notSuitablePrintf(entry, "line has only %d elements\n", ++ notSuitablePrintf(entry, 0, "line has only %d elements\n", + line->numElements); + return 0; + } + +- if (flags & GRUBBY_BADIMAGE_OKAY) return 1; ++ if (flags & GRUBBY_BADIMAGE_OKAY) { ++ notSuitablePrintf(entry, 1, "\n"); ++ return 1; ++ } + + fullName = alloca(strlen(bootPrefix) + + strlen(line->elements[1].item) + 1); +@@ -1622,7 +1653,7 @@ int suitableImage(struct singleEntry * entry, const char * bootPrefix, + sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/", + line->elements[1].item + rootspec_offset); + if (access(fullName, R_OK)) { +- notSuitablePrintf(entry, "access to %s failed\n", fullName); ++ notSuitablePrintf(entry, 0, "access to %s failed\n", fullName); + return 0; + } + for (i = 2; i < line->numElements; i++) +@@ -1643,7 +1674,7 @@ int suitableImage(struct singleEntry * entry, const char * bootPrefix, + + /* failed to find one */ + if (!line) { +- notSuitablePrintf(entry, "no line found\n"); ++ notSuitablePrintf(entry, 0, "no line found\n"); + return 0; + } + +@@ -1652,7 +1683,7 @@ int suitableImage(struct singleEntry * entry, const char * bootPrefix, + if (i < line->numElements) + dev = line->elements[i].item + 5; + else { +- notSuitablePrintf(entry, "no root= entry found\n"); ++ notSuitablePrintf(entry, 0, "no root= entry found\n"); + /* it failed too... can't find root= */ + return 0; + } +@@ -1661,32 +1692,33 @@ int suitableImage(struct singleEntry * entry, const char * bootPrefix, + + dev = getpathbyspec(dev); + if (!getpathbyspec(dev)) { +- notSuitablePrintf(entry, "can't find blkid entry for %s\n", dev); ++ notSuitablePrintf(entry, 0, "can't find blkid entry for %s\n", dev); + return 0; + } else + dev = getpathbyspec(dev); + + rootdev = findDiskForRoot(); + if (!rootdev) { +- notSuitablePrintf(entry, "can't find root device\n"); ++ notSuitablePrintf(entry, 0, "can't find root device\n"); + return 0; + } + + if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) { +- notSuitablePrintf(entry, "uuid missing: rootdev %s, dev %s\n", ++ notSuitablePrintf(entry, 0, "uuid missing: rootdev %s, dev %s\n", + getuuidbydev(rootdev), getuuidbydev(dev)); + free(rootdev); + return 0; + } + + if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) { +- notSuitablePrintf(entry, "uuid mismatch: rootdev %s, dev %s\n", ++ notSuitablePrintf(entry, 0, "uuid mismatch: rootdev %s, dev %s\n", + getuuidbydev(rootdev), getuuidbydev(dev)); + free(rootdev); + return 0; + } + + free(rootdev); ++ notSuitablePrintf(entry, 1, "\n"); + + return 1; + } +@@ -3898,6 +3930,20 @@ int main(int argc, const char ** argv) { + + signal(SIGSEGV, traceback); + ++ int i = 0; ++ for (int j = 1; j < argc; j++) ++ i += strlen(argv[j]) + 1; ++ saved_command_line = malloc(i); ++ if (!saved_command_line) { ++ fprintf(stderr, "grubby: %m\n"); ++ exit(1); ++ } ++ saved_command_line[0] = '\0'; ++ for (int j = 1; j < argc; j++) { ++ strcat(saved_command_line, argv[j]); ++ strncat(saved_command_line, j == argc -1 ? "" : " ", 1); ++ } ++ + optCon = poptGetContext("grubby", argc, argv, options, 0); + poptReadDefaultConfig(optCon, 1); + +diff --git a/log.c b/log.c +new file mode 100644 +index 0000000..1ddb8c1 +--- /dev/null ++++ b/log.c +@@ -0,0 +1,114 @@ ++/* ++ * log.c ++ * ++ * Copyright 2013 Red Hat, Inc. ++ * All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "log.h" ++ ++static int log_fd = -1; ++static FILE *f = NULL; ++ ++static int ++open_log(void) ++{ ++ if (log_fd > -1) ++ return 0; ++ log_fd = open("/var/log/grubby", O_RDWR|O_APPEND|O_CREAT|O_CLOEXEC, 0600); ++ if (log_fd < 0) ++ return log_fd; ++ ++ f = fdopen(log_fd, "a+"); ++ if (f == NULL) { ++ typeof(errno) saved_errno = errno; ++ close(log_fd); ++ log_fd = -1; ++ errno = saved_errno; ++ return -1; ++ } ++ ++ setbuf(f, NULL); ++ return 0; ++} ++ ++int ++log_time(FILE *log) ++{ ++ if (!log) { ++ int rc = open_log(); ++ if (rc < 0) ++ return rc; ++ } ++ ++ time_t t = time(NULL); ++ char timestr[27]; ++ ++ ctime_r(&t, timestr); ++ timestr[26] = '\0'; ++ for (int i = 26; i >= 0; i--) ++ if (timestr[i] == '\n') ++ timestr[i] = '\0'; ++ ++ return log_message(log, "DBG: %d: %s: ", getpid(), timestr); ++} ++ ++int ++log_vmessage(FILE *log, const char *msg, va_list ap) ++{ ++ int rc; ++ ++ if (!msg) ++ return -1; ++ if (msg[0] == '\0') ++ return 0; ++ ++ if (!log) { ++ rc = open_log(); ++ if (rc < 0) ++ return rc; ++ } ++ ++ vfprintf(log ? log : f, msg, ap); ++ fdatasync(log ? fileno(log) : log_fd); ++ ++ return 0; ++} ++ ++int ++log_message(FILE *log, const char *msg, ...) ++{ ++ va_list argp; ++ ++ va_start(argp, msg); ++ int rc = log_vmessage(log, msg, argp); ++ va_end(argp); ++ return rc; ++} +diff --git a/log.h b/log.h +new file mode 100644 +index 0000000..082a59e +--- /dev/null ++++ b/log.h +@@ -0,0 +1,27 @@ ++/* ++ * log.h ++ * ++ * Copyright 2013 Red Hat, Inc. ++ * All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++#ifndef GRUBBY_LOG_H ++#define GRUBBY_LOG_H 1 ++ ++extern int log_time(FILE *log); ++extern int log_vmessage(FILE *log, const char *msg, va_list ap); ++extern int log_message(FILE *log, const char *msg, ...); ++ ++#endif /* GRUBBY_LOG_H */ +diff --git a/test/results/debug/g2.1 b/test/results/debug/g2.1 +index 9de4595..45c64ae 100644 +--- a/test/results/debug/g2.1 ++++ b/test/results/debug/g2.1 +@@ -1,3 +1,4 @@ ++DBG: command line: --grub2 -c test/grub2.1 --boot-filesystem=/boot --default-kernel --debug + DBG: Image entry failed: access to /boot/vmlinuz-2.6.38.8-32.fc15.x86_64 failed + DBG: menuentry 'Linux, with Fedora 2.6.38.8-32.fc15.x86_64' --class gnu-linux --class gnu --class os { + DBG: load_video +-- +1.8.1.2 + diff --git a/grubby.spec b/grubby.spec index 785eaee..850bf91 100644 --- a/grubby.spec +++ b/grubby.spec @@ -1,6 +1,6 @@ Name: grubby Version: 8.22 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Command line tool for updating bootloader configs Group: System Environment/Base License: GPLv2+ @@ -21,6 +21,8 @@ Requires: s390utils-base Requires: uboot-tools %endif +Patch0: 0001-Add-logging-when-things-fail.patch + %description grubby is a command line tool for updating and displaying information about the configuration files for the grub, lilo, elilo (ia64), yaboot (powerpc) @@ -71,6 +73,9 @@ rm -rf $RPM_BUILD_ROOT %endif %changelog +* Wed Feb 20 2013 Peter Jones - 8.22-3 +- Add --debug style logging (for both success and failures) to /var/log/grubby + * Thu Feb 14 2013 Fedora Release Engineering - 8.22-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild