wxFileName::Get/SetTimes() finally seem to work under Windows

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14827 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2002-03-27 23:17:41 +00:00
parent 12132b3789
commit 6dbb903bb9
4 changed files with 79 additions and 55 deletions

View File

@@ -140,7 +140,10 @@ following functions:
\membersection{Operations} \membersection{Operations}
These methods allow to work with the file creation, access and modification These methods allow to work with the file creation, access and modification
times: times. Note that not all filesystems under all platforms implement these times
in the same way. For example, the access time under Windows has a resolution of
one day (so it is really the access date and not time). The access time may be
updated when the file is executed or not depending on the platform.
\helpref{GetModificationTime}{wxfilenamegetmodificationtime}\\ \helpref{GetModificationTime}{wxfilenamegetmodificationtime}\\
\helpref{GetTimes}{wxfilenamegettimes}\\ \helpref{GetTimes}{wxfilenamegettimes}\\
@@ -400,9 +403,9 @@ Return the short form of the path (returns identity on non-Windows platforms)
\membersection{wxFileName::GetTimes}\label{wxfilenamegettimes} \membersection{wxFileName::GetTimes}\label{wxfilenamegettimes}
\constfunc{bool}{GetTimes}{\param{wxDateTime* }{dtAccess}, \param{wxDateTime* }{dtMod}, \param{wxDateTime* }{dtChange}} \constfunc{bool}{GetTimes}{\param{wxDateTime* }{dtAccess}, \param{wxDateTime* }{dtMod}, \param{wxDateTime* }{dtCreate}}
return the last access, last modification and last change times return the last access, last modification and creation times
(any of the pointers may be NULL) (any of the pointers may be NULL)
@@ -584,7 +587,7 @@ full name is the file name + extension (but without the path)
\membersection{wxFileName::SetTimes}\label{wxfilenamesettimes} \membersection{wxFileName::SetTimes}\label{wxfilenamesettimes}
\func{bool}{SetTimes}{\param{const wxDateTime* }{dtCreate}, \param{const wxDateTime* }{dtAccess}, \param{const wxDateTime* }{dtMod}} \func{bool}{SetTimes}{\param{const wxDateTime* }{dtAccess}, \param{const wxDateTime* }{dtMod}, \param{const wxDateTime* }{dtCreate}}
set the file creation and last access/mod times set the file creation and last access/mod times
(any of the pointers may be NULL) (any of the pointers may be NULL)

View File

@@ -173,20 +173,20 @@ public:
// time functions // time functions
// set the file creation and last access/mod times // set the file last access/mod and creation times
// (any of the pointers may be NULL) // (any of the pointers may be NULL)
bool SetTimes(const wxDateTime *dtCreate, bool SetTimes(const wxDateTime *dtAccess,
const wxDateTime *dtAccess, const wxDateTime *dtMod,
const wxDateTime *dtMod); const wxDateTime *dtCreate);
// set the access and modification times to the current moment // set the access and modification times to the current moment
bool Touch(); bool Touch();
// return the last access, last modification and last change times // return the last access, last modification and create times
// (any of the pointers may be NULL) // (any of the pointers may be NULL)
bool GetTimes(wxDateTime *dtAccess, bool GetTimes(wxDateTime *dtAccess,
wxDateTime *dtMod, wxDateTime *dtMod,
wxDateTime *dtChange) const; wxDateTime *dtCreate) const;
// convenience wrapper: get just the last mod time of the file // convenience wrapper: get just the last mod time of the file
wxDateTime GetModificationTime() const wxDateTime GetModificationTime() const

View File

