Browse Source

Kernel: Use UnixDateTime wherever applicable

"Wherever applicable" = most places, actually :^), especially for
networking and filesystem timestamps.

This includes changes to unzip, which uses DOSPackedTime, since that is
changed for the FAT file systems.
kleines Filmröllchen 2 years ago
parent
commit
939600d2d4
41 changed files with 115 additions and 125 deletions
  1. 3 3
      AK/DOSPackedTime.cpp
  2. 1 1
      AK/DOSPackedTime.h
  3. 2 2
      Kernel/Arch/x86_64/RTC.cpp
  4. 1 1
      Kernel/Arch/x86_64/RTC.h
  5. 3 2
      Kernel/Devices/Audio/IntelHDA/Controller.cpp
  6. 1 1
      Kernel/FileSystem/DevPtsFS/Inode.cpp
  7. 2 2
      Kernel/FileSystem/Ext2FS/FileSystem.cpp
  8. 5 5
      Kernel/FileSystem/Ext2FS/Inode.cpp
  9. 1 1
      Kernel/FileSystem/Ext2FS/Inode.h
  10. 5 9
      Kernel/FileSystem/ISO9660FS/Inode.cpp
  11. 2 2
      Kernel/FileSystem/ISO9660FS/Inode.h
  12. 1 1
      Kernel/FileSystem/Inode.cpp
  13. 1 1
      Kernel/FileSystem/Inode.h
  14. 4 4
      Kernel/FileSystem/InodeMetadata.h
  15. 1 1
      Kernel/FileSystem/ProcFS/Inode.h
  16. 1 1
      Kernel/FileSystem/RAMFS/Inode.cpp
  17. 1 1
      Kernel/FileSystem/RAMFS/Inode.h
  18. 1 1
      Kernel/FileSystem/SysFS/Inode.cpp
  19. 1 1
      Kernel/FileSystem/SysFS/Inode.h
  20. 3 3
      Kernel/FileSystem/VirtualFileSystem.cpp
  21. 3 3
      Kernel/Net/IPv4Socket.cpp
  22. 4 4
      Kernel/Net/IPv4Socket.h
  23. 1 1
      Kernel/Net/LocalSocket.cpp
  24. 1 1
      Kernel/Net/LocalSocket.h
  25. 1 1
      Kernel/Net/NetworkAdapter.cpp
  26. 3 3
      Kernel/Net/NetworkAdapter.h
  27. 10 10
      Kernel/Net/NetworkTask.cpp
  28. 1 1
      Kernel/Net/Socket.cpp
  29. 1 1
      Kernel/Net/Socket.h
  30. 2 2
      Kernel/Net/TCPSocket.h
  31. 1 1
      Kernel/PerformanceManager.h
  32. 2 2
      Kernel/Process.cpp
  33. 1 1
      Kernel/Process.h
  34. 4 6
      Kernel/Syscalls/clock.cpp
  35. 1 1
      Kernel/Syscalls/socket.cpp
  36. 1 1
      Kernel/Syscalls/utime.cpp
  37. 1 1
      Kernel/TTY/SlavePTY.cpp
  38. 2 2
      Kernel/TTY/SlavePTY.h
  39. 24 26
      Kernel/Time/TimeManagement.cpp
  40. 10 13
      Kernel/Time/TimeManagement.h
  41. 1 1
      Userland/Utilities/unzip.cpp

+ 3 - 3
AK/DOSPackedTime.cpp

@@ -8,12 +8,12 @@
 
 
 namespace AK {
 namespace AK {
 
 
-Duration time_from_packed_dos(DOSPackedDate date, DOSPackedTime time)
+UnixDateTime time_from_packed_dos(DOSPackedDate date, DOSPackedTime time)
 {
 {
     if (date.value == 0)
     if (date.value == 0)
-        return Duration();
+        return UnixDateTime::from_unix_time_parts(first_dos_year, 1, 1, 0, 0, 0, 0);
 
 
-    return Duration::from_timestamp(first_dos_year + date.year, date.month, date.day, time.hour, time.minute, time.second * 2, 0);
+    return UnixDateTime::from_unix_time_parts(first_dos_year + date.year, date.month, date.day, time.hour, time.minute, time.second * 2, 0);
 }
 }
 
 
 DOSPackedDate to_packed_dos_date(unsigned year, unsigned month, unsigned day)
 DOSPackedDate to_packed_dos_date(unsigned year, unsigned month, unsigned day)

+ 1 - 1
AK/DOSPackedTime.h

@@ -33,7 +33,7 @@ static_assert(sizeof(DOSPackedDate) == 2);
 
 
 inline constexpr u16 first_dos_year = 1980;
 inline constexpr u16 first_dos_year = 1980;
 
 
-Duration time_from_packed_dos(DOSPackedDate, DOSPackedTime);
+UnixDateTime time_from_packed_dos(DOSPackedDate, DOSPackedTime);
 DOSPackedDate to_packed_dos_date(unsigned year, unsigned month, unsigned day);
 DOSPackedDate to_packed_dos_date(unsigned year, unsigned month, unsigned day);
 DOSPackedTime to_packed_dos_time(unsigned hour, unsigned minute, unsigned second);
 DOSPackedTime to_packed_dos_time(unsigned hour, unsigned minute, unsigned second);
 
 

+ 2 - 2
Kernel/Arch/x86_64/RTC.cpp

@@ -19,9 +19,9 @@ void initialize()
     s_boot_time = now();
     s_boot_time = now();
 }
 }
 
 
-Duration boot_time()
+UnixDateTime boot_time()
 {
 {
-    return Duration::from_timespec({ s_boot_time, 0 });
+    return UnixDateTime::from_seconds_since_epoch(s_boot_time);
 }
 }
 
 
 static bool update_in_progress()
 static bool update_in_progress()

+ 1 - 1
Kernel/Arch/x86_64/RTC.h

@@ -13,6 +13,6 @@ namespace Kernel::RTC {
 
 
 void initialize();
 void initialize();
 time_t now();
 time_t now();
-Duration boot_time();
+UnixDateTime boot_time();
 
 
 }
 }

+ 3 - 2
Kernel/Devices/Audio/IntelHDA/Controller.cpp

