Skip to content

Commit 1bb0815

Browse files
Hook up custom timestamp proc for SD/SDFS (#7686)
The SDFS implementation didn't include plumbing to support user-supplied timestamp generators (for file create/write times) because the SDFat library doesn't support a callback parameter. Work around it by using a single, global (inside sdfs namespace) that the static timestamp callback member can see and use. Add a test of the feature in CI. Fixes #7682
1 parent 996211f commit 1bb0815

File tree

3 files changed

+46
-4
lines changed

3 files changed

+46
-4
lines changed

libraries/SDFS/src/SDFS.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ FS SDFS = FS(FSImplPtr(new sdfs::SDFSImpl()));
3737

3838
namespace sdfs {
3939

40+
// Required to be global because SDFAT doesn't allow a this pointer in it's own time call
41+
time_t (*__sdfs_timeCallback)(void) = nullptr;
4042

4143
FileImplPtr SDFSImpl::open(const char* path, OpenMode openMode, AccessMode accessMode)
4244
{

libraries/SDFS/src/SDFS.h

+13-4
Original file line numberDiff line numberDiff line change
@@ -205,12 +205,21 @@ class SDFSImpl : public FSImpl
205205
return mktime(&tiempo);
206206
}
207207

208+
virtual void setTimeCallback(time_t (*cb)(void)) override {
209+
extern time_t (*__sdfs_timeCallback)(void);
210+
__sdfs_timeCallback = cb;
211+
}
212+
208213
// Because SdFat has a single, global setting for this we can only use a
209-
// static member of our class to return the time/date. However, since
210-
// this is static, we can't see the time callback variable. Punt for now,
211-
// using time(NULL) as the best we can do.
214+
// static member of our class to return the time/date.
212215
static void dateTimeCB(uint16_t *dosYear, uint16_t *dosTime) {
213-
time_t now = time(nullptr);
216+
time_t now;
217+
extern time_t (*__sdfs_timeCallback)(void);
218+
if (__sdfs_timeCallback) {
219+
now = __sdfs_timeCallback();
220+
} else {
221+
now = time(nullptr);
222+
}
214223
struct tm *tiempo = localtime(&now);
215224
*dosYear = ((tiempo->tm_year - 80) << 9) | ((tiempo->tm_mon + 1) << 5) | tiempo->tm_mday;
216225
*dosTime = (tiempo->tm_hour << 11) | (tiempo->tm_min << 5) | tiempo->tm_sec;

tests/host/fs/test_fs.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,35 @@ TEST_CASE("SD.h FILE_WRITE macro is append", "[fs]")
162162
REQUIRE(u == 0);
163163
}
164164

165+
// SDFS timestamp setter (#7682)
166+
static time_t _my_time(void)
167+
{
168+
struct tm t;
169+
bzero(&t, sizeof(t));
170+
t.tm_year = 120;
171+
t.tm_mon = 9;
172+
t.tm_mday = 22;
173+
t.tm_hour = 12;
174+
t.tm_min = 13;
175+
t.tm_sec = 14;
176+
return mktime(&t);
177+
}
178+
179+
TEST_CASE("SDFS timeCallback")
180+
{
181+
SDFS_MOCK_DECLARE(64, 8, 512, "");
182+
REQUIRE(SDFS.begin());
183+
REQUIRE(SD.begin(4));
184+
185+
SDFS.setTimeCallback(_my_time);
186+
File f = SD.open("/file.txt", "w");
187+
f.write("Had we but world enough, and time,");
188+
f.close();
189+
time_t expected = _my_time();
190+
f = SD.open("/file.txt", "r");
191+
REQUIRE(abs(f.getCreationTime() - expected) < 60); // FAT has less precision in timestamp than time_t
192+
REQUIRE(abs(f.getLastWrite() - expected) < 60); // FAT has less precision in timestamp than time_t
193+
f.close();
194+
}
195+
165196
};

0 commit comments

Comments
 (0)