mirror of
https://github.com/HowardHinnant/date.git
synced 2024-12-27 00:14:07 +08:00
Do a runtime test for realpath vs readlink
* Ubuntu needs to use readlink under current_zone and most everyone else needs realpath. Attempting to make everyone happy with this commit.
This commit is contained in:
parent
c8d311f6f1
commit
9a0ee25428
87
src/tz.cpp
87
src/tz.cpp
@ -3673,6 +3673,56 @@ tzdb::current_zone() const
|
|||||||
|
|
||||||
#else // !_WIN32
|
#else // !_WIN32
|
||||||
|
|
||||||
|
#if HAS_STRING_VIEW
|
||||||
|
|
||||||
|
static
|
||||||
|
std::string_view
|
||||||
|
extract_tz_name(char const* rp)
|
||||||
|
{
|
||||||
|
using namespace std;
|
||||||
|
string_view result = rp;
|
||||||
|
CONSTDATA string_view zoneinfo = "zoneinfo";
|
||||||
|
size_t pos = result.rfind(zoneinfo);
|
||||||
|
if (pos == result.npos)
|
||||||
|
throw runtime_error(
|
||||||
|
"current_zone() failed to find \"zoneinfo\" in " + string(result));
|
||||||
|
pos = result.find('/', pos);
|
||||||
|
result.remove_prefix(pos + 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // !HAS_STRING_VIEW
|
||||||
|
|
||||||
|
static
|
||||||
|
std::string
|
||||||
|
extract_tz_name(char const* rp)
|
||||||
|
{
|
||||||
|
using namespace std;
|
||||||
|
string result = rp;
|
||||||
|
CONSTDATA char zoneinfo[] = "zoneinfo";
|
||||||
|
size_t pos = result.rfind(zoneinfo);
|
||||||
|
if (pos == result.npos)
|
||||||
|
throw runtime_error(
|
||||||
|
"current_zone() failed to find \"zoneinfo\" in " + result);
|
||||||
|
pos = result.find('/', pos);
|
||||||
|
result.erase(0, pos + 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HAS_STRING_VIEW
|
||||||
|
|
||||||
|
static
|
||||||
|
bool
|
||||||
|
sniff_realpath(const char* timezone)
|
||||||
|
{
|
||||||
|
using namespace std;
|
||||||
|
char rp[PATH_MAX+1] = {};
|
||||||
|
if (realpath(timezone, rp) == nullptr)
|
||||||
|
throw system_error(errno, system_category(), "realpath() failed");
|
||||||
|
auto result = extract_tz_name(rp);
|
||||||
|
return result != "posixrules";
|
||||||
|
}
|
||||||
|
|
||||||
const time_zone*
|
const time_zone*
|
||||||
tzdb::current_zone() const
|
tzdb::current_zone() const
|
||||||
{
|
{
|
||||||
@ -3692,31 +3742,22 @@ tzdb::current_zone() const
|
|||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
CONSTDATA auto timezone = "/etc/localtime";
|
CONSTDATA auto timezone = "/etc/localtime";
|
||||||
if (lstat(timezone, &sb) == 0 && S_ISLNK(sb.st_mode) && sb.st_size > 0) {
|
if (lstat(timezone, &sb) == 0 && S_ISLNK(sb.st_mode) && sb.st_size > 0)
|
||||||
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
static const bool use_realpath = sniff_realpath(timezone);
|
||||||
char rp[PATH_MAX+1] = {};
|
char rp[PATH_MAX+1] = {};
|
||||||
if (realpath(timezone, rp) == nullptr)
|
if (use_realpath)
|
||||||
throw system_error(errno, system_category(), "realpath() failed");
|
{
|
||||||
#if HAS_STRING_VIEW
|
if (realpath(timezone, rp) == nullptr)
|
||||||
string_view result = rp;
|
throw system_error(errno, system_category(), "realpath() failed");
|
||||||
CONSTDATA string_view zoneinfo = "zoneinfo";
|
}
|
||||||
size_t pos = result.rfind(zoneinfo);
|
else
|
||||||
if (pos == result.npos)
|
{
|
||||||
throw runtime_error(
|
if (readlink(timezone, rp, sizeof(rp)-1) <= 0)
|
||||||
"current_zone() failed to find \"zoneinfo\" in " + string(result));
|
throw system_error(errno, system_category(), "readlink() failed");
|
||||||
pos = result.find('/', pos);
|
}
|
||||||
result.remove_prefix(pos + 1);
|
return locate_zone(extract_tz_name(rp));
|
||||||
#else
|
|
||||||
string result = rp;
|
|
||||||
CONSTDATA char zoneinfo[] = "zoneinfo";
|
|
||||||
size_t pos = result.rfind(zoneinfo);
|
|
||||||
if (pos == result.npos)
|
|
||||||
throw runtime_error(
|
|
||||||
"current_zone() failed to find \"zoneinfo\" in " + result);
|
|
||||||
pos = result.find('/', pos);
|
|
||||||
result.erase(0, pos + 1);
|
|
||||||
#endif
|
|
||||||
return locate_zone(result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// On embedded systems e.g. buildroot with uclibc the timezone is linked
|
// On embedded systems e.g. buildroot with uclibc the timezone is linked
|
||||||
|
Loading…
x
Reference in New Issue
Block a user