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..4697b01 100644 --- a/netmount-server/netmount-server.cpp +++ b/netmount-server/netmount-server.cpp @@ -256,15 +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); - log(LogLevel::DEBUG, "CLOSE_FILE handle {}\n", handle); + log(LogLevel::DEBUG, "CLOSE_FILE handle {} {:08X}\n", handle, date_time); try { - drive.get_handle_path(handle); + 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? diff --git a/netmount/netmount.c b/netmount/netmount.c index 4927f83..0d3f695 100644 --- a/netmount/netmount.c +++ b/netmount/netmount.c @@ -905,6 +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; + 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); @@ -1359,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; 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; };