Skip to content

Commit 45f2376

Browse files
implicitfieldspholz
authored andcommitted
Kernel/FATFS: Add support for writing timestamps
1 parent c3ea257 commit 45f2376

File tree

2 files changed

+56
-4
lines changed

2 files changed

+56
-4
lines changed

Kernel/FileSystem/FATFS/Inode.cpp

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <Kernel/Debug.h>
1010
#include <Kernel/FileSystem/FATFS/Inode.h>
1111
#include <Kernel/Library/KBufferBuilder.h>
12+
#include <Kernel/Tasks/Process.h>
1213

1314
namespace Kernel {
1415

@@ -544,7 +545,7 @@ InodeMetadata FATInode::metadata() const
544545
.gid = 0,
545546
.link_count = 0,
546547
.atime = time_from_packed_dos(m_entry.last_accessed_date, { 0 }),
547-
.ctime = time_from_packed_dos(m_entry.creation_date, m_entry.creation_time),
548+
.ctime = time_from_packed_dos(m_entry.creation_date, m_entry.creation_time) + Duration::from_milliseconds(m_entry.creation_time_seconds * 10),
548549
.mtime = time_from_packed_dos(m_entry.modification_date, m_entry.modification_time),
549550
.dtime = {},
550551
.block_count = cluster_count * fs().m_parameter_block->common_bpb()->sectors_per_cluster,
@@ -623,6 +624,24 @@ ErrorOr<size_t> FATInode::write_bytes_locked(off_t offset, size_t size, UserOrKe
623624
return size;
624625
}
625626

627+
ErrorOr<void> FATInode::fill_in_creation_time(FATEntry& entry, UnixDateTime const& timestamp)
628+
{
629+
auto packed_date = TRY(to_packed_dos_date(timestamp));
630+
auto packed_time = TRY(to_packed_dos_time(timestamp));
631+
632+
entry.creation_date = move(packed_date);
633+
entry.creation_time = move(packed_time);
634+
635+
// NOTE: The "creation_time_seconds" field not only compensates for the fact that seconds are counted in intervals of two,
636+
// it also adds in rudimentary support for millisecond precision, though this is limited to only two digits.
637+
auto day_start_precision = days_since_epoch(entry.creation_date.year + AK::first_dos_year, entry.creation_date.month, entry.creation_date.day) * 86'400;
638+
auto day_precision = entry.creation_time.hour * 60 * 60 + entry.creation_time.minute * 60 + entry.creation_time.second * 2;
639+
entry.creation_time_seconds = (timestamp.truncated_milliseconds_since_epoch() - day_start_precision * 1000 - day_precision * 1000) / 10;
640+
VERIFY(entry.creation_time_seconds < 200);
641+
642+
return {};
643+
}
644+
626645
ErrorOr<NonnullRefPtr<Inode>> FATInode::create_child(StringView name, mode_t mode, dev_t, UserID, GroupID)
627646
{
628647
MutexLocker locker(m_inode_lock);
@@ -649,7 +668,12 @@ ErrorOr<NonnullRefPtr<Inode>> FATInode::create_child(StringView name, mode_t mod
649668
if (mode & S_IFDIR)
650669
entry.attributes |= FATAttributes::Directory;
651670

652-
// FIXME: Set the dates
671+
auto now = kgettimeofday();
672+
if (auto error_or_void = fill_in_creation_time(entry, now); !error_or_void.is_error()) {
673+
entry.modification_date = entry.creation_date;
674+
entry.modification_time = entry.creation_time;
675+
entry.last_accessed_date = entry.creation_date;
676+
}
653677

654678
Vector<FATLongFileNameEntry> lfn_entries = {};
655679
if (!valid_sfn)
@@ -906,9 +930,36 @@ ErrorOr<void> FATInode::flush_metadata()
906930
return {};
907931
}
908932

909-
ErrorOr<void> FATInode::update_timestamps(Optional<UnixDateTime>, Optional<UnixDateTime>, Optional<UnixDateTime>)
933+
ErrorOr<void> FATInode::update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime)
910934
{
911-
// FIXME: Implement FATInode::update_timestamps
935+
MutexLocker locker(m_inode_lock);
936+
937+
Optional<DOSPackedDate> packed_last_accessed_date;
938+
Optional<DOSPackedDate> packed_modified_date;
939+
Optional<DOSPackedTime> packed_modified_time;
940+
941+
if (atime.has_value())
942+
packed_last_accessed_date = TRY(to_packed_dos_date(atime.value()));
943+
944+
if (mtime.has_value()) {
945+
packed_modified_date = TRY(to_packed_dos_date(mtime.value()));
946+
packed_modified_time = TRY(to_packed_dos_time(mtime.value()));
947+
}
948+
949+
// NOTE: This is initialized after we've parsed everything else
950+
// to ensure that no changes will be made if we fail to parse
951+
// any of the arguments.
952+
if (ctime.has_value())
953+
TRY(fill_in_creation_time(m_entry, ctime.value()));
954+
955+
if (atime.has_value())
956+
m_entry.last_accessed_date = packed_last_accessed_date.release_value();
957+
958+
if (mtime.has_value()) {
959+
m_entry.modification_date = packed_modified_date.release_value();
960+
m_entry.modification_time = packed_modified_time.release_value();
961+
}
962+
912963
return {};
913964
}
914965

Kernel/FileSystem/FATFS/Inode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class FATInode final : public Inode {
6161
static ErrorOr<void> create_unique_sfn_for(FATEntry& entry, NonnullRefPtr<SFNUtils::SFN> sfn, Vector<ByteBuffer> existing_sfns);
6262
static ErrorOr<void> encode_known_good_sfn_for(FATEntry& entry, StringView name);
6363
static ErrorOr<Vector<FATLongFileNameEntry>> create_lfn_entries(StringView name, u8 checksum);
64+
static ErrorOr<void> fill_in_creation_time(FATEntry&, UnixDateTime const&);
6465

6566
ErrorOr<RawPtr<Vector<u32>>> get_cluster_list();
6667
ErrorOr<Vector<u32>> compute_cluster_list(FATFS&, u32 first_cluster);

0 commit comments

Comments
 (0)