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.
This commit is contained in:
npwoods 2017-10-17 15:18:57 -04:00 committed by hap
parent 78c658c7a2
commit 86f50b0d65
15 changed files with 447 additions and 119 deletions

View File

@ -34,6 +34,21 @@ extern std::chrono::system_clock::duration system_clock_adjustment;
typedef std::chrono::duration<std::uint64_t, std::ratio<1, 10000000> > ntfs_duration;
//---------------------------------------------------------
// 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
@ -54,6 +69,17 @@ public:
static constexpr int base_minute = N;
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);
arbitrary_datetime dt;
dt.year = Y2;
dt.month = M2;
dt.day_of_month = D2;
dt.hour = H2;
dt.minute = N2;
dt.second = S2;
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));
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

View File

@ -752,6 +752,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;

View File

@ -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

View File

@ -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];

View File

@ -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>");

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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;
std::tm t = *localtime(&ansi_time);
uint32_t result = 0;
t = *localtime(&ansi_time);
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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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_time_now(void)
uint32_t mac_setup_time(time_t t)
{
time_t now;
time(&now);
return mac_setup_time(now);
imgtool::datetime dt(imgtool::datetime::datetime_type::LOCAL, t);
return mac_setup_time(dt);
}
//-------------------------------------------------
// mac_time_now
//-------------------------------------------------
uint32_t mac_time_now(void)
{
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)
{

View File

@ -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);

View File

@ -186,24 +186,19 @@ enum creation_policy_t
static time_t prodos_crack_time(uint32_t prodos_time)
static imgtool::datetime prodos_crack_time(uint32_t prodos_time)
{
struct tm t;
time_t now;
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;
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);
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;
}
}

View File

@ -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)