Add sub_leap_seconds(3) and add_leap_seconds(3).
Advertise leap seconds being counted via CLOCK_REALTIME_HAS_LEAP_SECONDS.
This commit is contained in:
parent
97c57ca604
commit
9033153c47
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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 ,
|
||||||
|
|
Loading…
Reference in New Issue