[grubby] Add --debug style logging (for both success and failures) to /var/log/grubby
Peter Jones
pjones at fedoraproject.org
Wed Feb 20 16:07:25 UTC 2013
commit a10345813c38b020dc29a8409f82f3f42398fe0c
Author: Peter Jones <pjones at redhat.com>
Date: Wed Feb 20 11:04:16 2013 -0500
Add --debug style logging (for both success and failures) to /var/log/grubby
Signed-off-by: Peter Jones <pjones at redhat.com>
0001-Add-logging-when-things-fail.patch | 414 +++++++++++++++++++++++++++++++
grubby.spec | 7 +-
2 files changed, 420 insertions(+), 1 deletions(-)
---
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 <pjones at redhat.com>
+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 <pjones at redhat.com>
+---
+ 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 <signal.h>
+ #include <blkid/blkid.h>
+
++#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 <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
++#include <errno.h>
++#include <fcntl.h>
++#include <stdarg.h>
++#include <stdio.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <time.h>
++#include <unistd.h>
++
++#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 <http://www.gnu.org/licenses/>.
++ */
++#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 <pjones at redhat.com> - 8.22-3
+- Add --debug style logging (for both success and failures) to /var/log/grubby
+
* Thu Feb 14 2013 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 8.22-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
More information about the scm-commits
mailing list