@@ -90,7 +90,7 @@
#undef TEST_ALL #undef TEST_ALL
static const bool TEST_ALL = TRUE; static const bool TEST_ALL = TRUE;
#else #else
#define TEST_WCHAR #define TEST_FILETIME
static const bool TEST_ALL = FALSE; static const bool TEST_ALL = FALSE;
#endif #endif
@@ -982,8 +982,8 @@ static void TestFileGetTimes()
{ {
wxFileName fn(_T("testdata.fc")); wxFileName fn(_T("testdata.fc"));
wxDateTime dtAccess, dtMod, dtChange; wxDateTime dtAccess, dtMod, dtCreate;
if ( !fn.GetTimes(&dtAccess, &dtMod, &dtChange) ) if ( !fn.GetTimes(&dtAccess, &dtMod, &dtCreate) )
{ {
wxPrintf(_T("ERROR: GetTimes() failed.\n")); wxPrintf(_T("ERROR: GetTimes() failed.\n"));
} }
@@ -992,9 +992,9 @@ static void TestFileGetTimes()
static const wxChar *fmt = _T("%Y-%b-%d %H:%M:%S"); static const wxChar *fmt = _T("%Y-%b-%d %H:%M:%S");
wxPrintf(_T("File times for '%s':\n"), fn.GetFullPath().c_str()); wxPrintf(_T("File times for '%s':\n"), fn.GetFullPath().c_str());
wxPrintf(_T("Access: \t%s\n"), dtAccess.Format(fmt).c_str()); wxPrintf(_T("Creation: \t%s\n"), dtCreate.Format(fmt).c_str());
wxPrintf(_T("Mod/creation:\t%s\n"), dtMod.Format(fmt).c_str()); wxPrintf(_T("Last read: \t%s\n"), dtAccess.Format(fmt).c_str());
wxPrintf(_T("Change: \t%s\n"), dtChange.Format(fmt).c_str()); wxPrintf(_T("Last write: \t%s\n"), dtMod.Format(fmt).c_str());
} }
} }

View File

