From 2396e2d3a207e5de2c8ae32c506d0ebb3be779f7 Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Sun, 8 Sep 2013 14:18:40 +0200 Subject: [PATCH] squash! Win32: Make the dirent implementation pluggable mingw: make the dirent implementation pluggable Emulating the POSIX `dirent` API on Windows via `FindFirstFile()`/`FindNextFile()` is pretty staightforward, however, most of the information provided in the `WIN32_FIND_DATA` structure is thrown away in the process. A more sophisticated implementation may cache this data, e.g. for later reuse in calls to `lstat()`. Make the `dirent` implementation pluggable so that it can be switched at runtime, e.g. based on a config option. Define a base DIR structure with pointers to `readdir()`/`closedir()` that match the `opendir()` implementation (similar to vtable pointers in Object-Oriented Programming). Define `readdir()`/`closedir()` so that they call the function pointers in the `DIR` structure. This allows to choose the `opendir()` implementation on a call-by-call basis. Make the fixed-size `dirent.d_name` buffer a flex array, as `d_name` may be implementation specific (e.g. a caching implementation may allocate a `struct dirent` with _just_ the size needed to hold the `d_name` in question). Signed-off-by: Karsten Blees Signed-off-by: Johannes Schindelin --- compat/win32/dirent.c | 6 ++---- compat/win32/dirent.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/compat/win32/dirent.c b/compat/win32/dirent.c index 8c654d722b..9fc8bfb645 100644 --- a/compat/win32/dirent.c +++ b/compat/win32/dirent.c @@ -2,10 +2,9 @@ typedef struct dirent_DIR { struct DIR base_dir; /* extend base struct DIR */ - struct dirent dd_dir; /* includes d_type */ HANDLE dd_handle; /* FindFirstFile handle */ int dd_stat; /* 0-based index */ - char dd_name[MAX_PATH * 3]; /* file name (* 3 for UTF-8 conversion) */ + struct dirent dd_dir; /* includes d_type */ } dirent_DIR; DIR *(*opendir)(const char *dirname) = dirent_opendir; @@ -95,10 +94,9 @@ DIR *dirent_opendir(const char *name) } /* initialize DIR structure and copy first dir entry */ - dir = xmalloc(sizeof(dirent_DIR)); + dir = xmalloc(sizeof(dirent_DIR) + MAX_LONG_PATH); dir->base_dir.preaddir = (struct dirent *(*)(DIR *dir)) dirent_readdir; dir->base_dir.pclosedir = (int (*)(DIR *dir)) dirent_closedir; - dir->dd_dir.d_name = dir->dd_name; dir->dd_handle = h; dir->dd_stat = 0; finddata2dirent(&dir->dd_dir, &fdata); diff --git a/compat/win32/dirent.h b/compat/win32/dirent.h index 6b3ddee51b..e0e0e1700f 100644 --- a/compat/win32/dirent.h +++ b/compat/win32/dirent.h @@ -8,7 +8,7 @@ struct dirent { unsigned char d_type; /* file type to prevent lstat after readdir */ - char *d_name; /* file name */ + char d_name[FLEX_ARRAY]; /* file name */ }; /*