diff --git a/libraries/SDFS/src/SDFS.cpp b/libraries/SDFS/src/SDFS.cpp index d862ff5d8..cbcc16600 100644 --- a/libraries/SDFS/src/SDFS.cpp +++ b/libraries/SDFS/src/SDFS.cpp @@ -37,6 +37,8 @@ FS SDFS = FS(FSImplPtr(new sdfs::SDFSImpl())); namespace sdfs { +// Required to be global because SDFAT doesn't allow a this pointer in it's own time call +time_t (*__sdfs_timeCallback)(void) = nullptr; FileImplPtr SDFSImpl::open(const char* path, OpenMode openMode, AccessMode accessMode) { diff --git a/libraries/SDFS/src/SDFS.h b/libraries/SDFS/src/SDFS.h index d92d40092..a3d159fbb 100644 --- a/libraries/SDFS/src/SDFS.h +++ b/libraries/SDFS/src/SDFS.h @@ -205,12 +205,21 @@ public: return mktime(&tiempo); } + virtual void setTimeCallback(time_t (*cb)(void)) override { + extern time_t (*__sdfs_timeCallback)(void); + __sdfs_timeCallback = cb; + } + // Because SdFat has a single, global setting for this we can only use a - // static member of our class to return the time/date. However, since - // this is static, we can't see the time callback variable. Punt for now, - // using time(NULL) as the best we can do. + // static member of our class to return the time/date. static void dateTimeCB(uint16_t *dosYear, uint16_t *dosTime) { - time_t now = time(nullptr); + time_t now; + extern time_t (*__sdfs_timeCallback)(void); + if (__sdfs_timeCallback) { + now = __sdfs_timeCallback(); + } else { + now = time(nullptr); + } struct tm *tiempo = localtime(&now); *dosYear = ((tiempo->tm_year - 80) << 9) | ((tiempo->tm_mon + 1) << 5) | tiempo->tm_mday; *dosTime = (tiempo->tm_hour << 11) | (tiempo->tm_min << 5) | tiempo->tm_sec; diff --git a/tests/host/fs/test_fs.cpp b/tests/host/fs/test_fs.cpp index fb73a6a27..e82d212fb 100644 --- a/tests/host/fs/test_fs.cpp +++ b/tests/host/fs/test_fs.cpp @@ -162,4 +162,35 @@ TEST_CASE("SD.h FILE_WRITE macro is append", "[fs]") REQUIRE(u == 0); } +// SDFS timestamp setter (#7682) +static time_t _my_time(void) +{ + struct tm t; + bzero(&t, sizeof(t)); + t.tm_year = 120; + t.tm_mon = 9; + t.tm_mday = 22; + t.tm_hour = 12; + t.tm_min = 13; + t.tm_sec = 14; + return mktime(&t); +} + +TEST_CASE("SDFS timeCallback") +{ + SDFS_MOCK_DECLARE(64, 8, 512, ""); + REQUIRE(SDFS.begin()); + REQUIRE(SD.begin(4)); + + SDFS.setTimeCallback(_my_time); + File f = SD.open("/file.txt", "w"); + f.write("Had we but world enough, and time,"); + f.close(); + time_t expected = _my_time(); + f = SD.open("/file.txt", "r"); + REQUIRE(abs(f.getCreationTime() - expected) < 60); // FAT has less precision in timestamp than time_t + REQUIRE(abs(f.getLastWrite() - expected) < 60); // FAT has less precision in timestamp than time_t + f.close(); +} + };