@@ -329,10 +329,11 @@ ErrorOr<u32> Controller::get_pcm_output_sample_rate(size_t channel_index)
 ErrorOr<void> wait_until(size_t delay_in_microseconds, size_t timeout_in_microseconds, Function<ErrorOr<bool>()> condition)
 ErrorOr<void> wait_until(size_t delay_in_microseconds, size_t timeout_in_microseconds, Function<ErrorOr<bool>()> condition)
 {
 {
     auto const& time_management = TimeManagement::the();
     auto const& time_management = TimeManagement::the();
-    u64 start_microseconds = time_management.now().to_microseconds();
+    // FIXME: Use monotonic time instead.
+    u64 start_microseconds = time_management.now().offset_to_epoch().to_microseconds();
     while (!TRY(condition())) {
     while (!TRY(condition())) {
         microseconds_delay(delay_in_microseconds);
         microseconds_delay(delay_in_microseconds);
-        if ((time_management.now().to_microseconds() - start_microseconds) >= timeout_in_microseconds)
+        if ((time_management.now().offset_to_epoch().to_microseconds() - start_microseconds) >= timeout_in_microseconds)
             return ETIMEDOUT;
             return ETIMEDOUT;
     }
     }
     return {};
     return {};

+ 1 - 1
Kernel/FileSystem/DevPtsFS/Inode.cpp

@@ -38,7 +38,7 @@ InodeMetadata DevPtsFSInode::metadata() const
 {
 {
     if (auto pty = m_pty.strong_ref()) {
     if (auto pty = m_pty.strong_ref()) {
         auto metadata = m_metadata;
         auto metadata = m_metadata;
-        metadata.mtime = Duration::from_timespec({ pty->time_of_last_write(), 0 });
+        metadata.mtime = pty->time_of_last_write();
         return metadata;
         return metadata;
     }
     }
     return m_metadata;
     return m_metadata;

+ 2 - 2
Kernel/FileSystem/Ext2FS/FileSystem.cpp

@@ -471,7 +471,7 @@ ErrorOr<NonnullRefPtr<Inode>> Ext2FS::create_inode(Ext2FSInode& parent_inode, St
         return ENOENT;
         return ENOENT;
 
 
     ext2_inode e2inode {};
     ext2_inode e2inode {};
-    auto now = kgettimeofday().to_truncated_seconds();
+    auto now = kgettimeofday().truncated_seconds_since_epoch();
     e2inode.i_mode = mode;
     e2inode.i_mode = mode;
     e2inode.i_uid = uid.value();
     e2inode.i_uid = uid.value();
     e2inode.i_gid = gid.value();
     e2inode.i_gid = gid.value();
@@ -572,7 +572,7 @@ ErrorOr<void> Ext2FS::free_inode(Ext2FSInode& inode)
 
 
     // NOTE: After this point, the inode metadata is wiped.
     // NOTE: After this point, the inode metadata is wiped.
     memset(&inode.m_raw_inode, 0, sizeof(ext2_inode));
     memset(&inode.m_raw_inode, 0, sizeof(ext2_inode));
-    inode.m_raw_inode.i_dtime = kgettimeofday().to_truncated_seconds();
+    inode.m_raw_inode.i_dtime = kgettimeofday().truncated_seconds_since_epoch();
     TRY(write_ext2_inode(inode.index(), inode.m_raw_inode));
     TRY(write_ext2_inode(inode.index(), inode.m_raw_inode));
 
 
     // Mark the inode as free.
     // Mark the inode as free.

+ 5 - 5
Kernel/FileSystem/Ext2FS/Inode.cpp

@@ -474,10 +474,10 @@ InodeMetadata Ext2FSInode::metadata() const
     metadata.uid = m_raw_inode.i_uid;
     metadata.uid = m_raw_inode.i_uid;
     metadata.gid = m_raw_inode.i_gid;
     metadata.gid = m_raw_inode.i_gid;
     metadata.link_count = m_raw_inode.i_links_count;
     metadata.link_count = m_raw_inode.i_links_count;
-    metadata.atime = Duration::from_timespec({ m_raw_inode.i_atime, 0 });
-    metadata.ctime = Duration::from_timespec({ m_raw_inode.i_ctime, 0 });
-    metadata.mtime = Duration::from_timespec({ m_raw_inode.i_mtime, 0 });
-    metadata.dtime = Duration::from_timespec({ m_raw_inode.i_dtime, 0 });
+    metadata.atime = UnixDateTime::from_seconds_since_epoch(m_raw_inode.i_atime);
+    metadata.ctime = UnixDateTime::from_seconds_since_epoch(m_raw_inode.i_ctime);
+    metadata.mtime = UnixDateTime::from_seconds_since_epoch(m_raw_inode.i_mtime);
+    metadata.dtime = UnixDateTime::from_seconds_since_epoch(m_raw_inode.i_dtime);
     metadata.block_size = fs().block_size();
     metadata.block_size = fs().block_size();
     metadata.block_count = m_raw_inode.i_blocks;
     metadata.block_count = m_raw_inode.i_blocks;
 
 
@@ -985,7 +985,7 @@ ErrorOr<NonnullRefPtr<Inode>> Ext2FSInode::lookup(StringView name)
     return fs().get_inode({ fsid(), inode_index });
     return fs().get_inode({ fsid(), inode_index });
 }
 }
 
 
-ErrorOr<void> Ext2FSInode::update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime)
+ErrorOr<void> Ext2FSInode::update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime)
 {
 {
     MutexLocker locker(m_inode_lock);
     MutexLocker locker(m_inode_lock);
     if (fs().is_readonly())
     if (fs().is_readonly())

+ 1 - 1
Kernel/FileSystem/Ext2FS/Inode.h

@@ -37,7 +37,7 @@ private:
     virtual ErrorOr<void> add_child(Inode& child, StringView name, mode_t) override;
     virtual ErrorOr<void> add_child(Inode& child, StringView name, mode_t) override;
     virtual ErrorOr<void> remove_child(StringView name) override;
     virtual ErrorOr<void> remove_child(StringView name) override;
     virtual ErrorOr<void> replace_child(StringView name, Inode& child) override;
     virtual ErrorOr<void> replace_child(StringView name, Inode& child) override;
-    virtual ErrorOr<void> update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime) override;
+    virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime) override;
     virtual ErrorOr<void> increment_link_count() override;
     virtual ErrorOr<void> increment_link_count() override;
     virtual ErrorOr<void> decrement_link_count() override;
     virtual ErrorOr<void> decrement_link_count() override;
     virtual ErrorOr<void> chmod(mode_t) override;
     virtual ErrorOr<void> chmod(mode_t) override;

+ 5 - 9
Kernel/FileSystem/ISO9660FS/Inode.cpp

@@ -145,7 +145,7 @@ ErrorOr<void> ISO9660Inode::truncate(u64)
     return EROFS;
     return EROFS;
 }
 }
 
 
-ErrorOr<void> ISO9660Inode::update_timestamps(Optional<Duration>, Optional<Duration>, Optional<Duration>)
+ErrorOr<void> ISO9660Inode::update_timestamps(Optional<UnixDateTime>, Optional<UnixDateTime>, Optional<UnixDateTime>)
 {
 {
     return EROFS;
     return EROFS;
 }
 }
@@ -169,7 +169,7 @@ void ISO9660Inode::create_metadata()
 {
 {
     u32 data_length = LittleEndian { m_record.data_length.little };
     u32 data_length = LittleEndian { m_record.data_length.little };
     bool is_directory = has_flag(m_record.file_flags, ISO::FileFlags::Directory);
     bool is_directory = has_flag(m_record.file_flags, ISO::FileFlags::Directory);
-    auto recorded_at = Duration::from_timespec({ parse_numerical_date_time(m_record.recording_date_and_time), 0 });
+    auto recorded_at = parse_numerical_date_time(m_record.recording_date_and_time);
 
 
     m_metadata = {
     m_metadata = {
         .inode = identifier(),
         .inode = identifier(),
@@ -189,16 +189,12 @@ void ISO9660Inode::create_metadata()
     };
     };
 }
 }
 
 
-time_t ISO9660Inode::parse_numerical_date_time(ISO::NumericalDateAndTime const& date)
+UnixDateTime ISO9660Inode::parse_numerical_date_time(ISO::NumericalDateAndTime const& date)
 {
 {
     i32 year_offset = date.years_since_1900 - 70;
     i32 year_offset = date.years_since_1900 - 70;
 
 
-    return (year_offset * 60 * 60 * 24 * 30 * 12)
-        + (date.month * 60 * 60 * 24 * 30)
-        + (date.day * 60 * 60 * 24)
-        + (date.hour * 60 * 60)
-        + (date.minute * 60)
-        + date.second;
+    // FIXME: This ignores timezone information in date.
+    return UnixDateTime::from_unix_time_parts(year_offset, date.month, date.day, date.hour, date.minute, date.second, 0);
 }
 }
 
 
 StringView ISO9660Inode::get_normalized_filename(ISO::DirectoryRecordHeader const& record, Bytes buffer)
 StringView ISO9660Inode::get_normalized_filename(ISO::DirectoryRecordHeader const& record, Bytes buffer)

+ 2 - 2
Kernel/FileSystem/ISO9660FS/Inode.h

@@ -32,7 +32,7 @@ public:
     virtual ErrorOr<void> chmod(mode_t) override;
     virtual ErrorOr<void> chmod(mode_t) override;
     virtual ErrorOr<void> chown(UserID, GroupID) override;
     virtual ErrorOr<void> chown(UserID, GroupID) override;
     virtual ErrorOr<void> truncate(u64) override;
     virtual ErrorOr<void> truncate(u64) override;
-    virtual ErrorOr<void> update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime) override;
+    virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime) override;
 
 
 private:
 private:
     // HACK: The base ISO 9660 standard says the maximum filename length is 37
     // HACK: The base ISO 9660 standard says the maximum filename length is 37
@@ -51,7 +51,7 @@ private:
     static StringView get_normalized_filename(ISO::DirectoryRecordHeader const& record, Bytes buffer);
     static StringView get_normalized_filename(ISO::DirectoryRecordHeader const& record, Bytes buffer);
 
 
     void create_metadata();
     void create_metadata();
