diff --git a/rtcore.h b/rtcore.h index 6abd92c..0d280f0 100644 --- a/rtcore.h +++ b/rtcore.h @@ -304,6 +304,11 @@ RTC_API s8 ReadEntireFileS8(s8 path, arena *a); /* Write the given buffer to a file */ RTC_API b32 WriteEntireFile(s8 path, byte *data, isize length); +/* Retrieves a timestamp representing the last time of last modification. + * The interpretation of the returned value depends on the host system. + * If the operation fails, 0 is returned. */ +RTC_API i64 GetFileModificationTimestamp(s8 path); + /* Atomics */ #if !defined(RTC_NO_ATOMICS) #if defined(__GNUC__) || defined(__clang__) @@ -461,6 +466,7 @@ RTC_API THREAD_RETURN_TYPE JoinThread(thread *t); #ifdef __linux__ #include + #include #elif defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include @@ -750,6 +756,35 @@ WriteEntireFile(s8 path, byte *data, isize length) return num == 1; } +RTC_API +i64 GetFileModificationTimestamp(s8 path) +{ + char _p[260]; + if (path.length >= CountOf(_p)) + return 0; + memcpy(_p, path.data, path.length); + _p[path.length] = '\0'; +#ifdef __linux__ + struct stat st; + if (stat(_p, &st) != 0) + return 0; + #if _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700 + /* Nanosecond precision */ + return (i64)st.st_mtim.tv_nsec; + #else + return (i64)st.st_mtim; + #endif +#elif defined(_WIN32) + WIN32_FILE_ATTRIBUTE_DATA data; + if (GetFileAttributesExA(_p, GetFileExInfoStandard, &data) == 0) + return 0; + ULARGE_INTEGER u; + u.u.LowPart = data.ftLastWriteTime.dwLowDateTime; + u.u.HighPart = data.ftLastWriteTime.dwHighDateTime; + return (i64)u.QuadPart; +#endif +} + /* Threading */ #ifdef __linux__ RTC_API thread * diff --git a/rtcore_test.c b/rtcore_test.c index a339d6f..316cdf5 100644 --- a/rtcore_test.c +++ b/rtcore_test.c @@ -68,6 +68,14 @@ TEST(ParseIntTest) AssertFalse(testing, S8ParseI32(S8("Not a number"), 10).ok); } +internal +TEST(FileTimestampsTest) +{ + NoSuite; + i64 ts = GetFileModificationTimestamp(S8("somedata.txt")); + AssertNotEqual(testing, ts, 0); +} + int main(int argc, char **argv) { @@ -78,5 +86,6 @@ main(int argc, char **argv) RegisterStandaloneTest(testing, ReadFileTest); RegisterStandaloneTest(testing, ThreadTest); RegisterStandaloneTest(testing, ParseIntTest); + RegisterStandaloneTest(testing, FileTimestampsTest); return ExecuteTests(testing, argc, argv) ? 0 : 1; }