fix(fs): track multiple directory handles with win32 backends (#3243)

* fix(fs_win32): Track multiple directory handles

* fix(fs_stdio): Track multiple directory handles (win32)
This commit is contained in:
Ryzee119
2022-04-04 22:19:07 +09:30
committed by GitHub
parent b7b22c190c
commit 57e3697dca
2 changed files with 84 additions and 55 deletions
+43 -26
View File
@@ -21,10 +21,19 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define MAX_PATH_LEN 256
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
typedef struct {
#ifdef WIN32
HANDLE dir_p;
char next_fn[MAX_PATH_LEN];
#else
DIR * dir_p;
#endif
} dir_handle_t;
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
@@ -105,7 +114,7 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
/*Make the path relative to the current directory (the projects root folder)*/ /*Make the path relative to the current directory (the projects root folder)*/
char buf[256]; char buf[MAX_PATH_LEN];
lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s", path); lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s", path);
return fopen(buf, flags); return fopen(buf, flags);
@@ -188,10 +197,6 @@ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
return LV_FS_RES_OK; return LV_FS_RES_OK;
} }
#ifdef WIN32
static char next_fn[256];
#endif
/** /**
* Initialize a 'DIR' or 'HANDLE' variable for directory reading * Initialize a 'DIR' or 'HANDLE' variable for directory reading
* @param drv pointer to a driver where this function belongs * @param drv pointer to a driver where this function belongs
@@ -201,37 +206,47 @@ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
{ {
LV_UNUSED(drv); LV_UNUSED(drv);
dir_handle_t * handle = (dir_handle_t *)lv_mem_alloc(sizeof(dir_handle_t));
#ifndef WIN32 #ifndef WIN32
/*Make the path relative to the current directory (the projects root folder)*/ /*Make the path relative to the current directory (the projects root folder)*/
char buf[256]; char buf[MAX_PATH_LEN];
lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s", path); lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s", path);
return opendir(buf); handle->dir_p = opendir(buf);
if(handle->dir_p == NULL) {
lv_mem_free(handle);
return NULL;
}
return handle;
#else #else
HANDLE d = INVALID_HANDLE_VALUE; handle->dir_p = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA fdata; WIN32_FIND_DATA fdata;
/*Make the path relative to the current directory (the projects root folder)*/ /*Make the path relative to the current directory (the projects root folder)*/
char buf[256]; char buf[MAX_PATH_LEN];
lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s\\*", path); lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s\\*", path);
strcpy(next_fn, ""); strcpy(handle->next_fn, "");
d = FindFirstFile(buf, &fdata); handle->dir_p = FindFirstFile(buf, &fdata);
do { do {
if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) {
continue; continue;
} }
else { else {
if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
sprintf(next_fn, "/%s", fdata.cFileName); lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName);
} }
else { else {
sprintf(next_fn, "%s", fdata.cFileName); lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName);
} }
break; break;
} }
} while(FindNextFileA(d, &fdata)); } while(FindNextFileA(handle->dir_p, &fdata));
return d; if(handle->dir_p == INVALID_HANDLE_VALUE) {
lv_mem_free(handle);
return INVALID_HANDLE_VALUE;
}
return handle;
#endif #endif
} }
@@ -246,13 +261,13 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn)
{ {
LV_UNUSED(drv); LV_UNUSED(drv);
dir_handle_t * handle = (dir_handle_t *)dir_p;
#ifndef WIN32 #ifndef WIN32
struct dirent * entry; struct dirent * entry;
do { do {
entry = readdir(dir_p); entry = readdir(handle->dir_p);
if(entry) { if(entry) {
if(entry->d_type == DT_DIR) sprintf(fn, "/%s", entry->d_name); if(entry->d_type == DT_DIR) lv_snprintf(fn, MAX_PATH_LEN, "/%s", entry->d_name);
else strcpy(fn, entry->d_name); else strcpy(fn, entry->d_name);
} }
else { else {
@@ -260,26 +275,26 @@ static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn)
} }
} while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0); } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0);
#else #else
strcpy(fn, next_fn); strcpy(fn, handle->next_fn);
strcpy(next_fn, ""); strcpy(handle->next_fn, "");
WIN32_FIND_DATA fdata; WIN32_FIND_DATA fdata;
if(FindNextFile(dir_p, &fdata) == false) return LV_FS_RES_OK; if(FindNextFile(handle->dir_p, &fdata) == false) return LV_FS_RES_OK;
do { do {
if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) {
continue; continue;
} }
else { else {
if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
sprintf(next_fn, "/%s", fdata.cFileName); lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName);
} }
else { else {
sprintf(next_fn, "%s", fdata.cFileName); lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName);
} }
break; break;
} }
} while(FindNextFile(dir_p, &fdata)); } while(FindNextFile(handle->dir_p, &fdata));
#endif #endif
return LV_FS_RES_OK; return LV_FS_RES_OK;
@@ -294,11 +309,13 @@ static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn)
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p)
{ {
LV_UNUSED(drv); LV_UNUSED(drv);
dir_handle_t * handle = (dir_handle_t *)dir_p;
#ifndef WIN32 #ifndef WIN32
closedir(dir_p); closedir(handle->dir_p);
#else #else
FindClose(dir_p); FindClose(handle->dir_p);
#endif #endif
lv_mem_free(handle);
return LV_FS_RES_OK; return LV_FS_RES_OK;
} }
+41 -29
View File
@@ -16,10 +16,16 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define MAX_PATH_LEN 256
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
typedef struct {
HANDLE dir_p;
char next_fn[MAX_PATH_LEN];
lv_fs_res_t next_error;
} dir_handle_t;
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
@@ -344,9 +350,6 @@ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
} }
} }
static char next_fn[256];
static lv_fs_res_t next_error = LV_FS_RES_OK;
/** /**
* Initialize a 'DIR' or 'HANDLE' variable for directory reading * Initialize a 'DIR' or 'HANDLE' variable for directory reading
* @param drv pointer to a driver where this function belongs * @param drv pointer to a driver where this function belongs
@@ -356,38 +359,45 @@ static lv_fs_res_t next_error = LV_FS_RES_OK;
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
{ {
LV_UNUSED(drv); LV_UNUSED(drv);
dir_handle_t * handle = (dir_handle_t *)lv_mem_alloc(sizeof(dir_handle_t));
HANDLE d = INVALID_HANDLE_VALUE; handle->dir_p = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAA fdata; handle->next_error = LV_FS_RES_OK;
WIN32_FIND_DATA fdata;
/*Make the path relative to the current directory (the projects root folder)*/ /*Make the path relative to the current directory (the projects root folder)*/
char buf[256]; char buf[MAX_PATH_LEN];
#ifdef LV_FS_WIN32_PATH #ifdef LV_FS_WIN32_PATH
lv_snprintf(buf, sizeof(buf), LV_FS_WIN32_PATH "%s\\*", path); lv_snprintf(buf, sizeof(buf), LV_FS_WIN32_PATH "%s\\*", path);
#else #else
lv_snprintf(buf, sizeof(buf), "%s\\*", path); lv_snprintf(buf, sizeof(buf), "%s\\*", path);
#endif #endif
strcpy(next_fn, ""); strcpy(handle->next_fn, "");
d = FindFirstFileA(buf, &fdata); handle->dir_p = FindFirstFile(buf, &fdata);
do { do {
if(is_dots_name(fdata.cFileName)) { if(is_dots_name(fdata.cFileName)) {
continue; continue;
} }
else { else {
if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
sprintf(next_fn, "/%s", fdata.cFileName); lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName);
} }
else { else {
sprintf(next_fn, "%s", fdata.cFileName); lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName);
} }
break; break;
} }
} while(FindNextFileA(handle->dir_p, &fdata));
} while(FindNextFileA(d, &fdata)); if(handle->dir_p == INVALID_HANDLE_VALUE) {
lv_mem_free(handle);
next_error = fs_error_from_win32(GetLastError()); handle->next_error = fs_error_from_win32(GetLastError());
return d; return INVALID_HANDLE_VALUE;
}
else {
handle->next_error = LV_FS_RES_OK;
return handle;
}
} }
/** /**
@@ -401,31 +411,30 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn)
{ {
LV_UNUSED(drv); LV_UNUSED(drv);
dir_handle_t * handle = (dir_handle_t *)dir_p;
strcpy(fn, handle->next_fn);
lv_fs_res_t current_error = handle->next_error;
strcpy(handle->next_fn, "");
strcpy(fn, next_fn); WIN32_FIND_DATA fdata;
lv_fs_res_t current_error = next_error;
next_error = LV_FS_RES_OK;
strcpy(next_fn, ""); while(FindNextFileA(handle->dir_p, &fdata)) {
WIN32_FIND_DATAA fdata;
while(FindNextFileA(dir_p, &fdata)) {
if(is_dots_name(fdata.cFileName)) { if(is_dots_name(fdata.cFileName)) {
continue; continue;
} }
else { else {
if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
sprintf(next_fn, "/%s", fdata.cFileName); lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName);
} }
else { else {
sprintf(next_fn, "%s", fdata.cFileName); lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName);
} }
break; break;
} }
} }
if(next_fn[0] == '\0') { if(handle->next_fn[0] == '\0') {
next_error = fs_error_from_win32(GetLastError()); handle->next_error = fs_error_from_win32(GetLastError());
} }
return current_error; return current_error;
@@ -440,9 +449,12 @@ static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn)
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p)
{ {
LV_UNUSED(drv); LV_UNUSED(drv);
return FindClose((HANDLE)dir_p) dir_handle_t * handle = (dir_handle_t *)dir_p;
? LV_FS_RES_OK lv_fs_res_t res = FindClose(handle->dir_p)
: fs_error_from_win32(GetLastError()); ? LV_FS_RES_OK
: fs_error_from_win32(GetLastError());
lv_mem_free(handle);
return res;
} }
#else /*LV_USE_FS_WIN32 == 0*/ #else /*LV_USE_FS_WIN32 == 0*/