diff --git a/include/timespec.h b/include/timespec.h index c612340..97330cf 100644 --- a/include/timespec.h +++ b/include/timespec.h @@ -1,5 +1,6 @@ #pragma once #include "mgos.h" +#include /* A simple time specifier for windows of time throughout a 24 hour day. * @@ -47,3 +48,7 @@ bool timespec_clear_spec(struct mgos_timespec *ts); bool timespec_get_spec(struct mgos_timespec *ts, char *ret, int retlen); bool timespec_match(const struct mgos_timespec *ts, const struct tm *tm); bool timespec_match_now(const struct mgos_timespec *ts); + +// File IO -- read or write the current timespec to a file +bool timespec_write_file(struct mgos_timespec *ts, const char *fn); +bool timespec_read_file(struct mgos_timespec *ts, const char *fn); diff --git a/src/.timespec.c.swp b/src/.timespec.c.swp new file mode 100644 index 0000000..f6798b5 Binary files /dev/null and b/src/.timespec.c.swp differ diff --git a/src/timespec.c b/src/timespec.c index 4599d79..fca57f3 100644 --- a/src/timespec.c +++ b/src/timespec.c @@ -250,3 +250,83 @@ bool timespec_get_spec(struct mgos_timespec *ts, char *ret, int retlen) { } return true; } + +bool timespec_write_file(struct mgos_timespec *ts, const char *fn) { + char buf[500]; + int fd; + + if (!timespec_get_spec(ts, buf, sizeof(buf))) { + LOG(LL_ERROR, ("Could not convert timespec to string")); + return false; + } + + if (!fn) { + return false; + } + + if (!(fd = open(fn, O_RDWR | O_CREAT | O_TRUNC))) { + LOG(LL_ERROR, ("Could not open %s for writing", fn)); + return false; + } + if ((uint32_t)strlen(buf) != (uint32_t)write(fd, buf, strlen(buf))) { + LOG(LL_ERROR, ("Short write on %s for data '%s'", fn, buf)); + return false; + } + close(fd); + + return true; +} + +bool timespec_read_file(struct mgos_timespec *ts, const char *fn) { + int fd; + char * buf; + char * spec; + char * buf_ptr; + struct stat fp_stat; + + if (!ts) { + return false; + } + + if (!fn) { + return false; + } + + if (0 != stat(fn, &fp_stat)) { + LOG(LL_ERROR, ("Could not stat %s", fn)); + } + if (fp_stat.st_size > 1024) { + LOG(LL_ERROR, ("File size of %s is larger than 1024 bytes (%u)", fn, (uint32_t)fp_stat.st_size)); + } + buf = malloc(fp_stat.st_size + 1); + if (!buf) { + LOG(LL_ERROR, ("Could not malloc %u bytes for file %s", (uint32_t)fp_stat.st_size, fn)); + } + + if (!(fd = open(fn, O_RDONLY))) { + LOG(LL_ERROR, ("Could not open %s for reading", fn)); + free(buf); + return false; + } + if (fp_stat.st_size != read(fd, buf, fp_stat.st_size)) { + LOG(LL_ERROR, ("Could not read %u bytes from %s", (uint32_t)fp_stat.st_size, fn)); + close(fd); + free(buf); + return false; + } + buf[fp_stat.st_size] = '\0'; + close(fd); + LOG(LL_INFO, ("buf='%s'", buf)); + + // Wipe the timespec and parse back + timespec_clear_spec(ts); + + buf_ptr = buf; + while ((spec = strtok_r(buf_ptr, ",", &buf_ptr))) { + if (!timespec_add_spec(ts, spec)) { + LOG(LL_WARN, ("Could not add spec '%s'", spec)); + } + } + free(buf); + return true; +} diff --git a/unittest/test_timespec.c b/unittest/test_timespec.c index 7a77fdb..fc36023 100644 --- a/unittest/test_timespec.c +++ b/unittest/test_timespec.c @@ -89,6 +89,13 @@ static void test_timespec_state(void) { struct mgos_timespec *ts = timespec_create(); struct tm target; char buf[500]; + char tmp_file[30]; + int fd; + + snprintf (tmp_file, sizeof(tmp_file)-1, "/tmp/timespec_XXXXXX"); + fd = mkstemp(tmp_file); + close(fd); + LOG(LL_INFO, ("Temporary filename: %s", tmp_file)); ASSERT(ts, "Created timespec"); timespec_get_spec(ts, buf, sizeof(buf)-1); @@ -157,7 +164,11 @@ static void test_timespec_state(void) { // Test timespec retrieval timespec_get_spec(ts, buf, sizeof(buf)-1); ASSERT(0 == strcmp(buf, "23:01:02-01:02:03,14:11:05-14:59:52,12:00:00-13:00:00,08:00:00-10:00:00"), "timespec_get_spec() didn't match input spec(s)"); - LOG(LL_INFO, ("Spec: '%s'", buf)); + + // Write to file and read back + ASSERT(timespec_write_file(ts, tmp_file), "Could not write timespec to file"); + ASSERT(timespec_read_file(ts, tmp_file), "Could not read timespec from file"); + ASSERT(0 == strcmp(buf, "23:01:02-01:02:03,14:11:05-14:59:52,12:00:00-13:00:00,08:00:00-10:00:00"), "timespec_read_file() didn't match input spec(s)"); ASSERT(timespec_destroy(&ts), "Destroyed timespec"); @@ -187,6 +198,11 @@ static void test_timespec_state(void) { timespec_get_spec(ts, buf, sizeof(buf)-1); ASSERT(0 == strcmp(buf, "03:02:03-04:03:04,02:00:00-02:00:01,23:00:00-01:00:00,00:00:00-00:00:00,08:00:00-10:00:00"), "timespec_get_spec() didn't match input spec(s)"); + // Write to file and read back + ASSERT(timespec_write_file(ts, tmp_file), "Could not write timespec to file"); + ASSERT(timespec_read_file(ts, tmp_file), "Could not read timespec from file"); + ASSERT(0 == strcmp(buf, "03:02:03-04:03:04,02:00:00-02:00:01,23:00:00-01:00:00,00:00:00-00:00:00,08:00:00-10:00:00"), "timespec_read_file() didn't match input spec(s)"); + ASSERT(timespec_destroy(&ts), "Destroyed timespec"); // Some other time counting tests @@ -201,7 +217,15 @@ static void test_timespec_state(void) { timespec_get_spec(ts, buf, sizeof(buf)-1); ASSERT(0 == strcmp(buf, "12:00:00-00:00:00,00:00:00-12:00:00"), "timespec_get_spec() didn't match input spec(s)"); + // Write to file and read back + ASSERT(timespec_write_file(ts, tmp_file), "Could not write timespec to file"); + ASSERT(timespec_read_file(ts, tmp_file), "Could not read timespec from file"); + ASSERT(0 == strcmp(buf, "12:00:00-00:00:00,00:00:00-12:00:00"), "timespec_read_file() didn't match input spec(s)"); + ASSERT(timespec_destroy(&ts), "Destroyed timespec"); + + LOG(LL_INFO, ("Removing temporary file: %s", tmp_file)); + unlink(tmp_file); } void test_timespec() {