Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 6 Aug 2018 10:46:42 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        Ian Lepore <ian@freebsd.org>, Warner Losh <imp@bsdimp.com>,  "Rodney W. Grimes" <rgrimes@freebsd.org>, Conrad Meyer <cem@freebsd.org>,  src-committers <src-committers@freebsd.org>, svn-src-all@freebsd.org,  svn-src-head@freebsd.org
Subject:   Re: svn commit: r337334 - head/lib/libc/sys
Message-ID:  <20180806095604.J860@besplex.bde.org>
In-Reply-To: <20180806074507.E920@besplex.bde.org>
References:  <201808042208.w74M8OmD057603@repo.freebsd.org>  <201808042224.w74MOgLi095274@pdx.rh.CN85.dnsmgr.net>  <CANCZdfpWh25X%2BkKsbrdNY697Ex%2BxG95crVRgKqVQpfrqZO_CoA@mail.gmail.com> <1533478958.9860.18.camel@freebsd.org> <20180806074507.E920@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 6 Aug 2018, Bruce Evans wrote:

> ...
> I forgot about FAT times, and only remembered that utc_offset() was used
> for RTC drivers.  I thought that utc_offset() is 0 unless something sets
> the timezone to nonzero or the RTC is on local time (wall_cmos_clock case).
> However, since the kernel needs the timezone for FAT times, it must be
> known even if the RTC is on UTC time.  Now I don't see how FAT times can
> even work unless the wall_cmos_clock.  They are just the UTC minus
> utc_offset(), where utc_offset() is
>
> 	(tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0))
>
> Here wall_cmos_clock is only for managing the RTC offset.  It must be 0
> unless the RTC is on local time.  But then either FAT times or RTC times
> must be broken except in the Greenwich meridian.  Otherwise, tz_minuteswest
> must be nonzero to ajust FAT times right, but this makes utc_offset()
> unusable for the RTC offset.

I verified the brokenness:
- adjkerntz() normally leaves tz_minuteswest as 0.  I verified that it does
   this when there is a nonzero dst adjustment.  dst adjustments are folded
   into machdep.adjkerntz.
- when wall_cmos_clock == 0, adjkerntz(8) does little or nothing, so all
   adjustments are 0, so utc_offset() is 0, so FAT times are broken except
   in the Greenwich meridian.

The broken FAT times are not completely obvious, since getting and setting
them use the same wrong offset of 0, so the times appear to be correct when
displayed on FreeBSD.  The are only obviously wrong when displayed on another
system with non-broken FAT times, perhaps by rebooting to the other system
or by moving removable media to such a system.

FAT times are used by other file systems.  I checked this in FreeBSD-9
so as to find axed file systems.  The were used by smbfs, nwfs and msdosfs.
Now they are only used by msdosfs.  I never liked de-deduplicating their
implementation into an over-engineered version with especially excessive
handling for leap years.  Leap year handling is unimportant compared with
offset handling.

tz_minuteswest is used by compatibility code.  It cannot usefully be
removed from the native version, since non-native syscalls use it and
non-native applications might use it.  Of course, it must have a correct
value to work in compatibility.  Its normal value of 0 breaks compatibility
code much like the bugs in utc_offset() breaks FAT time.  It is used in the
following compatibility code:
- amd64 linux32 linux_gettimeofday().  Like native gettimeofday().  It also
   reconstructs the dstflag part of the timezone struct.  If linux drops this,
   then strict compatiility requires the support to depend on the linux version.
- amd64 linux32 linux_settimeofday().  Like native settimeofday().  Has
   invisible reference to tz_minuteswest hidden in assignment of timezones.
   I only grepped for tz_minuteswest and only checked this indirect reference.
- freebsd32 freebsd32_gettimeofday().  Similarly, except we control it, so
   can avoid needing version checks by not dropping support.
- dev/tws/tws_services.h.  This uses utc_offset() for FreeBSD-7 and later,
   and its reference to tz_minuteswest is only explicit for older versions
   where it open-codes utc_offset() with bug for bug compatibility except for
   adding style bugs.
- smbfs.  This uses FAT times, and in nearby code it uses tzoff for the offset
   and has commented-out code with an open-coded fully-buggy utc_offset().
- ibcs2 xenix_ftime().  This is similar to gettimeofday().

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20180806095604.J860>