-    time_t parse_numerical_date_time(ISO::NumericalDateAndTime const&);
+    UnixDateTime parse_numerical_date_time(ISO::NumericalDateAndTime const&);
 
 
     InodeMetadata m_metadata;
     InodeMetadata m_metadata;
     ISO::DirectoryRecordHeader m_record;
     ISO::DirectoryRecordHeader m_record;

+ 1 - 1
Kernel/FileSystem/Inode.cpp

@@ -115,7 +115,7 @@ ErrorOr<size_t> Inode::read_until_filled_or_end(off_t offset, size_t length, Use
     return length - remaining_length;
     return length - remaining_length;
 }
 }
 
 
-ErrorOr<void> Inode::update_timestamps([[maybe_unused]] Optional<Duration> atime, [[maybe_unused]] Optional<Duration> ctime, [[maybe_unused]] Optional<Duration> mtime)
+ErrorOr<void> Inode::update_timestamps([[maybe_unused]] Optional<UnixDateTime> atime, [[maybe_unused]] Optional<UnixDateTime> ctime, [[maybe_unused]] Optional<UnixDateTime> mtime)
 {
 {
     return ENOTIMPL;
     return ENOTIMPL;
 }
 }

+ 1 - 1
Kernel/FileSystem/Inode.h

@@ -82,7 +82,7 @@ public:
 
 
     bool is_metadata_dirty() const { return m_metadata_dirty; }
     bool is_metadata_dirty() const { return m_metadata_dirty; }
 
 
-    virtual ErrorOr<void> update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime);
+    virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime);
     virtual ErrorOr<void> increment_link_count();
     virtual ErrorOr<void> increment_link_count();
     virtual ErrorOr<void> decrement_link_count();
     virtual ErrorOr<void> decrement_link_count();
 
 

+ 4 - 4
Kernel/FileSystem/InodeMetadata.h

@@ -120,10 +120,10 @@ struct InodeMetadata {
     UserID uid { 0 };
     UserID uid { 0 };
     GroupID gid { 0 };
     GroupID gid { 0 };
     nlink_t link_count { 0 };
     nlink_t link_count { 0 };
-    Duration atime {};
-    Duration ctime {};
-    Duration mtime {};
-    Duration dtime {};
+    UnixDateTime atime {};
+    UnixDateTime ctime {};
+    UnixDateTime mtime {};
+    UnixDateTime dtime {};
     blkcnt_t block_count { 0 };
     blkcnt_t block_count { 0 };
     blksize_t block_size { 0 };
     blksize_t block_size { 0 };
     MajorNumber major_device { 0 };
     MajorNumber major_device { 0 };

+ 1 - 1
Kernel/FileSystem/ProcFS/Inode.h

@@ -54,7 +54,7 @@ private:
 
 
     // ^Inode (Silent ignore handling)
     // ^Inode (Silent ignore handling)
     virtual ErrorOr<void> flush_metadata() override { return {}; }
     virtual ErrorOr<void> flush_metadata() override { return {}; }
-    virtual ErrorOr<void> update_timestamps(Optional<Duration>, Optional<Duration>, Optional<Duration>) override { return {}; }
+    virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime>, Optional<UnixDateTime>, Optional<UnixDateTime>) override { return {}; }
 
 
     // ^Inode
     // ^Inode
     virtual ErrorOr<void> attach(OpenFileDescription& description) override;
     virtual ErrorOr<void> attach(OpenFileDescription& description) override;

+ 1 - 1
Kernel/FileSystem/RAMFS/Inode.cpp

@@ -381,7 +381,7 @@ ErrorOr<void> RAMFSInode::truncate(u64 size)
     return {};
     return {};
 }
 }
 
 
-ErrorOr<void> RAMFSInode::update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime)
+ErrorOr<void> RAMFSInode::update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime)
 {
 {
     MutexLocker locker(m_inode_lock);
     MutexLocker locker(m_inode_lock);
 
 

+ 1 - 1
Kernel/FileSystem/RAMFS/Inode.h

@@ -35,7 +35,7 @@ public:
     virtual ErrorOr<void> chmod(mode_t) override;
     virtual ErrorOr<void> chmod(mode_t) override;
     virtual ErrorOr<void> chown(UserID, GroupID) override;
     virtual ErrorOr<void> chown(UserID, GroupID) override;
     virtual ErrorOr<void> truncate(u64) override;
     virtual ErrorOr<void> truncate(u64) override;
-    virtual ErrorOr<void> update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime) override;
+    virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime) override;
 
 
 private:
 private:
     RAMFSInode(RAMFS& fs, InodeMetadata const& metadata, LockWeakPtr<RAMFSInode> parent);
     RAMFSInode(RAMFS& fs, InodeMetadata const& metadata, LockWeakPtr<RAMFSInode> parent);

+ 1 - 1
Kernel/FileSystem/SysFS/Inode.cpp

@@ -110,7 +110,7 @@ ErrorOr<void> SysFSInode::truncate(u64 size)
     return m_associated_component->truncate(size);
     return m_associated_component->truncate(size);
 }
 }
 
 
-ErrorOr<void> SysFSInode::update_timestamps(Optional<Duration>, Optional<Duration>, Optional<Duration>)
+ErrorOr<void> SysFSInode::update_timestamps(Optional<UnixDateTime>, Optional<UnixDateTime>, Optional<UnixDateTime>)
 {
 {
     return {};
     return {};
 }
 }

+ 1 - 1
Kernel/FileSystem/SysFS/Inode.h

@@ -35,7 +35,7 @@ protected:
     virtual ErrorOr<void> chmod(mode_t) override;
     virtual ErrorOr<void> chmod(mode_t) override;
     virtual ErrorOr<void> chown(UserID, GroupID) override;
     virtual ErrorOr<void> chown(UserID, GroupID) override;
     virtual ErrorOr<void> truncate(u64) override;
     virtual ErrorOr<void> truncate(u64) override;
-    virtual ErrorOr<void> update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime) override;
+    virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime) override;
 
 
     virtual ErrorOr<void> attach(OpenFileDescription& description) override final;
     virtual ErrorOr<void> attach(OpenFileDescription& description) override final;
     virtual void did_seek(OpenFileDescription&, off_t) override final;
     virtual void did_seek(OpenFileDescription&, off_t) override final;

+ 3 - 3
Kernel/FileSystem/VirtualFileSystem.cpp

@@ -306,7 +306,7 @@ ErrorOr<void> VirtualFileSystem::utime(Credentials const& credentials, StringVie
     if (custody->is_readonly())
     if (custody->is_readonly())
         return EROFS;
         return EROFS;
 
 
-    TRY(inode.update_timestamps(Duration::from_timespec({ atime, 0 }), {}, Duration::from_timespec({ mtime, 0 })));
+    TRY(inode.update_timestamps(UnixDateTime::from_seconds_since_epoch(atime), {}, UnixDateTime::from_seconds_since_epoch(mtime)));
     return {};
     return {};
 }
 }
 
 
@@ -326,9 +326,9 @@ ErrorOr<void> VirtualFileSystem::do_utimens(Credentials const& credentials, Cust
 
 
     // NOTE: A standard ext2 inode cannot store nanosecond timestamps.
     // NOTE: A standard ext2 inode cannot store nanosecond timestamps.
     TRY(inode.update_timestamps(
     TRY(inode.update_timestamps(
-        (atime.tv_nsec != UTIME_OMIT) ? Duration::from_timespec(atime) : Optional<Duration> {},
+        (atime.tv_nsec != UTIME_OMIT) ? UnixDateTime::from_unix_timespec(atime) : Optional<UnixDateTime> {},
         {},
         {},
-        (mtime.tv_nsec != UTIME_OMIT) ? Duration::from_timespec(mtime) : Optional<Duration> {}));
+        (mtime.tv_nsec != UTIME_OMIT) ? UnixDateTime::from_unix_timespec(mtime) : Optional<UnixDateTime> {}));
 
 
     return {};
     return {};
 }
 }

+ 3 - 3
Kernel/Net/IPv4Socket.cpp

