summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/un7z.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2016-06-25 20:56:46 +1000
committer Vas Crabb <vas@vastheman.com>2016-06-25 20:56:59 +1000
commit7f22918675bbac5012d88f6ac97921066414b03f (patch)
treeb424dd13021049c1d7bcaaaba2fc082c60690d6b /src/lib/util/un7z.cpp
parent0b37361fdf2aaaf9cc46f378b499b5a395e2492c (diff)
Supply modified time for files in archives [Vas Crabb]
Diffstat (limited to 'src/lib/util/un7z.cpp')
-rw-r--r--src/lib/util/un7z.cpp106
1 files changed, 85 insertions, 21 deletions
diff --git a/src/lib/util/un7z.cpp b/src/lib/util/un7z.cpp
index 75377d4093a..4fee8d156d8 100644
--- a/src/lib/util/un7z.cpp
+++ b/src/lib/util/un7z.cpp
@@ -23,10 +23,13 @@
#include <algorithm>
#include <array>
#include <cassert>
+#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <cstring>
+#include <ctime>
#include <mutex>
+#include <ratio>
#include <utility>
#include <vector>
@@ -145,11 +148,14 @@ public:
bool current_is_directory() const { return m_curr_is_dir; }
const std::string &current_name() const { return m_curr_name; }
std::uint64_t current_uncompressed_length() const { return m_curr_length; }
+ virtual std::chrono::system_clock::time_point current_last_modified() const { return m_curr_modified; }
std::uint32_t current_crc() const { return m_curr_crc; }
archive_file::error decompress(void *buffer, std::uint32_t length);
private:
+ typedef std::chrono::duration<std::uint64_t, std::ratio<1, 10000000> > ntfs_duration;
+
m7z_file_impl(const m7z_file_impl &) = delete;
m7z_file_impl(m7z_file_impl &&) = delete;
m7z_file_impl &operator=(const m7z_file_impl &) = delete;
@@ -163,34 +169,39 @@ private:
bool matchname,
bool partialpath);
void make_utf8_name(int index);
+ void set_curr_modified();
+
+ static ntfs_duration calculate_ntfs_offset();
- static constexpr std::size_t CACHE_SIZE = 8;
- static std::array<ptr, CACHE_SIZE> s_cache;
- static std::mutex s_cache_mutex;
+ static constexpr std::size_t CACHE_SIZE = 8;
+ static const ntfs_duration s_ntfs_offset;
+ static std::array<ptr, CACHE_SIZE> s_cache;
+ static std::mutex s_cache_mutex;
- const std::string m_filename; // copy of _7Z filename (for caching)
+ const std::string m_filename; // copy of _7Z filename (for caching)
- int m_curr_file_idx; // current file index
- bool m_curr_is_dir; // current file is directory
- std::string m_curr_name; // current file name
- std::uint64_t m_curr_length; // current file uncompressed length
- std::uint32_t m_curr_crc; // current file crc
+ int m_curr_file_idx; // current file index
+ bool m_curr_is_dir; // current file is directory
+ std::string m_curr_name; // current file name
+ std::uint64_t m_curr_length; // current file uncompressed length
+ std::chrono::system_clock::time_point m_curr_modified; // current file modification time
+ std::uint32_t m_curr_crc; // current file crc
- std::vector<UInt16> m_utf16_buf;
- std::vector<unicode_char> m_uchar_buf;
- std::vector<char> m_utf8_buf;
+ std::vector<UInt16> m_utf16_buf;
+ std::vector<unicode_char> m_uchar_buf;
+ std::vector<char> m_utf8_buf;
- CFileInStream m_archive_stream;
- CLookToRead m_look_stream;
- CSzArEx m_db;
- ISzAlloc m_alloc_imp;
- ISzAlloc m_alloc_temp_imp;
- bool m_inited;
+ CFileInStream m_archive_stream;
+ CLookToRead m_look_stream;
+ CSzArEx m_db;
+ ISzAlloc m_alloc_imp;
+ ISzAlloc m_alloc_temp_imp;
+ bool m_inited;
// cached stuff for solid blocks
- UInt32 m_block_index;
- Byte * m_out_buffer;
- std::size_t m_out_buffer_size;
+ UInt32 m_block_index;
+ Byte * m_out_buffer;
+ std::size_t m_out_buffer_size;
};
@@ -220,6 +231,7 @@ public:
virtual bool current_is_directory() const override { return m_impl->current_is_directory(); }
virtual const std::string &current_name() const override { return m_impl->current_name(); }
virtual std::uint64_t current_uncompressed_length() const override { return m_impl->current_uncompressed_length(); }
+ virtual std::chrono::system_clock::time_point current_last_modified() const override { return m_impl->current_last_modified(); }
virtual std::uint32_t current_crc() const override { return m_impl->current_crc(); }
virtual error decompress(void *buffer, std::uint32_t length) override { return m_impl->decompress(buffer, length); }
@@ -234,6 +246,7 @@ private:
GLOBAL VARIABLES
***************************************************************************/
+const m7z_file_impl::ntfs_duration m7z_file_impl::s_ntfs_offset(calculate_ntfs_offset());
std::array<m7z_file_impl::ptr, m7z_file_impl::CACHE_SIZE> m7z_file_impl::s_cache;
std::mutex m7z_file_impl::s_cache_mutex;
@@ -277,6 +290,7 @@ m7z_file_impl::m7z_file_impl(const std::string &filename)
, m_curr_is_dir(false)
, m_curr_name()
, m_curr_length(0)
+ , m_curr_modified()
, m_curr_crc(0)
, m_utf16_buf(128)
, m_uchar_buf(128)
@@ -447,6 +461,7 @@ int m7z_file_impl::search(
m_curr_is_dir = is_dir;
m_curr_name = &m_utf8_buf[0];
m_curr_length = size;
+ set_curr_modified();
m_curr_crc = crc;
return i;
@@ -499,6 +514,55 @@ void m7z_file_impl::make_utf8_name(int index)
m_utf8_buf.resize(out_pos);
}
+
+void m7z_file_impl::set_curr_modified()
+{
+ if (SzBitWithVals_Check(&m_db.MTime, m_curr_file_idx))
+ {
+ CNtfsFileTime const &file_time(m_db.MTime.Vals[m_curr_file_idx]);
+ ntfs_duration const ticks((std::uint64_t(file_time.High) << 32) | std::uint64_t(file_time.Low));
+ m_curr_modified = std::chrono::system_clock::from_time_t(0) + (ticks - s_ntfs_offset);
+ }
+ else
+ {
+ // FIXME: what do we do about a lack of time?
+ }
+}
+
+
+m7z_file_impl::ntfs_duration m7z_file_impl::calculate_ntfs_offset()
+{
+ constexpr auto days_in_year(365);
+ constexpr auto days_in_four_years((days_in_year * 4) + 1);
+ constexpr auto days_in_century((days_in_four_years * 25) - 1);
+ constexpr auto days_in_four_centuries((days_in_century * 4) + 1);
+
+ constexpr ntfs_duration day(std::chrono::hours(24));
+ constexpr ntfs_duration year(day * days_in_year);
+ constexpr ntfs_duration four_years(day * days_in_four_years);
+ constexpr ntfs_duration century(day * days_in_century);
+ constexpr ntfs_duration four_centuries(day * days_in_four_centuries);
+
+ std::time_t const zero(0);
+ std::tm const epoch(*std::gmtime(&zero));
+
+ ntfs_duration result(day * epoch.tm_yday);
+ result += std::chrono::hours(epoch.tm_hour);
+ result += std::chrono::minutes(epoch.tm_min);
+ result += std::chrono::seconds(epoch.tm_sec);
+
+ int years(1900 - 1601 + epoch.tm_year);
+ result += four_centuries * (years / 400);
+ years %= 400;
+ result += century * (years / 100);
+ years %= 100;
+ result += four_years * (years / 4);
+ years %= 4;
+ result += year * years;
+
+ return result;
+}
+
} // anonymous namespace