summaryrefslogtreecommitdiff
path: root/zen
diff options
context:
space:
mode:
Diffstat (limited to 'zen')
-rw-r--r--zen/file_access.cpp9
-rw-r--r--zen/format_unit.cpp72
-rw-r--r--zen/format_unit.h8
3 files changed, 82 insertions, 7 deletions
diff --git a/zen/file_access.cpp b/zen/file_access.cpp
index a66cbc6b..d093d7ff 100644
--- a/zen/file_access.cpp
+++ b/zen/file_access.cpp
@@ -232,6 +232,7 @@ std::uint64_t zen::getFreeDiskSpace(const Zstring& path) //throw FileError, retu
nullptr, //__out_opt PULARGE_INTEGER lpTotalNumberOfBytes,
nullptr)) //__out_opt PULARGE_INTEGER lpTotalNumberOfFreeBytes
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot determine free disk space for %x."), L"%x", fmtPath(path)), L"GetDiskFreeSpaceEx");
+ //succeeds even if path is not yet existing!
//return 0 if info is not available: "The GetDiskFreeSpaceEx function returns zero for lpFreeBytesAvailable for all CD requests"
return get64BitUInt(bytesFree.LowPart, bytesFree.HighPart);
@@ -2233,9 +2234,11 @@ InSyncAttributes copyFileOsSpecific(const Zstring& sourceFile, //throw FileError
struct ::stat sourceInfo = {};
if (::fstat(fileIn.getHandle(), &sourceInfo) != 0)
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(sourceFile)), L"fstat");
-
- const int fdTarget = ::open(targetFile.c_str(), O_WRONLY | O_CREAT | O_EXCL,
- sourceInfo.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); //analog to "cp" which copies "mode" (considering umask) by default
+
+ const mode_t mode = sourceInfo.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); //analog to "cp" which copies "mode" (considering umask) by default
+ //it seems we don't need S_IWUSR, not even for the setFileTime() below! (tested with source file having different user/group!)
+
+ const int fdTarget = ::open(targetFile.c_str(), O_WRONLY | O_CREAT | O_EXCL, mode);
//=> need copyItemPermissions() only for "chown" and umask-agnostic permissions
if (fdTarget == -1)
{
diff --git a/zen/format_unit.cpp b/zen/format_unit.cpp
index cfaaa329..cb92f1e4 100644
--- a/zen/format_unit.cpp
+++ b/zen/format_unit.cpp
@@ -8,7 +8,7 @@
#include "basic_math.h"
#include "i18n.h"
#include "time.h"
-#include <cwchar> //swprintf
+#include <cwchar> //swprintf
#include <ctime>
#include <cstdio>
@@ -293,7 +293,7 @@ std::wstring zen::utcToLocalTimeString(std::int64_t utcTime)
auto errorMsg = [&] { return _("Error") + L" (time_t: " + numberTo<std::wstring>(utcTime) + L")"; };
#ifdef ZEN_WIN
- FILETIME lastWriteTimeUtc = timetToFileTime(utcTime); //convert ansi C time to FILETIME
+ const FILETIME lastWriteTimeUtc = timetToFileTime(utcTime); //convert ansi C time to FILETIME
SYSTEMTIME systemTimeLocal = {};
@@ -342,3 +342,71 @@ std::wstring zen::utcToLocalTimeString(std::int64_t utcTime)
std::wstring dateString = formatTime<std::wstring>(L"%x %X", loc);
return !dateString.empty() ? dateString : errorMsg();
}
+
+
+#ifdef ZEN_WIN_VISTA_AND_LATER
+Opt<std::int64_t> zen::mtpVariantTimetoUtc(double localVarTime) //returns empty on error
+{
+ SYSTEMTIME localSystemTime = {};
+ if (!::VariantTimeToSystemTime(localVarTime, //_In_ DOUBLE vtime,
+ &localSystemTime)) //_Out_ LPSYSTEMTIME lpSystemTime
+ return NoValue();
+
+ /*
+ Windows Explorer isn't even consistent within itself: the modification time shown in the details list is calculated differently than the
+ one shown in MTP file properties => different result shown for files from a DST interval distinct from the current one.
+ -> Variant 1 matches the calculation of Explorer's details list and produces stable results irrespective of currently selected DST
+ -> Explorer uses different algorithms for MTP and FAT file systems! FAT's local time jumps between DST intervals in Explorer (since Vista)!
+ */
+#if 1
+ SYSTEMTIME utcSystemTime = {};
+ if (!::TzSpecificLocalTimeToSystemTime(nullptr, //_In_opt_ LPTIME_ZONE_INFORMATION lpTimeZoneInformation,
+ &localSystemTime, //_In_ LPSYSTEMTIME lpLocalTime,
+ &utcSystemTime)) //_Out_ LPSYSTEMTIME lpUniversalTime
+ return NoValue();
+
+ FILETIME utcFiletime = {};
+ if (!::SystemTimeToFileTime(&utcSystemTime, //_In_ const SYSTEMTIME *lpSystemTime,
+ &utcFiletime)) //_Out_ LPFILETIME lpFileTime
+ return NoValue();
+
+#else
+ FILETIME localFiletime = {};
+ if (!::SystemTimeToFileTime(&localSystemTime, //_In_ const SYSTEMTIME *lpSystemTime,
+ &localFiletime)) //_Out_ LPFILETIME lpFileTime
+ return NoValue();
+
+ FILETIME utcFiletime = {};
+ if (!LocalFileTimeToFileTime(&localFiletime, //_In_ const FILETIME *lpLocalFileTime,
+ &utcFiletime)) //_Out_ LPFILETIME lpFileTime
+ return NoValue();
+
+#endif
+
+ return filetimeToTimeT(utcFiletime);
+}
+
+
+Opt<double> zen::utcToMtpVariantTime(std::int64_t utcTime) //returns empty on error
+{
+ const FILETIME lastWriteTimeUtc = timetToFileTime(utcTime); //convert ansi C time to FILETIME
+
+ SYSTEMTIME systemTimeUtc = {};
+ if (!::FileTimeToSystemTime(&lastWriteTimeUtc, //__in const FILETIME *lpFileTime,
+ &systemTimeUtc)) //__out LPSYSTEMTIME lpSystemTime
+ return NoValue();
+
+ SYSTEMTIME systemTimeLocal = {};
+ if (!::SystemTimeToTzSpecificLocalTime(nullptr, //__in_opt LPTIME_ZONE_INFORMATION lpTimeZone,
+ &systemTimeUtc, //__in LPSYSTEMTIME lpUniversalTime,
+ &systemTimeLocal)) //__out LPSYSTEMTIME lpLocalTime
+ return NoValue();
+
+ double localVarTime = 0;
+ if (!SystemTimeToVariantTime(&systemTimeLocal, //_In_ LPSYSTEMTIME lpSystemTime,
+ &localVarTime)) //_Out_ DOUBLE *pvtime
+ return NoValue();
+
+ return localVarTime;
+}
+#endif \ No newline at end of file
diff --git a/zen/format_unit.h b/zen/format_unit.h
index eacb8d46..fcc42dfa 100644
--- a/zen/format_unit.h
+++ b/zen/format_unit.h
@@ -9,6 +9,7 @@
#include <string>
#include <cstdint>
+#include "optional.h"
#include "string_tools.h"
@@ -26,8 +27,11 @@ template <class NumberType>
std::wstring toGuiString(NumberType number); //format integer number including thousands separator
-
-
+#ifdef ZEN_WIN_VISTA_AND_LATER
+ //reverse calculation of utcToLocalTimeString()
+ Opt<std::int64_t> mtpVariantTimetoUtc(double localTime); //returns empty on error
+ Opt<double> utcToMtpVariantTime(int64_t utcTime); //
+#endif
bgstack15