Skip to content

Commit

Permalink
filesystem: Adjust some metrics.
Browse files Browse the repository at this point in the history
- Decide on SDL file timestamps (nanoseconds since Unix epoch).
- File sizes are Uint64 (no more -1 for "unsupported").
- Fixed timestamp conversions.
  • Loading branch information
icculus committed Feb 27, 2024
1 parent 3e179f8 commit 4ed69b8
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 27 deletions.
13 changes: 7 additions & 6 deletions include/SDL3/SDL_filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand Down Expand Up @@ -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++ */
Expand Down
4 changes: 2 additions & 2 deletions src/dynapi/SDL_dynapi_procs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
15 changes: 8 additions & 7 deletions src/filesystem/SDL_filesystem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand Down
11 changes: 6 additions & 5 deletions src/filesystem/posix/SDL_sysfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
11 changes: 5 additions & 6 deletions src/filesystem/windows/SDL_sysfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion test/testfilesystem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 4ed69b8

Please sign in to comment.