summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author npwoods <npwoods@alumni.cmu.edu>2017-10-17 15:18:57 -0400
committer hap <happppp@users.noreply.github.com>2017-10-17 21:18:57 +0200
commit86f50b0d65e78f71d046218ffe7833271023d8c8 (patch)
treed16ad18dd925dcd16c3750b44291b877afc7a0a1
parent78c658c7a2bb2ee9e3f721dad292cb951d8f30ad (diff)
Created a more flexible imgtool::datetime structure for use within Imgtool (#2263)
* Created a more flexible imgtool::datetime structure for use within Imgtool This is intended to replace most usage of time_t * Changing the granularity of imgtool_clock from 1ms to 100ns, as per Vas' suggestion * Created arbitrary_datetime in timeconv.h to facilitate interpretation of datetime info I concluded that invoking std::mktime on manually assembled std::tm is bad, because it is indeterminate how the std::tm members may be "dominant". This required that I go further in imgtool, and update a number of drivers and eliminate the parameter of imgtool::datetime that takes std::tm.
-rw-r--r--src/lib/util/timeconv.h82
-rw-r--r--src/tools/imgtool/imgtool.cpp79
-rw-r--r--src/tools/imgtool/library.cpp120
-rw-r--r--src/tools/imgtool/library.h71
-rw-r--r--src/tools/imgtool/main.cpp8
-rw-r--r--src/tools/imgtool/modules/amiga.cpp31
-rw-r--r--src/tools/imgtool/modules/cybiko.cpp16
-rw-r--r--src/tools/imgtool/modules/cybikoxt.cpp17
-rw-r--r--src/tools/imgtool/modules/fat.cpp36
-rw-r--r--src/tools/imgtool/modules/mac.cpp4
-rw-r--r--src/tools/imgtool/modules/macbin.cpp4
-rw-r--r--src/tools/imgtool/modules/macutil.cpp40
-rw-r--r--src/tools/imgtool/modules/macutil.h3
-rw-r--r--src/tools/imgtool/modules/prodos.cpp35
-rw-r--r--src/tools/imgtool/modules/thomson.cpp24
15 files changed, 449 insertions, 121 deletions
diff --git a/src/lib/util/timeconv.h b/src/lib/util/timeconv.h
index 7f9a7830b8e..2fd491c9f17 100644
--- a/src/lib/util/timeconv.h
+++ b/src/lib/util/timeconv.h
@@ -35,6 +35,21 @@ typedef std::chrono::duration<std::uint64_t, std::ratio<1, 10000000> > ntfs_dura
//---------------------------------------------------------
+// arbitrary_datetime
+//---------------------------------------------------------
+
+struct arbitrary_datetime
+{
+ int year; // absolute year (1900 AD = 1900)
+ int month; // month (1-12)
+ int day_of_month; // day of month (1-31)
+ int hour; // hour (0-23)
+ int minute; // minute (0-59)
+ int second; // second (0-59)
+};
+
+
+//---------------------------------------------------------
// arbitrary_clock - an std::chrono clock that "knows" the
// date of the epoch's begining
//---------------------------------------------------------
@@ -55,6 +70,17 @@ public:
static constexpr int base_second = S;
//---------------------------------------------------------
+ // from_arbitrary_datetime - converts an
+ // from_arbitrary_datetime to this arbitrary_clock's scale
+ //---------------------------------------------------------
+
+ static time_point from_arbitrary_datetime(const arbitrary_datetime &dt, bool clamp)
+ {
+ return time_point(duration_from_arbitrary_datetime(dt, clamp));
+ }
+
+
+ //---------------------------------------------------------
// from_arbitrary_time_point - converts an arbitrary_clock
// with a different scale to this arbitrary_clock's scale
//---------------------------------------------------------
@@ -62,13 +88,15 @@ public:
template<typename Rep2, int Y2, int M2, int D2, int H2, int N2, int S2, typename Ratio2>
static time_point from_arbitrary_time_point(const std::chrono::time_point<arbitrary_clock<Rep2, Y2, M2, D2, H2, N2, S2, Ratio2> > &tp)
{
- const int64_t our_absolute_day = absolute_day(Y, M, D);
- const int64_t their_absolute_day = absolute_day(Y2, M2, D2);
-
- const auto our_fract_day = std::chrono::hours(H) + std::chrono::minutes(N) + std::chrono::seconds(S);
- const auto their_fract_day = std::chrono::hours(H2) + std::chrono::minutes(N2) + std::chrono::seconds(S2);
-
- const std::chrono::duration<Rep, Ratio> adjustment(std::chrono::hours(24) * (their_absolute_day - our_absolute_day) + (their_fract_day - our_fract_day));
+ arbitrary_datetime dt;
+ dt.year = Y2;
+ dt.month = M2;
+ dt.day_of_month = D2;
+ dt.hour = H2;
+ dt.minute = N2;
+ dt.second = S2;
+
+ const duration adjustment = duration_from_arbitrary_datetime(dt, false);
const duration result_duration = std::chrono::duration_cast<duration>(tp.time_since_epoch() + adjustment);
return time_point(result_duration);
}
@@ -142,6 +170,46 @@ private:
// end of every quadcentury
typedef arbitrary_clock<std::int64_t, 1601, 1, 1, 0, 0, 0, std::ratio<1, 1> > tm_conversion_clock;
+
+ //---------------------------------------------------------
+ // clamp_or_throw
+ //---------------------------------------------------------
+
+ static int clamp_or_throw(int value, int minimum, int maximum, bool clamp, const char *out_of_range_message)
+ {
+ if (value < minimum || value > maximum)
+ {
+ if (clamp)
+ value = std::min(std::max(value, minimum), maximum);
+ else
+ throw std::out_of_range(out_of_range_message);
+ }
+ return value;
+ }
+
+ //---------------------------------------------------------
+ // duration_from_arbitrary_datetime - converts an
+ // arbitrary_datetime to this arbitrary_clock's duration
+ //---------------------------------------------------------
+
+ static duration duration_from_arbitrary_datetime(const arbitrary_datetime &dt, bool clamp)
+ {
+ // range checking
+ const int month = clamp_or_throw(dt.month, 1, 12, clamp, "invalid dt.month");
+ const int day_of_month = clamp_or_throw(dt.day_of_month, 1, gregorian_days_in_month(month, dt.year), clamp, "invalid dt.day_of_month");
+ const int hour = clamp_or_throw(dt.hour, 0, 23, clamp, "invalid dt.hour");
+ const int minute = clamp_or_throw(dt.minute, 0, 59, clamp, "invalid dt.minute");
+ const int second = clamp_or_throw(dt.second, 0, 59, clamp, "invalid dt.second");
+
+ const int64_t our_absolute_day = absolute_day(Y, M, D);
+ const int64_t their_absolute_day = absolute_day(dt.year, month, day_of_month);
+
+ const auto our_fract_day = std::chrono::hours(H) + std::chrono::minutes(N) + std::chrono::seconds(S);
+ const auto their_fract_day = std::chrono::hours(hour) + std::chrono::minutes(minute) + std::chrono::seconds(second);
+
+ return std::chrono::duration<Rep, Ratio>(std::chrono::hours(24) * (their_absolute_day - our_absolute_day) + (their_fract_day - our_fract_day));
+ }
+
//---------------------------------------------------------
// internal_to_tm - formats a structure of type 'struct tm'
// based on a normalized clock
diff --git a/src/tools/imgtool/imgtool.cpp b/src/tools/imgtool/imgtool.cpp
index 52d4b23c759..75aafe0d25d 100644
--- a/src/tools/imgtool/imgtool.cpp
+++ b/src/tools/imgtool/imgtool.cpp
@@ -753,6 +753,77 @@ void imgtool::partition::get_attribute_name(uint32_t attribute, const imgtool_at
//-------------------------------------------------
+// test_imgtool_datetime - unit test for imgtool::datetime
+//-------------------------------------------------
+
+static bool test_imgtool_datetime(int second, int minute, int hour, int day_of_month, int month, int year)
+{
+ bool error = false;
+
+ util::arbitrary_datetime t;
+ t.second = second;
+ t.minute = minute;
+ t.hour = hour;
+ t.day_of_month = day_of_month;
+ t.month = month;
+ t.year = year;
+
+ imgtool::datetime dt(imgtool::datetime::datetime_type::GMT, t);
+ std::tm t2 = dt.gmtime();
+
+ if (t2.tm_sec != second)
+ {
+ util::stream_format(std::wcerr, L"test_imgtool_datetime(): Expected t2.tm_sec to be %d, instead got %d\n", second, t2.tm_sec);
+ error = true;
+ }
+ if (t2.tm_min != minute)
+ {
+ util::stream_format(std::wcerr, L"test_imgtool_datetime(): Expected t2.tm_min to be %d, instead got %d\n", minute, t2.tm_min);
+ error = true;
+ }
+ if (t2.tm_hour != hour)
+ {
+ util::stream_format(std::wcerr, L"test_imgtool_datetime(): Expected t2.tm_hour to be %d, instead got %d\n", hour, t2.tm_hour);
+ error = true;
+ }
+ if (t2.tm_mday != day_of_month)
+ {
+ util::stream_format(std::wcerr, L"test_imgtool_datetime(): Expected t2.tm_mday to be %d, instead got %d\n", day_of_month, t2.tm_mday);
+ error = true;
+ }
+ if (t2.tm_mon != month - 1)
+ {
+ util::stream_format(std::wcerr, L"test_imgtool_datetime(): Expected t2.tm_mon to be %d, instead got %d\n", month - 1, t2.tm_mon);
+ error = true;
+ }
+ if (t2.tm_year != year - 1900)
+ {
+ util::stream_format(std::wcerr, L"test_imgtool_datetime(): Expected t2.tm_mon to be %d, instead got %d\n", year - 1900, t2.tm_year);
+ error = true;
+ }
+ return error;
+}
+
+
+//-------------------------------------------------
+// test_imgtool_datetime - unit tests for imgtool::datetime
+//-------------------------------------------------
+
+static bool test_imgtool_datetime()
+{
+ bool error = false;
+
+ // various test cases for imgtool::datetime
+ if (test_imgtool_datetime(34, 23, 12, 18, 3, 1993)) // March 18th, 1993 12:23:34
+ error = true;
+ if (test_imgtool_datetime(0, 20, 16, 25, 12, 1976)) // December 25th, 1976 16:20:00
+ error = true;
+
+ return error;
+}
+
+
+//-------------------------------------------------
// imgtool_validitychecks - checks the validity
// of the imgtool modules
//-------------------------------------------------
@@ -764,6 +835,10 @@ bool imgtool_validitychecks(void)
imgtool_module_features features;
int created_library = false;
+ // various test cases for imgtool::datetime
+ if (test_imgtool_datetime())
+ error = true;
+
if (!global_imgtool_library)
{
imgtool_init(false, nullptr);
@@ -2290,12 +2365,12 @@ imgtoolerr_t imgtool::directory::get_next(imgtool_dirent &ent)
}
// don't trust the module!
- if (!m_partition.m_supports_creation_time && (ent.creation_time != 0))
+ if (!m_partition.m_supports_creation_time && (ent.creation_time.type() != imgtool::datetime::datetime_type::NONE))
{
internal_error(nullptr, "next_enum() specified creation_time, which is marked as unsupported by this module");
return IMGTOOLERR_UNEXPECTED;
}
- if (!m_partition.m_supports_lastmodified_time && (ent.lastmodified_time != 0))
+ if (!m_partition.m_supports_lastmodified_time && (ent.lastmodified_time.type() != imgtool::datetime::datetime_type::NONE))
{
internal_error(nullptr, "next_enum() specified lastmodified_time, which is marked as unsupported by this module");
return IMGTOOLERR_UNEXPECTED;
diff --git a/src/tools/imgtool/library.cpp b/src/tools/imgtool/library.cpp
index 9b04eecb03a..785054575b0 100644
--- a/src/tools/imgtool/library.cpp
+++ b/src/tools/imgtool/library.cpp
@@ -18,6 +18,126 @@
namespace imgtool {
+datetime::imgtool_clock::duration datetime::s_gmt_offset = datetime::calculate_gmt_offset();
+
+//-------------------------------------------------
+// datetime ctor
+//-------------------------------------------------
+
+datetime::datetime(datetime_type type, std::chrono::time_point<std::chrono::system_clock> tp)
+ : m_type(type)
+ , m_time_point(imgtool_clock::from_system_clock(tp))
+{
+}
+
+
+//-------------------------------------------------
+// datetime ctor
+//-------------------------------------------------
+
+datetime::datetime(datetime_type type, time_t t)
+ : datetime(type, std::chrono::system_clock::from_time_t(t))
+{
+}
+
+
+//-------------------------------------------------
+// datetime ctor
+//-------------------------------------------------
+
+datetime::datetime(datetime_type type, const util::arbitrary_datetime &dt, bool clamp)
+ : m_type(type)
+ , m_time_point(imgtool_clock::from_arbitrary_datetime(dt, clamp))
+{
+}
+
+
+//-------------------------------------------------
+// datetime::now
+//-------------------------------------------------
+
+datetime datetime::now(datetime_type type)
+{
+ return imgtool::datetime(
+ type,
+ std::chrono::system_clock::now());
+}
+
+
+//-------------------------------------------------
+// datetime::localtime
+//-------------------------------------------------
+
+std::tm datetime::localtime() const
+{
+ imgtool_clock::time_point tp;
+
+ switch (type())
+ {
+ case datetime_type::LOCAL:
+ tp = time_point();
+ break;
+ case datetime_type::GMT:
+ tp = time_point() + s_gmt_offset;
+ break;
+ default:
+ tp = imgtool_clock::time_point();
+ break;
+ }
+ return imgtool_clock::to_tm(tp);
+}
+
+
+//-------------------------------------------------
+// datetime::gmtime
+//-------------------------------------------------
+
+std::tm datetime::gmtime() const
+{
+ imgtool_clock::time_point tp;
+
+ switch (type())
+ {
+ case datetime_type::GMT:
+ tp = time_point();
+ break;
+ case datetime_type::LOCAL:
+ tp = time_point() - s_gmt_offset;
+ break;
+ default:
+ tp = imgtool_clock::time_point();
+ break;
+ }
+ return imgtool_clock::to_tm(tp);
+}
+
+
+//-------------------------------------------------
+// datetime::calculate_gmt_offset
+//-------------------------------------------------
+
+datetime::imgtool_clock::duration datetime::calculate_gmt_offset()
+{
+ time_t t = time(nullptr);
+ std::tm utc_tm = *std::gmtime(&t);
+ time_t utc = mktime(&utc_tm);
+ std::tm local_tm = *std::localtime(&t);
+ time_t local = mktime(&local_tm);
+ double d = difftime(local, utc) * imgtool_clock::period::den / imgtool_clock::period::num;
+ return imgtool_clock::duration((std::int64_t) d);
+}
+
+
+//-------------------------------------------------
+// datetime::to_time_t
+//-------------------------------------------------
+
+time_t datetime::to_time_t() const
+{
+ auto system_clock_tp = imgtool_clock::to_system_clock(time_point());
+ return std::chrono::system_clock::to_time_t(system_clock_tp);
+}
+
//-------------------------------------------------
// ctor
diff --git a/src/tools/imgtool/library.h b/src/tools/imgtool/library.h
index ec508bcbd0e..cf1e16a111b 100644
--- a/src/tools/imgtool/library.h
+++ b/src/tools/imgtool/library.h
@@ -19,6 +19,7 @@
#include <time.h>
#include <list>
+#include <chrono>
#include "corestr.h"
#include "opresolv.h"
@@ -26,6 +27,7 @@
#include "unicode.h"
#include "charconv.h"
#include "pool.h"
+#include "timeconv.h"
namespace imgtool
{
@@ -55,15 +57,78 @@ union filterinfo
typedef void (*filter_getinfoproc)(uint32_t state, union filterinfo *info);
+namespace imgtool
+{
+ class datetime
+ {
+ public:
+ typedef util::arbitrary_clock<std::int64_t, 1600, 1, 1, 0, 0, 0, std::ratio<1, 10000000> > imgtool_clock;
+
+ enum datetime_type
+ {
+ NONE,
+ LOCAL,
+ GMT
+ };
+
+ datetime()
+ : m_type(datetime_type::NONE)
+ {
+ }
+
+
+ template<typename Rep, int Y, int M, int D, int H, int N, int S, typename Ratio>
+ datetime(datetime_type type, std::chrono::time_point<util::arbitrary_clock<Rep, Y, M, D, H, N, S, Ratio> > tp)
+ : m_type(type)
+ , m_time_point(imgtool_clock::from_arbitrary_time_point(tp))
+ {
+ }
+
+ datetime(datetime_type type, std::chrono::time_point<std::chrono::system_clock> tp);
+ datetime(datetime_type type, time_t t);
+ datetime(datetime_type type, const util::arbitrary_datetime &dt, bool clamp = true);
+ datetime(const datetime &that) = default;
+ datetime(datetime &&that) = default;
+
+ // accessors
+ datetime_type type() const { return m_type; }
+ bool empty() const { return type() == datetime_type::NONE; }
+ std::chrono::time_point<imgtool_clock> time_point() const { return m_time_point; }
+
+ // operators
+ datetime &operator =(const datetime &that)
+ {
+ m_type = that.m_type;
+ m_time_point = that.m_time_point;
+ return *this;
+ }
+
+ // returns the current time
+ static datetime now(datetime_type type);
+
+ // returns time structures
+ std::tm localtime() const;
+ std::tm gmtime() const;
+ time_t to_time_t() const;
+
+ private:
+ static imgtool_clock::duration s_gmt_offset;
+ datetime_type m_type;
+ std::chrono::time_point<imgtool_clock> m_time_point;
+
+ static imgtool_clock::duration calculate_gmt_offset();
+ };
+};
+
struct imgtool_dirent
{
char filename[1024];
char attr[64];
uint64_t filesize;
- time_t creation_time;
- time_t lastmodified_time;
- time_t lastaccess_time;
+ imgtool::datetime creation_time;
+ imgtool::datetime lastmodified_time;
+ imgtool::datetime lastaccess_time;
char softlink[1024];
char comment[256];
diff --git a/src/tools/imgtool/main.cpp b/src/tools/imgtool/main.cpp
index ee3f603dc6f..50c65845ddb 100644
--- a/src/tools/imgtool/main.cpp
+++ b/src/tools/imgtool/main.cpp
@@ -234,9 +234,11 @@ static int cmd_dir(const struct command *c, int argc, char *argv[])
? "<DIR>"
: string_format("%u", (unsigned int) ent.filesize);
- if (ent.lastmodified_time != 0)
- strftime(last_modified, sizeof(last_modified), "%d-%b-%y %H:%M:%S",
- localtime(&ent.lastmodified_time));
+ if (!ent.lastmodified_time.empty())
+ {
+ std::tm t = ent.lastmodified_time.localtime();
+ strftime(last_modified, sizeof(last_modified), "%d-%b-%y %H:%M:%S", &t);
+ }
if (ent.hardlink)
strcat(ent.filename, " <hl>");
diff --git a/src/tools/imgtool/modules/amiga.cpp b/src/tools/imgtool/modules/amiga.cpp
index 7a7a3572320..c1c5563012e 100644
--- a/src/tools/imgtool/modules/amiga.cpp
+++ b/src/tools/imgtool/modules/amiga.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Dirk Best
/****************************************************************************
- amiga.c
+ amiga.cpp
Amiga floppies
@@ -290,15 +290,11 @@ static int is_leap(int year)
/* Convert amiga time to standard time */
-static time_t amiga_crack_time(amiga_date *date)
+static imgtool::datetime amiga_crack_time(amiga_date *date)
{
int month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int year = 1978, month = 1, year_days = 365; /* base date */
int day = date->days;
- struct tm t;
-
- /* initialize struct */
- memset(&t, 0, sizeof(t));
/* first calculate the year */
while (day >= year_days)
@@ -316,15 +312,16 @@ static time_t amiga_crack_time(amiga_date *date)
month++;
}
- /* fill the struct with our calculated values */
- t.tm_year = year - 1900;
- t.tm_mon = month - 1;
- t.tm_mday = day + 1;
- t.tm_hour = date->mins / 60;
- t.tm_min = date->mins % 60;
- t.tm_sec = date->ticks / 50;
+ // fill the struct with our calculated values
+ util::arbitrary_datetime dt;
+ dt.year = year;
+ dt.month = month;
+ dt.day_of_month = day;
+ dt.hour = date->mins / 60;
+ dt.minute = date->mins % 60;
+ dt.second = date->ticks / 50;
- return mktime(&t);
+ return imgtool::datetime(imgtool::datetime::datetime_type::LOCAL, dt);
}
@@ -1785,9 +1782,9 @@ static void amiga_image_info(imgtool::image &img, std::ostream &stream)
ret = read_root_block(img, &root);
if (ret) return;
- t_c = amiga_crack_time(&root.c);
- t_v = amiga_crack_time(&root.v);
- t_r = amiga_crack_time(&root.r);
+ t_c = amiga_crack_time(&root.c).to_time_t();
+ t_v = amiga_crack_time(&root.v).to_time_t();
+ t_r = amiga_crack_time(&root.r).to_time_t();
strftime(c, sizeof(c), "%d-%b-%y %H:%M:%S", localtime(&t_c));
strftime(v, sizeof(v), "%d-%b-%y %H:%M:%S", localtime(&t_v));
diff --git a/src/tools/imgtool/modules/cybiko.cpp b/src/tools/imgtool/modules/cybiko.cpp
index 81184533291..4ba278ddd2b 100644
--- a/src/tools/imgtool/modules/cybiko.cpp
+++ b/src/tools/imgtool/modules/cybiko.cpp
@@ -64,15 +64,19 @@ static cybiko_file_system *get_cfs(imgtool::image &image)
}
// 2208988800 is the number of seconds between 1900/01/01 and 1970/01/01
+typedef util::arbitrary_clock<std::uint32_t, 1900, 1, 1, 0, 0, 0, std::ratio<1, 1> > cybiko_clock;
-static time_t time_crack( uint32_t cfs_time)
+imgtool::datetime cybiko_time_crack(uint32_t cfs_time)
{
- return (time_t)(cfs_time - 2208988800UL);
+ cybiko_clock::duration d(cfs_time);
+ std::chrono::time_point<cybiko_clock> tp(d);
+ return imgtool::datetime(imgtool::datetime::datetime_type::LOCAL, tp);
}
-static uint32_t time_setup( time_t ansi_time)
+uint32_t cybiko_time_setup(const imgtool::datetime &t)
{
- return (uint32_t)(ansi_time + 2208988800UL);
+ auto cybiko_time_point = cybiko_clock::from_arbitrary_time_point(t.time_point());
+ return cybiko_time_point.time_since_epoch().count();
}
static uint32_t buffer_read_32_be( uint8_t *buffer)
@@ -412,7 +416,7 @@ static imgtoolerr_t cybiko_image_next_enum(imgtool::directory &enumeration, imgt
{
strcpy(ent.filename, file.name);
ent.filesize = file.size;
- ent.lastmodified_time = time_crack(file.date);
+ ent.lastmodified_time = cybiko_time_crack(file.date);
ent.filesize = file.size;
}
else
@@ -501,7 +505,7 @@ static imgtoolerr_t cybiko_image_write_file(imgtool::partition &partition, const
{
buffer[6] = 0;
strcpy(BLOCK_FILENAME(buffer), filename);
- buffer_write_32_be( buffer + 6 + FILE_HEADER_SIZE - 4, time_setup( time( NULL)));
+ buffer_write_32_be(buffer + 6 + FILE_HEADER_SIZE - 4, cybiko_time_setup(imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL)));
sourcef.read(buffer + 6 + FILE_HEADER_SIZE, buffer[1]);
}
else
diff --git a/src/tools/imgtool/modules/cybikoxt.cpp b/src/tools/imgtool/modules/cybikoxt.cpp
index a649dbe8909..8c2980de449 100644
--- a/src/tools/imgtool/modules/cybikoxt.cpp
+++ b/src/tools/imgtool/modules/cybikoxt.cpp
@@ -55,17 +55,8 @@ static cybiko_file_system *get_cfs(imgtool::image &image)
return (cybiko_file_system*)image.extra_bytes();
}
-// 2208988800 is the number of seconds between 1900/01/01 and 1970/01/01
-
-static time_t time_crack( uint32_t cfs_time)
-{
- return (time_t)(cfs_time - 2208988800UL);
-}
-
-static uint32_t time_setup( time_t ansi_time)
-{
- return (uint32_t)(ansi_time + 2208988800UL);
-}
+extern imgtool::datetime cybiko_time_crack(uint32_t cfs_time);
+extern uint32_t cybiko_time_setup(const imgtool::datetime &t);
static uint32_t buffer_read_32_be( uint8_t *buffer)
{
@@ -382,7 +373,7 @@ static imgtoolerr_t cybiko_image_next_enum(imgtool::directory &enumeration, imgt
{
strcpy(ent.filename, file.name);
ent.filesize = file.size;
- ent.lastmodified_time = time_crack(file.date);
+ ent.lastmodified_time = cybiko_time_crack(file.date);
ent.filesize = file.size;
}
else
@@ -475,7 +466,7 @@ static imgtoolerr_t cybiko_image_write_file(imgtool::partition &partition, const
{
buffer[6] = 0x20;
strcpy(BLOCK_FILENAME(buffer), filename);
- buffer_write_32_be( buffer + 6 + FILE_HEADER_SIZE - 4, time_setup( time( NULL)));
+ buffer_write_32_be( buffer + 6 + FILE_HEADER_SIZE - 4, cybiko_time_setup(imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL)));
sourcef.read(buffer + 6 + FILE_HEADER_SIZE, buffer[1]);
}
else
diff --git a/src/tools/imgtool/modules/fat.cpp b/src/tools/imgtool/modules/fat.cpp
index aa15a4783f6..3dcdd1e5301 100644
--- a/src/tools/imgtool/modules/fat.cpp
+++ b/src/tools/imgtool/modules/fat.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Raphael Nabet
/****************************************************************************
- fat.c
+ fat.cpp
PC FAT disk images
@@ -184,8 +184,8 @@ struct fat_dirent
uint32_t first_cluster;
uint32_t dirent_sector_index;
uint32_t dirent_sector_offset;
- time_t creation_time;
- time_t lastmodified_time;
+ imgtool::datetime creation_time;
+ imgtool::datetime lastmodified_time;
};
struct fat_freeentry_info
@@ -1241,33 +1241,25 @@ static void fat_cannonicalize_sfn(char *sfn, const uint8_t *sfn_bytes)
-static time_t fat_crack_time(uint32_t fat_time)
+static imgtool::datetime fat_crack_time(uint32_t fat_time)
{
- struct tm t;
- time_t now;
-
- time(&now);
- t = *localtime(&now);
-
- t.tm_sec = ((fat_time >> 0) & 0x001F) * 2;
- t.tm_min = ((fat_time >> 5) & 0x003F);
- t.tm_hour = ((fat_time >> 11) & 0x001F);
- t.tm_mday = ((fat_time >> 16) & 0x001F);
- t.tm_mon = ((fat_time >> 21) & 0x000F);
- t.tm_year = ((fat_time >> 25) & 0x007F) + 1980 - 1900;
-
- return mktime(&t);
+ util::arbitrary_datetime dt;
+ dt.second = ((fat_time >> 0) & 0x001F) * 2;
+ dt.minute = ((fat_time >> 5) & 0x003F);
+ dt.hour = ((fat_time >> 11) & 0x001F);
+ dt.day_of_month = ((fat_time >> 16) & 0x001F);
+ dt.month = ((fat_time >> 21) & 0x000F);
+ dt.year = ((fat_time >> 25) & 0x007F) + 1980;
+ return imgtool::datetime(imgtool::datetime::LOCAL, dt);
}
static uint32_t fat_setup_time(time_t ansi_time)
{
- struct tm t;
- uint32_t result = 0;
-
- t = *localtime(&ansi_time);
+ std::tm t = *localtime(&ansi_time);
+ uint32_t result = 0;
result |= (((uint32_t) (t.tm_sec / 2)) & 0x001F) << 0;
result |= (((uint32_t) t.tm_min) & 0x003F) << 5;
result |= (((uint32_t) t.tm_hour) & 0x001F) << 11;
diff --git a/src/tools/imgtool/modules/mac.cpp b/src/tools/imgtool/modules/mac.cpp
index 546a153a7e8..f606451c6e1 100644
--- a/src/tools/imgtool/modules/mac.cpp
+++ b/src/tools/imgtool/modules/mac.cpp
@@ -5827,10 +5827,10 @@ static imgtoolerr_t mac_image_getattrs(imgtool::partition &partition, const char
break;
case IMGTOOLATTR_TIME_CREATED:
- values[i].t = mac_crack_time(cat_info.createDate);
+ values[i].t = mac_crack_time(cat_info.createDate).to_time_t();
break;
case IMGTOOLATTR_TIME_LASTMODIFIED:
- values[i].t = mac_crack_time(cat_info.modifyDate);
+ values[i].t = mac_crack_time(cat_info.modifyDate).to_time_t();
break;
}
}
diff --git a/src/tools/imgtool/modules/macbin.cpp b/src/tools/imgtool/modules/macbin.cpp
index c937ff22163..30400dffdbb 100644
--- a/src/tools/imgtool/modules/macbin.cpp
+++ b/src/tools/imgtool/modules/macbin.cpp
@@ -323,8 +323,8 @@ static imgtoolerr_t macbinary_writefile(imgtool::partition &partition, const cha
return err;
/* set up attributes */
- attr_values[0].t = mac_crack_time(creation_time);
- attr_values[1].t = mac_crack_time(lastmodified_time);
+ attr_values[0].t = mac_crack_time(creation_time).to_time_t();
+ attr_values[1].t = mac_crack_time(lastmodified_time).to_time_t();
attr_values[2].i = type_code;
attr_values[3].i = creator_code;
attr_values[4].i = finder_flags;
diff --git a/src/tools/imgtool/modules/macutil.cpp b/src/tools/imgtool/modules/macutil.cpp
index 1bab14487cd..08c8b84989f 100644
--- a/src/tools/imgtool/modules/macutil.cpp
+++ b/src/tools/imgtool/modules/macutil.cpp
@@ -15,32 +15,54 @@
typedef util::arbitrary_clock<std::uint32_t, 1904, 1, 1, 0, 0, 0, std::ratio<1, 1> > classic_mac_clock;
-time_t mac_crack_time(uint32_t t)
+//-------------------------------------------------
+// mac_crack_time
+//-------------------------------------------------
+
+imgtool::datetime mac_crack_time(uint32_t t)
{
classic_mac_clock::duration d(t);
- std::chrono::time_point<std::chrono::system_clock> tp = classic_mac_clock::to_system_clock(std::chrono::time_point<classic_mac_clock>(d));
- return std::chrono::system_clock::to_time_t(tp);
+ std::chrono::time_point<classic_mac_clock> tp(d);
+ return imgtool::datetime(imgtool::datetime::datetime_type::LOCAL, tp);
}
+//-------------------------------------------------
+// mac_setup_time
+//-------------------------------------------------
-uint32_t mac_setup_time(time_t t)
+uint32_t mac_setup_time(const imgtool::datetime &t)
{
- auto system_time_point = std::chrono::system_clock::from_time_t(t);
- auto mac_time_point = classic_mac_clock::from_system_clock(system_time_point);
+ auto mac_time_point = classic_mac_clock::from_arbitrary_time_point(t.time_point());
return mac_time_point.time_since_epoch().count();
}
+//-------------------------------------------------
+// mac_setup_time
+//-------------------------------------------------
+
+uint32_t mac_setup_time(time_t t)
+{
+ imgtool::datetime dt(imgtool::datetime::datetime_type::LOCAL, t);
+ return mac_setup_time(dt);
+}
+
+
+//-------------------------------------------------
+// mac_time_now
+//-------------------------------------------------
uint32_t mac_time_now(void)
{
- time_t now;
- time(&now);
- return mac_setup_time(now);
+ imgtool::datetime dt = imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL);
+ return mac_setup_time(dt);
}
+//-------------------------------------------------
+// mac_identify_fork
+//-------------------------------------------------
imgtoolerr_t mac_identify_fork(const char *fork_string, mac_fork_t *fork_num)
{
diff --git a/src/tools/imgtool/modules/macutil.h b/src/tools/imgtool/modules/macutil.h
index fcec0728c95..0ab3315874b 100644
--- a/src/tools/imgtool/modules/macutil.h
+++ b/src/tools/imgtool/modules/macutil.h
@@ -29,7 +29,8 @@ enum mac_filecategory_t
/* converting Classic Mac OS time <==> Imgtool time */
-time_t mac_crack_time(uint32_t t);
+imgtool::datetime mac_crack_time(uint32_t t);
+uint32_t mac_setup_time(const imgtool::datetime &t);
uint32_t mac_setup_time(time_t t);
uint32_t mac_time_now(void);
diff --git a/src/tools/imgtool/modules/prodos.cpp b/src/tools/imgtool/modules/prodos.cpp
index 4c01612283f..f5b27537671 100644
--- a/src/tools/imgtool/modules/prodos.cpp
+++ b/src/tools/imgtool/modules/prodos.cpp
@@ -186,24 +186,19 @@ enum creation_policy_t
-static time_t prodos_crack_time(uint32_t prodos_time)
-{
- struct tm t;
- time_t now;
-
- time(&now);
- t = *localtime(&now);
-
- t.tm_sec = 0;
- t.tm_min = (prodos_time >> 16) & 0x3F;
- t.tm_hour = (prodos_time >> 24) & 0x1F;
- t.tm_mday = (prodos_time >> 0) & 0x1F;
- t.tm_mon = (prodos_time >> 5) & 0x0F;
- t.tm_year = (prodos_time >> 9) & 0x7F;
-
- if (t.tm_year <= 49)
- t.tm_year += 100;
- return mktime(&t);
+static imgtool::datetime prodos_crack_time(uint32_t prodos_time)
+{
+ util::arbitrary_datetime dt;
+ dt.second = 0;
+ dt.minute = ((prodos_time >> 16) & 0x3F);
+ dt.hour = ((prodos_time >> 24) & 0x1F);
+ dt.day_of_month = ((prodos_time >> 0) & 0x1F);
+ dt.month = ((prodos_time >> 5) & 0x0F) + 1;
+ dt.year = ((prodos_time >> 9) & 0x7F) + 1900;
+ if (dt.year <= 1949)
+ dt.year += 100;
+
+ return imgtool::datetime(imgtool::datetime::datetime_type::LOCAL, dt);
}
@@ -2039,10 +2034,10 @@ static imgtoolerr_t prodos_diskimage_getattrs(imgtool::partition &partition, con
break;
case IMGTOOLATTR_TIME_CREATED:
- values[i].t = prodos_crack_time(ent.creation_time);
+ values[i].t = prodos_crack_time(ent.creation_time).to_time_t();
break;
case IMGTOOLATTR_TIME_LASTMODIFIED:
- values[i].t = prodos_crack_time(ent.lastmodified_time);
+ values[i].t = prodos_crack_time(ent.lastmodified_time).to_time_t();
break;
}
}
diff --git a/src/tools/imgtool/modules/thomson.cpp b/src/tools/imgtool/modules/thomson.cpp
index d7adce9dbb9..d2848a00cde 100644
--- a/src/tools/imgtool/modules/thomson.cpp
+++ b/src/tools/imgtool/modules/thomson.cpp
@@ -485,24 +485,20 @@ static void thom_conv_filename(const char* s, char name[9], char ext[4])
}
}
-static time_t thom_crack_time(thom_dirent* d)
+static imgtool::datetime thom_crack_time(thom_dirent* d)
{
- struct tm t;
- time_t now;
-
/* check */
- if ( d->day < 1 || d->day > 31 || d->month < 1 || d->month > 12 ) return 0;
+ if ( d->day < 1 || d->day > 31 || d->month < 1 || d->month > 12 ) return imgtool::datetime();
/* converts */
- time( &now );
- t = *localtime( &now );
- t.tm_sec = 0;
- t.tm_min = 0;
- t.tm_hour = 0;
- t.tm_mday = d->day;
- t.tm_mon = d->month - 1;
- t.tm_year = (d->year < 65 ) ? d->year + 100 : d->year;
- return mktime(&t);
+ util::arbitrary_datetime dt;
+ dt.second = 0;
+ dt.minute = 0;
+ dt.hour = 0;
+ dt.day_of_month = d->day;
+ dt.month = d->month;
+ dt.year = d->year + (d->year < 65 ? 2000 : 1900);
+ return imgtool::datetime(imgtool::datetime::datetime_type::LOCAL, dt);
}
static void thom_make_time(thom_dirent* d, time_t time)