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
