https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125467
--- Comment #1 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jonathan Wakely <[email protected]>: https://gcc.gnu.org/g:cc195f7b11a4061ff8b0261372faadbef22791ee commit r17-2048-gcc195f7b11a4061ff8b0261372faadbef22791ee Author: Jonathan Wakely <[email protected]> Date: Sat Jun 6 21:44:56 2026 +0100 libstdc++: Use realpath for /etc/localtime symlink [PR125467] 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 is what HowardHinnant/date does). 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. We could fall back to filesystem::weakly_canonical for this case, but this patch leaves that for a future change, if it turns out to be needed by any users. - When /etc/localtime is a symlink to /usr/share/zoneinfo/Foo/Bar where "Foo/Bar" is a valid zone in the chrono::tzdb object, but the Bar file is another symlink to ./Baz where "Foo/Bar" is also a valid zone. With the previous implementation current_zone() would have returned the "Foo/Bar" zone. With this change it would return "Foo/Baz". I don't think it's realistic to have two zones which are distinct zones (not a Zone and a Link to it) but where one of them is defined on-disk using a symlink to the other. libstdc++-v3/ChangeLog: PR libstdc++/125467 * src/c++20/tzdb.cc (tzdb::current_zone): Use realpath to resolve the /etc/localtime symlink instead of readlink. Reviewed-by: Tomasz KamiÅski <[email protected]>
