On Mon, 29 Jun 2026 at 11:31, Jonathan Wakely <[email protected]> wrote:
>
> On Mon, 29 Jun 2026 at 10:21, Tomasz Kaminski <[email protected]> wrote:
> >
> >
> >
> > On Mon, Jun 29, 2026 at 10:34 AM Jonathan Wakely <[email protected]> 
> > wrote:
> >>
> >>
> >>
> >> On Mon, 29 Jun 2026, 07:23 Tomasz Kaminski, <[email protected]> wrote:
> >>>
> >>>
> >>>
> >>> On Fri, Jun 26, 2026 at 7:02 PM Jonathan Wakely <[email protected]> 
> >>> wrote:
> >>>>
> >>>> Although the systemd docs say that /etc/localtime should be a symlink to
> >>>> one of the zoneinfo files, some systems make it a symlink to another
> >>>> path, where that second path is a symlink to a zoneinfo file (e.g. if
> >>>> /etc is mounted read-only then /etc/localtime can be a symlink to
> >>>> another symlink on a writable disk, so that the system timezone can be
> >>>> altered by re-pointing the symlink on the writable disk).
> >>>>
> >>>> In that case, using readlink would only tell us the location of the
> >>>> second symlink, not which zoneinfo file it points to. Therefore, we
> >>>> would not be able to extract a valid time zone name from the path, and
> >>>> chrono::current_zone() would fail.
> >>>>
> >>>> To support multiple symlinks we could recursively keep resolving
> >>>> symlinks with readlink until we reach a path from which we can extract a
> >>>> zone name. Alternatively, we can just use realpath to resolve all
> >>>> symlinks to a physical file, which will be . This means we only need one 
> >>>> system call and
> >>>> don't need the extra complexity of calling readlink in a loop.
> >>>>
> >>>> The realpath system call also removes redunant slashes, so we can remove
> >>>> the code that did that manually.
> >>>>
> >>>> The possible downsides of this approach that I'm aware of are:
> >>>>
> >>>> - When /etc/localtime is a symlink to /invalid/Europe/London but that
> >>>>   file doesn't exist. With the previous implementation we would have
> >>>>   resolved that symlink to the zone "Europe/London" as long as that name
> >>>>   is known to the current chrono::tzdb object. With this change, we
> >>>>   won't get a valid zone name and current_zone() will fail. I'm not sure
> >>>>   how realistic this case is. It might be plausible if libstdc++ is
> >>>>   using the embedded static copy of tzdata.zi and there are no zoneinfo
> >>>>   files on disk at all. In that case the system might still use
> >>>>   /etc/localtime to name a zone, even though the symlink is dangling.
> >>>>   Maybe we could fall back to filesystem::weakly_canonical for this
> >>>>   case?
> >>>
> >>> I would be concerned about doing that silently, as this could lead to
> >>> non-local errors in the deployed environment are extremely hard to debug.
> >>> What I mean is the situation where tzdata should be mounted.
> >>> If the mounting fails, we will resolve the zone without issue,
> >>
> >>
> >> Will we? We might resolve a name, but it still needs to be looked up in 
> >> tzdb to find a time_zone. If there's no tzdata that will fail (unless it's 
> >> one of the zones that is always present like UTC and GMT).
> >
> > From my reading, we fail first to the embeded static tzdb data if opening 
> > tzdb file fails:
> >       tzdata_stream() : istream(nullptr)
> >       {
> >         if (string path = zoneinfo_file(tzdata_file); !path.empty())
> >         {
> >           filebuf fbuf;
> >           if (fbuf.open(path, std::ios::in))
> >             {
> >               std::construct_at(&fb, std::move(fbuf));
> >               this->init(&fb);
> >               return;
> >             }
> >         }
> >         std::construct_at(&sb);
> >         this->init(&sb);
> >       }
> > We can successfully look up the zone if we know about it, even if we cannot 
> > read the zone database.
>
> Right - but that seems orthogonal to chrono::current_zone(), and I
> don't think it is an argument against using weakly_canonical to deal
> with dangling /etc/localtime symlinks.
>
> The semantics of current_zone are to decide on a name, then use
> locate_zone(str) to look that name up (and maybe retry if the lookup
> fails and we can try a different name). The presence or absence of a
> valid tzdb object affects the locate_zone(str) step but I don't think
> it should affect the process for deciding on a name. With the code on
> trunk today, we can still extract a name from a dangling symlink (but
> we can't extract a name from a chain of two or more symlinks). With my
> proposed patch we would be able to extract a name from a chain of
> symlinks, but would not be able to get anything from dangling
> symlinks.
>
> > Maybe I am missing something here.
> >
> >>
> >>
> >>> and then only
> >>> If the data requires updating, the update will fail. From that 
> >>> perspective I much
> >>> more prefer loud failure.
> >>
> >>
> >> A dangling symlink to the Etc/GMT or UTC zone would always work OK even if 
> >> there is no tzdata, and maybe that's the expected behaviour for some 
> >> system.
> >
> > This system would be better served by having TZDB disabled, if that is the 
> > consistent behavior.
>
> That requires a custom build of libstdc++.so whereas a minimal
> container could use the system libstdc++.so and remove all the tzdata
> files to save disk space.

Which is a supported use case in Fedora (since F39, and so also true
for RHEL 10):
https://fedoraproject.org/wiki/Changes/AllowRemovalOfTzdata

But libstdc++ doesn't need to cope with dangling symlinks to make the
"Etc/UTC" case work because if we don't find anything for
/etc/localtime then we default to UTC anyway:
https://gcc.gnu.org/cgit/gcc/commit/?id=4abd5bc600193e821fbc41995a0b8d9ea42b42c3

Reply via email to