diff options
author | 2017-10-17 15:18:57 -0400 | |
---|---|---|
committer | 2017-10-17 21:18:57 +0200 | |
commit | 86f50b0d65e78f71d046218ffe7833271023d8c8 (patch) | |
tree | d16ad18dd925dcd16c3750b44291b877afc7a0a1 | |
parent | 78c658c7a2bb2ee9e3f721dad292cb951d8f30ad (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.h | 82 | ||||
-rw-r--r-- | src/tools/imgtool/imgtool.cpp | 79 | ||||
-rw-r--r-- | src/tools/imgtool/library.cpp | 120 | ||||
-rw-r--r-- | src/tools/imgtool/library.h | 71 | ||||
-rw-r--r-- | src/tools/imgtool/main.cpp | 8 | ||||
-rw-r--r-- | src/tools/imgtool/modules/amiga.cpp | 31 | ||||
-rw-r--r-- | src/tools/imgtool/modules/cybiko.cpp | 16 | ||||
-rw-r--r-- | src/tools/imgtool/modules/cybikoxt.cpp | 17 | ||||
-rw-r--r-- | src/tools/imgtool/modules/fat.cpp | 36 | ||||
-rw-r--r-- | src/tools/imgtool/modules/mac.cpp | 4 | ||||
-rw-r--r-- | src/tools/imgtool/modules/macbin.cpp | 4 | ||||
-rw-r--r-- | src/tools/imgtool/modules/macutil.cpp | 40 | ||||
-rw-r--r-- | src/tools/imgtool/modules/macutil.h | 3 | ||||
-rw-r--r-- | src/tools/imgtool/modules/prodos.cpp | 35 | ||||
-rw-r--r-- | src/tools/imgtool/modules/thomson.cpp | 24 |
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) |