@@ -287,7 +287,7 @@ ErrorOr<size_t> IPv4Socket::receive_byte_buffered(OpenFileDescription& descripti
     return nreceived_or_error;
     return nreceived_or_error;
 }
 }
 
 
-ErrorOr<size_t> IPv4Socket::receive_packet_buffered(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> addr, Userspace<socklen_t*> addr_length, Duration& packet_timestamp, bool blocking)
+ErrorOr<size_t> IPv4Socket::receive_packet_buffered(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> addr, Userspace<socklen_t*> addr_length, UnixDateTime& packet_timestamp, bool blocking)
 {
 {
     MutexLocker locker(mutex());
     MutexLocker locker(mutex());
     ReceivedPacket taken_packet;
     ReceivedPacket taken_packet;
@@ -382,7 +382,7 @@ ErrorOr<size_t> IPv4Socket::receive_packet_buffered(OpenFileDescription& descrip
     return protocol_receive(packet->data->bytes(), buffer, buffer_length, flags);
     return protocol_receive(packet->data->bytes(), buffer, buffer_length, flags);
 }
 }
 
 
-ErrorOr<size_t> IPv4Socket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> user_addr, Userspace<socklen_t*> user_addr_length, Duration& packet_timestamp, bool blocking)
+ErrorOr<size_t> IPv4Socket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> user_addr, Userspace<socklen_t*> user_addr_length, UnixDateTime& packet_timestamp, bool blocking)
 {
 {
     if (user_addr_length) {
     if (user_addr_length) {
         socklen_t addr_length;
         socklen_t addr_length;
@@ -415,7 +415,7 @@ ErrorOr<size_t> IPv4Socket::recvfrom(OpenFileDescription& description, UserOrKer
     return total_nreceived;
     return total_nreceived;
 }
 }
 
 
-bool IPv4Socket::did_receive(IPv4Address const& source_address, u16 source_port, ReadonlyBytes packet, Duration const& packet_timestamp)
+bool IPv4Socket::did_receive(IPv4Address const& source_address, u16 source_port, ReadonlyBytes packet, UnixDateTime const& packet_timestamp)
 {
 {
     MutexLocker locker(mutex());
     MutexLocker locker(mutex());
 
 

+ 4 - 4
Kernel/Net/IPv4Socket.h

@@ -40,13 +40,13 @@ public:
     virtual bool can_read(OpenFileDescription const&, u64) const override;
     virtual bool can_read(OpenFileDescription const&, u64) const override;
     virtual bool can_write(OpenFileDescription const&, u64) const override;
     virtual bool can_write(OpenFileDescription const&, u64) const override;
     virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int, Userspace<sockaddr const*>, socklen_t) override;
     virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int, Userspace<sockaddr const*>, socklen_t) override;
-    virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Duration&, bool blocking) override;
+    virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, UnixDateTime&, bool blocking) override;
     virtual ErrorOr<void> setsockopt(int level, int option, Userspace<void const*>, socklen_t) override;
     virtual ErrorOr<void> setsockopt(int level, int option, Userspace<void const*>, socklen_t) override;
     virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override;
     virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override;
 
 
     virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override;
     virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override;
 
 
-    bool did_receive(IPv4Address const& peer_address, u16 peer_port, ReadonlyBytes, Duration const&);
+    bool did_receive(IPv4Address const& peer_address, u16 peer_port, ReadonlyBytes, UnixDateTime const&);
 
 
     IPv4Address const& local_address() const { return m_local_address; }
     IPv4Address const& local_address() const { return m_local_address; }
     u16 local_port() const { return m_local_port; }
     u16 local_port() const { return m_local_port; }
@@ -99,7 +99,7 @@ private:
     virtual bool is_ipv4() const override { return true; }
     virtual bool is_ipv4() const override { return true; }
 
 
     ErrorOr<size_t> receive_byte_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, bool blocking);
     ErrorOr<size_t> receive_byte_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, bool blocking);
-    ErrorOr<size_t> receive_packet_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Duration&, bool blocking);
+    ErrorOr<size_t> receive_packet_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, UnixDateTime&, bool blocking);
 
 
     void set_can_read(bool);
     void set_can_read(bool);
 
 
@@ -112,7 +112,7 @@ private:
     struct ReceivedPacket {
     struct ReceivedPacket {
         IPv4Address peer_address;
         IPv4Address peer_address;
         u16 peer_port;
         u16 peer_port;
-        Duration timestamp;
+        UnixDateTime timestamp;
         OwnPtr<KBuffer> data;
         OwnPtr<KBuffer> data;
     };
     };
 
 

+ 1 - 1
Kernel/Net/LocalSocket.cpp

@@ -333,7 +333,7 @@ DoubleBuffer* LocalSocket::send_buffer_for(OpenFileDescription& description)
     return nullptr;
     return nullptr;
 }
 }
 
 
-ErrorOr<size_t> LocalSocket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_size, int, Userspace<sockaddr*>, Userspace<socklen_t*>, Duration&, bool blocking)
+ErrorOr<size_t> LocalSocket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_size, int, Userspace<sockaddr*>, Userspace<socklen_t*>, UnixDateTime&, bool blocking)
 {
 {
     auto* socket_buffer = receive_buffer_for(description);
     auto* socket_buffer = receive_buffer_for(description);
     if (!socket_buffer)
     if (!socket_buffer)

+ 1 - 1
Kernel/Net/LocalSocket.h

@@ -47,7 +47,7 @@ public:
     virtual bool can_read(OpenFileDescription const&, u64) const override;
     virtual bool can_read(OpenFileDescription const&, u64) const override;
     virtual bool can_write(OpenFileDescription const&, u64) const override;
     virtual bool can_write(OpenFileDescription const&, u64) const override;
     virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int, Userspace<sockaddr const*>, socklen_t) override;
     virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int, Userspace<sockaddr const*>, socklen_t) override;
-    virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Duration&, bool blocking) override;
+    virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, UnixDateTime&, bool blocking) override;
     virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override;
     virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override;
     virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override;
     virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override;
     virtual ErrorOr<void> chown(Credentials const&, OpenFileDescription&, UserID, GroupID) override;
     virtual ErrorOr<void> chown(Credentials const&, OpenFileDescription&, UserID, GroupID) override;

+ 1 - 1
Kernel/Net/NetworkAdapter.cpp

@@ -95,7 +95,7 @@ void NetworkAdapter::did_receive(ReadonlyBytes payload)
         on_receive();
         on_receive();
 }
 }
 
 
