aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrh <>2025-05-13 16:58:36 +0000
committerdrh <>2025-05-13 16:58:36 +0000
commit494830ca8ecdd771f73d4751aa959ed81746c345 (patch)
treebe143959319dcc8f35c397e8d3a14a434755f0f0
parent0df6c5b9a70c6c1b87430c7f69f6849c145803b9 (diff)
downloadsqlite-494830ca8ecdd771f73d4751aa959ed81746c345.tar.gz
sqlite-494830ca8ecdd771f73d4751aa959ed81746c345.zip
First cut at enhancing the fsdir virtual table so that it works with
unicode characters on Windows. FossilOrigin-Name: c9e04dadfdf6c860631ce5603693add565ff2033aa25af5736302af7045fc91e
-rw-r--r--ext/misc/fileio.c57
-rw-r--r--manifest16
-rw-r--r--manifest.uuid2
-rw-r--r--src/test_windirent.c48
-rw-r--r--src/test_windirent.h1
5 files changed, 87 insertions, 37 deletions
diff --git a/ext/misc/fileio.c b/ext/misc/fileio.c
index 80ac3b3e7..96a7f82bd 100644
--- a/ext/misc/fileio.c
+++ b/ext/misc/fileio.c
@@ -98,14 +98,9 @@ SQLITE_EXTENSION_INIT1
# include <direct.h>
# include "test_windirent.h"
# define dirent DIRENT
-# ifndef chmod
-# define chmod _chmod
-# endif
-# ifndef stat
-# define stat _stat
-# endif
-# define mkdir(path,mode) _mkdir(path)
-# define lstat(path,buf) stat(path,buf)
+# define stat _stat
+# define chmod(path,mode) fileio_chmod(path,mode)
+# define mkdir(path,mode) fileio_mkdir(path)
#endif
#include <time.h>
#include <errno.h>
@@ -130,6 +125,40 @@ SQLITE_EXTENSION_INIT1
#define FSDIR_COLUMN_PATH 4 /* Path to top of search */
#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
+/*
+** UTF8 chmod() function for Windows
+*/
+#if defined(_WIN32) || defined(WIN32)
+static int fileio_chmod(const char *zPath, int pmode){
+ sqlite3_int64 sz = strlen(zPath);
+ wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
+ int rc;
+ if( b1==0 ) return -1;
+ sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
+ b1[sz] = 0;
+ rc = _wchmod(b1, pmode);
+ sqlite3_free(b1);
+ return rc;
+}
+#endif
+
+/*
+** UTF8 mkdir() function for Windows
+*/
+#if defined(_WIN32) || defined(WIN32)
+static int fileio_mkdir(const char *zPath){
+ sqlite3_int64 sz = strlen(zPath);
+ wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
+ int rc;
+ if( b1==0 ) return -1;
+ sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
+ b1[sz] = 0;
+ rc = _wmkdir(b1);
+ sqlite3_free(b1);
+ return rc;
+}
+#endif
+
/*
** Set the result stored by context ctx to a blob containing the
@@ -291,7 +320,13 @@ static int fileStat(
struct stat *pStatBuf
){
#if defined(_WIN32)
- int rc = stat(zPath, pStatBuf);
+ sqlite3_int64 sz = strlen(zPath);
+ wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
+ int rc;
+ if( b1==0 ) return 1;
+ sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
+ b1[sz] = 0;
+ rc = _wstat(b1, pStatBuf);
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
return rc;
#else
@@ -309,9 +344,7 @@ static int fileLinkStat(
struct stat *pStatBuf
){
#if defined(_WIN32)
- int rc = lstat(zPath, pStatBuf);
- if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
- return rc;
+ return fileStat(zPath, pStatBuf);
#else
return lstat(zPath, pStatBuf);
#endif
diff --git a/manifest b/manifest
index 59c72ca9d..91fd2a7ef 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Omit\sthe\sunused\sreaddir_r()\sroutine\sfrom\stest_windirent.c
-D 2025-05-13T15:09:13.894
+C First\scut\sat\senhancing\sthe\sfsdir\svirtual\stable\sso\sthat\sit\sworks\swith\nunicode\scharacters\son\sWindows.
+D 2025-05-13T16:58:36.884
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -418,7 +418,7 @@ F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f82
F ext/misc/decimal.c 228d47e9ef4de60daf5851da19e3ac9ac1eda9e94432816914469501db6a1129
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
-F ext/misc/fileio.c 07cf3109ec6452789e3a989a010234e2a17b599ce82ea29212c948572456abac
+F ext/misc/fileio.c 34993b810514c58ff99d7b4254d4a388d844a4774ea77bec68a1dafe8de5ce41
F ext/misc/fossildelta.c 0aeb099e9627eea693cf21ae47826ecd1e0319b93143bed23090838b2ef0c162
F ext/misc/fuzzer.c 6b231352815304ba60d8e9ec2ee73d4918e74d9b76bda8940ba2b64e8777515e
F ext/misc/ieee754.c c9dd9d77c8e8e18e0a5706f8ffcccf4ccb6562073709f7453d4d73f5122f4362
@@ -841,8 +841,8 @@ F src/test_tclvar.c ae873248a0188459b1c16ca7cc431265dacce524399e8b46725c2b3b7e04
F src/test_thread.c 3edb4a5b5aeb1a6e9a275dccc848ac95acab7f496b3e9230f6d2d04953a2b862
F src/test_vdbecov.c 5c426d9cd2b351f5f9ceb30cabf8c64a63bfcad644c507e0bd9ce2f6ae1a3bf3
F src/test_vfs.c b4135c1308516adf0dfd494e6d6c33114e03732be899eace0502919b674586b5
-F src/test_windirent.c 43082333bc8e73e7965c598db074f52721b7ee01248e6a122ca3e50078d838d1
-F src/test_windirent.h 16772b8b3f1ba2801ca5ce39257b385ab0fcd09a9a031ae0cc1209348eebddf8
+F src/test_windirent.c cbee2b9a118b56b5a26b99c895adcbc861587bc66d24b88d1ad6e4c1d09dad7b
+F src/test_windirent.h f8245d8002aa0d4322192d35b0f8bbfc757479e90d60fd0beb386d3913f72cdd
F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8ea72
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
@@ -2207,8 +2207,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P b96cfff52b4f364388f168198e999ae2407c4afbc7b020f8bb350ab103ffb55c
-R c6bd7bd531adacaf4d8be27fe59fb21e
+P f9a216e3ad1b3bc9be350aad5ef3dc8b3534d3ee67d160bfedda81a61295320c
+R 0172fac07ac39e635656e41c69267475
U drh
-Z ea9a2abb79b951b73cb14d7586f194ec
+Z a9ac0628984f4dd39e26358da2707d12
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index be332dea1..94d9dbf69 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-f9a216e3ad1b3bc9be350aad5ef3dc8b3534d3ee67d160bfedda81a61295320c
+c9e04dadfdf6c860631ce5603693add565ff2033aa25af5736302af7045fc91e
diff --git a/src/test_windirent.c b/src/test_windirent.c
index 1458e2b1c..de4192d7c 100644
--- a/src/test_windirent.c
+++ b/src/test_windirent.c
@@ -48,11 +48,13 @@ const char *windirent_getenv(
** Implementation of the POSIX opendir() function using the MSVCRT.
*/
LPDIR opendir(
- const char *dirname
+ const char *dirname /* Directory name, UTF8 encoding */
){
- struct _finddata_t data;
+ struct _wfinddata_t data;
LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
+ wchar_t *b1;
+ sqlite3_int64 sz;
if( dirp==NULL ) return NULL;
memset(dirp, 0, sizeof(DIR));
@@ -62,9 +64,25 @@ LPDIR opendir(
dirname = windirent_getenv("SystemDrive");
}
- memset(&data, 0, sizeof(struct _finddata_t));
- _snprintf(data.name, namesize, "%s\\*", dirname);
- dirp->d_handle = _findfirst(data.name, &data);
+ memset(&data, 0, sizeof(data));
+ sz = strlen(dirname);
+ b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) );
+ if( b1==0 ){
+ closedir(dirp);
+ return NULL;
+ }
+ sz = MultiByteToWideChar(CP_UTF8, 0, dirname, sz, b1, sz);
+ b1[sz++] = '\\';
+ b1[sz++] = '*';
+ b1[sz] = 0;
+ if( sz+1>(sqlite3_int64)namesize ){
+ closedir(dirp);
+ sqlite3_free(b1);
+ return NULL;
+ }
+ memcpy(data.name, b1, (sz+1)*sizeof(b1[0]));
+ sqlite3_free(b1);
+ dirp->d_handle = _wfindfirst(data.name, &data);
if( dirp->d_handle==BAD_INTPTR_T ){
closedir(dirp);
@@ -75,8 +93,8 @@ LPDIR opendir(
if( is_filtered(data) ){
next:
- memset(&data, 0, sizeof(struct _finddata_t));
- if( _findnext(dirp->d_handle, &data)==-1 ){
+ memset(&data, 0, sizeof(data));
+ if( _wfindnext(dirp->d_handle, &data)==-1 ){
closedir(dirp);
return NULL;
}
@@ -86,9 +104,8 @@ next:
}
dirp->d_first.d_attributes = data.attrib;
- strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
- dirp->d_first.d_name[NAME_MAX] = '\0';
-
+ WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
+ dirp->d_first.d_name, DIRENT_NAME_MAX, 0, 0);
return dirp;
}
@@ -98,7 +115,7 @@ next:
LPDIRENT readdir(
LPDIR dirp
){
- struct _finddata_t data;
+ struct _wfinddata_t data;
if( dirp==NULL ) return NULL;
@@ -111,17 +128,16 @@ LPDIRENT readdir(
next:
- memset(&data, 0, sizeof(struct _finddata_t));
- if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
+ memset(&data, 0, sizeof(data));
+ if( _wfindnext(dirp->d_handle, &data)==-1 ) return NULL;
/* TODO: Remove this block to allow hidden and/or system files. */
if( is_filtered(data) ) goto next;
dirp->d_next.d_ino++;
dirp->d_next.d_attributes = data.attrib;
- strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
- dirp->d_next.d_name[NAME_MAX] = '\0';
-
+ WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
+ dirp->d_next.d_name, DIRENT_NAME_MAX, 0, 0);
return &dirp->d_next;
}
diff --git a/src/test_windirent.h b/src/test_windirent.h
index 24a888eed..527dfaa8f 100644
--- a/src/test_windirent.h
+++ b/src/test_windirent.h
@@ -88,6 +88,7 @@
# else
# define NAME_MAX (260)
# endif
+# define DIRENT_NAME_MAX (NAME_MAX)
#endif
/*