diff options
author | drh <> | 2025-05-13 16:58:36 +0000 |
---|---|---|
committer | drh <> | 2025-05-13 16:58:36 +0000 |
commit | 494830ca8ecdd771f73d4751aa959ed81746c345 (patch) | |
tree | be143959319dcc8f35c397e8d3a14a434755f0f0 | |
parent | 0df6c5b9a70c6c1b87430c7f69f6849c145803b9 (diff) | |
download | sqlite-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.c | 57 | ||||
-rw-r--r-- | manifest | 16 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/test_windirent.c | 48 | ||||
-rw-r--r-- | src/test_windirent.h | 1 |
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 @@ -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 /* |