From a2b1b098e4bad957d13843ba7228440ff32e7584 Mon Sep 17 00:00:00 2001 From: Kobayashi Takashi Date: Mon, 8 Dec 2025 15:45:44 +0900 Subject: [PATCH 1/4] Enable date and time settings for remote files --- netmount-server/fs.cpp | 25 +++++++++++++++++++++++++ netmount-server/fs.hpp | 3 +++ netmount-server/netmount-server.cpp | 5 +++-- netmount/netmount.c | 1 + shared/drvproto.h | 1 + 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/netmount-server/fs.cpp b/netmount-server/fs.cpp index fbcf36a..e5494a2 100644 --- a/netmount-server/fs.cpp +++ b/netmount-server/fs.cpp @@ -147,6 +147,23 @@ uint32_t time_to_fat(time_t t) { return res; } +time_t fat_to_time(uint32_t date_time) { + struct tm ltime; + ltime.tm_isdst = -1; + ltime.tm_sec = (date_time & 0x1f) * 2; + date_time >>= 5; + ltime.tm_min = date_time & 0x3f; + date_time >>= 6; + ltime.tm_hour = date_time & 0x1f; + date_time >>= 5; + ltime.tm_mday = date_time & 0x1f; + date_time >>= 5; + ltime.tm_mon = (date_time & 0x0f) - 1; + date_time >>= 4; + ltime.tm_year = date_time + 80; + return mktime(<ime); +} + } // namespace @@ -362,6 +379,14 @@ int32_t Drive::get_file_size(uint16_t handle) { } +void Drive::set_file_date_time(uint16_t handle, uint32_t date_time) { + auto & item = get_item(handle); + auto file_time = std::chrono::file_clock::from_sys(std::chrono::system_clock::from_time_t(fat_to_time(date_time))); + std::filesystem::last_write_time(item.path, file_time); + item.update_last_used_timestamp(); +} + + bool Drive::find_file( uint16_t handle, const fcb_file_name & tmpl, unsigned char attr, DosFileProperties & properties, uint16_t & nth) { diff --git a/netmount-server/fs.hpp b/netmount-server/fs.hpp index 32465f8..81218fd 100644 --- a/netmount-server/fs.hpp +++ b/netmount-server/fs.hpp @@ -117,6 +117,9 @@ class Drive { /// Returns the size of file defined by handle (or -1 on error) int32_t get_file_size(uint16_t handle); + /// Throws exception on error + void set_file_date_time(uint16_t handle, uint32_t date_time); + /// Searches for files matching template `tmpl` in directory defined by `handle` /// with at most attributes `attr`. /// Fills in `properties` with the next match after `nth` and updates `nth` diff --git a/netmount-server/netmount-server.cpp b/netmount-server/netmount-server.cpp index 3cdaf3e..a35e531 100644 --- a/netmount-server/netmount-server.cpp +++ b/netmount-server/netmount-server.cpp @@ -262,9 +262,10 @@ int process_request(ReplyCache::ReplyInfo & reply_info, const uint8_t * request_ // Only checking the existence of the handle because I don't keep files open. auto * const request = reinterpret_cast(request_data); const uint16_t handle = from_little16(request->start_cluster); - log(LogLevel::DEBUG, "CLOSE_FILE handle {}\n", handle); + const uint32_t date_time = from_little32(request->date_time); + log(LogLevel::DEBUG, "CLOSE_FILE handle {} {:08X}\n", handle, date_time); try { - drive.get_handle_path(handle); + drive.set_file_date_time(handle, date_time); } catch (const std::runtime_error & ex) { log(LogLevel::WARNING, "CLOSE_FILE handle {}: {}\n", handle, ex.what()); // TODO: Send error to client? diff --git a/netmount/netmount.c b/netmount/netmount.c index 4927f83..f612b4d 100644 --- a/netmount/netmount.c +++ b/netmount/netmount.c @@ -905,6 +905,7 @@ static void handle_request_for_our_drive(void) { struct drive_proto_closef * const args = (struct drive_proto_closef * const)buff; args->start_cluster = sftptr->start_cluster; + args->date_time = sftptr->file_time; if (send_request(subfunction, reqdrv, sizeof(*args), &reply, &ax) == 0) { if (ax != 0) { set_error(r, ax); diff --git a/shared/drvproto.h b/shared/drvproto.h index eedc734..2b05dad 100644 --- a/shared/drvproto.h +++ b/shared/drvproto.h @@ -36,6 +36,7 @@ struct drive_proto_hdr { struct drive_proto_closef { uint16_t start_cluster; + uint32_t date_time; }; From d90e88581f66a5b889a0bc92934d7731766e125e Mon Sep 17 00:00:00 2001 From: Kobayashi Takashi Date: Fri, 12 Dec 2025 17:31:47 +0900 Subject: [PATCH 2/4] Fix to prevent date/time settings from being applied when closing files if file writing occurs --- netmount/netmount.c | 1 + 1 file changed, 1 insertion(+) diff --git a/netmount/netmount.c b/netmount/netmount.c index f612b4d..8b258d9 100644 --- a/netmount/netmount.c +++ b/netmount/netmount.c @@ -1119,6 +1119,7 @@ static void handle_request_for_our_drive(void) { } *recvbufflen_ptr = 0; } while (bytes_left > 0); + sftptr->file_time = 0; } break; case INT2F_LOCK_UNLOCK_FILE: { From 96524662ab5d38e3af4e84c49d0e6f5f768c0afc Mon Sep 17 00:00:00 2001 From: Kobayashi Takashi Date: Fri, 12 Dec 2025 17:34:27 +0900 Subject: [PATCH 3/4] Fixed the server to accept file close packets without date and time data. Fix to prevent date/time settings from being applied when closing files if file writing occurs. --- netmount-server/netmount-server.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/netmount-server/netmount-server.cpp b/netmount-server/netmount-server.cpp index a35e531..4697b01 100644 --- a/netmount-server/netmount-server.cpp +++ b/netmount-server/netmount-server.cpp @@ -256,16 +256,22 @@ int process_request(ReplyCache::ReplyInfo & reply_info, const uint8_t * request_ } case INT2F_CLOSE_FILE: { - if (request_data_len != sizeof(drive_proto_closef)) { + auto * const request = reinterpret_cast(request_data); + uint32_t date_time = 0; + if (request_data_len == sizeof(drive_proto_closef)) { + date_time = from_little32(request->date_time); + } else if (request_data_len != sizeof(drive_proto_closef) - sizeof(uint32_t)) { return -1; } // Only checking the existence of the handle because I don't keep files open. - auto * const request = reinterpret_cast(request_data); const uint16_t handle = from_little16(request->start_cluster); - const uint32_t date_time = from_little32(request->date_time); log(LogLevel::DEBUG, "CLOSE_FILE handle {} {:08X}\n", handle, date_time); try { - drive.set_file_date_time(handle, date_time); + if (date_time != 0) { + drive.set_file_date_time(handle, date_time); + } else { + drive.get_handle_path(handle); + } } catch (const std::runtime_error & ex) { log(LogLevel::WARNING, "CLOSE_FILE handle {}: {}\n", handle, ex.what()); // TODO: Send error to client? From 87fe7983801ad2a67b01f4f9b6bc42ab3ae4c93b Mon Sep 17 00:00:00 2001 From: Kobayashi Takashi Date: Tue, 16 Dec 2025 17:38:44 +0900 Subject: [PATCH 4/4] Modified to update only if the date and time changed when closing the file. --- netmount/netmount.c | 10 ++++++---- shared/dos.h | 9 +++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/netmount/netmount.c b/netmount/netmount.c index 8b258d9..0d3f695 100644 --- a/netmount/netmount.c +++ b/netmount/netmount.c @@ -905,7 +905,11 @@ static void handle_request_for_our_drive(void) { struct drive_proto_closef * const args = (struct drive_proto_closef * const)buff; args->start_cluster = sftptr->start_cluster; - args->date_time = sftptr->file_time; + if (sftptr->start_file_time != sftptr->file_time) { + args->date_time = sftptr->file_time; + } else { + args->date_time = 0; + } if (send_request(subfunction, reqdrv, sizeof(*args), &reply, &ax) == 0) { if (ax != 0) { set_error(r, ax); @@ -1119,7 +1123,6 @@ static void handle_request_for_our_drive(void) { } *recvbufflen_ptr = 0; } while (bytes_left > 0); - sftptr->file_time = 0; } break; case INT2F_LOCK_UNLOCK_FILE: { @@ -1361,8 +1364,7 @@ static void handle_request_for_our_drive(void) { sft_ptr->file_pos = 0; sft_ptr->open_mode &= 0xFF00U; sft_ptr->open_mode |= args->mode; - sft_ptr->rel_sector = 0xFFFFU; - sft_ptr->abs_sector = 0xFFFFU; + sft_ptr->start_file_time = args->date_time; sft_ptr->dir_sector = 0; sft_ptr->dir_entry_no = 0xFF; // why such value? no idea, EtherDFS says PHANTON.C uses that sft_ptr->file_name = args->name; diff --git a/shared/dos.h b/shared/dos.h index 132b18e..590bd78 100644 --- a/shared/dos.h +++ b/shared/dos.h @@ -223,8 +223,13 @@ struct dos_sft { uint32_t file_time; // file date and time uint32_t file_size; // file length uint32_t file_pos; // current file position - uint16_t rel_sector; - uint16_t abs_sector; + union { + struct { + uint16_t rel_sector; + uint16_t abs_sector; + }; + uint32_t start_file_time; + }; uint16_t dir_sector; uint8_t dir_entry_no; // if local, number of directory entry within sector struct fcb_file_name file_name;