diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2013-07-16 15:56:22 -0400 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2013-07-17 23:41:10 -0400 |
commit | d121b396ccb19dc33aacfc75a7f7a719914267c8 (patch) | |
tree | 8ad223e9d016159116503d87956add7b9fd2113c /src | |
parent | affba8e90243526be673ad9f9b306a740b8824a6 (diff) |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/journal/journalctl.c | 164 |
1 files changed, 80 insertions, 84 deletions
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 7099706696..9a40d69a75 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; |