diff --git a/src/add-ons/kernel/file_systems/udf/Utils.cpp b/src/add-ons/kernel/file_systems/udf/Utils.cpp index b1e556eaad..a5f1d517b1 100644 --- a/src/add-ons/kernel/file_systems/udf/Utils.cpp +++ b/src/add-ons/kernel/file_systems/udf/Utils.cpp @@ -12,6 +12,15 @@ #include "Utils.h" +extern "C" { + #ifndef _IMPEXP_KERNEL + # define _IMPEXP_KERNEL + #endif + + extern int32 timezone_offset; +} + + namespace Udf { udf_long_address @@ -32,4 +41,58 @@ to_vnode_id(udf_long_address address) return (address.block() << 16) | (address.partition()); } +time_t +make_time(udf_timestamp ×tamp) +{ + DEBUG_INIT_ETC(CF_HELPER | CF_HIGH_VOLUME, NULL, ("timestamp: (tnt: 0x%x, type: %d, timezone: %d = 0x%x, year: %d, " + "month: %d, day: %d, hour: %d, minute: %d, second: %d)", timestamp.type_and_timezone(), + timestamp.type(), timestamp.timezone(), + timestamp.timezone(),timestamp.year(), + timestamp.month(), timestamp.day(), timestamp.hour(), timestamp.minute(), timestamp.second())); + + time_t result = 0; + + if (timestamp.year() >= 1970) { + const int monthLengths[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + int year = timestamp.year(); + int month = timestamp.month(); + int day = timestamp.day(); + int hour = timestamp.hour(); + int minute = timestamp.minute(); + int second = timestamp.second(); + + // Range check the timezone offset, then round it down + // to the nearest hour, since no one I know treats timezones + // with a per-minute granularity, and none of the other OSes + // I've looked at appear to either. + int timezone_offset = timestamp.timezone(); + if (-1440 > timezone_offset || timezone_offset > 1440) + timezone_offset = 0; + timezone_offset -= timezone_offset % 60; + + int previousLeapYears = (year - 1968) / 4; + bool isLeapYear = (year - 1968) % 4 == 0; + if (isLeapYear) + --previousLeapYears; + + // Years to days + result = (year - 1970) * 365 + previousLeapYears; + // Months to days + for (int i = 0; i < month-1; i++) { + result += monthLengths[i]; + } + if (month > 2 && isLeapYear) + ++result; + // Days to hours + result = (result + day - 1) * 24; + // Hours to minutes + result = (result + hour) * 60 + timezone_offset; + // Minutes to seconds + result = (result + minute) * 60 + second; + } + + return result; +} + } // namespace Udf diff --git a/src/add-ons/kernel/file_systems/udf/Utils.h b/src/add-ons/kernel/file_systems/udf/Utils.h index 3bf5453377..5a4d3e32af 100644 --- a/src/add-ons/kernel/file_systems/udf/Utils.h +++ b/src/add-ons/kernel/file_systems/udf/Utils.h @@ -28,6 +28,8 @@ udf_long_address to_long_address(vnode_id id, uint32 length = 0); vnode_id to_vnode_id(udf_long_address address); +time_t make_time(udf_timestamp ×tamp); + } // namespace Udf #endif // _UDF_UTILS_H