From 4481c75192779afa217bdd0852454040969351ca Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Thu, 5 Sep 2019 18:12:35 -0400 Subject: [PATCH] Improve current_zone(). Fixes #454 --- src/tz.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/tz.cpp b/src/tz.cpp index ea7db65..a395108 100644 --- a/src/tz.cpp +++ b/src/tz.cpp @@ -3692,16 +3692,26 @@ tzdb::current_zone() const CONSTDATA auto timezone = "/etc/localtime"; if (lstat(timezone, &sb) == 0 && S_ISLNK(sb.st_mode) && sb.st_size > 0) { using namespace std; - string result; char rp[PATH_MAX+1] = {}; - if (readlink(timezone, rp, sizeof(rp)-1) > 0) - result = string(rp); - else - throw system_error(errno, system_category(), "readlink() failed"); - - const size_t pos = result.find(get_tz_dir()); - if (pos != result.npos) - result.erase(0, get_tz_dir().size() + 1 + pos); + if (realpath(timezone, rp) == nullptr) + throw system_error(errno, system_category(), "realpath() failed"); +#if HAS_STRING_VIEW + string_view result = rp; + CONSTDATA string_view zoneinfo = "/zoneinfo/"; + const size_t pos = result.rfind(zoneinfo); + if (pos == result.npos) + throw runtime_error( + "current_zone() failed to find \"/zoneinfo/\" in " + string(result)); + result.remove_prefix(pos + zoneinfo.size()); +#else + string result = rp; + CONSTDATA char zoneinfo[] = "/zoneinfo/"; + const size_t pos = result.rfind(zoneinfo); + if (pos == result.npos) + throw runtime_error( + "current_zone() failed to find \"/zoneinfo/\" in " + result); + result.erase(0, pos + sizeof(zoneinfo) - 1); +#endif return locate_zone(result); } }