From: uz Date: Sun, 1 Apr 2012 16:56:42 +0000 (+0000) Subject: Add a new module that works around a bug in the Microsoft version of stat. The X-Git-Tag: V2.14~435 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=65fe2ad0d368c98b88488cbb5025097bf6e0bef1;p=cc65 Add a new module that works around a bug in the Microsoft version of stat. The function is buggy since the first version of windows that supports something else than FAT, and instead of fixing the problem, Microsoft has declared it "works as designed". The problem has made it into .NET and is also visible in the standard windows file explorer (modification times of untouched files will change when entering or leaving DST). Please note that the new FileStat function returns incorrect times for files on FAT file systems. This is because I have currently no idea on how to identify the file system for a given file. However, it should be correct in quite some more cases than stat(). git-svn-id: svn://svn.cc65.org/cc65/trunk@5632 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/common/filestat.c b/src/common/filestat.c new file mode 100644 index 000000000..6a965af36 --- /dev/null +++ b/src/common/filestat.c @@ -0,0 +1,143 @@ +/*****************************************************************************/ +/* */ +/* filestat.c */ +/* */ +/* Replacement for buggy Microsoft code */ +/* */ +/* */ +/* */ +/* (C) 2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors 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. */ +/* */ +/*****************************************************************************/ + + + +/* This module works around bugs in the time conversion code supplied by + * Microsoft. See here for a description of the problem: + * http://www.codeproject.com/KB/datetime/dstbugs.aspx + * Please let me note that I find it absolutely unacceptable to just declare + * buggy behaviour like this "works as designed" as Microsoft does. The + * problems did even make it into .NET, where the DateTime builtin data type + * has exactly the same problems as described in the article above. + */ + + + +#include +#include +#if defined(__WATCOMC__) && defined(__NT__) +#define BUGGY_OS 1 +#include +#include +#endif + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +#if defined(BUGGY_OS) + + + +static time_t FileTimeToUnixTime (const FILETIME* T) +/* Calculate a unix time_t value from a FILETIME. FILETIME contains a 64 bit + * value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals. + * time_t is in seconds since 1970-01-01 00:00:00. + */ +{ + /* Offset between 1600-01-01 and the Epoch in seconds. Watcom C has no + * way to express a number > 32 bit (known to me) but is able to do + * calculations with 64 bit integers, so we need to do it this way. + */ + static const ULARGE_INTEGER Offs = { 0xB6109100UL, 0x20000000UL }; + ULARGE_INTEGER V; + V.LowPart = T->dwLowDateTime; + V.HighPart = T->dwHighDateTime; + return (V.QuadPart / 10000000U) - Offs.QuadPart; +} + + + +int FileStat (const char* Path, struct stat* Buf) +/* Replacement function for stat() */ +{ + + HANDLE H; + BY_HANDLE_FILE_INFORMATION Info; + + /* First call stat() */ + int Error = stat (Path, Buf); + if (Error != 0) { + return Error; + } + + /* Open the file using backup semantics, so we won't change atime. Then + * retrieve the correct times in UTC and replace the ones in Buf. Return + * EACCES in case of errors to avoid the hassle of translating windows + * error codes to standard ones. + */ + H = CreateFile (Path, + GENERIC_READ, + FILE_SHARE_READ, + 0, /* Security attributes */ + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + 0); /* Template file */ + if (H != INVALID_HANDLE_VALUE) { + if (GetFileInformationByHandle (H, &Info)) { + Buf->st_ctime = FileTimeToUnixTime (&Info.ftCreationTime); + Buf->st_atime = FileTimeToUnixTime (&Info.ftLastAccessTime); + Buf->st_mtime = FileTimeToUnixTime (&Info.ftLastWriteTime); + } else { + Error = EACCES; + } + CloseHandle (H); + } else { + Error = EACCES; + } + + /* Done */ + return Error; +} + + + +#else + + + +int FileStat (const char* Path, struct stat* Buf) +/* Replacement function for stat() */ +{ + /* Just call the function which works without errors */ + return stat (Path, Buf); +} + + + +#endif diff --git a/src/common/filestat.h b/src/common/filestat.h new file mode 100644 index 000000000..9f19188f2 --- /dev/null +++ b/src/common/filestat.h @@ -0,0 +1,73 @@ +/*****************************************************************************/ +/* */ +/* filestat.h */ +/* */ +/* Replacement for buggy Microsoft code */ +/* */ +/* */ +/* */ +/* (C) 2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors 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. */ +/* */ +/*****************************************************************************/ + + + +/* This module works around bugs in the time conversion code supplied by + * Microsoft. See here for a description of the problem: + * http://www.codeproject.com/KB/datetime/dstbugs.aspx + * Please let me note that I find it absolutely unacceptable to just declare + * buggy behaviour like this "works as designed" as Microsoft does. The + * problems did even make it into .NET, where the DateTime builtin data type + * has exactly the same problems as described in the article above. + */ + + + +#ifndef FILESTAT_H +#define FILESTAT_H + + + +#include +#include + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +int FileStat (const char* Path, struct stat* Buf); +/* Replacement function for stat() */ + + + +/* End of filestat.h */ + +#endif + + + diff --git a/src/common/make/gcc.mak b/src/common/make/gcc.mak index 499080ad3..1ed1f4fad 100644 --- a/src/common/make/gcc.mak +++ b/src/common/make/gcc.mak @@ -27,6 +27,7 @@ OBJS = abend.o \ exprdefs.o \ fileid.o \ filepos.o \ + filestat.o \ filetype.o \ fname.o \ fp.o \ diff --git a/src/common/make/watcom.mak b/src/common/make/watcom.mak index 07e39155e..e041937fc 100644 --- a/src/common/make/watcom.mak +++ b/src/common/make/watcom.mak @@ -69,6 +69,7 @@ OBJS = abend.obj \ exprdefs.obj \ fileid.obj \ filepos.obj \ + filestat.obj \ filetype.obj \ fname.obj \ fp.obj \