From: Zbigniew Jędrzejewski-Szmek Date: Tue, 16 Jul 2013 19:56:22 +0000 (-0400) Subject: journalctl: remove ":" from the --boot syntax X-Git-Tag: v206~50 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=d121b396ccb19dc33aacfc75a7f7a719914267c8;hp=affba8e90243526be673ad9f9b306a740b8824a6 journalctl: remove ":" from the --boot syntax Instead of :-0, :1, :5, etc., use -0, 1 or +1, 5, etc. For BOOT_ID+OFFSET, use BOOT_ID+offset or BOOT_ID-offset (either + or - is required). Also make error handling a bit more robust and verbose. Modify the man page to describe the most common case (-b) first, and the second most common case (-b -1) second. --- diff --git a/man/journalctl.xml b/man/journalctl.xml index 3e03c45f1..65a59ea4e 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -399,42 +399,50 @@ - - + + - Show messages from the specified - boot ID or from - current boot if no ID - is given. This will add a match for + Show messages from a specific + boot. This will add a match for _BOOT_ID=. - The argument is a 128 bit ID given in - short or UUID form and optionally followed by - :n which identifies the nth - boot relative to the boot ID given to the left - of :. Supplying a negative - value for n will look for a past boot and a - positive value for a future boot. The boot IDs - are searched for in chronological order. If no - number is provided after :, - -1 is assumed. A value of 0 - is valid and equivalent to omitting - :0. - - Alternatively, the argument may constist - only of :n. In this case, a - positive value will look up the nth boot - starting from the beginning of the jouranl, a - negative value will look up a previous boot - relative to the current boot. :0 - will look for the current boot ID. Thus, - :1 is the first boot found in - the journal, :2 the second - and so on; while :-1 is the - previous boot, :-2 the boot - before that and so on. Omitting a value after - : will look for the previous - boot. + The argument may be empty, in which case + logs for the current boot will be shown. + + If the boot ID is omitted, a positive + offset will look up + the boots starting from the beginning of the + journal, and a equal-or-less-than zero + offset will look up + boots starting from the end of the + journal. Thus, 1 means the + first boot found in the journal in the + chronological order, 2 the + second and so on; while -0 + is the last boot, -1 the + boot before that, and so on. An empty + offset is equivalent + to specifying -0, except + when the current boot is not the last boot + (e.g. because was + specified to look at logs from a different + machine). + + If the 32 character + ID is specified, it + may optionally be followed by + offset which + identifies the boot relative to the one given by + boot ID. Negative + values mean earlier boots and a positive values + mean later boots. If + offset is not + specified, a value of zero is assumed and the + logs for the boot given by + ID are shown. + + + diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 709970669..9a40d69a7 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -70,8 +70,8 @@ static int arg_lines = -1; static bool arg_no_tail = false; static bool arg_quiet = false; static bool arg_merge = false; -static bool arg_boot_id = false; -static char *arg_boot_id_descriptor = NULL; +static bool arg_boot = false; +static char *arg_boot_descriptor = NULL; static bool arg_dmesg = false; static const char *arg_cursor = NULL; static const char *arg_after_cursor = NULL; @@ -346,17 +346,24 @@ static int parse_argv(int argc, char *argv[]) { break; case 'b': + arg_boot = true; + if (optarg) - arg_boot_id_descriptor = optarg; - else if (optind < argc && argv[optind][0] != '-') { - arg_boot_id_descriptor = argv[optind]; - optind++; + arg_boot_descriptor = optarg; + else if (optind < argc) { + int boot; + + if (argv[optind][0] != '-' || + safe_atoi(argv[optind], &boot) >= 0) { + arg_boot_descriptor = argv[optind]; + optind++; + } } - arg_boot_id = true; + break; case 'k': - arg_boot_id = arg_dmesg = true; + arg_boot = arg_dmesg = true; break; case ARG_SYSTEM: @@ -671,23 +678,17 @@ static int boot_id_cmp(const void *a, const void *b) { static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative) { int r; const void *data; - unsigned int id_count = 0; + unsigned int count = 0; size_t length, allocated = 0; - boot_id_t ref_boot_id, *id; + boot_id_t ref_boot_id = {SD_ID128_NULL}, *id; _cleanup_free_ boot_id_t *all_ids = NULL; - bool find_first_boot = false, ref_boot_found = false; assert(j); assert(boot_id); - if (relative == 0) + if (relative == 0 && !sd_id128_equal(*boot_id, SD_ID128_NULL)) return 0; - if (sd_id128_equal(*boot_id, SD_ID128_NULL) && relative > 0) { - find_first_boot = true; - relative--; - } - r = sd_journal_query_unique(j, "_BOOT_ID"); if (r < 0) return r; @@ -696,123 +697,118 @@ static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative if (length < strlen("_BOOT_ID=")) continue; - if (!GREEDY_REALLOC(all_ids, allocated, id_count + 1)) + if (!GREEDY_REALLOC(all_ids, allocated, count + 1)) return log_oom(); - id = &all_ids[id_count]; + id = &all_ids[count]; r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id); - if (r < 0) { + if (r < 0) continue; - } - sd_journal_flush_matches(j); r = sd_journal_add_match(j, data, length); if (r < 0) - continue; + return r; r = sd_journal_seek_head(j); if (r < 0) - continue; + return r; r = sd_journal_next(j); - if (r <= 0) - continue; + if (r < 0) + return r; + else if (r == 0) + goto flush; r = sd_journal_get_realtime_usec(j, &id->timestamp); if (r < 0) - continue; + return r; - if (!find_first_boot && sd_id128_equal(id->id, *boot_id)) { + if (sd_id128_equal(id->id, *boot_id)) ref_boot_id = *id; - ref_boot_found = true; - } - id_count++; + count++; + flush: + sd_journal_flush_matches(j); } - *boot_id = SD_ID128_NULL; - sd_journal_flush_matches(j); + qsort(all_ids, count, sizeof(boot_id_t), boot_id_cmp); - if (id_count == 0 || (!find_first_boot && !ref_boot_found)) - return 0; + if (sd_id128_equal(*boot_id, SD_ID128_NULL)) { + if (relative > (int) count || relative <= -(int)count) + return -EADDRNOTAVAIL; - qsort(all_ids, id_count, sizeof(boot_id_t), boot_id_cmp); - if (find_first_boot) - id = all_ids; - else - id = bsearch(&ref_boot_id, all_ids, id_count, sizeof(boot_id_t), boot_id_cmp); + *boot_id = all_ids[(relative <= 0)*count + relative - 1].id; + } else { + id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp); - if (!id || (relative < 0 && ((id - all_ids) + relative) < 0) || - (relative >= 0 && (unsigned long)((id - all_ids) + relative) >= id_count)) - return 0; + if (!id || + relative <= 0 ? (id - all_ids) + relative < 0 : + (id - all_ids) + relative >= count) + return -EADDRNOTAVAIL; + + *boot_id = (id + relative)->id; + } - id += relative; - *boot_id = id->id; return 0; } static int add_boot(sd_journal *j) { char match[9+32+1] = "_BOOT_ID="; - char *marker; - sd_id128_t boot_id; + char *offset; + sd_id128_t boot_id = SD_ID128_NULL; int r, relative = 0; assert(j); - if (!arg_boot_id) + if (!arg_boot) return 0; - if (arg_boot_id_descriptor) { - marker = strchr(arg_boot_id_descriptor, ':'); - if (marker) { - *marker = '\0'; - marker++; + if (!arg_boot_descriptor) + return add_match_this_boot(j); - if (*marker == '\0') - relative = -1; - else { - r = safe_atoi(marker, &relative); - if (r < 0) { - log_error("Failed to parse relative boot ID number '%s'", marker); - return -EINVAL; - } - } + if (strlen(arg_boot_descriptor) >= 32) { + char tmp = arg_boot_descriptor[32]; + arg_boot_descriptor[32] = '\0'; + r = sd_id128_from_string(arg_boot_descriptor, &boot_id); + arg_boot_descriptor[32] = tmp; + + if (r < 0) { + log_error("Failed to parse boot ID '%.32s': %s", + arg_boot_descriptor, strerror(-r)); + return r; } - } - if (isempty(arg_boot_id_descriptor)) { - if (relative > 0) { - /* We cannot look into the future. Instead, we look - * into the past (starting from first boot). The ID - * will be looked up later */ - boot_id = SD_ID128_NULL; - } else { - r = sd_id128_get_boot(&boot_id); - if (r < 0) { - log_error("Failed to get boot ID: %s", strerror(-r)); - return r; - } + offset = arg_boot_descriptor + 32; + + if (*offset != '-' && *offset != '+') { + log_error("Relative boot ID offset must start with a '+' or a '-', found '%s' ", offset); + return -EINVAL; } - } else { - r = sd_id128_from_string(arg_boot_id_descriptor, &boot_id); + } else + offset = arg_boot_descriptor; + + if (*offset) { + r = safe_atoi(offset, &relative); if (r < 0) { - log_error("Failed to parse boot ID: %s", strerror(-r)); - return r; + log_error("Failed to parse relative boot ID number '%s'", offset); + return -EINVAL; } } r = get_relative_boot_id(j, &boot_id, relative); if (r < 0) { - log_error("Failed to look up boot ID: %s", strerror(-r)); + if (sd_id128_equal(boot_id, SD_ID128_NULL)) + log_error("Failed to look up boot %+d: %s", relative, strerror(-r)); + else + log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+d: %s", + SD_ID128_FORMAT_VAL(boot_id), relative, strerror(-r)); return r; - } else if (sd_id128_equal(boot_id, SD_ID128_NULL)) { - log_error("Failed to find boot ID"); - return -1; } sd_id128_to_string(boot_id, match + 9); - r = sd_journal_add_match(j, match, strlen(match)); + + r = sd_journal_add_match(j, match, sizeof(match) - 1); if (r < 0) { log_error("Failed to add match: %s", strerror(-r)); return r;