Merge pull request #655 from inckie/bugfix_filetime
Make vfs::Entry time stamps consistent (as Windows FILETIME)
This commit is contained in:
commit
2070570307
|
@ -127,9 +127,11 @@ bool DiscImageDevice::ReadEntry(ParseState* state, const uint8_t* buffer,
|
||||||
entry->attributes_ = attributes | kFileAttributeReadOnly;
|
entry->attributes_ = attributes | kFileAttributeReadOnly;
|
||||||
entry->size_ = length;
|
entry->size_ = length;
|
||||||
entry->allocation_size_ = xe::round_up(length, bytes_per_sector());
|
entry->allocation_size_ = xe::round_up(length, bytes_per_sector());
|
||||||
entry->create_timestamp_ = 0;
|
|
||||||
entry->access_timestamp_ = 0;
|
// Set to January 1, 1970 (UTC) in 100-nanosecond intervals
|
||||||
entry->write_timestamp_ = 0;
|
entry->create_timestamp_ = 10000 * 11644473600000LL;
|
||||||
|
entry->access_timestamp_ = 10000 * 11644473600000LL;
|
||||||
|
entry->write_timestamp_ = 10000 * 11644473600000LL;
|
||||||
|
|
||||||
if (attributes & kFileAttributeDirectory) {
|
if (attributes & kFileAttributeDirectory) {
|
||||||
// Folder.
|
// Folder.
|
||||||
|
|
|
@ -16,6 +16,11 @@
|
||||||
#include "xenia/base/math.h"
|
#include "xenia/base/math.h"
|
||||||
#include "xenia/vfs/devices/stfs_container_entry.h"
|
#include "xenia/vfs/devices/stfs_container_entry.h"
|
||||||
|
|
||||||
|
#if XE_PLATFORM_WIN32
|
||||||
|
#include "xenia/base/platform_win.h"
|
||||||
|
#define timegm _mkgmtime
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace vfs {
|
namespace vfs {
|
||||||
|
|
||||||
|
@ -28,6 +33,25 @@ uint32_t load_uint24_le(const uint8_t* p) {
|
||||||
(static_cast<uint32_t>(p[1]) << 8) | static_cast<uint32_t>(p[0]);
|
(static_cast<uint32_t>(p[1]) << 8) | static_cast<uint32_t>(p[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert FAT timestamp to 100-nanosecond intervals since January 1, 1601 (UTC)
|
||||||
|
uint64_t decode_fat_timestamp(uint32_t date, uint32_t time) {
|
||||||
|
struct tm tm = {0};
|
||||||
|
// 80 is the difference between 1980 (FAT) and 1900 (tm);
|
||||||
|
tm.tm_year = ((0xFE00 & date) >> 9) + 80;
|
||||||
|
tm.tm_mon = (0x01E0 & date) >> 5;
|
||||||
|
tm.tm_mday = (0x001F & date) >> 0;
|
||||||
|
tm.tm_hour = (0xF800 & time) >> 11;
|
||||||
|
tm.tm_min = (0x07E0 & time) >> 5;
|
||||||
|
tm.tm_sec = (0x001F & time) << 1; // the value stored in 2-seconds intervals
|
||||||
|
tm.tm_isdst = 0;
|
||||||
|
time_t timet = timegm(&tm);
|
||||||
|
if (timet == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// 11644473600LL is a difference between 1970 and 1601
|
||||||
|
return (timet + 11644473600LL) * 10000000;
|
||||||
|
}
|
||||||
|
|
||||||
StfsContainerDevice::StfsContainerDevice(const std::string& mount_path,
|
StfsContainerDevice::StfsContainerDevice(const std::string& mount_path,
|
||||||
const std::wstring& local_path)
|
const std::wstring& local_path)
|
||||||
: Device(mount_path), local_path_(local_path) {}
|
: Device(mount_path), local_path_(local_path) {}
|
||||||
|
@ -157,8 +181,12 @@ StfsContainerDevice::Error StfsContainerDevice::ReadAllEntries(
|
||||||
uint32_t start_block_index = load_uint24_le(p + 0x2F);
|
uint32_t start_block_index = load_uint24_le(p + 0x2F);
|
||||||
uint16_t path_indicator = xe::load_and_swap<uint16_t>(p + 0x32);
|
uint16_t path_indicator = xe::load_and_swap<uint16_t>(p + 0x32);
|
||||||
uint32_t file_size = xe::load_and_swap<uint32_t>(p + 0x34);
|
uint32_t file_size = xe::load_and_swap<uint32_t>(p + 0x34);
|
||||||
uint32_t update_timestamp = xe::load_and_swap<uint32_t>(p + 0x38);
|
|
||||||
uint32_t access_timestamp = xe::load_and_swap<uint32_t>(p + 0x3C);
|
// both date and time parts of the timestamp are big endian
|
||||||
|
uint16_t update_date = xe::load_and_swap<uint16_t>(p + 0x38);
|
||||||
|
uint16_t update_time = xe::load_and_swap<uint16_t>(p + 0x3A);
|
||||||
|
uint32_t access_date = xe::load_and_swap<uint16_t>(p + 0x3C);
|
||||||
|
uint32_t access_time = xe::load_and_swap<uint16_t>(p + 0x3E);
|
||||||
p += 0x40;
|
p += 0x40;
|
||||||
|
|
||||||
StfsContainerEntry* parent_entry = nullptr;
|
StfsContainerEntry* parent_entry = nullptr;
|
||||||
|
@ -184,9 +212,11 @@ StfsContainerDevice::Error StfsContainerDevice::ReadAllEntries(
|
||||||
}
|
}
|
||||||
entry->size_ = file_size;
|
entry->size_ = file_size;
|
||||||
entry->allocation_size_ = xe::round_up(file_size, bytes_per_sector());
|
entry->allocation_size_ = xe::round_up(file_size, bytes_per_sector());
|
||||||
entry->create_timestamp_ = update_timestamp;
|
|
||||||
entry->access_timestamp_ = access_timestamp;
|
entry->create_timestamp_ = decode_fat_timestamp(update_date, update_time);
|
||||||
entry->write_timestamp_ = update_timestamp;
|
entry->access_timestamp_ = decode_fat_timestamp(access_date, access_time);
|
||||||
|
entry->write_timestamp_ = entry->create_timestamp_;
|
||||||
|
|
||||||
all_entries.push_back(entry.get());
|
all_entries.push_back(entry.get());
|
||||||
|
|
||||||
// Fill in all block records.
|
// Fill in all block records.
|
||||||
|
|
Loading…
Reference in New Issue