@@ -135,23 +135,31 @@
class wxFileHandle class wxFileHandle
{ {
public: public:
wxFileHandle(const wxString& filename) enum OpenMode
{
Read,
Write
};
wxFileHandle(const wxString& filename, OpenMode mode)
{ {
m_hFile = ::CreateFile m_hFile = ::CreateFile
( (
filename, // name filename, // name
GENERIC_READ, // access mask mode == Read ? GENERIC_READ // access mask
0, // no sharing : GENERIC_WRITE,
NULL, // no secutity attr 0, // no sharing
OPEN_EXISTING, // creation disposition NULL, // no secutity attr
0, // no flags OPEN_EXISTING, // creation disposition
NULL // no template file 0, // no flags
NULL // no template file
); );
if ( m_hFile == INVALID_HANDLE_VALUE ) if ( m_hFile == INVALID_HANDLE_VALUE )
{ {
wxLogSysError(_("Failed to open '%s' for reading"), wxLogSysError(_("Failed to open '%s' for %s"),
filename.c_str()); filename.c_str(),
mode == Read ? _("reading") : _("writing"));
} }
} }
@@ -187,32 +195,45 @@ private:
// convert between wxDateTime and FILETIME which is a 64-bit value representing // convert between wxDateTime and FILETIME which is a 64-bit value representing
// the number of 100-nanosecond intervals since January 1, 1601. // the number of 100-nanosecond intervals since January 1, 1601.
// the number of milliseconds between the Unix Epoch (January 1, 1970) and the
// FILETIME reference point (January 1, 1601)
static const wxLongLong FILETIME_EPOCH_OFFSET = wxLongLong(0xa97, 0x30b66800);
static void ConvertFileTimeToWx(wxDateTime *dt, const FILETIME &ft) static void ConvertFileTimeToWx(wxDateTime *dt, const FILETIME &ft)
{ {
wxLongLong ll(ft.dwHighDateTime, ft.dwLowDateTime); FILETIME ftLocal;
if ( !::FileTimeToLocalFileTime(&ft, &ftLocal) )
{
wxLogLastError(_T("FileTimeToLocalFileTime"));
}
// convert 100ns to ms SYSTEMTIME st;
ll /= 10000; if ( !::FileTimeToSystemTime(&ftLocal, &st) )
{
wxLogLastError(_T("FileTimeToSystemTime"));
}
// move it to our Epoch dt->Set(st.wDay, wxDateTime::Month(st.wMonth - 1), st.wYear,
ll -= FILETIME_EPOCH_OFFSET; st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
*dt = wxDateTime(ll);
} }
static void ConvertWxToFileTime(FILETIME *ft, const wxDateTime& dt) static void ConvertWxToFileTime(FILETIME *ft, const wxDateTime& dt)
{ {
// do the reverse of ConvertFileTimeToWx() SYSTEMTIME st;
wxLongLong ll = dt.GetValue(); st.wDay = dt.GetDay();
ll += FILETIME_EPOCH_OFFSET; st.wMonth = dt.GetMonth() + 1;
ll *= 10000; st.wYear = dt.GetYear();
st.wHour = dt.GetHour();
st.wMinute = dt.GetMinute();
st.wSecond = dt.GetSecond();
st.wMilliseconds = dt.GetMillisecond();
ft->dwHighDateTime = ll.GetHi(); FILETIME ftLocal;
ft->dwLowDateTime = ll.GetLo(); if ( !::SystemTimeToFileTime(&st, &ftLocal) )
{
wxLogLastError(_T("SystemTimeToFileTime"));
}
if ( !::LocalFileTimeToFileTime(&ftLocal, ft) )
{
wxLogLastError(_T("LocalFileTimeToFileTime"));
}
} }
#endif // __WIN32__ #endif // __WIN32__
@@ -1561,9 +1582,9 @@ void wxFileName::SplitPath(const wxString& fullpath,
// time functions // time functions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool wxFileName::SetTimes(const wxDateTime *dtCreate, bool wxFileName::SetTimes(const wxDateTime *dtAccess,
const wxDateTime *dtAccess, const wxDateTime *dtMod,
const wxDateTime *dtMod) const wxDateTime *dtCreate)
{ {
#if defined(__UNIX_LIKE__) || (defined(__DOS__) && defined(__WATCOMC__)) #if defined(__UNIX_LIKE__) || (defined(__DOS__) && defined(__WATCOMC__))
if ( !dtAccess && !dtMod ) if ( !dtAccess && !dtMod )
@@ -1582,7 +1603,7 @@ bool wxFileName::SetTimes(const wxDateTime *dtCreate,
return TRUE; return TRUE;
} }
#elif defined(__WIN32__) #elif defined(__WIN32__)
wxFileHandle fh(GetFullPath()); wxFileHandle fh(GetFullPath(), wxFileHandle::Write);
if ( fh.IsOk() ) if ( fh.IsOk() )
{ {
FILETIME ftAccess, ftCreate, ftWrite; FILETIME ftAccess, ftCreate, ftWrite;
@@ -1626,13 +1647,13 @@ bool wxFileName::Touch()
#else // other platform #else // other platform
wxDateTime dtNow = wxDateTime::Now(); wxDateTime dtNow = wxDateTime::Now();
return SetTimes(NULL /* don't change create time */, &dtNow, &dtNow); return SetTimes(&dtNow, &dtNow, NULL /* don't change create time */);
#endif // platforms #endif // platforms
} }
bool wxFileName::GetTimes(wxDateTime *dtAccess, bool wxFileName::GetTimes(wxDateTime *dtAccess,
wxDateTime *dtMod, wxDateTime *dtMod,
wxDateTime *dtChange) const wxDateTime *dtCreate) const
{ {
#if defined(__UNIX_LIKE__) || defined(__WXMAC__) || (defined(__DOS__) && defined(__WATCOMC__)) #if defined(__UNIX_LIKE__) || defined(__WXMAC__) || (defined(__DOS__) && defined(__WATCOMC__))
wxStructStat stBuf; wxStructStat stBuf;
@@ -1642,13 +1663,13 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess,
dtAccess->Set(stBuf.st_atime); dtAccess->Set(stBuf.st_atime);
if ( dtMod ) if ( dtMod )
dtMod->Set(stBuf.st_mtime); dtMod->Set(stBuf.st_mtime);
if ( dtChange ) if ( dtCreate )
dtChange->Set(stBuf.st_ctime); dtCreate->Set(stBuf.st_ctime);
return TRUE; return TRUE;
} }
#elif defined(__WIN32__) #elif defined(__WIN32__)
wxFileHandle fh(GetFullPath()); wxFileHandle fh(GetFullPath(), wxFileHandle::Read);
if ( fh.IsOk() ) if ( fh.IsOk() )
{ {
FILETIME ftAccess, ftCreate, ftWrite; FILETIME ftAccess, ftCreate, ftWrite;
@@ -1656,14 +1677,14 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess,
if ( ::GetFileTime(fh, if ( ::GetFileTime(fh,
dtMod ? &ftCreate : NULL, dtMod ? &ftCreate : NULL,
dtAccess ? &ftAccess : NULL, dtAccess ? &ftAccess : NULL,
dtChange ? &ftWrite : NULL) ) dtCreate ? &ftWrite : NULL) )
{ {
if ( dtMod ) if ( dtMod )
ConvertFileTimeToWx(dtMod, ftCreate); ConvertFileTimeToWx(dtMod, ftCreate);
if ( dtAccess ) if ( dtAccess )
ConvertFileTimeToWx(dtAccess, ftAccess); ConvertFileTimeToWx(dtAccess, ftAccess);
if ( dtChange ) if ( dtCreate )
ConvertFileTimeToWx(dtChange, ftWrite); ConvertFileTimeToWx(dtCreate, ftWrite);
return TRUE; return TRUE;
} }