You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
3.5 KiB
165 lines
3.5 KiB
/* |
|
* Copyright (C) 2011-2013 Daniel Scharrer |
|
* |
|
* This software is provided 'as-is', without any express or implied |
|
* warranty. In no event will the author(s) be held liable for any damages |
|
* arising from the use of this software. |
|
* |
|
* Permission is granted to anyone to use this software for any purpose, |
|
* including commercial applications, and to alter it and redistribute it |
|
* freely, subject to the following restrictions: |
|
* |
|
* 1. The origin of this software must not be misrepresented; you must not |
|
* claim that you wrote the original software. If you use this software |
|
* in a product, an acknowledgment in the product documentation would be |
|
* appreciated but is not required. |
|
* 2. Altered source versions must be plainly marked as such, and must not be |
|
* misrepresented as being the original software. |
|
* 3. This notice may not be removed or altered from any source distribution. |
|
*/ |
|
|
|
#include "util/time.hpp" |
|
|
|
#include "configure.hpp" |
|
|
|
#if INNOEXTRACT_HAVE_TIMEGM || INNOEXTRACT_HAVE_MKGMTIME \ |
|
|| INNOEXTRACT_HAVE_GMTIME_R || INNOEXTRACT_HAVE_GMTIME_S |
|
#include <time.h> |
|
#endif |
|
|
|
#if !INNOEXTRACT_HAVE_TIMEGM |
|
#include <stdlib.h> |
|
#endif |
|
|
|
#if INNOEXTRACT_HAVE_UTIMES |
|
#include <sys/time.h> |
|
#elif defined(_WIN32) |
|
#include <windows.h> |
|
#else |
|
#include <boost/filesystem/operations.hpp> |
|
#endif |
|
|
|
namespace util { |
|
|
|
std::time_t parse_time(std::tm tm) { |
|
|
|
#if INNOEXTRACT_HAVE_TIMEGM |
|
|
|
return timegm(&tm); |
|
|
|
#elif INNOEXTRACT_HAVE_MKGMTIME |
|
|
|
return _mkgmtime(&tm); |
|
|
|
#else |
|
|
|
char * tz = getenv("TZ"); |
|
setenv("TZ", "UTC", 1); |
|
tzset(); |
|
|
|
std::time_t ret = std::mktime(&tm); |
|
|
|
if(tz) { |
|
setenv("TZ", tz, 1); |
|
} else { |
|
unsetenv("TZ"); |
|
} |
|
tzset(); |
|
|
|
return ret; |
|
|
|
#endif |
|
|
|
} |
|
|
|
std::tm format_time(time_t t) { |
|
|
|
std::tm ret; |
|
|
|
#if INNOEXTRACT_HAVE_GMTIME_R |
|
|
|
gmtime_r(&t, &ret); |
|
|
|
#elif INNOEXTRACT_HAVE_GMTIME_S |
|
|
|
_gmtime_s(&ret, &t); |
|
|
|
#else |
|
|
|
// Hope that this is threadsafe... |
|
ret = *gmtime(&t); |
|
|
|
#endif |
|
|
|
return ret; |
|
} |
|
|
|
time_t to_local_time(time_t t) { |
|
|
|
// Format time as UTC ... |
|
std::tm time = format_time(t); |
|
|
|
//... and interpret it as local time |
|
return std::mktime(&time); |
|
} |
|
|
|
#if defined(_WIN32) |
|
static HANDLE open_file(LPCSTR name) { |
|
return CreateFileA(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); |
|
} |
|
static HANDLE open_file(LPCWSTR name) { |
|
return CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); |
|
} |
|
#endif |
|
|
|
bool set_file_time(const boost::filesystem::path & path, std::time_t t, uint32_t nsec) { |
|
|
|
#if INNOEXTRACT_HAVE_UTIMES |
|
|
|
struct timeval times[2]; |
|
|
|
times[0].tv_sec = t; |
|
times[0].tv_usec = long(nsec / 1000); |
|
times[1] = times[0]; |
|
|
|
return (utimes(path.c_str(), times) == 0); |
|
|
|
#elif defined(_WIN32) |
|
|
|
// Prevent unused function warnings |
|
(void)(HANDLE(*)(LPCSTR))open_file; |
|
(void)(HANDLE(*)(LPCWSTR))open_file; |
|
|
|
HANDLE handle = open_file(path.c_str()); |
|
if(handle == INVALID_HANDLE_VALUE) { |
|
return false; |
|
} |
|
|
|
// Convert the std::time_t and nanoseconds to a FILETIME struct |
|
static const int64_t FiletimeOffset = 0x19DB1DED53E8000ll; |
|
int64_t time = int64_t(t) * 10000000 + int64_t(nsec) / 100; |
|
time += FiletimeOffset; |
|
FILETIME filetime; |
|
filetime.dwLowDateTime = DWORD(time); |
|
filetime.dwHighDateTime = DWORD(time >> 32); |
|
|
|
bool ret = SetFileTime(handle, &filetime, &filetime, &filetime); |
|
CloseHandle(handle); |
|
|
|
return ret; |
|
|
|
#else |
|
|
|
try { |
|
(void)nsec; // sub-second precision not supported by boost |
|
boost::filesystem::last_write_time(path, t); |
|
return true; |
|
} catch(...) { |
|
return false; |
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|
} // namespace util
|
|
|