-size_t NetworkAdapter::dequeue_packet(u8* buffer, size_t buffer_size, Duration& packet_timestamp)
+size_t NetworkAdapter::dequeue_packet(u8* buffer, size_t buffer_size, UnixDateTime& packet_timestamp)
 {
 {
     InterruptDisabler disabler;
     InterruptDisabler disabler;
     if (m_packet_queue.is_empty())
     if (m_packet_queue.is_empty())

+ 3 - 3
Kernel/Net/NetworkAdapter.h

@@ -29,7 +29,7 @@ class NetworkAdapter;
 using NetworkByteBuffer = AK::Detail::ByteBuffer<1500>;
 using NetworkByteBuffer = AK::Detail::ByteBuffer<1500>;
 
 
 struct PacketWithTimestamp final : public AtomicRefCounted<PacketWithTimestamp> {
 struct PacketWithTimestamp final : public AtomicRefCounted<PacketWithTimestamp> {
-    PacketWithTimestamp(NonnullOwnPtr<KBuffer> buffer, Duration timestamp)
+    PacketWithTimestamp(NonnullOwnPtr<KBuffer> buffer, UnixDateTime timestamp)
         : buffer(move(buffer))
         : buffer(move(buffer))
         , timestamp(timestamp)
         , timestamp(timestamp)
     {
     {
@@ -38,7 +38,7 @@ struct PacketWithTimestamp final : public AtomicRefCounted<PacketWithTimestamp>
     ReadonlyBytes bytes() { return buffer->bytes(); }
     ReadonlyBytes bytes() { return buffer->bytes(); }
 
 
     NonnullOwnPtr<KBuffer> buffer;
     NonnullOwnPtr<KBuffer> buffer;
-    Duration timestamp;
+    UnixDateTime timestamp;
     IntrusiveListNode<PacketWithTimestamp, RefPtr<PacketWithTimestamp>> packet_node;
     IntrusiveListNode<PacketWithTimestamp, RefPtr<PacketWithTimestamp>> packet_node;
 };
 };
 
 
@@ -79,7 +79,7 @@ public:
     void send(MACAddress const&, ARPPacket const&);
     void send(MACAddress const&, ARPPacket const&);
     void fill_in_ipv4_header(PacketWithTimestamp&, IPv4Address const&, MACAddress const&, IPv4Address const&, IPv4Protocol, size_t, u8 type_of_service, u8 ttl);
     void fill_in_ipv4_header(PacketWithTimestamp&, IPv4Address const&, MACAddress const&, IPv4Address const&, IPv4Protocol, size_t, u8 type_of_service, u8 ttl);
 
 
-    size_t dequeue_packet(u8* buffer, size_t buffer_size, Duration& packet_timestamp);
+    size_t dequeue_packet(u8* buffer, size_t buffer_size, UnixDateTime& packet_timestamp);
 
 
     bool has_queued_packets() const { return !m_packet_queue.is_empty(); }
     bool has_queued_packets() const { return !m_packet_queue.is_empty(); }
 
 

+ 10 - 10
Kernel/Net/NetworkTask.cpp

@@ -26,10 +26,10 @@
 namespace Kernel {
 namespace Kernel {
 
 
 static void handle_arp(EthernetFrameHeader const&, size_t frame_size);
 static void handle_arp(EthernetFrameHeader const&, size_t frame_size);
-static void handle_ipv4(EthernetFrameHeader const&, size_t frame_size, Duration const& packet_timestamp);
-static void handle_icmp(EthernetFrameHeader const&, IPv4Packet const&, Duration const& packet_timestamp);
-static void handle_udp(IPv4Packet const&, Duration const& packet_timestamp);
-static void handle_tcp(IPv4Packet const&, Duration const& packet_timestamp);
+static void handle_ipv4(EthernetFrameHeader const&, size_t frame_size, UnixDateTime const& packet_timestamp);
+static void handle_icmp(EthernetFrameHeader const&, IPv4Packet const&, UnixDateTime const& packet_timestamp);
+static void handle_udp(IPv4Packet const&, UnixDateTime const& packet_timestamp);
+static void handle_tcp(IPv4Packet const&, UnixDateTime const& packet_timestamp);
 static void send_delayed_tcp_ack(TCPSocket& socket);
 static void send_delayed_tcp_ack(TCPSocket& socket);
 static void send_tcp_rst(IPv4Packet const& ipv4_packet, TCPPacket const& tcp_packet, RefPtr<NetworkAdapter> adapter);
 static void send_tcp_rst(IPv4Packet const& ipv4_packet, TCPPacket const& tcp_packet, RefPtr<NetworkAdapter> adapter);
 static void flush_delayed_tcp_acks();
 static void flush_delayed_tcp_acks();
@@ -74,7 +74,7 @@ void NetworkTask_main(void*)
         };
         };
     });
     });
 
 
-    auto dequeue_packet = [&pending_packets](u8* buffer, size_t buffer_size, Duration& packet_timestamp) -> size_t {
+    auto dequeue_packet = [&pending_packets](u8* buffer, size_t buffer_size, UnixDateTime& packet_timestamp) -> size_t {
         if (pending_packets == 0)
         if (pending_packets == 0)
             return 0;
             return 0;
         size_t packet_size = 0;
         size_t packet_size = 0;
@@ -94,7 +94,7 @@ void NetworkTask_main(void*)
         TODO();
         TODO();
     auto buffer_region = region_or_error.release_value();
     auto buffer_region = region_or_error.release_value();
     auto buffer = (u8*)buffer_region->vaddr().get();
     auto buffer = (u8*)buffer_region->vaddr().get();
-    Duration packet_timestamp;
+    UnixDateTime packet_timestamp;
 
 
     for (;;) {
     for (;;) {
         flush_delayed_tcp_acks();
         flush_delayed_tcp_acks();
@@ -177,7 +177,7 @@ void handle_arp(EthernetFrameHeader const& eth, size_t frame_size)
     }
     }
 }
 }
 
 
-void handle_ipv4(EthernetFrameHeader const& eth, size_t frame_size, Duration const& packet_timestamp)
+void handle_ipv4(EthernetFrameHeader const& eth, size_t frame_size, UnixDateTime const& packet_timestamp)
 {
 {
     constexpr size_t minimum_ipv4_frame_size = sizeof(EthernetFrameHeader) + sizeof(IPv4Packet);
     constexpr size_t minimum_ipv4_frame_size = sizeof(EthernetFrameHeader) + sizeof(IPv4Packet);
     if (frame_size < minimum_ipv4_frame_size) {
     if (frame_size < minimum_ipv4_frame_size) {
@@ -222,7 +222,7 @@ void handle_ipv4(EthernetFrameHeader const& eth, size_t frame_size, Duration con
     }
     }
 }
 }
 
 
-void handle_icmp(EthernetFrameHeader const& eth, IPv4Packet const& ipv4_packet, Duration const& packet_timestamp)
+void handle_icmp(EthernetFrameHeader const& eth, IPv4Packet const& ipv4_packet, UnixDateTime const& packet_timestamp)
 {
 {
     auto& icmp_header = *static_cast<ICMPHeader const*>(ipv4_packet.payload());
     auto& icmp_header = *static_cast<ICMPHeader const*>(ipv4_packet.payload());
     dbgln_if(ICMP_DEBUG, "handle_icmp: source={}, destination={}, type={:#02x}, code={:#02x}", ipv4_packet.source().to_string(), ipv4_packet.destination().to_string(), icmp_header.type(), icmp_header.code());
     dbgln_if(ICMP_DEBUG, "handle_icmp: source={}, destination={}, type={:#02x}, code={:#02x}", ipv4_packet.source().to_string(), ipv4_packet.destination().to_string(), icmp_header.type(), icmp_header.code());
@@ -273,7 +273,7 @@ void handle_icmp(EthernetFrameHeader const& eth, IPv4Packet const& ipv4_packet,
     }
     }
 }
 }
 
 
