return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"--since= must be before --until=.");
- if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1)
+ if (!!arg_cursor + !!arg_after_cursor + !!arg_cursor_file + !!arg_since_set > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Please specify only one of --since=, --cursor=, and --after-cursor=.");
+ "Please specify only one of --since=, --cursor=, --cursor-file=, and --after-cursor=.");
if (arg_follow && arg_reverse)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
}
static int run(int argc, char *argv[]) {
- bool need_seek = false, since_seeked = false, use_cursor = false, after_cursor = false;
+ bool need_seek = false, since_seeked = false, after_cursor = false;
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(umount_and_freep) char *mounted_dir = NULL;
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
+ _cleanup_free_ char *cursor_from_file = NULL;
+ const char *cursor = NULL;
int n_shown, r, poll_fd = -EBADF;
setlocale(LC_ALL, "");
}
if (arg_cursor || arg_after_cursor || arg_cursor_file) {
- _cleanup_free_ char *cursor_from_file = NULL;
- const char *cursor = arg_cursor ?: arg_after_cursor;
+ cursor = arg_cursor ?: arg_after_cursor;
if (arg_cursor_file) {
r = read_one_line_file(arg_cursor_file, &cursor_from_file);
}
} else
after_cursor = arg_after_cursor;
+ }
- if (cursor) {
- r = sd_journal_seek_cursor(j, cursor);
- if (r < 0)
- return log_error_errno(r, "Failed to seek to cursor: %m");
+ if (cursor) {
+ r = sd_journal_seek_cursor(j, cursor);
+ if (r < 0)
+ return log_error_errno(r, "Failed to seek to cursor: %m");
- use_cursor = true;
+ r = sd_journal_step_one(j, !arg_reverse);
+ if (r < 0)
+ return log_error_errno(r, "Failed to iterate through journal: %m");
+
+ if (after_cursor && r > 0) {
+ /* With --after-cursor=/--cursor-file= we want to skip the first entry only if it's
+ * the entry the cursor is pointing at, otherwise, if some journal filters are used,
+ * we might skip the first entry of the filter match, which leads to unexpectedly
+ * missing journal entries. */
+ int k;
+
+ k = sd_journal_test_cursor(j, cursor);
+ if (k < 0)
+ return log_error_errno(k, "Failed to test cursor against current entry: %m");
+ if (k > 0)
+ /* Current entry matches the one our cursor is pointing at, so let's try
+ * to advance the next entry. */
+ r = sd_journal_step_one(j, !arg_reverse);
}
- }
-
- if (use_cursor) {
- if (!arg_reverse)
- r = sd_journal_next_skip(j, 1 + after_cursor);
- else
- r = sd_journal_previous_skip(j, 1 + after_cursor);
- if (after_cursor && r < 2) {
+ if (r == 0) {
/* We couldn't find the next entry after the cursor. */
if (arg_follow)
need_seek = true;
else
arg_lines = 0;
}
-
} else if (arg_until_set && (arg_reverse || arg_lines_needs_seek_end())) {
/* If both --until and any of --reverse and --lines=N is specified, things get
* a little tricky. We seek to the place of --until first. If only --reverse or