diff --git a/include/SDL3/SDL_filesystem.h b/include/SDL3/SDL_filesystem.h index 17666a95d2a757..972e919e917d95 100644 --- a/include/SDL3/SDL_filesystem.h +++ b/include/SDL3/SDL_filesystem.h @@ -246,13 +246,14 @@ typedef enum SDL_StatPathType SDL_STATPATHTYPE_OTHER /**< something completely different like a device node (not a symlink, those are always followed) */ } SDL_StatPathType; +/* SDL timestamps are in _nanoseconds_ since the Unix epoch (Jan 1, 1970). */ typedef struct SDL_Stat { SDL_StatPathType filetype; /* is this a file? a dir? something else? */ - Sint64 filesize; /* size in bytes */ - Sint64 modtime; /* SDL filesystem timestamp */ - Sint64 createtime; /* SDL filesystem timestamp */ - Sint64 accesstime; /* SDL filesystem timestamp */ + Uint64 filesize; /* size in bytes */ + Uint64 modtime; /* SDL filesystem timestamp */ + Uint64 createtime; /* SDL filesystem timestamp */ + Uint64 accesstime; /* SDL filesystem timestamp */ } SDL_Stat; @@ -349,10 +350,10 @@ extern DECLSPEC void SDLCALL SDL_DestroyFilesystem(SDL_FSops *fs); extern DECLSPEC const char * SDLCALL SDL_GetFilePathSeparator(void); /* converts an SDL file timestamp into a win32 FILETIME (100-nanosecond intervals since January 1, 1601). Fills in the two 32-bit values of the win32 struct. */ -extern DECLSPEC void SDLCALL SDL_FileTimeToWindows(Sint64 ftime, Uint32 *low, Uint32 *high); +extern DECLSPEC void SDLCALL SDL_FileTimeToWindows(Uint64 ftime, Uint32 *low, Uint32 *high); /* converts an SDL file timestamp into a Unix time_t (seconds since the Unix epoch). */ -extern DECLSPEC Sint64 SDLCALL SDL_FileTimeToUnix(Sint64 ftime); +extern DECLSPEC Uint64 SDLCALL SDL_FileTimeToUnix(Uint64 ftime); /* Ends C function definitions when using C++ */ diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 325066fdd9d241..3d2e9f83ba7fa7 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1030,5 +1030,5 @@ SDL_DYNAPI_PROC(int,SDL_FSstat,(SDL_FSops *a, const char *b, SDL_Stat *c),(a,b,c SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetFSProperties,(SDL_FSops *a),(a),return) SDL_DYNAPI_PROC(void,SDL_DestroyFilesystem,(SDL_FSops *a),(a),) SDL_DYNAPI_PROC(const char*,SDL_GetFilePathSeparator,(void),(),return) -SDL_DYNAPI_PROC(void,SDL_FileTimeToWindows,(Sint64 a, Uint32 *b, Uint32 *c),(a,b,c),) -SDL_DYNAPI_PROC(Sint64,SDL_FileTimeToUnix,(Sint64 a),(a),return) +SDL_DYNAPI_PROC(void,SDL_FileTimeToWindows,(Uint64 a, Uint32 *b, Uint32 *c),(a,b,c),) +SDL_DYNAPI_PROC(Uint64,SDL_FileTimeToUnix,(Uint64 a),(a),return) diff --git a/src/filesystem/SDL_filesystem.c b/src/filesystem/SDL_filesystem.c index 5ac4c2c13eeab0..874b925e766ed5 100644 --- a/src/filesystem/SDL_filesystem.c +++ b/src/filesystem/SDL_filesystem.c @@ -108,21 +108,22 @@ const char *SDL_GetFilePathSeparator(void) return PLATFORM_PATH_SEPARATOR; } -void SDL_FileTimeToWindows(Sint64 ftime, Uint32 *low, Uint32 *high) +void SDL_FileTimeToWindows(Uint64 ftime, Uint32 *low, Uint32 *high) { - const Uint64 delta_1601_epoch_s = 11644473600; // [seconds] (seconds between 1/1/1601 and 1/1/1970) - const Uint64 cvt = (delta_1601_epoch_s + ftime) * 10000000ull; // [100ns] + const Uint64 delta_1601_epoch_ns = 11644473600ull * SDL_NS_PER_SECOND; // [ns] (nanoseconds between 1/1/1601 and 1/1/1970, 11644473600 seconds * 1000000000) + const Uint64 cvt = (ftime + delta_1601_epoch_ns) / 100ull; // [100ns] (adjust to epoch and convert nanoseconds to 1/100th nanosecond units). if (low) { - *low = cvt & 0xFFFFFFFFull; + *low = (Uint32) cvt; } if (high) { - *high = cvt >> 32; + *high = (Uint32) (cvt >> 32); } } -Sint64 SDL_FileTimeToUnix(Sint64 ftime) +Uint64 SDL_FileTimeToUnix(Uint64 ftime) { - return ftime; // currently SDL time is just the unix epoch. + // SDL time uses the unix epoch, but in nanoseconds. Divide to convert to seconds. + return ftime / SDL_NS_PER_SECOND; } diff --git a/src/filesystem/posix/SDL_sysfsops.c b/src/filesystem/posix/SDL_sysfsops.c index a1412f33d08b26..a48f1456ec89b6 100644 --- a/src/filesystem/posix/SDL_sysfsops.c +++ b/src/filesystem/posix/SDL_sysfsops.c @@ -79,18 +79,19 @@ int SDL_SYS_FSstat(SDL_FSops *fs, const char *fullpath, SDL_Stat *st) return SDL_SetError("Can't stat: %s", strerror(errno)); } else if (S_ISREG(statbuf.st_mode)) { st->filetype = SDL_STATPATHTYPE_FILE; - st->filesize = statbuf.st_size; + st->filesize = (Uint64) statbuf.st_size; } else if(S_ISDIR(statbuf.st_mode)) { st->filetype = SDL_STATPATHTYPE_DIRECTORY; st->filesize = 0; } else { st->filetype = SDL_STATPATHTYPE_OTHER; - st->filesize = statbuf.st_size; + st->filesize = (Uint64) statbuf.st_size; } - st->modtime = statbuf.st_mtime; - st->createtime = statbuf.st_ctime; - st->accesstime = statbuf.st_atime; + // SDL file time is nanoseconds since the Unix epoch, so we just need to convert secs -> nanosecs. + st->modtime = ((Uint64) statbuf.st_mtime) * SDL_NS_PER_SECOND; + st->createtime = ((Uint64) statbuf.st_ctime) * SDL_NS_PER_SECOND; + st->accesstime = ((Uint64) statbuf.st_atime) * SDL_NS_PER_SECOND; return 0; } diff --git a/src/filesystem/windows/SDL_sysfsops.c b/src/filesystem/windows/SDL_sysfsops.c index 96ab93cbf732ac..a8fab983b24e93 100644 --- a/src/filesystem/windows/SDL_sysfsops.c +++ b/src/filesystem/windows/SDL_sysfsops.c @@ -117,17 +117,16 @@ int SDL_SYS_FSmkdir(SDL_FSops *fs, const char *fullpath) return !rc ? WIN_SetError("Couldn't create directory") : 0; } -static Sint64 FileTimeToSDLTime(const FILETIME *ft) +static Uint64 FileTimeToSDLTime(const FILETIME *ft) { - const ULONGLONG nanosecToMillisec = 10000000ull; - const ULONGLONG delta_1601_epoch_s = 11644473600ull; // [seconds] (seconds between 1/1/1601 and 1/1/1970) + const Uint64 delta_1601_epoch_100ns = 11644473600ull * 10000000ull; // [ns] (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) ((large.QuadPart - delta_1601_epoch_s) / nanosecToMillisec); + return (((Uint64)large.QuadPart) - delta_1601_epoch_100ns) * 100; // [ns] (adjust to epoch and convert 1/100th nanosecond units to nanoseconds). } int SDL_SYS_FSstat(SDL_FSops *fs, const char *fullpath, SDL_Stat *st) @@ -153,10 +152,10 @@ int SDL_SYS_FSstat(SDL_FSops *fs, const char *fullpath, SDL_Stat *st) st->filesize = 0; } else if (winstat.dwFileAttributes & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_DEVICE)) { st->filetype = SDL_STATPATHTYPE_OTHER; - st->filesize = (Sint64) ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow); + st->filesize = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow); } else { st->filetype = SDL_STATPATHTYPE_FILE; - st->filesize = (Sint64) ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow); + st->filesize = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow); } return 1; diff --git a/test/testfilesystem.c b/test/testfilesystem.c index bd15ee6161a28c..36bb81bc1b5cbb 100644 --- a/test/testfilesystem.c +++ b/test/testfilesystem.c @@ -38,7 +38,7 @@ static int SDLCALL enum_callback(void *userdata, SDL_FSops *fsops, const char *o } else { type = "OTHER"; } - SDL_Log("%s (type=%s, size=%" SDL_PRIs64 ", mod=%" SDL_PRIs64 ", create=%" SDL_PRIs64 ", access=%" SDL_PRIs64 ")", + SDL_Log("%s (type=%s, size=%" SDL_PRIu64 ", mod=%" SDL_PRIu64 ", create=%" SDL_PRIu64 ", access=%" SDL_PRIu64 ")", fullpath, type, statbuf.filesize, statbuf.modtime, statbuf.createtime, statbuf.accesstime); if (statbuf.filetype == SDL_STATPATHTYPE_DIRECTORY) {