From 11d69ee443a869740102d53eb292598c8d159ff6 Mon Sep 17 00:00:00 2001 From: Javier Date: Sat, 30 Apr 2022 13:43:03 +0200 Subject: add hack to make filemgr stop leaking dir handles --- sftsr.c | 20 ++++++++++++++++++-- sftsr.h | 6 +++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/sftsr.c b/sftsr.c index db231dc..2294089 100644 --- a/sftsr.c +++ b/sftsr.c @@ -377,7 +377,7 @@ static vboxerr close_openfile(unsigned index) { vboxerr err; - dlog_print("close_openfile "); + dlog_print("close openfile="); dlog_printu(index); dlog_endline(); @@ -803,7 +803,6 @@ static void handle_rename(union INTPACK __far *r) translate_filename_to_host(&shflstr.shflstr); // Reusing shfldirinfo buffer space here for our second filename - // Hoping no one does concurrent find_next and rename copy_drive_relative_filename(&shfldirinfo.dirinfo.name, dst); translate_filename_to_host(&shfldirinfo.dirinfo.name); @@ -1109,6 +1108,23 @@ static void handle_find_first(union INTPACK __far *r) clear_sdb_openfile_index(&data.dossda->sdb); } + // We will still leak the directory handle if the program stops calling + // FindNext before reaching the end of the directory, e.g. if it expects + // a specific file. But why would a program use a wildcard search just to + // check the existence of a particular file? + // Hopefully this is a rare situation and we don't leak too many fds. + + // Naturally, Windows 3.x's Winfile does exactly what is described above. + // On mkdir, it will create a testdir.tmp file on the new directory, + // then proceed to findfirst "*.*" on it and expect the testdir.tmp file, + // never to call findnext again. + // Cue hack to avoid leaking one dirfd for each mkdir... + if (_fmemcmp(data.dossda->found_file.filename, "TESTDIR TMP", 8+3) == 0) { + dlog_puts("win3.x testdir detected"); + close_openfile(openfile); + clear_sdb_openfile_index(&data.dossda->sdb); + } + clear_dos_err(r); } diff --git a/sftsr.h b/sftsr.h index 52e86f3..9b254f7 100644 --- a/sftsr.h +++ b/sftsr.h @@ -32,7 +32,7 @@ #define LASTDRIVE 'Z' #define NUM_DRIVES ((LASTDRIVE - 'A') + 1) -/** Maximum number of open files */ +/** Maximum number of open files and open directories (being enumerated). */ #define NUM_FILES 60 /** Parameters used for returning disk geometry. @@ -51,6 +51,10 @@ typedef struct { uint32_t root; uint64_t handle; } OPENFILE; +// TODO: Technically we could reduce the size of the above struct to save a bit of mem +// In the current implementation the max handle virtualbox can give is < 4K, +// but we still waste a full uint64_t to store a value that is always < 4K. +// Similarly, at most 64 roots are supported, but we waste a uint32_t. typedef struct { // TSR installation data -- cgit v1.2.3