@@ -446,37 +446,76 @@ static int output_timestamp_realtime(
446
446
return (int ) strlen (buf );
447
447
}
448
448
449
+ static void parse_display_realtime (
450
+ sd_journal * j ,
451
+ const char * source_realtime ,
452
+ const char * source_monotonic ,
453
+ usec_t * ret ) {
454
+
455
+ usec_t t , s , u ;
456
+
457
+ assert (j );
458
+
459
+ /* First, try _SOURCE_REALTIME_TIMESTAMP. */
460
+ if (source_realtime && safe_atou64 (source_realtime , & t ) >= 0 && VALID_REALTIME (t )) {
461
+ * ret = t ;
462
+ return ;
463
+ }
464
+
465
+ /* Read realtime timestamp in the entry header. */
466
+ if (sd_journal_get_realtime_usec (j , & t ) < 0 ) {
467
+ * ret = USEC_INFINITY ;
468
+ return ;
469
+ }
470
+
471
+ /* If _SOURCE_MONOTONIC_TIMESTAMP is provided, adjust the header timestamp. */
472
+ if (source_monotonic && safe_atou64 (source_monotonic , & s ) >= 0 && VALID_MONOTONIC (s ) &&
473
+ sd_journal_get_monotonic_usec (j , & u , & (sd_id128_t ) {}) >= 0 ) {
474
+ * ret = map_clock_usec_raw (t , u , s );
475
+ return ;
476
+ }
477
+
478
+ /* Otherwise, use the header timestamp as is. */
479
+ * ret = t ;
480
+ }
481
+
449
482
static void parse_display_timestamp (
450
483
sd_journal * j ,
451
- const char * realtime ,
452
- const char * monotonic ,
484
+ const char * source_realtime ,
485
+ const char * source_monotonic ,
453
486
dual_timestamp * ret_display_ts ,
454
487
sd_id128_t * ret_boot_id ) {
455
488
456
- bool realtime_good = false, monotonic_good = false, boot_id_good = false;
489
+ dual_timestamp
490
+ header_ts = { USEC_INFINITY , USEC_INFINITY },
491
+ source_ts = { USEC_INFINITY , USEC_INFINITY };
492
+ sd_id128_t boot_id = SD_ID128_NULL ;
493
+ usec_t t ;
457
494
458
495
assert (j );
459
496
assert (ret_display_ts );
460
497
assert (ret_boot_id );
461
498
462
- if (realtime )
463
- realtime_good = safe_atou64 (realtime , & ret_display_ts -> realtime ) >= 0 ;
464
- if (!realtime_good || !VALID_REALTIME (ret_display_ts -> realtime ))
465
- realtime_good = sd_journal_get_realtime_usec (j , & ret_display_ts -> realtime ) >= 0 ;
466
- if (!realtime_good )
467
- ret_display_ts -> realtime = USEC_INFINITY ;
468
-
469
- if (monotonic )
470
- monotonic_good = safe_atou64 (monotonic , & ret_display_ts -> monotonic ) >= 0 ;
471
- if (!monotonic_good || !VALID_MONOTONIC (ret_display_ts -> monotonic ))
472
- monotonic_good = boot_id_good = sd_journal_get_monotonic_usec (j , & ret_display_ts -> monotonic , ret_boot_id ) >= 0 ;
473
- if (!monotonic_good )
474
- ret_display_ts -> monotonic = USEC_INFINITY ;
475
-
476
- if (!boot_id_good )
477
- boot_id_good = sd_journal_get_monotonic_usec (j , NULL , ret_boot_id ) >= 0 ;
478
- if (!boot_id_good )
479
- * ret_boot_id = SD_ID128_NULL ;
499
+ if (source_realtime && safe_atou64 (source_realtime , & t ) >= 0 && VALID_REALTIME (t ))
500
+ source_ts .realtime = t ;
501
+
502
+ if (source_monotonic && safe_atou64 (source_monotonic , & t ) >= 0 && VALID_MONOTONIC (t ))
503
+ source_ts .monotonic = t ;
504
+
505
+ (void ) sd_journal_get_realtime_usec (j , & header_ts .realtime );
506
+ (void ) sd_journal_get_monotonic_usec (j , & header_ts .monotonic , & boot_id );
507
+
508
+ /* Adjust timestamp if possible. */
509
+ if (header_ts .realtime != USEC_INFINITY && header_ts .monotonic != USEC_INFINITY ) {
510
+ if (source_ts .realtime == USEC_INFINITY && source_ts .monotonic != USEC_INFINITY )
511
+ source_ts .realtime = map_clock_usec_raw (header_ts .realtime , header_ts .monotonic , source_ts .monotonic );
512
+ else if (source_ts .realtime != USEC_INFINITY && source_ts .monotonic == USEC_INFINITY )
513
+ source_ts .monotonic = map_clock_usec_raw (header_ts .monotonic , header_ts .realtime , source_ts .realtime );
514
+ }
515
+
516
+ ret_display_ts -> realtime = source_ts .realtime != USEC_INFINITY ? source_ts .realtime : header_ts .realtime ;
517
+ ret_display_ts -> monotonic = source_ts .monotonic != USEC_INFINITY ? source_ts .monotonic : header_ts .monotonic ;
518
+ * ret_boot_id = boot_id ;
480
519
}
481
520
482
521
static int output_short (
@@ -487,8 +526,8 @@ static int output_short(
487
526
OutputFlags flags ,
488
527
const Set * output_fields ,
489
528
const size_t highlight [2 ],
490
- dual_timestamp * previous_display_ts , /* in and out */
491
- sd_id128_t * previous_boot_id ) { /* in and out */
529
+ dual_timestamp * previous_display_ts , /* in and out, used only when mode is OUTPUT_SHORT_MONOTONIC, OUTPUT_SHORT_DELTA. */
530
+ sd_id128_t * previous_boot_id ) { /* in and out, used only when mode is OUTPUT_SHORT_MONOTONIC, OUTPUT_SHORT_DELTA. */
492
531
493
532
int r ;
494
533
const void * data ;
@@ -553,8 +592,6 @@ static int output_short(
553
592
if (identifier && set_contains (j -> exclude_syslog_identifiers , identifier ))
554
593
return 0 ;
555
594
556
- parse_display_timestamp (j , realtime , monotonic , & display_ts , & boot_id );
557
-
558
595
if (!(flags & OUTPUT_SHOW_ALL ))
559
596
strip_tab_ansi (& message , & message_len , highlight_shifted );
560
597
@@ -566,10 +603,14 @@ static int output_short(
566
603
567
604
audit = streq_ptr (transport , "audit" );
568
605
569
- if (IN_SET (mode , OUTPUT_SHORT_MONOTONIC , OUTPUT_SHORT_DELTA ))
606
+ if (IN_SET (mode , OUTPUT_SHORT_MONOTONIC , OUTPUT_SHORT_DELTA )) {
607
+ parse_display_timestamp (j , realtime , monotonic , & display_ts , & boot_id );
570
608
r = output_timestamp_monotonic (f , mode , & display_ts , & boot_id , previous_display_ts , previous_boot_id );
571
- else
572
- r = output_timestamp_realtime (f , j , mode , flags , display_ts .realtime );
609
+ } else {
610
+ usec_t usec ;
611
+ parse_display_realtime (j , realtime , monotonic , & usec );
612
+ r = output_timestamp_realtime (f , j , mode , flags , usec );
613
+ }
573
614
if (r < 0 )
574
615
return r ;
575
616
n += r ;
@@ -690,17 +731,15 @@ static int output_short(
690
731
if (flags & OUTPUT_CATALOG )
691
732
(void ) print_catalog (f , j );
692
733
693
- * previous_display_ts = display_ts ;
694
- * previous_boot_id = boot_id ;
734
+ if (IN_SET (mode , OUTPUT_SHORT_MONOTONIC , OUTPUT_SHORT_DELTA )) {
735
+ * previous_display_ts = display_ts ;
736
+ * previous_boot_id = boot_id ;
737
+ }
695
738
696
739
return ellipsized ;
697
740
}
698
741
699
- static int get_display_timestamp (
700
- sd_journal * j ,
701
- dual_timestamp * ret_display_ts ,
702
- sd_id128_t * ret_boot_id ) {
703
-
742
+ static int get_display_realtime (sd_journal * j , usec_t * ret ) {
704
743
const void * data ;
705
744
_cleanup_free_ char * realtime = NULL , * monotonic = NULL ;
706
745
size_t length ;
@@ -711,8 +750,7 @@ static int get_display_timestamp(
711
750
int r ;
712
751
713
752
assert (j );
714
- assert (ret_display_ts );
715
- assert (ret_boot_id );
753
+ assert (ret );
716
754
717
755
JOURNAL_FOREACH_DATA_RETVAL (j , data , length , r ) {
718
756
r = parse_fieldv (data , length , message_fields , ELEMENTSOF (message_fields ));
@@ -725,7 +763,7 @@ static int get_display_timestamp(
725
763
if (r < 0 )
726
764
return r ;
727
765
728
- (void ) parse_display_timestamp (j , realtime , monotonic , ret_display_ts , ret_boot_id );
766
+ (void ) parse_display_realtime (j , realtime , monotonic , ret );
729
767
730
768
/* Restart all data before */
731
769
sd_journal_restart_data (j );
@@ -750,32 +788,31 @@ static int output_verbose(
750
788
size_t length ;
751
789
_cleanup_free_ char * cursor = NULL ;
752
790
char buf [FORMAT_TIMESTAMP_MAX + 7 ];
753
- dual_timestamp display_ts ;
754
- sd_id128_t boot_id ;
755
791
const char * timestamp ;
792
+ usec_t usec ;
756
793
int r ;
757
794
758
795
assert (f );
759
796
assert (j );
760
797
761
798
(void ) sd_journal_set_data_threshold (j , 0 );
762
799
763
- r = get_display_timestamp (j , & display_ts , & boot_id );
800
+ r = get_display_realtime (j , & usec );
764
801
if (IN_SET (r , - EBADMSG , - EADDRNOTAVAIL )) {
765
802
log_debug_errno (r , "Skipping message we can't read: %m" );
766
803
return 0 ;
767
804
}
768
805
if (r < 0 )
769
806
return log_error_errno (r , "Failed to get journal fields: %m" );
770
807
771
- if (!VALID_REALTIME (display_ts . realtime ))
808
+ if (!VALID_REALTIME (usec ))
772
809
return log_error_errno (SYNTHETIC_ERRNO (EINVAL ), "No valid realtime timestamp available" );
773
810
774
811
r = sd_journal_get_cursor (j , & cursor );
775
812
if (r < 0 )
776
813
return log_error_errno (r , "Failed to get cursor: %m" );
777
814
778
- timestamp = format_timestamp_style (buf , sizeof buf , display_ts . realtime ,
815
+ timestamp = format_timestamp_style (buf , sizeof buf , usec ,
779
816
flags & OUTPUT_UTC ? TIMESTAMP_US_UTC : TIMESTAMP_US );
780
817
fprintf (f , "%s%s%s %s[%s]%s\n" ,
781
818
timestamp && (flags & OUTPUT_COLOR ) ? ANSI_UNDERLINE : "" ,
0 commit comments