1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012-2022 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// Function to return the current date/time as a string.
#ifndef OPENVPN_TIME_TIMESTR_H
#define OPENVPN_TIME_TIMESTR_H
#include <string>
#include <cstring> // for std::strlen and std::memset
#include <time.h>
#include <stdio.h>
#include <ctype.h>
#include <cstdint> // for std::uint64_t
#include <openvpn/common/platform.hpp>
#include <openvpn/common/size.hpp>
#include <openvpn/common/string.hpp>
#if defined(OPENVPN_PLATFORM_WIN)
#include <windows.h>
#else
#include <sys/time.h>
#endif
namespace openvpn {
#if defined(OPENVPN_PLATFORM_WIN)
inline std::string date_time(const time_t now)
{
struct tm *lt = localtime(&now);
char *ret = asctime(lt);
const size_t len = std::strlen(ret);
if (len > 0 && ret[len - 1] == '\n')
ret[len - 1] = '\0';
return ret;
}
inline std::string date_time()
{
const time_t now = time(NULL);
return date_time(now);
}
inline std::string date_time_store_time_t(time_t &save)
{
save = time(NULL);
return date_time(save);
}
#else
inline std::string date_time(const time_t t)
{
struct tm lt;
char buf[64];
std::memset(<, 0, sizeof(lt));
if (!localtime_r(&t, <))
return "LOCALTIME_ERROR";
if (!asctime_r(<, buf))
return "ASCTIME_ERROR";
const size_t len = std::strlen(buf);
if (len > 0 && buf[len - 1] == '\n')
buf[len - 1] = '\0';
return std::string(buf);
}
inline std::string date_time_utc(const time_t t)
{
struct tm lt;
char buf[64];
std::memset(<, 0, sizeof(lt));
if (!gmtime_r(&t, <))
return "GMTIME_ERROR";
if (!asctime_r(<, buf))
return "ASCTIME_ERROR";
const size_t len = std::strlen(buf);
if (len > 0 && buf[len - 1] == '\n')
buf[len - 1] = '\0';
return std::string(buf);
}
// msecs == false : Tue Feb 17 01:24:30 2015
// msecs == true : Tue Feb 17 01:24:30.123 2015
inline std::string date_time(const struct timeval *tv, const bool msecs)
{
const std::string dt = date_time(tv->tv_sec);
if (msecs)
{
// find correct position in string to insert milliseconds
const size_t pos = dt.find_last_of(':');
if (pos != std::string::npos
&& pos + 3 < dt.length()
&& string::is_digit(dt[pos + 1])
&& string::is_digit(dt[pos + 2])
&& string::is_space(dt[pos + 3]))
{
char ms[5];
::snprintf(ms, sizeof(ms), ".%03u", static_cast<unsigned int>(tv->tv_usec / 1000));
return dt.substr(0, pos + 3) + ms + dt.substr(pos + 3);
}
}
return dt;
}
inline std::string nanosec_time_to_string(const std::uint64_t ns_time)
{
const std::uint64_t sec = ns_time / std::uint64_t(1000000000);
const std::uint64_t ns = ns_time % std::uint64_t(1000000000);
const std::string dt = date_time_utc(sec);
// find correct position in string to insert nanoseconds
const size_t pos = dt.find_last_of(':');
if (pos != std::string::npos
&& pos + 3 < dt.length()
&& string::is_digit(dt[pos + 1])
&& string::is_digit(dt[pos + 2])
&& string::is_space(dt[pos + 3]))
{
char ms[11];
::snprintf(ms, sizeof(ms), ".%09u", (unsigned int)ns);
return dt.substr(0, pos + 3) + ms + dt.substr(pos + 3);
}
return dt;
}
inline std::string date_time()
{
struct timeval tv;
if (::gettimeofday(&tv, nullptr) < 0)
{
tv.tv_sec = 0;
tv.tv_usec = 0;
}
return date_time(&tv, true);
}
inline std::string date_time_store_time_t(time_t &save)
{
struct timeval tv;
if (::gettimeofday(&tv, nullptr) < 0)
{
tv.tv_sec = 0;
tv.tv_usec = 0;
}
save = tv.tv_sec;
return date_time(&tv, true);
}
#endif
inline std::string date_time_rfc822(const time_t t)
{
struct tm lt;
char buf[64];
#if defined(OPENVPN_PLATFORM_WIN)
if (gmtime_s(<, &t))
return "";
// MinGW doesn't yet support %T, so use %H:%M:%S
// https://sourceforge.net/p/mingw-w64/bugs/793/
if (!strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", <))
return "";
#else
if (!gmtime_r(&t, <))
return "";
if (!strftime(buf, sizeof(buf), "%a, %d %b %Y %T %Z", <))
return "";
#endif
return std::string(buf);
}
inline std::string date_time_rfc822()
{
return date_time_rfc822(::time(nullptr));
}
} // namespace openvpn
#endif
|