Compare commits
35 Commits
2239ab6271
...
70c5499709
Author | SHA1 | Date |
---|---|---|
|
70c5499709 | |
|
2ccbb69032 | |
|
49e25c1bd4 | |
|
b9d8175545 | |
|
0fef08bbc4 | |
|
b304e34d56 | |
|
40e3432faf | |
|
9ba552a1b5 | |
|
54f99f8269 | |
|
263a1ec1f1 | |
|
2d8f7bc57a | |
|
5948a2be00 | |
|
2f36596b6d | |
|
7e0555f2c2 | |
|
8730de52de | |
|
3eeab1d368 | |
|
8990553795 | |
|
fb76556f95 | |
|
d9aef1d8d9 | |
|
72814b830c | |
|
4a455be70a | |
|
0305241095 | |
|
ef75110afb | |
|
0482958335 | |
|
f6257155cc | |
|
d93fb760d5 | |
|
ee5f69c0c3 | |
|
bb570bbbf2 | |
|
42a8e34e80 | |
|
60471c9f52 | |
|
4227cbfa94 | |
|
2799f04cad | |
|
e9e57dc9af | |
|
9033153c47 | |
|
97c57ca604 |
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -37,6 +37,8 @@ extern "C" {
|
||||||
#define CLOCK_THREAD_CPUTIME_ID 8
|
#define CLOCK_THREAD_CPUTIME_ID 8
|
||||||
#define CLOCK_THREAD_SYSTIME_ID 9
|
#define CLOCK_THREAD_SYSTIME_ID 9
|
||||||
|
|
||||||
|
#define CLOCK_REALTIME_HAS_LEAP_SECONDS 1
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <sortix/clock.h>
|
|
||||||
#include <sortix/fcntl.h>
|
#include <sortix/fcntl.h>
|
||||||
#include <sortix/mman.h>
|
#include <sortix/mman.h>
|
||||||
#include <sortix/stat.h>
|
#include <sortix/stat.h>
|
||||||
|
@ -429,70 +428,6 @@ static void SystemIdleThread(void* /*user*/)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kthread_mutex_t driver_threads_lock = KTHREAD_MUTEX_INITIALIZER;
|
|
||||||
kthread_cond_t driver_threads_cond = KTHREAD_COND_INITIALIZER;
|
|
||||||
size_t driver_threads_done = 0;
|
|
||||||
size_t driver_threads_total = 0;
|
|
||||||
|
|
||||||
// Parallelize the initialization of slow drivers.
|
|
||||||
static void RunDriverThread(void (*entry)(void*), void* user, const char* name)
|
|
||||||
{
|
|
||||||
kthread_mutex_lock(&driver_threads_lock);
|
|
||||||
driver_threads_total++;
|
|
||||||
kthread_mutex_unlock(&driver_threads_lock);
|
|
||||||
if ( !RunKernelThread(entry, user, name) )
|
|
||||||
PanicF("RunKernelThread: %s", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FinishedDriverThread()
|
|
||||||
{
|
|
||||||
ScopedLock lock(&driver_threads_lock);
|
|
||||||
driver_threads_done++;
|
|
||||||
kthread_cond_broadcast(&driver_threads_cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PS2ThreadCtx
|
|
||||||
{
|
|
||||||
PS2Keyboard* keyboard;
|
|
||||||
PS2Mouse* mouse;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void PS2Thread(void* user)
|
|
||||||
{
|
|
||||||
struct PS2ThreadCtx* ctx = (struct PS2ThreadCtx*) user;
|
|
||||||
PS2::Init(ctx->keyboard, ctx->mouse);
|
|
||||||
FinishedDriverThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DevCtx
|
|
||||||
{
|
|
||||||
Ref<Descriptor> dev;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void AHCIThread(void* user)
|
|
||||||
{
|
|
||||||
AHCI::Init("/dev", ((struct DevCtx*) user)->dev);
|
|
||||||
FinishedDriverThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ATAThread(void* user)
|
|
||||||
{
|
|
||||||
ATA::Init("/dev", ((struct DevCtx*) user)->dev);
|
|
||||||
FinishedDriverThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BGAThread(void* /*user*/)
|
|
||||||
{
|
|
||||||
BGA::Init();
|
|
||||||
FinishedDriverThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void EMThread(void* user)
|
|
||||||
{
|
|
||||||
EM::Init("/dev", ((struct DevCtx*) user)->dev);
|
|
||||||
FinishedDriverThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BootThread(void* /*user*/)
|
static void BootThread(void* /*user*/)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -576,7 +511,6 @@ static void BootThread(void* /*user*/)
|
||||||
Ref<Descriptor> slashdev = droot->open(&ctx, "dev", O_READ | O_DIRECTORY);
|
Ref<Descriptor> slashdev = droot->open(&ctx, "dev", O_READ | O_DIRECTORY);
|
||||||
if ( !slashdev )
|
if ( !slashdev )
|
||||||
Panic("Unable to create descriptor for RAM filesystem /dev directory.");
|
Panic("Unable to create descriptor for RAM filesystem /dev directory.");
|
||||||
struct DevCtx dev_ctx = { slashdev };
|
|
||||||
|
|
||||||
// Initialize the keyboard.
|
// Initialize the keyboard.
|
||||||
PS2Keyboard* keyboard = new PS2Keyboard();
|
PS2Keyboard* keyboard = new PS2Keyboard();
|
||||||
|
@ -594,8 +528,7 @@ static void BootThread(void* /*user*/)
|
||||||
Panic("Could not allocate PS2 Mouse driver");
|
Panic("Could not allocate PS2 Mouse driver");
|
||||||
|
|
||||||
// Initialize the PS/2 controller.
|
// Initialize the PS/2 controller.
|
||||||
struct PS2ThreadCtx ps2_context = { keyboard, mouse };
|
PS2::Init(keyboard, mouse);
|
||||||
RunDriverThread(PS2Thread, &ps2_context, "ps2");
|
|
||||||
|
|
||||||
// Register /dev/tty as the current-terminal factory.
|
// Register /dev/tty as the current-terminal factory.
|
||||||
Ref<Inode> tty(new DevTTY(slashdev->dev, 0666, 0, 0));
|
Ref<Inode> tty(new DevTTY(slashdev->dev, 0666, 0, 0));
|
||||||
|
@ -683,13 +616,13 @@ static void BootThread(void* /*user*/)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Initialize AHCI devices.
|
// Initialize AHCI devices.
|
||||||
RunDriverThread(AHCIThread, &dev_ctx, "ahci");
|
AHCI::Init("/dev", slashdev);
|
||||||
|
|
||||||
// Initialize ATA devices.
|
// Initialize ATA devices.
|
||||||
RunDriverThread(ATAThread, &dev_ctx, "ata");
|
ATA::Init("/dev", slashdev);
|
||||||
|
|
||||||
// Initialize the BGA driver.
|
// Initialize the BGA driver.
|
||||||
RunDriverThread(BGAThread, NULL, "bga");
|
BGA::Init();
|
||||||
|
|
||||||
// Initialize the filesystem network.
|
// Initialize the filesystem network.
|
||||||
NetFS::Init();
|
NetFS::Init();
|
||||||
|
@ -711,15 +644,9 @@ static void BootThread(void* /*user*/)
|
||||||
{
|
{
|
||||||
// Initialize the EM driver.
|
// Initialize the EM driver.
|
||||||
if ( enable_em )
|
if ( enable_em )
|
||||||
RunDriverThread(EMThread, &dev_ctx, "em");
|
EM::Init("/dev", slashdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Await the drivers initialized in the background threads.
|
|
||||||
kthread_mutex_lock(&driver_threads_lock);
|
|
||||||
while ( driver_threads_done != driver_threads_total )
|
|
||||||
kthread_cond_wait(&driver_threads_cond, &driver_threads_lock);
|
|
||||||
kthread_mutex_unlock(&driver_threads_lock);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Stage 6. Executing Hosted Environment ("User-Space")
|
// Stage 6. Executing Hosted Environment ("User-Space")
|
||||||
//
|
//
|
||||||
|
|
|
@ -780,6 +780,10 @@ scram/scram.2 \
|
||||||
sys/dnsconfig/getdnsconfig.2 \
|
sys/dnsconfig/getdnsconfig.2 \
|
||||||
sys/dnsconfig/setdnsconfig.2 \
|
sys/dnsconfig/setdnsconfig.2 \
|
||||||
|
|
||||||
|
MANPAGES3=\
|
||||||
|
time/add_leap_seconds.3 \
|
||||||
|
time/sub_leap_seconds.3 \
|
||||||
|
|
||||||
HEADERS:=$(shell find include -type f)
|
HEADERS:=$(shell find include -type f)
|
||||||
|
|
||||||
LIBK_OBJS:=$(FREEOBJS:.o=.libk.o)
|
LIBK_OBJS:=$(FREEOBJS:.o=.libk.o)
|
||||||
|
@ -906,3 +910,5 @@ install-libs-kernel: $(INSTALLLIBSKERNEL)
|
||||||
install-man:
|
install-man:
|
||||||
mkdir -p $(DESTDIR)$(MANDIR)/man2
|
mkdir -p $(DESTDIR)$(MANDIR)/man2
|
||||||
cp $(MANPAGES2) $(DESTDIR)$(MANDIR)/man2
|
cp $(MANPAGES2) $(DESTDIR)$(MANDIR)/man2
|
||||||
|
mkdir -p $(DESTDIR)$(MANDIR)/man3
|
||||||
|
cp $(MANPAGES3) $(DESTDIR)$(MANDIR)/man3
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2012, 2013, 2014 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2011, 2012, 2013, 2014, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -163,7 +163,9 @@ time_t timegm(struct tm*);
|
||||||
#if __USE_SORTIX
|
#if __USE_SORTIX
|
||||||
int clock_gettimeres(clockid_t, struct timespec*, struct timespec*);
|
int clock_gettimeres(clockid_t, struct timespec*, struct timespec*);
|
||||||
int clock_settimeres(clockid_t, const struct timespec*, const struct timespec*);
|
int clock_settimeres(clockid_t, const struct timespec*, const struct timespec*);
|
||||||
int timens(struct tmns* tmns);
|
int timens(struct tmns*);
|
||||||
|
int sub_leap_seconds(time_t*);
|
||||||
|
int add_leap_seconds(time_t*);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern char* tzname[2];
|
extern char* tzname[2];
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
.Dd March 26, 2023
|
||||||
|
.Dt ADD_LEAP_SECONDS 2
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm add_leap_seconds ,
|
||||||
|
.Nm sub_leap_seconds
|
||||||
|
.Nd convert between utc and tai-10 timestamps
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In time.h
|
||||||
|
.Ft int
|
||||||
|
.Fn add_leap_seconds "time_t *timestamp"
|
||||||
|
.Ft int
|
||||||
|
.Fn sub_leap_seconds "time_t *timestamp"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn add_leap_seconds
|
||||||
|
adds leap seconds to the UTC
|
||||||
|
.Fa timestamp
|
||||||
|
to give the corresponding TAI-10 timestamp.
|
||||||
|
.Pp
|
||||||
|
.Fn sub_leap_seconds
|
||||||
|
subtracts leap seconds from the TAI-10
|
||||||
|
.Fa timestamp
|
||||||
|
to give the corresponding UTC timestamp.
|
||||||
|
.Pp
|
||||||
|
Leap seconds are announced usually six months in advanced by the
|
||||||
|
International Earth Rotation and Reference Systems Service (IERS) in Bulletin C.
|
||||||
|
Leap seconds can be added or removed at the end of the June or December (UTC)
|
||||||
|
where the last minute can be 61 or 59 seconds.
|
||||||
|
Leap seconds correct the difference between solar time and civil time when
|
||||||
|
planetary rotation varies.
|
||||||
|
Leap seconds have never been removed as of mid 2023.
|
||||||
|
.Pp
|
||||||
|
.Dv CLOCK_REALTIME
|
||||||
|
on this system is in the TAI-10 format which measures the number of actual
|
||||||
|
seconds including leap seconds that has happened since the Unix epoch of
|
||||||
|
1970-01-01 00:00:00 UTC.
|
||||||
|
The inclusion of leap seconds is advertised by the
|
||||||
|
.Dv CLOCK_REALTIME_HAS_LEAP_SECONDS
|
||||||
|
definition.
|
||||||
|
This violates POSIX's requirement that
|
||||||
|
.Dv CLOCK_REALTIME
|
||||||
|
is in UTC, which pretends leap seconds don't happen.
|
||||||
|
The
|
||||||
|
.Fn add_leap_seconds
|
||||||
|
and
|
||||||
|
.Fn sub_leap_seconds
|
||||||
|
functions are useful when exchanging timestamps with other operating systems.
|
||||||
|
.Pp
|
||||||
|
TAI-10 is International Atomic Time (TAI) subtracted by 10 seconds so the epoch
|
||||||
|
is the same moment in TAI-10 and UTC.
|
||||||
|
.Pp
|
||||||
|
TAI-10 has the advantage that every actual past moment in time has an unique and
|
||||||
|
unambiguous and continuous representation.
|
||||||
|
The time difference between two TAI-10 timestamps can be calculated as a simple
|
||||||
|
subtraction.
|
||||||
|
Durations can be simply added to TAI-10 timestamps to produce the the timestamp
|
||||||
|
changed by that many seconds.
|
||||||
|
However it's not possible to compute which TAI10 timestamp corresponds to a
|
||||||
|
calendar date and time more than 6 months in the future, as the leap seconds
|
||||||
|
have not been announced yet.
|
||||||
|
The system leap second table needs to be up to date in order to perform properly
|
||||||
|
between TAI-10 and calendar time.
|
||||||
|
TAI-10 is the most useful format when dealing with relative times, as it's
|
||||||
|
guaranteed a certain amount of time has elapsed.
|
||||||
|
.Pp
|
||||||
|
UTC has the disadvantage that two different seconds can have the same timestamp
|
||||||
|
when leap seconds are removed, and UTC can be discontinuous if a leap second
|
||||||
|
removed where a timestamp could correspond to no actual moment in time.
|
||||||
|
The actual time between two UTC timestamps cannot be computed by a simple
|
||||||
|
subtraction (a leap second table is required) and durations cannot simply be
|
||||||
|
added to wait for a particular amount of time.
|
||||||
|
UTC is the most useful format when dealing with calendar times, as it's always
|
||||||
|
possible to losslessly convert UTC to and from calendar time.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
On success 1 is returned.
|
||||||
|
.Pp
|
||||||
|
0 is returned when the input timestamp has no representation in the output
|
||||||
|
format or is ambigous.
|
||||||
|
The output timestamp will be the best approximation.
|
||||||
|
This can happen in
|
||||||
|
.Fn sub_leap_seconds
|
||||||
|
when converting from TAI-10 to UTC and a leap second has been
|
||||||
|
inserted, or in
|
||||||
|
.Fn add_leap_seconds
|
||||||
|
when converting from UTC to TAI-10 and a leap second has been removed (which has
|
||||||
|
never happened so far).
|
||||||
|
.Pp
|
||||||
|
-1 is returned when the input timestamp is too far in the future and it is
|
||||||
|
unknown whether a leap second will occur.
|
||||||
|
The output timestamp will be the best approximation.
|
||||||
|
The accurate result can be obtained when the system leap second table has been
|
||||||
|
updated.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr clock_gettime 2 ,
|
||||||
|
.Xr gmtime_r 3 ,
|
||||||
|
.Xr localtime_r 3 ,
|
||||||
|
.Xr mktime 3 ,
|
||||||
|
.Xr timegm 3
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn add_leap_seconds
|
||||||
|
and
|
||||||
|
.Fn sub_leap_seconds
|
||||||
|
functions originally appeared in Sortix 1.1.
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -23,23 +23,25 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
static const int DAYS_JANUARY = 31;
|
#define DAYS_JANUARY 31
|
||||||
static const int DAYS_FEBRUARY = 28;
|
#define DAYS_FEBRUARY 28
|
||||||
static const int DAYS_MARCH = 31;
|
#define DAYS_MARCH 31
|
||||||
static const int DAYS_APRIL = 30;
|
#define DAYS_APRIL 30
|
||||||
static const int DAYS_MAY = 31;
|
#define DAYS_MAY 31
|
||||||
static const int DAYS_JUNE = 30;
|
#define DAYS_JUNE 30
|
||||||
static const int DAYS_JULY = 31;
|
#define DAYS_JULY 31
|
||||||
static const int DAYS_AUGUST = 31;
|
#define DAYS_AUGUST 31
|
||||||
static const int DAYS_SEPTEMBER = 30;
|
#define DAYS_SEPTEMBER 30
|
||||||
static const int DAYS_OCTOBER = 31;
|
#define DAYS_OCTOBER 31
|
||||||
static const int DAYS_NOVEMBER = 30;
|
#define DAYS_NOVEMBER 30
|
||||||
static const int DAYS_DECEMBER = 31;
|
#define DAYS_DECEMBER 31
|
||||||
|
|
||||||
|
#define UNKNOWN 127
|
||||||
|
|
||||||
#define DECL_LEAP_SECOND(year, jun, dec) \
|
#define DECL_LEAP_SECOND(year, jun, dec) \
|
||||||
{0, 0, 0, 0, 0, jun, 0, 0, 0, 0, 0, dec}
|
{0, 0, 0, 0, 0, jun, 0, 0, 0, 0, 0, dec}
|
||||||
|
|
||||||
static int8_t leap_seconds[][12] =
|
static const char leap_seconds[][12] =
|
||||||
{
|
{
|
||||||
DECL_LEAP_SECOND(1970, 0, 0),
|
DECL_LEAP_SECOND(1970, 0, 0),
|
||||||
DECL_LEAP_SECOND(1971, 0, 0),
|
DECL_LEAP_SECOND(1971, 0, 0),
|
||||||
|
@ -88,18 +90,47 @@ static int8_t leap_seconds[][12] =
|
||||||
DECL_LEAP_SECOND(2014, 0, 0),
|
DECL_LEAP_SECOND(2014, 0, 0),
|
||||||
DECL_LEAP_SECOND(2015, 1, 0),
|
DECL_LEAP_SECOND(2015, 1, 0),
|
||||||
DECL_LEAP_SECOND(2016, 0, 1),
|
DECL_LEAP_SECOND(2016, 0, 1),
|
||||||
|
DECL_LEAP_SECOND(2017, 0, 0),
|
||||||
|
DECL_LEAP_SECOND(2018, 0, 0),
|
||||||
|
DECL_LEAP_SECOND(2019, 0, 0),
|
||||||
|
DECL_LEAP_SECOND(2020, 0, 0),
|
||||||
|
DECL_LEAP_SECOND(2021, 0, 0),
|
||||||
|
DECL_LEAP_SECOND(2022, 0, 0),
|
||||||
|
DECL_LEAP_SECOND(2023, 0, UNKNOWN),
|
||||||
};
|
};
|
||||||
|
|
||||||
static time_t get_leap_second(int year, int month)
|
static const char month_days_list[12] =
|
||||||
|
{
|
||||||
|
DAYS_JANUARY,
|
||||||
|
DAYS_FEBRUARY,
|
||||||
|
DAYS_MARCH,
|
||||||
|
DAYS_APRIL,
|
||||||
|
DAYS_MAY,
|
||||||
|
DAYS_JUNE,
|
||||||
|
DAYS_JULY,
|
||||||
|
DAYS_AUGUST,
|
||||||
|
DAYS_SEPTEMBER,
|
||||||
|
DAYS_OCTOBER,
|
||||||
|
DAYS_NOVEMBER,
|
||||||
|
DAYS_DECEMBER,
|
||||||
|
};
|
||||||
|
|
||||||
|
static time_t get_leap_second_maybe(int year, int month)
|
||||||
{
|
{
|
||||||
const time_t num_years = sizeof(leap_seconds) / sizeof(leap_seconds[0]);
|
const time_t num_years = sizeof(leap_seconds) / sizeof(leap_seconds[0]);
|
||||||
if ( year < 1970 )
|
if ( year < 1970 )
|
||||||
return 0;
|
return 0;
|
||||||
if ( num_years <= year-1970 )
|
if ( num_years <= year-1970 )
|
||||||
return 0;
|
return UNKNOWN;
|
||||||
return leap_seconds[year-1970][month];
|
return leap_seconds[year-1970][month];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static time_t get_leap_second(int year, int month)
|
||||||
|
{
|
||||||
|
time_t result = get_leap_second_maybe(year, month);
|
||||||
|
return result == UNKNOWN ? 0 : result;
|
||||||
|
}
|
||||||
|
|
||||||
static time_t leap_seconds_in_year(int year)
|
static time_t leap_seconds_in_year(int year)
|
||||||
{
|
{
|
||||||
time_t ret = 0;
|
time_t ret = 0;
|
||||||
|
@ -129,6 +160,11 @@ static time_t days_in_year(int year)
|
||||||
DAYS_DECEMBER;
|
DAYS_DECEMBER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int days_in_month(int year, int month)
|
||||||
|
{
|
||||||
|
return month_days_list[month] + (month == 1 && is_leap_year(year));
|
||||||
|
}
|
||||||
|
|
||||||
struct tm* gmtime_r(const time_t* time_ptr, struct tm* ret)
|
struct tm* gmtime_r(const time_t* time_ptr, struct tm* ret)
|
||||||
{
|
{
|
||||||
time_t left = *time_ptr;
|
time_t left = *time_ptr;
|
||||||
|
@ -165,29 +201,13 @@ struct tm* gmtime_r(const time_t* time_ptr, struct tm* ret)
|
||||||
ret->tm_wday = (ret->tm_wday - year_days + 7*7*7*7) % 7;
|
ret->tm_wday = (ret->tm_wday - year_days + 7*7*7*7) % 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
int month_days_list[12] =
|
|
||||||
{
|
|
||||||
DAYS_JANUARY,
|
|
||||||
DAYS_FEBRUARY + (is_leap_year(ret->tm_year) ? 1 : 0),
|
|
||||||
DAYS_MARCH,
|
|
||||||
DAYS_APRIL,
|
|
||||||
DAYS_MAY,
|
|
||||||
DAYS_JUNE,
|
|
||||||
DAYS_JULY,
|
|
||||||
DAYS_AUGUST,
|
|
||||||
DAYS_SEPTEMBER,
|
|
||||||
DAYS_OCTOBER,
|
|
||||||
DAYS_NOVEMBER,
|
|
||||||
DAYS_DECEMBER,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Figure out the correct month.
|
// Figure out the correct month.
|
||||||
ret->tm_mon = 0;
|
ret->tm_mon = 0;
|
||||||
ret->tm_yday = 0;
|
ret->tm_yday = 0;
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
int month_leaps = get_leap_second(ret->tm_year, ret->tm_mon);
|
int month_leaps = get_leap_second(ret->tm_year, ret->tm_mon);
|
||||||
int month_days = month_days_list[ret->tm_mon];
|
int month_days = days_in_month(ret->tm_year, ret->tm_mon);
|
||||||
int month_seconds = month_days * 24 * 60 * 60 + month_leaps;
|
int month_seconds = month_days * 24 * 60 * 60 + month_leaps;
|
||||||
if ( month_seconds <= left )
|
if ( month_seconds <= left )
|
||||||
{
|
{
|
||||||
|
@ -204,7 +224,7 @@ struct tm* gmtime_r(const time_t* time_ptr, struct tm* ret)
|
||||||
left = left % (24 * 60 * 60);
|
left = left % (24 * 60 * 60);
|
||||||
|
|
||||||
// If this is a regular timestamp.
|
// If this is a regular timestamp.
|
||||||
if ( ret->tm_mday < month_days_list[ret->tm_mon] )
|
if ( ret->tm_mday < days_in_month(ret->tm_year, ret->tm_mon) )
|
||||||
{
|
{
|
||||||
ret->tm_yday += ret->tm_mday;
|
ret->tm_yday += ret->tm_mday;
|
||||||
|
|
||||||
|
@ -257,26 +277,10 @@ time_t timegm(struct tm* tm)
|
||||||
ret += year_seconds;
|
ret += year_seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
int month_days_list[12] =
|
for ( int m = 0; m < month; m++ )
|
||||||
{
|
|
||||||
DAYS_JANUARY,
|
|
||||||
DAYS_FEBRUARY + (is_leap_year(year) ? 1 : 0),
|
|
||||||
DAYS_MARCH,
|
|
||||||
DAYS_APRIL,
|
|
||||||
DAYS_MAY,
|
|
||||||
DAYS_JUNE,
|
|
||||||
DAYS_JULY,
|
|
||||||
DAYS_AUGUST,
|
|
||||||
DAYS_SEPTEMBER,
|
|
||||||
DAYS_OCTOBER,
|
|
||||||
DAYS_NOVEMBER,
|
|
||||||
DAYS_DECEMBER,
|
|
||||||
};
|
|
||||||
|
|
||||||
for ( uint8_t m = 0; m < month; m++ )
|
|
||||||
{
|
{
|
||||||
int month_leaps = get_leap_second(year, m);
|
int month_leaps = get_leap_second(year, m);
|
||||||
int month_days = month_days_list[m];
|
int month_days = days_in_month(year, m);
|
||||||
int month_seconds = month_days * 24 * 60 * 60 + month_leaps;
|
int month_seconds = month_days * 24 * 60 * 60 + month_leaps;
|
||||||
ret += month_seconds;
|
ret += month_seconds;
|
||||||
}
|
}
|
||||||
|
@ -290,3 +294,58 @@ time_t timegm(struct tm* tm)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sub_leap_seconds(time_t* ptr)
|
||||||
|
{
|
||||||
|
time_t t = *ptr;
|
||||||
|
time_t next = 0;
|
||||||
|
time_t offset = 0;
|
||||||
|
for ( int year = 1970; true; year++ )
|
||||||
|
{
|
||||||
|
for ( int month = 0; month < 12; month++ )
|
||||||
|
{
|
||||||
|
time_t seconds = days_in_month(year, month) * 24 * 60 * 60;
|
||||||
|
time_t leap = get_leap_second_maybe(year, month);
|
||||||
|
next += seconds;
|
||||||
|
if ( leap == UNKNOWN )
|
||||||
|
{
|
||||||
|
*ptr = t - offset;
|
||||||
|
return t < next - 1 ? 1 : -1;
|
||||||
|
}
|
||||||
|
next += leap;
|
||||||
|
if ( t < next )
|
||||||
|
{
|
||||||
|
*ptr = t - offset;
|
||||||
|
return 0 < leap && t + 1 == next ? 0 : 1;
|
||||||
|
}
|
||||||
|
offset += leap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_leap_seconds(time_t* ptr)
|
||||||
|
{
|
||||||
|
time_t t = *ptr;
|
||||||
|
time_t next = 0;
|
||||||
|
time_t offset = 0;
|
||||||
|
for ( int year = 1970; true; year++ )
|
||||||
|
{
|
||||||
|
for ( int month = 0; month < 12; month++ )
|
||||||
|
{
|
||||||
|
time_t seconds = days_in_month(year, month) * 24 * 60 * 60;
|
||||||
|
time_t leap = get_leap_second_maybe(year, month);
|
||||||
|
next += seconds;
|
||||||
|
if ( leap == UNKNOWN )
|
||||||
|
{
|
||||||
|
*ptr = t + offset;
|
||||||
|
return t < next - 1 ? 1 : -1;
|
||||||
|
}
|
||||||
|
if ( t < next )
|
||||||
|
{
|
||||||
|
*ptr = t + offset;
|
||||||
|
return leap < 0 && t + 1 == next ? 0 : 1;
|
||||||
|
}
|
||||||
|
offset += leap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
add_leap_seconds.3
|
|
@ -127,9 +127,9 @@ diff -Paur --no-dereference -- nginx.upstream/auto/install nginx/auto/install
|
||||||
+
|
+
|
||||||
+ mkdir -p '\$(DESTDIR)$NGX_SYSCONFDIR/default/passwd.d'
|
+ mkdir -p '\$(DESTDIR)$NGX_SYSCONFDIR/default/passwd.d'
|
||||||
+ mkdir -p '\$(DESTDIR)$NGX_SYSCONFDIR/default/group.d'
|
+ mkdir -p '\$(DESTDIR)$NGX_SYSCONFDIR/default/group.d'
|
||||||
+ echo "_nginx:x:100:100:_nginx:/var/empty:sh" \\
|
+ echo "_nginx:x:101:101:_nginx:/var/empty:sh" \\
|
||||||
+ > '\$(DESTDIR)$NGX_SYSCONFDIR/default/passwd.d/nginx'
|
+ > '\$(DESTDIR)$NGX_SYSCONFDIR/default/passwd.d/nginx'
|
||||||
+ echo "_nginx::100:_nginx" \\
|
+ echo "_nginx::101:_nginx" \\
|
||||||
+ > '\$(DESTDIR)$NGX_SYSCONFDIR/default/group.d/nginx'
|
+ > '\$(DESTDIR)$NGX_SYSCONFDIR/default/group.d/nginx'
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
|
@ -80,9 +80,9 @@ diff -Paur --no-dereference -- ntpd.upstream/Makefile.in ntpd/Makefile.in
|
||||||
+ $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/default"
|
+ $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/default"
|
||||||
+ $(INSTALL) -m 644 "$(srcdir)/ntpd.conf" "$(DESTDIR)$(sysconfdir)/default/ntpd.conf"
|
+ $(INSTALL) -m 644 "$(srcdir)/ntpd.conf" "$(DESTDIR)$(sysconfdir)/default/ntpd.conf"
|
||||||
+ $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/default/passwd.d"
|
+ $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/default/passwd.d"
|
||||||
+ echo "_ntp:x:101:101:_ntp:/var/empty:sh" > "$(DESTDIR)$(sysconfdir)/default/passwd.d/ntpd"
|
+ echo "_ntp:x:100:100:_ntp:/var/empty:sh" > "$(DESTDIR)$(sysconfdir)/default/passwd.d/ntpd"
|
||||||
+ $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/default/group.d"
|
+ $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/default/group.d"
|
||||||
+ echo "_ntp::101:_ntp" > "$(DESTDIR)$(sysconfdir)/default/group.d/ntpd"
|
+ echo "_ntp::100:_ntp" > "$(DESTDIR)$(sysconfdir)/default/group.d/ntpd"
|
||||||
|
|
||||||
uninstall-local:
|
uninstall-local:
|
||||||
- @if cmp -s "$(DESTDIR)$(sysconfdir)/ntpd.conf" "$(srcdir)/ntpd.conf"; then \
|
- @if cmp -s "$(DESTDIR)$(sysconfdir)/ntpd.conf" "$(srcdir)/ntpd.conf"; then \
|
||||||
|
@ -134,7 +134,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/client.c ntpd/src/client.c
|
||||||
interval = error_interval();
|
interval = error_interval();
|
||||||
set_next(p, interval);
|
set_next(p, interval);
|
||||||
- log_info("reply from %s: negative delay %fs, "
|
- log_info("reply from %s: negative delay %fs, "
|
||||||
+ log_info("reply from %s: negative delay %llims, "
|
+ log_info("reply from %s: negative delay %lldms, "
|
||||||
"next query %llds",
|
"next query %llds",
|
||||||
log_sockaddr((struct sockaddr *)&p->addr->ss),
|
log_sockaddr((struct sockaddr *)&p->addr->ss),
|
||||||
- p->reply[p->shift].delay, (long long)interval);
|
- p->reply[p->shift].delay, (long long)interval);
|
||||||
|
@ -148,7 +148,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/client.c ntpd/src/client.c
|
||||||
interval = scale_interval(INTERVAL_QUERY_NORMAL);
|
interval = scale_interval(INTERVAL_QUERY_NORMAL);
|
||||||
|
|
||||||
- log_debug("reply from %s: offset %f delay %f, "
|
- log_debug("reply from %s: offset %f delay %f, "
|
||||||
+ log_debug("reply from %s: offset %llims delay %llims, "
|
+ log_debug("reply from %s: offset %lldms delay %lldms, "
|
||||||
"next query %llds",
|
"next query %llds",
|
||||||
log_sockaddr((struct sockaddr *)&p->addr->ss),
|
log_sockaddr((struct sockaddr *)&p->addr->ss),
|
||||||
- offset, delay,
|
- offset, delay,
|
||||||
|
@ -198,13 +198,27 @@ diff -Paur --no-dereference -- ntpd.upstream/src/constraint.c ntpd/src/constrain
|
||||||
gettime_from_timeval(&tv[1]);
|
gettime_from_timeval(&tv[1]);
|
||||||
|
|
||||||
- log_info("constraint reply from %s: offset %f",
|
- log_info("constraint reply from %s: offset %f",
|
||||||
+ log_info("constraint reply from %s: offset %lli ms",
|
+ log_info("constraint reply from %s: offset %lld ms",
|
||||||
log_sockaddr((struct sockaddr *)&cstr->addr->ss),
|
log_sockaddr((struct sockaddr *)&cstr->addr->ss),
|
||||||
- offset);
|
- offset);
|
||||||
+ (long long)(offset * 1000));
|
+ (long long)(offset * 1000));
|
||||||
|
|
||||||
cstr->state = STATE_REPLY_RECEIVED;
|
cstr->state = STATE_REPLY_RECEIVED;
|
||||||
cstr->last = getmonotime();
|
cstr->last = getmonotime();
|
||||||
|
@@ -1095,6 +1100,13 @@
|
||||||
|
/* Return parsed date as local time */
|
||||||
|
t = timegm(&httpsdate->tls_tm);
|
||||||
|
|
||||||
|
+ /* PATCH: Adjust for leap seconds in Sortix CLOCK_REALTIME. */
|
||||||
|
+#ifdef CLOCK_REALTIME_HAS_LEAP_SECONDS
|
||||||
|
+ if (!sub_leap_seconds(&t) || !sub_leap_seconds(&when.tv_sec)) {
|
||||||
|
+ return (NULL); /* Ignore during added leap second. */
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Report parsed Date: as "received time" */
|
||||||
|
rectv->tv_sec = t;
|
||||||
|
rectv->tv_usec = 0;
|
||||||
diff -Paur --no-dereference -- ntpd.upstream/src/control.c ntpd/src/control.c
|
diff -Paur --no-dereference -- ntpd.upstream/src/control.c ntpd/src/control.c
|
||||||
--- ntpd.upstream/src/control.c
|
--- ntpd.upstream/src/control.c
|
||||||
+++ ntpd/src/control.c
|
+++ ntpd/src/control.c
|
||||||
|
@ -233,10 +247,8 @@ diff -Paur --no-dereference -- ntpd.upstream/src/control.c ntpd/src/control.c
|
||||||
diff -Paur --no-dereference -- ntpd.upstream/src/init/ntpd ntpd/src/init/ntpd
|
diff -Paur --no-dereference -- ntpd.upstream/src/init/ntpd ntpd/src/init/ntpd
|
||||||
--- ntpd.upstream/src/init/ntpd
|
--- ntpd.upstream/src/init/ntpd
|
||||||
+++ ntpd/src/init/ntpd
|
+++ ntpd/src/init/ntpd
|
||||||
@@ -0,0 +1,4 @@
|
@@ -0,0 +1,2 @@
|
||||||
+require network
|
+require network
|
||||||
+#program=ntpd
|
|
||||||
+#exec $program -d
|
|
||||||
+exec ntpd -d
|
+exec ntpd -d
|
||||||
diff -Paur --no-dereference -- ntpd.upstream/src/Makefile.in ntpd/src/Makefile.in
|
diff -Paur --no-dereference -- ntpd.upstream/src/Makefile.in ntpd/src/Makefile.in
|
||||||
--- ntpd.upstream/src/Makefile.in
|
--- ntpd.upstream/src/Makefile.in
|
||||||
|
@ -336,7 +348,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntp.c ntpd/src/ntp.c
|
||||||
diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
|
diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
|
||||||
--- ntpd.upstream/src/ntpd.c
|
--- ntpd.upstream/src/ntpd.c
|
||||||
+++ ntpd/src/ntpd.c
|
+++ ntpd/src/ntpd.c
|
||||||
@@ -45,6 +45,107 @@
|
@@ -45,6 +45,53 @@
|
||||||
|
|
||||||
#include "ntpd.h"
|
#include "ntpd.h"
|
||||||
|
|
||||||
|
@ -364,60 +376,6 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+/*
|
|
||||||
+From musl:
|
|
||||||
+
|
|
||||||
+Copyright © 2005-2014 Rich Felker, et al.
|
|
||||||
+
|
|
||||||
+Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
+a copy of this software and associated documentation files (the
|
|
||||||
+"Software"), to deal in the Software without restriction, including
|
|
||||||
+without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
+distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
+permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
+the following conditions:
|
|
||||||
+
|
|
||||||
+The above copyright notice and this permission notice shall be
|
|
||||||
+included in all copies or substantial portions of the Software.
|
|
||||||
+
|
|
||||||
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
+*/
|
|
||||||
+int daemon(int nochdir, int noclose)
|
|
||||||
+{
|
|
||||||
+ if (!nochdir && chdir("/"))
|
|
||||||
+ return -1;
|
|
||||||
+ if (!noclose) {
|
|
||||||
+ int fd, failed = 0;
|
|
||||||
+ if ((fd = open("/dev/null", O_RDWR)) < 0) return -1;
|
|
||||||
+ if (dup2(fd, 0) < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0)
|
|
||||||
+ failed++;
|
|
||||||
+ if (fd > 2) close(fd);
|
|
||||||
+ if (failed) return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ switch(fork()) {
|
|
||||||
+ case 0: break;
|
|
||||||
+ case -1: return -1;
|
|
||||||
+ default: _exit(0);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (setsid() < 0) return -1;
|
|
||||||
+
|
|
||||||
+ switch(fork()) {
|
|
||||||
+ case 0: break;
|
|
||||||
+ case -1: return -1;
|
|
||||||
+ default: _exit(0);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int
|
+int
|
||||||
+adjfreq(const int64_t *freq, int64_t *oldfreq)
|
+adjfreq(const int64_t *freq, int64_t *oldfreq)
|
||||||
+{
|
+{
|
||||||
|
@ -444,7 +402,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
|
||||||
void sighdlr(int);
|
void sighdlr(int);
|
||||||
__dead void usage(void);
|
__dead void usage(void);
|
||||||
int auto_preconditions(const struct ntpd_conf *);
|
int auto_preconditions(const struct ntpd_conf *);
|
||||||
@@ -70,6 +171,7 @@
|
@@ -70,6 +117,7 @@
|
||||||
volatile sig_atomic_t sigchld = 0;
|
volatile sig_atomic_t sigchld = 0;
|
||||||
struct imsgbuf *ibuf;
|
struct imsgbuf *ibuf;
|
||||||
int timeout = INFTIM;
|
int timeout = INFTIM;
|
||||||
|
@ -452,7 +410,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
|
||||||
|
|
||||||
extern u_int constraint_cnt;
|
extern u_int constraint_cnt;
|
||||||
|
|
||||||
@@ -108,6 +210,17 @@
|
@@ -108,6 +156,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +428,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
|
||||||
__dead void
|
__dead void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
@@ -176,7 +289,10 @@
|
@@ -176,7 +235,10 @@
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +440,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
|
||||||
|
|
||||||
memset(&lconf, 0, sizeof(lconf));
|
memset(&lconf, 0, sizeof(lconf));
|
||||||
|
|
||||||
@@ -222,6 +338,12 @@
|
@@ -222,6 +284,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,34 +453,63 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
|
||||||
/* log to stderr until daemonized */
|
/* log to stderr until daemonized */
|
||||||
logdest = LOG_TO_STDERR;
|
logdest = LOG_TO_STDERR;
|
||||||
if (!lconf.debug)
|
if (!lconf.debug)
|
||||||
@@ -335,6 +457,10 @@
|
@@ -287,11 +355,13 @@
|
||||||
if (pledge("stdio rpath inet settime proc exec id", NULL) == -1)
|
logdest = lconf.debug ? LOG_TO_STDERR : LOG_TO_SYSLOG;
|
||||||
err(1, "pledge");
|
if (!lconf.settime) {
|
||||||
|
log_init(logdest, lconf.verbose, LOG_DAEMON);
|
||||||
+ if (!lconf.settime) {
|
+#if 0 /* PATCH: Modern daemons must not background. */
|
||||||
+ ready();
|
if (!lconf.debug) {
|
||||||
+ }
|
if (daemon(1, 0))
|
||||||
+
|
fatal("daemon");
|
||||||
while (quit == 0) {
|
writepid(&lconf);
|
||||||
new_cnt = PFD_MAX + constraint_cnt;
|
}
|
||||||
if (new_cnt > pfd_elms) {
|
+#endif
|
||||||
@@ -380,6 +506,7 @@
|
} else {
|
||||||
|
settime_deadline = getmonotime();
|
||||||
|
timeout = 100;
|
||||||
|
@@ -375,11 +445,14 @@
|
||||||
|
log_init(logdest, lconf.verbose, LOG_DAEMON);
|
||||||
|
log_warnx("no reply received in time, skipping initial "
|
||||||
|
"time setting");
|
||||||
|
+#if 0
|
||||||
|
if (!lconf.debug) {
|
||||||
|
if (daemon(1, 0))
|
||||||
fatal("daemon");
|
fatal("daemon");
|
||||||
writepid(&lconf);
|
writepid(&lconf);
|
||||||
}
|
}
|
||||||
|
+#endif
|
||||||
+ ready();
|
+ ready();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT))
|
if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT))
|
||||||
@@ -487,6 +614,7 @@
|
@@ -473,20 +546,25 @@
|
||||||
|
case IMSG_SETTIME:
|
||||||
|
if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d))
|
||||||
|
fatalx("invalid IMSG_SETTIME received");
|
||||||
|
- if (!lconf->settime)
|
||||||
|
+ if (!lconf->settime) {
|
||||||
|
+ ready();
|
||||||
|
break;
|
||||||
|
+ }
|
||||||
|
log_init(lconf->debug ? LOG_TO_STDERR : LOG_TO_SYSLOG,
|
||||||
|
lconf->verbose, LOG_DAEMON);
|
||||||
|
memcpy(&d, imsg.data, sizeof(d));
|
||||||
|
ntpd_settime(d);
|
||||||
|
+#if 0
|
||||||
|
/* daemonize now */
|
||||||
|
if (!lconf->debug) {
|
||||||
|
if (daemon(1, 0))
|
||||||
|
fatal("daemon");
|
||||||
|
writepid(lconf);
|
||||||
}
|
}
|
||||||
|
+#endif
|
||||||
lconf->settime = 0;
|
lconf->settime = 0;
|
||||||
timeout = INFTIM;
|
timeout = INFTIM;
|
||||||
+ ready();
|
+ ready();
|
||||||
break;
|
break;
|
||||||
case IMSG_CONSTRAINT_QUERY:
|
case IMSG_CONSTRAINT_QUERY:
|
||||||
priv_constraint_msg(imsg.hdr.peerid,
|
priv_constraint_msg(imsg.hdr.peerid,
|
||||||
@@ -507,9 +635,8 @@
|
@@ -507,9 +585,8 @@
|
||||||
void
|
void
|
||||||
reset_adjtime(void)
|
reset_adjtime(void)
|
||||||
{
|
{
|
||||||
|
@ -533,25 +520,52 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
|
||||||
if (adjtime(&tv, NULL) == -1)
|
if (adjtime(&tv, NULL) == -1)
|
||||||
log_warn("reset adjtime failed");
|
log_warn("reset adjtime failed");
|
||||||
}
|
}
|
||||||
@@ -523,9 +650,9 @@
|
@@ -523,9 +600,9 @@
|
||||||
|
|
||||||
d += getoffset();
|
d += getoffset();
|
||||||
if (d >= threshold || d <= -1 * threshold)
|
if (d >= threshold || d <= -1 * threshold)
|
||||||
- log_info("adjusting local clock by %fs", d);
|
- log_info("adjusting local clock by %fs", d);
|
||||||
+ log_info("adjusting local clock by %llims", (long long)(d * 1000));
|
+ log_info("adjusting local clock by %lldms", (long long)(d * 1000));
|
||||||
else
|
else
|
||||||
- log_debug("adjusting local clock by %fs", d);
|
- log_debug("adjusting local clock by %fs", d);
|
||||||
+ log_debug("adjusting local clock by %llims", (long long)(d * 1000));
|
+ log_debug("adjusting local clock by %lldms", (long long)(d * 1000));
|
||||||
|
|
||||||
#ifdef HAVE_ADJTIMEX
|
#ifdef HAVE_ADJTIMEX
|
||||||
int rc;
|
int rc;
|
||||||
@@ -614,14 +741,26 @@
|
@@ -582,12 +659,12 @@
|
||||||
|
if (wrlog) {
|
||||||
|
if (ppmfreq >= LOG_NEGLIGIBLE_ADJFREQ ||
|
||||||
|
ppmfreq <= -LOG_NEGLIGIBLE_ADJFREQ)
|
||||||
|
- log_info("adjusting clock frequency by %f to %fppm%s",
|
||||||
|
- ppmfreq, curfreq / 1e3 / (1LL << 32),
|
||||||
|
+ log_info("adjusting clock frequency by %lld to %lldppm%s",
|
||||||
|
+ (long long)ppmfreq, (long long)(curfreq / 1e3 / (1LL << 32)),
|
||||||
|
r ? "" : " (no drift file)");
|
||||||
|
else
|
||||||
|
- log_debug("adjusting clock frequency by %f to %fppm%s",
|
||||||
|
- ppmfreq, curfreq / 1e3 / (1LL << 32),
|
||||||
|
+ log_debug("adjusting clock frequency by %lld to %lldppm%s",
|
||||||
|
+ (long long)ppmfreq, (long long)(curfreq / 1e3 / (1LL << 32)),
|
||||||
|
r ? "" : " (no drift file)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -610,18 +687,36 @@
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d_to_tv(d, &tv);
|
||||||
|
+#ifdef CLOCK_REALTIME_HAS_LEAP_SECONDS
|
||||||
|
+ if (!add_leap_seconds(&tv.tv_sec)) {
|
||||||
|
+ /* You finally, really did it. You maniacs! You blew it up! God damn
|
||||||
|
+ you. God damn you all to hell. */
|
||||||
|
+ return; /* Removed leap seconds have no representation here. */
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
curtime.tv_usec += tv.tv_usec + 1000000;
|
||||||
curtime.tv_sec += tv.tv_sec - 1 + (curtime.tv_usec / 1000000);
|
curtime.tv_sec += tv.tv_sec - 1 + (curtime.tv_usec / 1000000);
|
||||||
curtime.tv_usec %= 1000000;
|
curtime.tv_usec %= 1000000;
|
||||||
|
|
||||||
+#if defined(__sortix__)
|
+#if defined(__sortix__)
|
||||||
+ struct timespec ts =
|
+ struct timespec ts = {
|
||||||
+ {
|
|
||||||
+ .tv_sec = curtime.tv_sec,
|
+ .tv_sec = curtime.tv_sec,
|
||||||
+ .tv_nsec = curtime.tv_usec * 1000
|
+ .tv_nsec = curtime.tv_usec * 1000
|
||||||
+ };
|
+ };
|
||||||
|
@ -569,38 +583,60 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
|
||||||
strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y",
|
strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y",
|
||||||
localtime(&tval));
|
localtime(&tval));
|
||||||
- log_info("set local clock to %s (offset %fs)", buf, d);
|
- log_info("set local clock to %s (offset %fs)", buf, d);
|
||||||
+ log_info("set local clock to %s (offset %llims)", buf, (long long)(d * 1000.0));
|
+ log_info("set local clock to %s (offset %lldms)", buf, (long long)(d * 1000.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static FILE *freqfp;
|
static FILE *freqfp;
|
||||||
@@ -632,6 +771,7 @@
|
@@ -632,6 +727,7 @@
|
||||||
int64_t current;
|
int64_t current;
|
||||||
int fd;
|
int fd;
|
||||||
double d;
|
double d;
|
||||||
+ long long lli;
|
+ long long lld;
|
||||||
|
|
||||||
fd = open(DRIFTFILE, O_RDWR);
|
fd = open(DRIFTFILE, O_RDWR);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
@@ -649,7 +789,8 @@
|
@@ -649,7 +745,8 @@
|
||||||
if (adjfreq(NULL, ¤t) == -1)
|
if (adjfreq(NULL, ¤t) == -1)
|
||||||
log_warn("adjfreq failed");
|
log_warn("adjfreq failed");
|
||||||
else if (current == 0 && freqfp) {
|
else if (current == 0 && freqfp) {
|
||||||
- if (fscanf(freqfp, "%lf", &d) == 1) {
|
- if (fscanf(freqfp, "%lf", &d) == 1) {
|
||||||
+ if (fscanf(freqfp, "%lli", &lli) == 1) {
|
+ if (fscanf(freqfp, "%lld", &lld) == 1) {
|
||||||
+ d = (double)lli;
|
+ d = (double)lld;
|
||||||
d /= 1e6; /* scale from ppm */
|
d /= 1e6; /* scale from ppm */
|
||||||
ntpd_adjfreq(d, 0);
|
ntpd_adjfreq(d, 0);
|
||||||
} else
|
} else
|
||||||
@@ -667,7 +808,8 @@
|
@@ -667,7 +764,8 @@
|
||||||
if (freqfp == NULL)
|
if (freqfp == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
rewind(freqfp);
|
rewind(freqfp);
|
||||||
- r = fprintf(freqfp, "%.3f\n", d * 1e6); /* scale to ppm */
|
- r = fprintf(freqfp, "%.3f\n", d * 1e6); /* scale to ppm */
|
||||||
+ long long lli = (long long)(d * 1e6);
|
+ long long lld = (long long)(d * 1e6);
|
||||||
+ r = fprintf(freqfp, "%lli\n", lli); /* scale to ppm */
|
+ r = fprintf(freqfp, "%lld\n", lld); /* scale to ppm */
|
||||||
if (r < 0 || fflush(freqfp) != 0) {
|
if (r < 0 || fflush(freqfp) != 0) {
|
||||||
if (warnonce) {
|
if (warnonce) {
|
||||||
log_warnx("can't write %s", DRIFTFILE);
|
log_warnx("can't write %s", DRIFTFILE);
|
||||||
|
@@ -901,8 +999,8 @@
|
||||||
|
clock_offset = cstatus->clock_offset < 0 ?
|
||||||
|
-1.0 * cstatus->clock_offset : cstatus->clock_offset;
|
||||||
|
if (clock_offset > 5e-7)
|
||||||
|
- printf(", clock offset is %.3fms\n",
|
||||||
|
- cstatus->clock_offset);
|
||||||
|
+ printf(", clock offset is %lldms\n",
|
||||||
|
+ (long long)cstatus->clock_offset);
|
||||||
|
else
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
@@ -952,8 +1050,8 @@
|
||||||
|
(long long)cpeer->next, (long long)cpeer->poll);
|
||||||
|
|
||||||
|
if (cpeer->trustlevel >= TRUSTLEVEL_BADPEER)
|
||||||
|
- printf(" %12.3fms %9.3fms %8.3fms\n", cpeer->offset,
|
||||||
|
- cpeer->delay, cpeer->jitter);
|
||||||
|
+ printf(" %12lldms %9lldms %8lldms\n", (long long)cpeer->offset,
|
||||||
|
+ (long long)cpeer->delay, (long long)cpeer->jitter);
|
||||||
|
else
|
||||||
|
printf(" ---- peer not valid ----\n");
|
||||||
|
|
||||||
diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.h ntpd/src/ntpd.h
|
diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.h ntpd/src/ntpd.h
|
||||||
--- ntpd.upstream/src/ntpd.h
|
--- ntpd.upstream/src/ntpd.h
|
||||||
+++ ntpd/src/ntpd.h
|
+++ ntpd/src/ntpd.h
|
||||||
|
@ -794,12 +830,21 @@ diff -Paur --no-dereference -- ntpd.upstream/src/util.c ntpd/src/util.c
|
||||||
double
|
double
|
||||||
gettime_corrected(void)
|
gettime_corrected(void)
|
||||||
{
|
{
|
||||||
diff -Paur --no-dereference -- ntpd.upstream/TODO.sortix ntpd/TODO.sortix
|
@@ -48,6 +50,17 @@
|
||||||
--- ntpd.upstream/TODO.sortix
|
if (gettimeofday(&tv, NULL) == -1)
|
||||||
+++ ntpd/TODO.sortix
|
fatal("gettimeofday");
|
||||||
@@ -0,0 +1,5 @@
|
|
||||||
+- nptd is unaware of leap seconds but Sortix is aware of them to the clock doesn't actually get synced correctly.
|
+/* PATCH: Sortix counts leap seconds in CLOCK_REALTIME but ntpd doesn't measure
|
||||||
+- Sortix needs `adjtime` or the time adjustments can be jarring.
|
+ leap seconds. Subtract them from the internal time to be UTC. */
|
||||||
+- Sortix needs `strptime`.
|
+#ifdef CLOCK_REALTIME_HAS_LEAP_SECONDS
|
||||||
+- Sortix needs `getservbyname` but worked around by hard-coding the ntp port.
|
+ while (!sub_leap_seconds(&tv.tv_sec)) {
|
||||||
+- The dns process wasn't being properly killed and awaited when exiting.
|
+ /* UTC cannot represent the current second because a leap second is
|
||||||
|
+ being inserted right now. Wait for it to pass and ignore it. */
|
||||||
|
+ sleep(1);
|
||||||
|
+ gettimeofday(&tv, NULL);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
return (gettime_from_timeval(&tv));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,5 +9,4 @@ UPSTREAM_SITE=https://ftp.openbsd.org/pub/OpenBSD/OpenNTPD
|
||||||
UPSTREAM_ARCHIVE=$ARCHIVE
|
UPSTREAM_ARCHIVE=$ARCHIVE
|
||||||
BUILD_SYSTEM=configure
|
BUILD_SYSTEM=configure
|
||||||
MAKE_VARS='V=1'
|
MAKE_VARS='V=1'
|
||||||
POST_INSTALL=tix-eradicate-libtool-la
|
|
||||||
VERSION_REGEX='([0-9]+\.[0-9]+p[0-9]+)'
|
VERSION_REGEX='([0-9]+\.[0-9]+p[0-9]+)'
|
||||||
|
|
|
@ -271,6 +271,17 @@ and such.
|
||||||
.Dv CLOCK_REALTIME
|
.Dv CLOCK_REALTIME
|
||||||
counts the number of seconds since the epoch including leap seconds, unlike
|
counts the number of seconds since the epoch including leap seconds, unlike
|
||||||
other operating systems and in violation of POSIX.
|
other operating systems and in violation of POSIX.
|
||||||
|
.Dv CLOCK_REALTIME_HAS_LEAP_SECONDS
|
||||||
|
definition advertises
|
||||||
|
.Dv CLOCK_REALTIME
|
||||||
|
contains leap seconds since the epoch in the TAI-10 format.
|
||||||
|
.Pp
|
||||||
|
.Xr sub_leap_seconds 3
|
||||||
|
converts timestamps from TAI-10 to UTC by subtracting the leap seconds, while
|
||||||
|
.Xr add_leap_seconds 3
|
||||||
|
converts timestamps from UTC TO TAI-10 by adding the leap seconds.
|
||||||
|
These functions are useful when communicating with other operating systems
|
||||||
|
either via the network or exchanged data files.
|
||||||
.Ss u_char, u_short, u_int, u_long
|
.Ss u_char, u_short, u_int, u_long
|
||||||
.Vt unsigned char ,
|
.Vt unsigned char ,
|
||||||
.Vt unsigned short ,
|
.Vt unsigned short ,
|
||||||
|
|
55
utils/date.c
55
utils/date.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2021 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2021, 2023 Jonas 'Sortie' Termansen.
|
||||||
* Copyright (c) 2022 Juhani 'nortti' Krekelä.
|
* Copyright (c) 2022 Juhani 'nortti' Krekelä.
|
||||||
* Copyright (c) 2022 Dennis Wölfing.
|
* Copyright (c) 2022 Dennis Wölfing.
|
||||||
*
|
*
|
||||||
|
@ -19,6 +19,8 @@
|
||||||
* Print or set system date and time.
|
* Print or set system date and time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -50,13 +52,18 @@ static char* astrftime(const char* format, const struct tm* tm)
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
const char* format = "+%a %b %e %H:%M:%S %Z %Y";
|
const char* date = NULL;
|
||||||
|
bool set = false;
|
||||||
|
const char* reference = NULL;
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
while ( (opt = getopt(argc, argv, "u")) != -1 )
|
while ( (opt = getopt(argc, argv, "d:r:s:u")) != -1 )
|
||||||
{
|
{
|
||||||
switch ( opt )
|
switch ( opt )
|
||||||
{
|
{
|
||||||
|
case 'd': date = optarg; break;
|
||||||
|
case 'r': reference = optarg; break;
|
||||||
|
case 's': date = optarg; set = true; break;
|
||||||
case 'u':
|
case 'u':
|
||||||
if ( setenv("TZ", "UTC0", 1) )
|
if ( setenv("TZ", "UTC0", 1) )
|
||||||
err(1, "setenv");
|
err(1, "setenv");
|
||||||
|
@ -65,20 +72,52 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( date && reference )
|
||||||
|
errx(1, "the -d and -r options are mutually incompatible");
|
||||||
|
if ( set && reference )
|
||||||
|
errx(1, "the -s and -r options are mutually incompatible");
|
||||||
|
|
||||||
|
const char* format = "+%a %b %e %H:%M:%S %Z %Y";
|
||||||
if ( 1 <= argc - optind )
|
if ( 1 <= argc - optind )
|
||||||
{
|
{
|
||||||
if ( argv[optind][0] != '+' )
|
if ( argv[optind][0] != '+' )
|
||||||
errx(1, "setting the system time is not implemented");
|
errx(1, "the format specifier must start with a +");
|
||||||
format = argv[optind];
|
format = argv[optind];
|
||||||
}
|
}
|
||||||
if ( 2 <= argc - optind )
|
if ( 2 <= argc - optind )
|
||||||
errx(1, "unexpected extra operand: %s", argv[optind + 1]);
|
errx(1, "unexpected extra operand: %s", argv[optind + 1]);
|
||||||
|
|
||||||
time_t current_time = time(NULL);
|
struct timespec moment = {0};
|
||||||
|
struct tm tm = {0};
|
||||||
|
|
||||||
struct tm tm;
|
if ( date )
|
||||||
if ( !localtime_r(¤t_time, &tm) )
|
{
|
||||||
err(1, "localtime_r(%ji)", (intmax_t) current_time);
|
memset(&tm, 0, sizeof(tm));
|
||||||
|
if ( !strptime(date, format + 1, &tm) )
|
||||||
|
errx(1, "date didn't match %s: %s", format + 1, date);
|
||||||
|
moment.tv_sec = timegm(&tm); // TODO: timelocal
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( reference )
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if ( stat(reference, &st) < 0 )
|
||||||
|
err(1, "%s", reference);
|
||||||
|
moment = st.st_mtim;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
clock_gettime(CLOCK_REALTIME, &moment);
|
||||||
|
if ( !localtime_r(&moment.tv_sec, &tm) )
|
||||||
|
err(1, "localtime_r(%ji)", (intmax_t) moment.tv_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( set )
|
||||||
|
{
|
||||||
|
if ( clock_settime(CLOCK_REALTIME, &moment) < 0 )
|
||||||
|
err(1, "clock_settime: CLOCK_REALTIME");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char* string = astrftime(format, &tm);
|
char* string = astrftime(format, &tm);
|
||||||
if ( !string )
|
if ( !string )
|
||||||
|
|
Loading…
Reference in New Issue