[tz] make rearguard_tarballs fails on macOS

Robert Elz kre at munnari.OZ.AU
Sun Oct 18 21:10:24 UTC 2020

    Date:        Sun, 18 Oct 2020 13:11:43 -0700
    From:        Paul Eggert <eggert at cs.ucla.edu>
    Message-ID:  <519bc685-8844-b341-31d3-91f5d8f2cb91 at cs.ucla.edu>

  | <https://man.netbsd.org/timeval.3> says struct bintime
  | is meant to be used in the kernel only.

Yes ... but nothing enforces that, and unenforced rules
exist purely for the purposes of being broken, right?

  | I wonder how a nanosecond-resolution timestamp would
  | be converted to bintime and back without rounding error,

The static inline functions used are in <sys/time.h>


but they don't.   If you were to do that sequence you'd
typically loose a ns each time around.

So we don't do that, if we have timespecs we work in timespecs,
converting them backwards and forwards would be foolish.

For parsedate, we start with text, so we can generate anything.
Depending upon the input, we may lose precision whatever we convert
that into, if the text form has sufficient precision - converting
something with 15 digits after the radix into a timespec you have to
lose the low order).

Generating the format with the greatest precision available
means we're less likely to lose - to use it for touch we'll
need to convert to a timespec (and for some filesystems
perhaps eventually to a timeval - or for others even to a time_t)
and we might lose some of the accuracy then, but parsedate()
(or some new variant thereof) output can also be used for other
things than feeding to filesystem sys calls.


ps: here's a little userland (NetBSD buildable) program,
with absolutely no error checking, which demonstrates the
rounding issue.

#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>

main(int argc, char *argv[])
	struct timespec ts, nts;
	struct bintime bt;

	ts.tv_sec = strtol(argv[1], 0, 0);
	ts.tv_nsec = strtol(argv[2], 0, 0);

	timespec2bintime(&ts, &bt);
	bintime2timespec(&bt, &nts);

	printf("%jd.%9.9ju -> %jx.%8.8jx -> %jd.%9.9ju",
		(intmax_t)ts.tv_sec, (intmax_t)ts.tv_nsec,
		(intmax_t)bt.sec, (intmax_t)bt.frac,
		(intmax_t)nts.tv_sec, (intmax_t)nts.tv_nsec);

	if (ts.tv_nsec != nts.tv_nsec)
		printf("   %jd ns change", (intmax_t)(nts.tv_nsec - ts.tv_nsec));
	return 0;

More information about the tz mailing list