SDL file times are 64-bit integers representing nanoseconds since the Unix epoch

This commit is contained in:
Sam Lantinga
2024-03-17 13:11:13 -07:00
parent 9153287fa0
commit 747300b356
8 changed files with 65 additions and 49 deletions

View File

@@ -22,27 +22,38 @@
#include "SDL_internal.h"
#include "SDL_sysfilesystem.h"
void SDL_FileTimeToWindows(Sint64 ftime, Uint32 *low, Uint32 *high)
static const Sint64 delta_1601_epoch_100ns = 11644473600ll * 10000000ll; // [100 ns] (100 ns units between 1/1/1601 and 1/1/1970, 11644473600 seconds)
void SDL_FileTimeToWindows(SDL_FileTime ftime, Uint32 *dwLowDateTime, Uint32 *dwHighDateTime)
{
const Sint64 delta_1601_epoch_s = 11644473600ull; // [seconds] (seconds between 1/1/1601 and 1/1/1970, 11644473600 seconds)
Uint64 wtime;
Sint64 cvt = (ftime + delta_1601_epoch_s) * (SDL_NS_PER_SECOND / 100ull); // [100ns] (adjust to epoch and convert nanoseconds to 1/100th nanosecond units).
// Convert ftime to 100ns units
Sint64 ftime_100ns = (ftime / 100);
// Windows FILETIME is unsigned, so if we're trying to show a timestamp from before before the
// Windows epoch, (Jan 1, 1601), clamp it to zero so it doesn't go way into the future.
if (cvt < 0) {
cvt = 0;
if (ftime_100ns < 0 && -ftime_100ns > delta_1601_epoch_100ns) {
// If we're trying to show a timestamp from before before the Windows epoch, (Jan 1, 1601), clamp it to zero
wtime = 0;
} else {
wtime = (Uint64)(delta_1601_epoch_100ns + ftime_100ns);
}
if (low) {
*low = (Uint32) cvt;
if (dwLowDateTime) {
*dwLowDateTime = (Uint32)wtime;
}
if (high) {
*high = (Uint32) (cvt >> 32);
if (dwHighDateTime) {
*dwHighDateTime = (Uint32)(wtime >> 32);
}
}
SDL_FileTime SDL_FileTimeFromWindows(Uint32 dwLowDateTime, Uint32 dwHighDateTime)
{
Uint64 wtime = (((Uint64)dwHighDateTime << 32) | dwLowDateTime);
return (Sint64)(wtime - delta_1601_epoch_100ns) * 100;
}
int SDL_RemovePath(const char *path)
{
if (!path) {

View File

@@ -124,12 +124,9 @@ int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info)
info->size = (Uint64) statbuf.st_size;
}
// SDL file time is seconds since the Unix epoch, so we're already good here.
// Note that this will fail on machines with 32-bit time_t in 2038, but that's not
// an SDL bug; those machines need to be fixed or everything will fail in the same way.
info->create_time = (Sint64) statbuf.st_ctime;
info->modify_time = (Sint64) statbuf.st_mtime;
info->access_time = (Sint64) statbuf.st_atime;
info->create_time = (SDL_FileTime)SDL_SECONDS_TO_NS(statbuf.st_ctime);
info->modify_time = (SDL_FileTime)SDL_SECONDS_TO_NS(statbuf.st_mtime);
info->access_time = (SDL_FileTime)SDL_SECONDS_TO_NS(statbuf.st_atime);
return 0;
}

View File

@@ -140,18 +140,6 @@ int SDL_SYS_CreateDirectory(const char *path)
return !rc ? WIN_SetError("Couldn't create directory") : 0;
}
static Sint64 FileTimeToSDLTime(const FILETIME *ft)
{
const Uint64 delta_1601_epoch_100ns = 11644473600ull * 10000000ull; // [100ns] (100-ns chunks between 1/1/1601 and 1/1/1970, 11644473600 seconds * 10000000)
ULARGE_INTEGER large;
large.LowPart = ft->dwLowDateTime;
large.HighPart = ft->dwHighDateTime;
if (large.QuadPart == 0) {
return 0; // unsupported on this filesystem...0 is fine, I guess.
}
return (Sint64) ((((Uint64)large.QuadPart) - delta_1601_epoch_100ns) / (SDL_NS_PER_SECOND / 100ull)); // [secs] (adjust to epoch and convert 1/100th nanosecond units to seconds).
}
int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info)
{
WCHAR *wpath = WIN_UTF8ToString(path);
@@ -177,9 +165,9 @@ int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info)
info->size = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow);
}
info->create_time = FileTimeToSDLTime(&winstat.ftCreationTime);
info->modify_time = FileTimeToSDLTime(&winstat.ftLastWriteTime);
info->access_time = FileTimeToSDLTime(&winstat.ftLastAccessTime);
info->create_time = SDL_FileTimeFromWindows(winstat.ftCreationTime.dwLowDateTime, winstat.ftCreationTime.dwHighDateTime);
info->modify_time = SDL_FileTimeFromWindows(winstat.ftLastWriteTime.dwLowDateTime, winstat.ftLastWriteTime.dwHighDateTime);
info->access_time = SDL_FileTimeFromWindows(winstat.ftLastAccessTime.dwLowDateTime, winstat.ftLastAccessTime.dwHighDateTime);
return 1;
}