-void handle_udp(IPv4Packet const& ipv4_packet, Duration const& packet_timestamp)
+void handle_udp(IPv4Packet const& ipv4_packet, UnixDateTime const& packet_timestamp)
 {
 {
     if (ipv4_packet.payload_size() < sizeof(UDPPacket)) {
     if (ipv4_packet.payload_size() < sizeof(UDPPacket)) {
         dbgln("handle_udp: Packet too small ({}, need {})", ipv4_packet.payload_size(), sizeof(UDPPacket));
         dbgln("handle_udp: Packet too small ({}, need {})", ipv4_packet.payload_size(), sizeof(UDPPacket));
@@ -367,7 +367,7 @@ void send_tcp_rst(IPv4Packet const& ipv4_packet, TCPPacket const& tcp_packet, Re
     routing_decision.adapter->release_packet_buffer(*packet);
     routing_decision.adapter->release_packet_buffer(*packet);
 }
 }
 
 
-void handle_tcp(IPv4Packet const& ipv4_packet, Duration const& packet_timestamp)
+void handle_tcp(IPv4Packet const& ipv4_packet, UnixDateTime const& packet_timestamp)
 {
 {
     if (ipv4_packet.payload_size() < sizeof(TCPPacket)) {
     if (ipv4_packet.payload_size() < sizeof(TCPPacket)) {
         dbgln("handle_tcp: IPv4 payload is too small to be a TCP packet ({}, need {})", ipv4_packet.payload_size(), sizeof(TCPPacket));
         dbgln("handle_tcp: IPv4 payload is too small to be a TCP packet ({}, need {})", ipv4_packet.payload_size(), sizeof(TCPPacket));

+ 1 - 1
Kernel/Net/Socket.cpp

@@ -245,7 +245,7 @@ ErrorOr<size_t> Socket::read(OpenFileDescription& description, u64, UserOrKernel
 {
 {
     if (is_shut_down_for_reading())
     if (is_shut_down_for_reading())
         return 0;
         return 0;
-    Duration t {};
+    UnixDateTime t {};
     return recvfrom(description, buffer, size, 0, {}, 0, t, description.is_blocking());
     return recvfrom(description, buffer, size, 0, {}, 0, t, description.is_blocking());
 }
 }
 
 

+ 1 - 1
Kernel/Net/Socket.h

@@ -79,7 +79,7 @@ public:
     virtual bool is_local() const { return false; }
     virtual bool is_local() const { return false; }
     virtual bool is_ipv4() const { return false; }
     virtual bool is_ipv4() const { return false; }
     virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int flags, Userspace<sockaddr const*>, socklen_t) = 0;
     virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int flags, Userspace<sockaddr const*>, socklen_t) = 0;
-    virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Duration&, bool blocking) = 0;
+    virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, UnixDateTime&, bool blocking) = 0;
 
 
     virtual ErrorOr<void> setsockopt(int level, int option, Userspace<void const*>, socklen_t);
     virtual ErrorOr<void> setsockopt(int level, int option, Userspace<void const*>, socklen_t);
     virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>);
     virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>);

+ 2 - 2
Kernel/Net/TCPSocket.h

@@ -216,11 +216,11 @@ private:
     u32 m_duplicate_acks { 0 };
     u32 m_duplicate_acks { 0 };
 
 
     u32 m_last_ack_number_sent { 0 };
     u32 m_last_ack_number_sent { 0 };
-    Duration m_last_ack_sent_time;
+    UnixDateTime m_last_ack_sent_time;
 
 
     // FIXME: Make this configurable (sysctl)
     // FIXME: Make this configurable (sysctl)
     static constexpr u32 maximum_retransmits = 5;
     static constexpr u32 maximum_retransmits = 5;
-    Duration m_last_retransmit_time;
+    UnixDateTime m_last_retransmit_time;
     u32 m_retransmit_attempts { 0 };
     u32 m_retransmit_attempts { 0 };
 
 
     // FIXME: Parse window size TCP option from the peer
     // FIXME: Parse window size TCP option from the peer

+ 1 - 1
Kernel/PerformanceManager.h

@@ -164,7 +164,7 @@ public:
 
 
     static void timer_tick(RegisterState const& regs)
     static void timer_tick(RegisterState const& regs)
     {
     {
-        static Duration last_wakeup;
+        static UnixDateTime last_wakeup;
         auto now = kgettimeofday();
         auto now = kgettimeofday();
         constexpr auto ideal_interval = Duration::from_microseconds(1000'000 / OPTIMAL_PROFILE_TICKS_PER_SECOND_RATE);
         constexpr auto ideal_interval = Duration::from_microseconds(1000'000 / OPTIMAL_PROFILE_TICKS_PER_SECOND_RATE);
         auto expected_wakeup = last_wakeup + ideal_interval;
         auto expected_wakeup = last_wakeup + ideal_interval;

+ 2 - 2
Kernel/Process.cpp

@@ -635,7 +635,7 @@ ErrorOr<Process::ScopedDescriptionAllocation> Process::OpenFileDescriptions::all
     return EMFILE;
     return EMFILE;
 }
 }
 
 
-Duration kgettimeofday()
+UnixDateTime kgettimeofday()
 {
 {
     return TimeManagement::now();
     return TimeManagement::now();
 }
 }
@@ -699,7 +699,7 @@ ErrorOr<void> Process::dump_core()
         return {};
         return {};
     }
     }
     auto coredump_path = TRY(name().with([&](auto& process_name) {
     auto coredump_path = TRY(name().with([&](auto& process_name) {
-        return KString::formatted("{}/{}_{}_{}", coredump_directory_path->view(), process_name->view(), pid().value(), kgettimeofday().to_truncated_seconds());
+        return KString::formatted("{}/{}_{}_{}", coredump_directory_path->view(), process_name->view(), pid().value(), kgettimeofday().seconds_since_epoch());
     }));
     }));
     auto coredump = TRY(Coredump::try_create(*this, coredump_path->view()));
     auto coredump = TRY(Coredump::try_create(*this, coredump_path->view()));
     return coredump->write();
     return coredump->write();

+ 1 - 1
Kernel/Process.h

@@ -41,7 +41,7 @@
 namespace Kernel {
 namespace Kernel {
 
 
 MutexProtected<OwnPtr<KString>>& hostname();
 MutexProtected<OwnPtr<KString>>& hostname();
-Duration kgettimeofday();
+UnixDateTime kgettimeofday();
 
 
 #define ENUMERATE_PLEDGE_PROMISES         \
 #define ENUMERATE_PLEDGE_PROMISES         \
     __ENUMERATE_PLEDGE_PROMISE(stdio)     \
     __ENUMERATE_PLEDGE_PROMISE(stdio)     \

+ 4 - 6
Kernel/Syscalls/clock.cpp

@@ -44,7 +44,7 @@ ErrorOr<FlatPtr> Process::sys$clock_settime(clockid_t clock_id, Userspace<timesp
     if (!credentials->is_superuser())
     if (!credentials->is_superuser())
         return EPERM;
         return EPERM;
 
 
-    auto time = TRY(copy_time_from_user(user_ts));
+    auto time = UnixDateTime::epoch() + TRY(copy_time_from_user(user_ts));
 
 
     switch (clock_id) {
     switch (clock_id) {
     case CLOCK_REALTIME:
     case CLOCK_REALTIME:
@@ -110,9 +110,8 @@ ErrorOr<FlatPtr> Process::sys$adjtime(Userspace<timeval const*> user_delta, User
 {
 {
     VERIFY_NO_PROCESS_BIG_LOCK(this);
     VERIFY_NO_PROCESS_BIG_LOCK(this);
     if (user_old_delta) {
     if (user_old_delta) {
-        timespec old_delta_ts = TimeManagement::the().remaining_epoch_time_adjustment();
-        timeval old_delta;
-        timespec_to_timeval(old_delta_ts, old_delta);
+        auto old_delta_duration = TimeManagement::the().remaining_epoch_time_adjustment();
+        auto old_delta = old_delta_duration.to_timeval();
         TRY(copy_to_user(user_old_delta, &old_delta));
         TRY(copy_to_user(user_old_delta, &old_delta));
     }
     }
 
 
@@ -123,8 +122,7 @@ ErrorOr<FlatPtr> Process::sys$adjtime(Userspace<timeval const*> user_delta, User
             return EPERM;
             return EPERM;
         auto delta = TRY(copy_time_from_user(user_delta));
         auto delta = TRY(copy_time_from_user(user_delta));
 
 
-        // FIXME: Should use AK::Duration internally
-        TimeManagement::the().set_remaining_epoch_time_adjustment(delta.to_timespec());
+        TimeManagement::the().set_remaining_epoch_time_adjustment(delta);
     }
     }
 
 
     return 0;
     return 0;

+ 1 - 1
Kernel/Syscalls/socket.cpp

@@ -272,7 +272,7 @@ ErrorOr<FlatPtr> Process::sys$recvmsg(int sockfd, Userspace<struct msghdr*> user
         return 0;
         return 0;
 
 
     auto data_buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len));
     auto data_buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len));
-    Duration timestamp {};
+    UnixDateTime timestamp {};
     bool blocking = (flags & MSG_DONTWAIT) ? false : description->is_blocking();
     bool blocking = (flags & MSG_DONTWAIT) ? false : description->is_blocking();
     auto result = socket.recvfrom(*description, data_buffer, iovs[0].iov_len, flags, user_addr, user_addr_length, timestamp, blocking);
     auto result = socket.recvfrom(*description, data_buffer, iovs[0].iov_len, flags, user_addr, user_addr_length, timestamp, blocking);
 
 

+ 1 - 1
Kernel/Syscalls/utime.cpp

@@ -19,7 +19,7 @@ ErrorOr<FlatPtr> Process::sys$utime(Userspace<char const*> user_path, size_t pat
     if (user_buf) {
     if (user_buf) {
         TRY(copy_from_user(&buf, user_buf));
         TRY(copy_from_user(&buf, user_buf));
     } else {
     } else {
-        auto now = kgettimeofday().to_truncated_seconds();
+        auto now = kgettimeofday().truncated_seconds_since_epoch();
         // Not a bug!
         // Not a bug!
         buf = { now, now };
         buf = { now, now };
     }
     }

+ 1 - 1
Kernel/TTY/SlavePTY.cpp

@@ -80,7 +80,7 @@ void SlavePTY::on_master_write(UserOrKernelBuffer const& buffer, size_t size)
 
 
 ErrorOr<size_t> SlavePTY::on_tty_write(UserOrKernelBuffer const& data, size_t size)
 ErrorOr<size_t> SlavePTY::on_tty_write(UserOrKernelBuffer const& data, size_t size)
 {
 {
-    m_time_of_last_write = kgettimeofday().to_truncated_seconds();
+    m_time_of_last_write = kgettimeofday();
     return m_master->on_slave_write(data, size);
     return m_master->on_slave_write(data, size);
 }
 }
 
 

+ 2 - 2
Kernel/TTY/SlavePTY.h

@@ -21,7 +21,7 @@ public:
     void on_master_write(UserOrKernelBuffer const&, size_t);
     void on_master_write(UserOrKernelBuffer const&, size_t);
     unsigned index() const { return m_index; }
     unsigned index() const { return m_index; }
 
 
-    time_t time_of_last_write() const { return m_time_of_last_write; }
+    UnixDateTime time_of_last_write() const { return m_time_of_last_write; }
 
 
     virtual FileBlockerSet& blocker_set() override;
     virtual FileBlockerSet& blocker_set() override;
 
 
@@ -45,7 +45,7 @@ private:
     SlavePTY(NonnullRefPtr<MasterPTY>, unsigned index);
     SlavePTY(NonnullRefPtr<MasterPTY>, unsigned index);
 
 
     NonnullRefPtr<MasterPTY> const m_master;
     NonnullRefPtr<MasterPTY> const m_master;
-    time_t m_time_of_last_write { 0 };
+    UnixDateTime m_time_of_last_write {};
     unsigned m_index { 0 };
     unsigned m_index { 0 };
 
 
     mutable IntrusiveListNode<SlavePTY> m_list_node;
     mutable IntrusiveListNode<SlavePTY> m_list_node;

+ 24 - 26
Kernel/Time/TimeManagement.cpp

@@ -87,9 +87,9 @@ Duration TimeManagement::current_time(clockid_t clock_id) const
     case CLOCK_MONOTONIC_RAW:
     case CLOCK_MONOTONIC_RAW:
         return monotonic_time_raw();
         return monotonic_time_raw();
     case CLOCK_REALTIME:
     case CLOCK_REALTIME:
-        return epoch_time(TimePrecision::Precise);
+        return epoch_time(TimePrecision::Precise).offset_to_epoch();
     case CLOCK_REALTIME_COARSE:
     case CLOCK_REALTIME_COARSE:
-        return epoch_time(TimePrecision::Coarse);
+        return epoch_time(TimePrecision::Coarse).offset_to_epoch();
     default:
     default:
         // Syscall entrypoint is missing a is_valid_clock_id(..) check?
         // Syscall entrypoint is missing a is_valid_clock_id(..) check?
         VERIFY_NOT_REACHED();
         VERIFY_NOT_REACHED();
@@ -101,12 +101,13 @@ bool TimeManagement::is_system_timer(HardwareTimerBase const& timer) const
     return &timer == m_system_timer.ptr();
     return &timer == m_system_timer.ptr();
 }
 }
 
 
-void TimeManagement::set_epoch_time(Duration ts)
+void TimeManagement::set_epoch_time(UnixDateTime ts)
 {
 {
+    // FIXME: The interrupt disabler intends to enforce atomic update of epoch time and remaining adjustment,
+    //        but that sort of assumption is known to break on SMP.
     InterruptDisabler disabler;
     InterruptDisabler disabler;
-    // FIXME: Should use AK::Duration internally
-    m_epoch_time = ts.to_timespec();
-    m_remaining_epoch_time_adjustment = { 0, 0 };
+    m_epoch_time = ts;
+    m_remaining_epoch_time_adjustment = {};
 }
 }
 
 
 Duration TimeManagement::monotonic_time(TimePrecision precision) const
 Duration TimeManagement::monotonic_time(TimePrecision precision) const
@@ -147,16 +148,16 @@ Duration TimeManagement::monotonic_time(TimePrecision precision) const
     return Duration::from_timespec({ (i64)seconds, (i32)ns });
     return Duration::from_timespec({ (i64)seconds, (i32)ns });
 }
 }
 
 
-Duration TimeManagement::epoch_time(TimePrecision) const
+UnixDateTime TimeManagement::epoch_time(TimePrecision) const
 {
 {
     // TODO: Take into account precision
     // TODO: Take into account precision
-    timespec ts;
+    UnixDateTime time;
     u32 update_iteration;
     u32 update_iteration;
     do {
     do {
         update_iteration = m_update1.load(AK::MemoryOrder::memory_order_acquire);
         update_iteration = m_update1.load(AK::MemoryOrder::memory_order_acquire);
-        ts = m_epoch_time;
+        time = m_epoch_time;
     } while (update_iteration != m_update2.load(AK::MemoryOrder::memory_order_acquire));
     } while (update_iteration != m_update2.load(AK::MemoryOrder::memory_order_acquire));
-    return Duration::from_timespec(ts);
+    return time;
 }
 }
 
 
 u64 TimeManagement::uptime_ms() const
 u64 TimeManagement::uptime_ms() const
@@ -226,7 +227,7 @@ time_t TimeManagement::ticks_per_second() const
     return m_time_keeper_timer->ticks_per_second();
     return m_time_keeper_timer->ticks_per_second();
 }
 }
 
 
-Duration TimeManagement::boot_time()
+UnixDateTime TimeManagement::boot_time()
 {
 {
 #if ARCH(X86_64)
 #if ARCH(X86_64)
     return RTC::boot_time();
     return RTC::boot_time();
@@ -252,14 +253,14 @@ UNMAP_AFTER_INIT TimeManagement::TimeManagement()
     if (ACPI::is_enabled()) {
     if (ACPI::is_enabled()) {
         if (!ACPI::Parser::the()->x86_specific_flags().cmos_rtc_not_present) {
         if (!ACPI::Parser::the()->x86_specific_flags().cmos_rtc_not_present) {
             RTC::initialize();
             RTC::initialize();
-            m_epoch_time.tv_sec += boot_time().to_timespec().tv_sec;
+            m_epoch_time += boot_time().offset_to_epoch();
         } else {
         } else {
             dmesgln("ACPI: RTC CMOS Not present");
             dmesgln("ACPI: RTC CMOS Not present");
         }
         }
     } else {
     } else {
         // We just assume that we can access RTC CMOS, if ACPI isn't usable.
         // We just assume that we can access RTC CMOS, if ACPI isn't usable.
         RTC::initialize();
         RTC::initialize();
-        m_epoch_time.tv_sec += boot_time().to_timespec().tv_sec;
+        m_epoch_time += boot_time().offset_to_epoch();
     }
     }
     if (probe_non_legacy_hardware_timers) {
     if (probe_non_legacy_hardware_timers) {
         if (!probe_and_set_x86_non_legacy_hardware_timers())
         if (!probe_and_set_x86_non_legacy_hardware_timers())
@@ -275,7 +276,7 @@ UNMAP_AFTER_INIT TimeManagement::TimeManagement()
 #endif
 #endif
 }
 }
 
 
-Duration TimeManagement::now()
+UnixDateTime TimeManagement::now()
 {
 {
     return s_the.ptr()->epoch_time();
     return s_the.ptr()->epoch_time();
 }
 }
@@ -437,7 +438,8 @@ void TimeManagement::increment_time_since_boot_hpet()
     m_seconds_since_boot = seconds_since_boot;
     m_seconds_since_boot = seconds_since_boot;
     m_ticks_this_second = ticks_this_second;
     m_ticks_this_second = ticks_this_second;
     // TODO: Apply m_remaining_epoch_time_adjustment
     // TODO: Apply m_remaining_epoch_time_adjustment
-    timespec_add(m_epoch_time, { (time_t)(delta_ns / 1000000000), (long)(delta_ns % 1000000000) }, m_epoch_time);
+    timespec time_adjustment = { (time_t)(delta_ns / 1000000000), (long)(delta_ns % 1000000000) };
+    m_epoch_time += Duration::from_timespec(time_adjustment);
 
 
     m_update1.store(update_iteration + 1, AK::MemoryOrder::memory_order_release);
     m_update1.store(update_iteration + 1, AK::MemoryOrder::memory_order_release);
 
 
@@ -483,20 +485,16 @@ void TimeManagement::increment_time_since_boot()
     // Compute time adjustment for adjtime. Let the clock run up to 1% fast or slow.
     // Compute time adjustment for adjtime. Let the clock run up to 1% fast or slow.
     // That way, adjtime can adjust up to 36 seconds per hour, without time getting very jumpy.
     // That way, adjtime can adjust up to 36 seconds per hour, without time getting very jumpy.
     // Once we have a smarter NTP service that also adjusts the frequency instead of just slewing time, maybe we can lower this.
     // Once we have a smarter NTP service that also adjusts the frequency instead of just slewing time, maybe we can lower this.
-    long NanosPerTick = 1'000'000'000 / m_time_keeper_timer->frequency();
-    time_t MaxSlewNanos = NanosPerTick / 100;
+    long nanos_per_tick = 1'000'000'000 / m_time_keeper_timer->frequency();
+    time_t max_slew_nanos = nanos_per_tick / 100;
 
 
     u32 update_iteration = m_update2.fetch_add(1, AK::MemoryOrder::memory_order_acquire);
     u32 update_iteration = m_update2.fetch_add(1, AK::MemoryOrder::memory_order_acquire);
 
 
-    // Clamp twice, to make sure intermediate fits into a long.
-    long slew_nanos = clamp(clamp(m_remaining_epoch_time_adjustment.tv_sec, (time_t)-1, (time_t)1) * 1'000'000'000 + m_remaining_epoch_time_adjustment.tv_nsec, -MaxSlewNanos, MaxSlewNanos);
-    timespec slew_nanos_ts;
-    timespec_sub({ 0, slew_nanos }, { 0, 0 }, slew_nanos_ts); // Normalize tv_nsec to be positive.
-    timespec_sub(m_remaining_epoch_time_adjustment, slew_nanos_ts, m_remaining_epoch_time_adjustment);
+    auto slew_nanos = Duration::from_nanoseconds(
+        clamp(m_remaining_epoch_time_adjustment.to_nanoseconds(), -max_slew_nanos, max_slew_nanos));
+    m_remaining_epoch_time_adjustment -= slew_nanos;
 
 
-    timespec epoch_tick = { .tv_sec = 0, .tv_nsec = NanosPerTick };
-    epoch_tick.tv_nsec += slew_nanos; // No need for timespec_add(), guaranteed to be in range.
-    timespec_add(m_epoch_time, epoch_tick, m_epoch_time);
+    m_epoch_time += Duration::from_nanoseconds(nanos_per_tick + slew_nanos.to_nanoseconds());
 
 
     if (++m_ticks_this_second >= m_time_keeper_timer->ticks_per_second()) {
     if (++m_ticks_this_second >= m_time_keeper_timer->ticks_per_second()) {
         // FIXME: Synchronize with other clock somehow to prevent drifting apart.
         // FIXME: Synchronize with other clock somehow to prevent drifting apart.
@@ -540,7 +538,7 @@ void TimeManagement::update_time_page()
 {
 {
     auto& page = time_page();
     auto& page = time_page();
     u32 update_iteration = AK::atomic_fetch_add(&page.update2, 1u, AK::MemoryOrder::memory_order_acquire);
     u32 update_iteration = AK::atomic_fetch_add(&page.update2, 1u, AK::MemoryOrder::memory_order_acquire);
-    page.clocks[CLOCK_REALTIME_COARSE] = m_epoch_time;
+    page.clocks[CLOCK_REALTIME_COARSE] = m_epoch_time.to_timespec();
     page.clocks[CLOCK_MONOTONIC_COARSE] = monotonic_time(TimePrecision::Coarse).to_timespec();
     page.clocks[CLOCK_MONOTONIC_COARSE] = monotonic_time(TimePrecision::Coarse).to_timespec();
     AK::atomic_store(&page.update1, update_iteration + 1u, AK::MemoryOrder::memory_order_release);
     AK::atomic_store(&page.update1, update_iteration + 1u, AK::MemoryOrder::memory_order_release);
 }
 }

+ 10 - 13
Kernel/Time/TimeManagement.h

@@ -48,10 +48,10 @@ public:
         // TODO: implement
         // TODO: implement
         return monotonic_time(TimePrecision::Precise);
         return monotonic_time(TimePrecision::Precise);
     }
     }
-    Duration epoch_time(TimePrecision = TimePrecision::Precise) const;
-    void set_epoch_time(Duration);
+    UnixDateTime epoch_time(TimePrecision = TimePrecision::Precise) const;
+    void set_epoch_time(UnixDateTime);
     time_t ticks_per_second() const;
     time_t ticks_per_second() const;
-    static Duration boot_time();
+    static UnixDateTime boot_time();
     Duration clock_resolution() const;
     Duration clock_resolution() const;
 
 
     bool is_system_timer(HardwareTimerBase const&) const;
     bool is_system_timer(HardwareTimerBase const&) const;
@@ -64,14 +64,12 @@ public:
     bool disable_profile_timer();
     bool disable_profile_timer();
 
 
     u64 uptime_ms() const;
     u64 uptime_ms() const;
-    static Duration now();
+    static UnixDateTime now();
 
 
-    // FIXME: Should use AK::Duration internally
-    // FIXME: Also, most likely broken, because it does not check m_update[12] for in-progress updates.
-    timespec remaining_epoch_time_adjustment() const { return m_remaining_epoch_time_adjustment; }
-    // FIXME: Should use AK::Duration internally
-    // FIXME: Also, most likely broken, because it does not check m_update[12] for in-progress updates.
-    void set_remaining_epoch_time_adjustment(timespec const& adjustment) { m_remaining_epoch_time_adjustment = adjustment; }
+    // FIXME: Most likely broken, because it does not check m_update[12] for in-progress updates.
+    Duration remaining_epoch_time_adjustment() const { return m_remaining_epoch_time_adjustment; }
+    // FIXME: Most likely broken, because it does not check m_update[12] for in-progress updates.
+    void set_remaining_epoch_time_adjustment(Duration adjustment) { m_remaining_epoch_time_adjustment = adjustment; }
 
 
     bool can_query_precise_time() const { return m_can_query_precise_time; }
     bool can_query_precise_time() const { return m_can_query_precise_time; }
 
 
@@ -102,9 +100,8 @@ private:
     Atomic<u32> m_update1 { 0 };
     Atomic<u32> m_update1 { 0 };
     u32 m_ticks_this_second { 0 };
     u32 m_ticks_this_second { 0 };
     u64 m_seconds_since_boot { 0 };
     u64 m_seconds_since_boot { 0 };
-    // FIXME: Should use AK::Duration internally
-    timespec m_epoch_time { 0, 0 };
-    timespec m_remaining_epoch_time_adjustment { 0, 0 };
+    UnixDateTime m_epoch_time {};
+    Duration m_remaining_epoch_time_adjustment {};
     Atomic<u32> m_update2 { 0 };
     Atomic<u32> m_update2 { 0 };
 
 
     u32 m_time_ticks_per_second { 0 }; // may be different from interrupts/second (e.g. hpet)
     u32 m_time_ticks_per_second { 0 }; // may be different from interrupts/second (e.g. hpet)

+ 1 - 1
Userland/Utilities/unzip.cpp

@@ -22,7 +22,7 @@
 static ErrorOr<void> adjust_modification_time(Archive::ZipMember const& zip_member)
 static ErrorOr<void> adjust_modification_time(Archive::ZipMember const& zip_member)
 {
 {
     auto time = time_from_packed_dos(zip_member.modification_date, zip_member.modification_time);
     auto time = time_from_packed_dos(zip_member.modification_date, zip_member.modification_time);
-    auto seconds = static_cast<time_t>(time.to_seconds());
+    auto seconds = static_cast<time_t>(time.seconds_since_epoch());
     struct utimbuf buf {
     struct utimbuf buf {
         .actime = seconds,
         .actime = seconds,
         .modtime = seconds
         .modtime = seconds