| | @@ -16,11 +16,11 @@ |
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | 19 | ** |
| 20 | 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | | -** 18bda13e197e4b4ec7464b3e70012f71edc0 with changes in files: |
| 21 | +** 121f4d97f9a855131859d342bc2ade5f8c34 with changes in files: |
| 22 | 22 | ** |
| 23 | 23 | ** |
| 24 | 24 | */ |
| 25 | 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | 26 | #define SQLITE_CORE 1 |
| | @@ -465,11 +465,11 @@ |
| 465 | 465 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 466 | 466 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 467 | 467 | */ |
| 468 | 468 | #define SQLITE_VERSION "3.50.0" |
| 469 | 469 | #define SQLITE_VERSION_NUMBER 3050000 |
| 470 | | -#define SQLITE_SOURCE_ID "2025-03-16 00:13:29 18bda13e197e4b4ec7464b3e70012f71edc05f73d8b14bb48bad452f81c7e185" |
| 470 | +#define SQLITE_SOURCE_ID "2025-03-27 23:29:25 121f4d97f9a855131859d342bc2ade5f8c34ba7732029ae156d02cec7cb6dd85" |
| 471 | 471 | |
| 472 | 472 | /* |
| 473 | 473 | ** CAPI3REF: Run-Time Library Version Numbers |
| 474 | 474 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 475 | 475 | ** |
| | @@ -30270,10 +30270,12 @@ |
| 30270 | 30270 | */ |
| 30271 | 30271 | #include "windows.h" |
| 30272 | 30272 | |
| 30273 | 30273 | #ifdef __CYGWIN__ |
| 30274 | 30274 | # include <sys/cygwin.h> |
| 30275 | +# include <sys/stat.h> /* amalgamator: dontcache */ |
| 30276 | +# include <unistd.h> /* amalgamator: dontcache */ |
| 30275 | 30277 | # include <errno.h> /* amalgamator: dontcache */ |
| 30276 | 30278 | #endif |
| 30277 | 30279 | |
| 30278 | 30280 | /* |
| 30279 | 30281 | ** Determine if we are dealing with Windows NT. |
| | @@ -47726,20 +47728,20 @@ |
| 47726 | 47728 | { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 }, |
| 47727 | 47729 | #else |
| 47728 | 47730 | { "FileTimeToLocalFileTime", (SYSCALL)0, 0 }, |
| 47729 | 47731 | #endif |
| 47730 | 47732 | |
| 47731 | | -#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \ |
| 47733 | +#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(const FILETIME*, \ |
| 47732 | 47734 | LPFILETIME))aSyscall[11].pCurrent) |
| 47733 | 47735 | |
| 47734 | 47736 | #if SQLITE_OS_WINCE |
| 47735 | 47737 | { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 }, |
| 47736 | 47738 | #else |
| 47737 | 47739 | { "FileTimeToSystemTime", (SYSCALL)0, 0 }, |
| 47738 | 47740 | #endif |
| 47739 | 47741 | |
| 47740 | | -#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \ |
| 47742 | +#define osFileTimeToSystemTime ((BOOL(WINAPI*)(const FILETIME*, \ |
| 47741 | 47743 | LPSYSTEMTIME))aSyscall[12].pCurrent) |
| 47742 | 47744 | |
| 47743 | 47745 | { "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 }, |
| 47744 | 47746 | |
| 47745 | 47747 | #define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent) |
| | @@ -48015,11 +48017,11 @@ |
| 48015 | 48017 | { "LockFile", (SYSCALL)LockFile, 0 }, |
| 48016 | 48018 | #else |
| 48017 | 48019 | { "LockFile", (SYSCALL)0, 0 }, |
| 48018 | 48020 | #endif |
| 48019 | 48021 | |
| 48020 | | -#ifndef osLockFile |
| 48022 | +#if !defined(osLockFile) && defined(SQLITE_WIN32_HAS_ANSI) |
| 48021 | 48023 | #define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ |
| 48022 | 48024 | DWORD))aSyscall[47].pCurrent) |
| 48023 | 48025 | #endif |
| 48024 | 48026 | |
| 48025 | 48027 | #if !SQLITE_OS_WINCE |
| | @@ -48079,20 +48081,20 @@ |
| 48079 | 48081 | |
| 48080 | 48082 | #define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent) |
| 48081 | 48083 | |
| 48082 | 48084 | { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 }, |
| 48083 | 48085 | |
| 48084 | | -#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \ |
| 48086 | +#define osSystemTimeToFileTime ((BOOL(WINAPI*)(const SYSTEMTIME*, \ |
| 48085 | 48087 | LPFILETIME))aSyscall[56].pCurrent) |
| 48086 | 48088 | |
| 48087 | 48089 | #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT |
| 48088 | 48090 | { "UnlockFile", (SYSCALL)UnlockFile, 0 }, |
| 48089 | 48091 | #else |
| 48090 | 48092 | { "UnlockFile", (SYSCALL)0, 0 }, |
| 48091 | 48093 | #endif |
| 48092 | 48094 | |
| 48093 | | -#ifndef osUnlockFile |
| 48095 | +#if !defined(osUnlockFile) && defined(SQLITE_WIN32_HAS_ANSI) |
| 48094 | 48096 | #define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ |
| 48095 | 48097 | DWORD))aSyscall[57].pCurrent) |
| 48096 | 48098 | #endif |
| 48097 | 48099 | |
| 48098 | 48100 | #if !SQLITE_OS_WINCE |
| | @@ -48316,10 +48318,67 @@ |
| 48316 | 48318 | { "CancelIo", (SYSCALL)0, 0 }, |
| 48317 | 48319 | #endif |
| 48318 | 48320 | |
| 48319 | 48321 | #define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent) |
| 48320 | 48322 | |
| 48323 | +#if defined(SQLITE_WIN32_HAS_WIDE) && defined(_WIN32) |
| 48324 | + { "GetModuleHandleW", (SYSCALL)GetModuleHandleW, 0 }, |
| 48325 | +#else |
| 48326 | + { "GetModuleHandleW", (SYSCALL)0, 0 }, |
| 48327 | +#endif |
| 48328 | + |
| 48329 | +#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[82].pCurrent) |
| 48330 | + |
| 48331 | +#ifndef _WIN32 |
| 48332 | + { "getenv", (SYSCALL)getenv, 0 }, |
| 48333 | +#else |
| 48334 | + { "getenv", (SYSCALL)0, 0 }, |
| 48335 | +#endif |
| 48336 | + |
| 48337 | +#define osGetenv ((const char *(*)(const char *))aSyscall[83].pCurrent) |
| 48338 | + |
| 48339 | +#ifndef _WIN32 |
| 48340 | + { "getcwd", (SYSCALL)getcwd, 0 }, |
| 48341 | +#else |
| 48342 | + { "getcwd", (SYSCALL)0, 0 }, |
| 48343 | +#endif |
| 48344 | + |
| 48345 | +#define osGetcwd ((char*(*)(char*,size_t))aSyscall[84].pCurrent) |
| 48346 | + |
| 48347 | +#ifndef _WIN32 |
| 48348 | + { "readlink", (SYSCALL)readlink, 0 }, |
| 48349 | +#else |
| 48350 | + { "readlink", (SYSCALL)0, 0 }, |
| 48351 | +#endif |
| 48352 | + |
| 48353 | +#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[85].pCurrent) |
| 48354 | + |
| 48355 | +#ifndef _WIN32 |
| 48356 | + { "lstat", (SYSCALL)lstat, 0 }, |
| 48357 | +#else |
| 48358 | + { "lstat", (SYSCALL)0, 0 }, |
| 48359 | +#endif |
| 48360 | + |
| 48361 | +#define osLstat ((int(*)(const char*,struct stat*))aSyscall[86].pCurrent) |
| 48362 | + |
| 48363 | +#ifndef _WIN32 |
| 48364 | + { "__errno", (SYSCALL)__errno, 0 }, |
| 48365 | +#else |
| 48366 | + { "__errno", (SYSCALL)0, 0 }, |
| 48367 | +#endif |
| 48368 | + |
| 48369 | +#define osErrno (*((int*(*)(void))aSyscall[87].pCurrent)()) |
| 48370 | + |
| 48371 | +#ifndef _WIN32 |
| 48372 | + { "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 }, |
| 48373 | +#else |
| 48374 | + { "cygwin_conv_path", (SYSCALL)0, 0 }, |
| 48375 | +#endif |
| 48376 | + |
| 48377 | +#define osCygwin_conv_path ((size_t(*)(unsigned int, \ |
| 48378 | + const void *, void *, size_t))aSyscall[88].pCurrent) |
| 48379 | + |
| 48321 | 48380 | }; /* End of the overrideable system calls */ |
| 48322 | 48381 | |
| 48323 | 48382 | /* |
| 48324 | 48383 | ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| 48325 | 48384 | ** "win32" VFSes. Return SQLITE_OK upon successfully updating the |
| | @@ -48489,10 +48548,11 @@ |
| 48489 | 48548 | sqlite3_mutex_leave(pMainMtx); |
| 48490 | 48549 | return rc; |
| 48491 | 48550 | } |
| 48492 | 48551 | #endif /* SQLITE_WIN32_MALLOC */ |
| 48493 | 48552 | |
| 48553 | +#ifdef _WIN32 |
| 48494 | 48554 | /* |
| 48495 | 48555 | ** This function outputs the specified (ANSI) string to the Win32 debugger |
| 48496 | 48556 | ** (if available). |
| 48497 | 48557 | */ |
| 48498 | 48558 | |
| | @@ -48531,10 +48591,11 @@ |
| 48531 | 48591 | }else{ |
| 48532 | 48592 | fprintf(stderr, "%s", zBuf); |
| 48533 | 48593 | } |
| 48534 | 48594 | #endif |
| 48535 | 48595 | } |
| 48596 | +#endif /* _WIN32 */ |
| 48536 | 48597 | |
| 48537 | 48598 | /* |
| 48538 | 48599 | ** The following routine suspends the current thread for at least ms |
| 48539 | 48600 | ** milliseconds. This is equivalent to the Win32 Sleep() interface. |
| 48540 | 48601 | */ |
| | @@ -48831,10 +48892,11 @@ |
| 48831 | 48892 | SQLITE_PRIVATE void sqlite3MemSetDefault(void){ |
| 48832 | 48893 | sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32()); |
| 48833 | 48894 | } |
| 48834 | 48895 | #endif /* SQLITE_WIN32_MALLOC */ |
| 48835 | 48896 | |
| 48897 | +#ifdef _WIN32 |
| 48836 | 48898 | /* |
| 48837 | 48899 | ** Convert a UTF-8 string to Microsoft Unicode. |
| 48838 | 48900 | ** |
| 48839 | 48901 | ** Space to hold the returned string is obtained from sqlite3_malloc(). |
| 48840 | 48902 | */ |
| | @@ -48856,10 +48918,11 @@ |
| 48856 | 48918 | sqlite3_free(zWideText); |
| 48857 | 48919 | zWideText = 0; |
| 48858 | 48920 | } |
| 48859 | 48921 | return zWideText; |
| 48860 | 48922 | } |
| 48923 | +#endif /* _WIN32 */ |
| 48861 | 48924 | |
| 48862 | 48925 | /* |
| 48863 | 48926 | ** Convert a Microsoft Unicode string to UTF-8. |
| 48864 | 48927 | ** |
| 48865 | 48928 | ** Space to hold the returned string is obtained from sqlite3_malloc(). |
| | @@ -48890,32 +48953,33 @@ |
| 48890 | 48953 | ** code page. |
| 48891 | 48954 | ** |
| 48892 | 48955 | ** Space to hold the returned string is obtained from sqlite3_malloc(). |
| 48893 | 48956 | */ |
| 48894 | 48957 | static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){ |
| 48895 | | - int nByte; |
| 48958 | + int nWideChar; |
| 48896 | 48959 | LPWSTR zMbcsText; |
| 48897 | 48960 | int codepage = useAnsi ? CP_ACP : CP_OEMCP; |
| 48898 | 48961 | |
| 48899 | | - nByte = osMultiByteToWideChar(codepage, 0, zText, -1, NULL, |
| 48900 | | - 0)*sizeof(WCHAR); |
| 48901 | | - if( nByte==0 ){ |
| 48962 | + nWideChar = osMultiByteToWideChar(codepage, 0, zText, -1, NULL, |
| 48963 | + 0); |
| 48964 | + if( nWideChar==0 ){ |
| 48902 | 48965 | return 0; |
| 48903 | 48966 | } |
| 48904 | | - zMbcsText = sqlite3MallocZero( nByte*sizeof(WCHAR) ); |
| 48967 | + zMbcsText = sqlite3MallocZero( nWideChar*sizeof(WCHAR) ); |
| 48905 | 48968 | if( zMbcsText==0 ){ |
| 48906 | 48969 | return 0; |
| 48907 | 48970 | } |
| 48908 | | - nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText, |
| 48909 | | - nByte); |
| 48910 | | - if( nByte==0 ){ |
| 48971 | + nWideChar = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText, |
| 48972 | + nWideChar); |
| 48973 | + if( nWideChar==0 ){ |
| 48911 | 48974 | sqlite3_free(zMbcsText); |
| 48912 | 48975 | zMbcsText = 0; |
| 48913 | 48976 | } |
| 48914 | 48977 | return zMbcsText; |
| 48915 | 48978 | } |
| 48916 | 48979 | |
| 48980 | +#ifdef _WIN32 |
| 48917 | 48981 | /* |
| 48918 | 48982 | ** Convert a Microsoft Unicode string to a multi-byte character string, |
| 48919 | 48983 | ** using the ANSI or OEM code page. |
| 48920 | 48984 | ** |
| 48921 | 48985 | ** Space to hold the returned string is obtained from sqlite3_malloc(). |
| | @@ -48939,10 +49003,11 @@ |
| 48939 | 49003 | sqlite3_free(zText); |
| 48940 | 49004 | zText = 0; |
| 48941 | 49005 | } |
| 48942 | 49006 | return zText; |
| 48943 | 49007 | } |
| 49008 | +#endif /* _WIN32 */ |
| 48944 | 49009 | |
| 48945 | 49010 | /* |
| 48946 | 49011 | ** Convert a multi-byte character string to UTF-8. |
| 48947 | 49012 | ** |
| 48948 | 49013 | ** Space to hold the returned string is obtained from sqlite3_malloc(). |
| | @@ -48958,10 +49023,11 @@ |
| 48958 | 49023 | zTextUtf8 = winUnicodeToUtf8(zTmpWide); |
| 48959 | 49024 | sqlite3_free(zTmpWide); |
| 48960 | 49025 | return zTextUtf8; |
| 48961 | 49026 | } |
| 48962 | 49027 | |
| 49028 | +#ifdef _WIN32 |
| 48963 | 49029 | /* |
| 48964 | 49030 | ** Convert a UTF-8 string to a multi-byte character string. |
| 48965 | 49031 | ** |
| 48966 | 49032 | ** Space to hold the returned string is obtained from sqlite3_malloc(). |
| 48967 | 49033 | */ |
| | @@ -49007,10 +49073,11 @@ |
| 49007 | 49073 | #ifndef SQLITE_OMIT_AUTOINIT |
| 49008 | 49074 | if( sqlite3_initialize() ) return 0; |
| 49009 | 49075 | #endif |
| 49010 | 49076 | return winUnicodeToUtf8(zWideText); |
| 49011 | 49077 | } |
| 49078 | +#endif /* _WIN32 */ |
| 49012 | 49079 | |
| 49013 | 49080 | /* |
| 49014 | 49081 | ** This is a public wrapper for the winMbcsToUtf8() function. |
| 49015 | 49082 | */ |
| 49016 | 49083 | SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zText){ |
| | @@ -49024,10 +49091,11 @@ |
| 49024 | 49091 | if( sqlite3_initialize() ) return 0; |
| 49025 | 49092 | #endif |
| 49026 | 49093 | return winMbcsToUtf8(zText, osAreFileApisANSI()); |
| 49027 | 49094 | } |
| 49028 | 49095 | |
| 49096 | +#ifdef _WIN32 |
| 49029 | 49097 | /* |
| 49030 | 49098 | ** This is a public wrapper for the winMbcsToUtf8() function. |
| 49031 | 49099 | */ |
| 49032 | 49100 | SQLITE_API char *sqlite3_win32_mbcs_to_utf8_v2(const char *zText, int useAnsi){ |
| 49033 | 49101 | #ifdef SQLITE_ENABLE_API_ARMOR |
| | @@ -49148,10 +49216,11 @@ |
| 49148 | 49216 | unsigned long type, /* Identifier for directory being set or reset */ |
| 49149 | 49217 | void *zValue /* New value for directory being set or reset */ |
| 49150 | 49218 | ){ |
| 49151 | 49219 | return sqlite3_win32_set_directory16(type, zValue); |
| 49152 | 49220 | } |
| 49221 | +#endif /* _WIN32 */ |
| 49153 | 49222 | |
| 49154 | 49223 | /* |
| 49155 | 49224 | ** The return value of winGetLastErrorMsg |
| 49156 | 49225 | ** is zero if the error message fits in the buffer, or non-zero |
| 49157 | 49226 | ** otherwise (if the message was truncated). |
| | @@ -49696,13 +49765,15 @@ |
| 49696 | 49765 | OVERLAPPED ovlp; |
| 49697 | 49766 | memset(&ovlp, 0, sizeof(OVERLAPPED)); |
| 49698 | 49767 | ovlp.Offset = offsetLow; |
| 49699 | 49768 | ovlp.OffsetHigh = offsetHigh; |
| 49700 | 49769 | return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp); |
| 49770 | +#ifdef SQLITE_WIN32_HAS_ANSI |
| 49701 | 49771 | }else{ |
| 49702 | 49772 | return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow, |
| 49703 | 49773 | numBytesHigh); |
| 49774 | +#endif |
| 49704 | 49775 | } |
| 49705 | 49776 | #endif |
| 49706 | 49777 | } |
| 49707 | 49778 | |
| 49708 | 49779 | /* |
| | @@ -49806,13 +49877,15 @@ |
| 49806 | 49877 | OVERLAPPED ovlp; |
| 49807 | 49878 | memset(&ovlp, 0, sizeof(OVERLAPPED)); |
| 49808 | 49879 | ovlp.Offset = offsetLow; |
| 49809 | 49880 | ovlp.OffsetHigh = offsetHigh; |
| 49810 | 49881 | return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp); |
| 49882 | +#ifdef SQLITE_WIN32_HAS_ANSI |
| 49811 | 49883 | }else{ |
| 49812 | 49884 | return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow, |
| 49813 | 49885 | numBytesHigh); |
| 49886 | +#endif |
| 49814 | 49887 | } |
| 49815 | 49888 | #endif |
| 49816 | 49889 | } |
| 49817 | 49890 | |
| 49818 | 49891 | /* |
| | @@ -51222,18 +51295,95 @@ |
| 51222 | 51295 | |
| 51223 | 51296 | /* |
| 51224 | 51297 | ** Convert a UTF-8 filename into whatever form the underlying |
| 51225 | 51298 | ** operating system wants filenames in. Space to hold the result |
| 51226 | 51299 | ** is obtained from malloc and must be freed by the calling |
| 51227 | | -** function. |
| 51300 | +** function |
| 51301 | +** |
| 51302 | +** On Cygwin, 3 possible input forms are accepted: |
| 51303 | +** - If the filename starts with "<drive>:/" or "<drive>:\", |
| 51304 | +** it is converted to UTF-16 as-is. |
| 51305 | +** - If the filename contains '/', it is assumed to be a |
| 51306 | +** Cygwin absolute path, it is converted to a win32 |
| 51307 | +** absolute path in UTF-16. |
| 51308 | +** - Otherwise it must be a filename only, the win32 filename |
| 51309 | +** is returned in UTF-16. |
| 51310 | +** Note: If the function cygwin_conv_path() fails, only |
| 51311 | +** UTF-8 -> UTF-16 conversion will be done. This can only |
| 51312 | +** happen when the file path >32k, in which case winUtf8ToUnicode() |
| 51313 | +** will fail too. |
| 51228 | 51314 | */ |
| 51229 | 51315 | static void *winConvertFromUtf8Filename(const char *zFilename){ |
| 51230 | 51316 | void *zConverted = 0; |
| 51231 | 51317 | if( osIsNT() ){ |
| 51318 | +#ifdef __CYGWIN__ |
| 51319 | + int nChar; |
| 51320 | + LPWSTR zWideFilename; |
| 51321 | + |
| 51322 | + if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename) |
| 51323 | + && winIsDirSep(zFilename[2])) ){ |
| 51324 | + int nByte; |
| 51325 | + int convertflag = CCP_POSIX_TO_WIN_W; |
| 51326 | + if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE; |
| 51327 | + nByte = (int)osCygwin_conv_path(convertflag, |
| 51328 | + zFilename, 0, 0); |
| 51329 | + if( nByte>0 ){ |
| 51330 | + zConverted = sqlite3MallocZero(nByte+12); |
| 51331 | + if ( zConverted==0 ){ |
| 51332 | + return zConverted; |
| 51333 | + } |
| 51334 | + zWideFilename = zConverted; |
| 51335 | + /* Filenames should be prefixed, except when converted |
| 51336 | + * full path already starts with "\\?\". */ |
| 51337 | + if( osCygwin_conv_path(convertflag, zFilename, |
| 51338 | + zWideFilename+4, nByte)==0 ){ |
| 51339 | + if( (convertflag&CCP_RELATIVE) ){ |
| 51340 | + memmove(zWideFilename, zWideFilename+4, nByte); |
| 51341 | + }else if( memcmp(zWideFilename+4, L"\\\\", 4) ){ |
| 51342 | + memcpy(zWideFilename, L"\\\\?\\", 8); |
| 51343 | + }else if( zWideFilename[6]!='?' ){ |
| 51344 | + memmove(zWideFilename+6, zWideFilename+4, nByte); |
| 51345 | + memcpy(zWideFilename, L"\\\\?\\UNC", 14); |
| 51346 | + }else{ |
| 51347 | + memmove(zWideFilename, zWideFilename+4, nByte); |
| 51348 | + } |
| 51349 | + return zConverted; |
| 51350 | + } |
| 51351 | + sqlite3_free(zConverted); |
| 51352 | + } |
| 51353 | + } |
| 51354 | + nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); |
| 51355 | + if( nChar==0 ){ |
| 51356 | + return 0; |
| 51357 | + } |
| 51358 | + zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+12 ); |
| 51359 | + if( zWideFilename==0 ){ |
| 51360 | + return 0; |
| 51361 | + } |
| 51362 | + nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, |
| 51363 | + zWideFilename, nChar); |
| 51364 | + if( nChar==0 ){ |
| 51365 | + sqlite3_free(zWideFilename); |
| 51366 | + zWideFilename = 0; |
| 51367 | + }else if( nChar>MAX_PATH |
| 51368 | + && winIsDriveLetterAndColon(zFilename) |
| 51369 | + && winIsDirSep(zFilename[2]) ){ |
| 51370 | + memmove(zWideFilename+4, zWideFilename, nChar*sizeof(WCHAR)); |
| 51371 | + zWideFilename[2] = '\\'; |
| 51372 | + memcpy(zWideFilename, L"\\\\?\\", 8); |
| 51373 | + }else if( nChar>MAX_PATH |
| 51374 | + && winIsDirSep(zFilename[0]) && winIsDirSep(zFilename[1]) |
| 51375 | + && zFilename[2] != '?' ){ |
| 51376 | + memmove(zWideFilename+6, zWideFilename, nChar*sizeof(WCHAR)); |
| 51377 | + memcpy(zWideFilename, L"\\\\?\\UNC", 14); |
| 51378 | + } |
| 51379 | + zConverted = zWideFilename; |
| 51380 | +#else |
| 51232 | 51381 | zConverted = winUtf8ToUnicode(zFilename); |
| 51382 | +#endif /* __CYGWIN__ */ |
| 51233 | 51383 | } |
| 51234 | | -#ifdef SQLITE_WIN32_HAS_ANSI |
| 51384 | +#if defined(SQLITE_WIN32_HAS_ANSI) && defined(_WIN32) |
| 51235 | 51385 | else{ |
| 51236 | 51386 | zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); |
| 51237 | 51387 | } |
| 51238 | 51388 | #endif |
| 51239 | 51389 | /* caller will handle out of memory */ |
| | @@ -52058,11 +52208,11 @@ |
| 52058 | 52208 | ** |
| 52059 | 52209 | ** This division contains the implementation of methods on the |
| 52060 | 52210 | ** sqlite3_vfs object. |
| 52061 | 52211 | */ |
| 52062 | 52212 | |
| 52063 | | -#if defined(__CYGWIN__) |
| 52213 | +#if 0 /* No longer necessary */ |
| 52064 | 52214 | /* |
| 52065 | 52215 | ** Convert a filename from whatever the underlying operating system |
| 52066 | 52216 | ** supports for filenames into UTF-8. Space to hold the result is |
| 52067 | 52217 | ** obtained from malloc and must be freed by the calling function. |
| 52068 | 52218 | */ |
| | @@ -52091,11 +52241,18 @@ |
| 52091 | 52241 | int nLen = sqlite3Strlen30(zBuf); |
| 52092 | 52242 | if( nLen>0 ){ |
| 52093 | 52243 | if( winIsDirSep(zBuf[nLen-1]) ){ |
| 52094 | 52244 | return 1; |
| 52095 | 52245 | }else if( nLen+1<nBuf ){ |
| 52096 | | - zBuf[nLen] = winGetDirSep(); |
| 52246 | + if( !osGetenv ){ |
| 52247 | + zBuf[nLen] = winGetDirSep(); |
| 52248 | + }else if( winIsDriveLetterAndColon(zBuf) && winIsDirSep(zBuf[2]) ){ |
| 52249 | + zBuf[nLen] = '\\'; |
| 52250 | + zBuf[2]='\\'; |
| 52251 | + }else{ |
| 52252 | + zBuf[nLen] = '/'; |
| 52253 | + } |
| 52097 | 52254 | zBuf[nLen+1] = '\0'; |
| 52098 | 52255 | return 1; |
| 52099 | 52256 | } |
| 52100 | 52257 | } |
| 52101 | 52258 | } |
| | @@ -52118,11 +52275,11 @@ |
| 52118 | 52275 | /* |
| 52119 | 52276 | ** Create a temporary file name and store the resulting pointer into pzBuf. |
| 52120 | 52277 | ** The pointer returned in pzBuf must be freed via sqlite3_free(). |
| 52121 | 52278 | */ |
| 52122 | 52279 | static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ |
| 52123 | | - static char zChars[] = |
| 52280 | + static const char zChars[] = |
| 52124 | 52281 | "abcdefghijklmnopqrstuvwxyz" |
| 52125 | 52282 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| 52126 | 52283 | "0123456789"; |
| 52127 | 52284 | size_t i, j; |
| 52128 | 52285 | DWORD pid; |
| | @@ -52169,11 +52326,11 @@ |
| 52169 | 52326 | } |
| 52170 | 52327 | sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); |
| 52171 | 52328 | } |
| 52172 | 52329 | |
| 52173 | 52330 | #if defined(__CYGWIN__) |
| 52174 | | - else{ |
| 52331 | + else if( osGetenv!=NULL ){ |
| 52175 | 52332 | static const char *azDirs[] = { |
| 52176 | 52333 | 0, /* getenv("SQLITE_TMPDIR") */ |
| 52177 | 52334 | 0, /* getenv("TMPDIR") */ |
| 52178 | 52335 | 0, /* getenv("TMP") */ |
| 52179 | 52336 | 0, /* getenv("TEMP") */ |
| | @@ -52185,24 +52342,24 @@ |
| 52185 | 52342 | 0 /* List terminator */ |
| 52186 | 52343 | }; |
| 52187 | 52344 | unsigned int i; |
| 52188 | 52345 | const char *zDir = 0; |
| 52189 | 52346 | |
| 52190 | | - if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR"); |
| 52191 | | - if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR"); |
| 52192 | | - if( !azDirs[2] ) azDirs[2] = getenv("TMP"); |
| 52193 | | - if( !azDirs[3] ) azDirs[3] = getenv("TEMP"); |
| 52194 | | - if( !azDirs[4] ) azDirs[4] = getenv("USERPROFILE"); |
| 52347 | + if( !azDirs[0] ) azDirs[0] = osGetenv("SQLITE_TMPDIR"); |
| 52348 | + if( !azDirs[1] ) azDirs[1] = osGetenv("TMPDIR"); |
| 52349 | + if( !azDirs[2] ) azDirs[2] = osGetenv("TMP"); |
| 52350 | + if( !azDirs[3] ) azDirs[3] = osGetenv("TEMP"); |
| 52351 | + if( !azDirs[4] ) azDirs[4] = osGetenv("USERPROFILE"); |
| 52195 | 52352 | for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){ |
| 52196 | 52353 | void *zConverted; |
| 52197 | 52354 | if( zDir==0 ) continue; |
| 52198 | 52355 | /* If the path starts with a drive letter followed by the colon |
| 52199 | 52356 | ** character, assume it is already a native Win32 path; otherwise, |
| 52200 | 52357 | ** it must be converted to a native Win32 path via the Cygwin API |
| 52201 | 52358 | ** prior to using it. |
| 52202 | 52359 | */ |
| 52203 | | - if( winIsDriveLetterAndColon(zDir) ){ |
| 52360 | + { |
| 52204 | 52361 | zConverted = winConvertFromUtf8Filename(zDir); |
| 52205 | 52362 | if( !zConverted ){ |
| 52206 | 52363 | sqlite3_free(zBuf); |
| 52207 | 52364 | OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); |
| 52208 | 52365 | return SQLITE_IOERR_NOMEM_BKPT; |
| | @@ -52211,19 +52368,20 @@ |
| 52211 | 52368 | sqlite3_snprintf(nMax, zBuf, "%s", zDir); |
| 52212 | 52369 | sqlite3_free(zConverted); |
| 52213 | 52370 | break; |
| 52214 | 52371 | } |
| 52215 | 52372 | sqlite3_free(zConverted); |
| 52373 | +#if 0 /* No longer necessary */ |
| 52216 | 52374 | }else{ |
| 52217 | 52375 | zConverted = sqlite3MallocZero( nMax+1 ); |
| 52218 | 52376 | if( !zConverted ){ |
| 52219 | 52377 | sqlite3_free(zBuf); |
| 52220 | 52378 | OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); |
| 52221 | 52379 | return SQLITE_IOERR_NOMEM_BKPT; |
| 52222 | 52380 | } |
| 52223 | | - if( cygwin_conv_path( |
| 52224 | | - osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir, |
| 52381 | + if( osCygwin_conv_path( |
| 52382 | + CCP_POSIX_TO_WIN_W, zDir, |
| 52225 | 52383 | zConverted, nMax+1)<0 ){ |
| 52226 | 52384 | sqlite3_free(zConverted); |
| 52227 | 52385 | sqlite3_free(zBuf); |
| 52228 | 52386 | OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n")); |
| 52229 | 52387 | return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno, |
| | @@ -52245,14 +52403,17 @@ |
| 52245 | 52403 | sqlite3_free(zUtf8); |
| 52246 | 52404 | sqlite3_free(zConverted); |
| 52247 | 52405 | break; |
| 52248 | 52406 | } |
| 52249 | 52407 | sqlite3_free(zConverted); |
| 52408 | +#endif /* No longer necessary */ |
| 52250 | 52409 | } |
| 52251 | 52410 | } |
| 52252 | 52411 | } |
| 52253 | | -#elif !SQLITE_OS_WINRT && !defined(__CYGWIN__) |
| 52412 | +#endif |
| 52413 | + |
| 52414 | +#if !SQLITE_OS_WINRT && defined(_WIN32) |
| 52254 | 52415 | else if( osIsNT() ){ |
| 52255 | 52416 | char *zMulti; |
| 52256 | 52417 | LPWSTR zWidePath = sqlite3MallocZero( nMax*sizeof(WCHAR) ); |
| 52257 | 52418 | if( !zWidePath ){ |
| 52258 | 52419 | sqlite3_free(zBuf); |
| | @@ -52372,11 +52533,11 @@ |
| 52372 | 52533 | &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){} |
| 52373 | 52534 | if( !rc ){ |
| 52374 | 52535 | return 0; /* Invalid name? */ |
| 52375 | 52536 | } |
| 52376 | 52537 | attr = sAttrData.dwFileAttributes; |
| 52377 | | -#if SQLITE_OS_WINCE==0 |
| 52538 | +#if SQLITE_OS_WINCE==0 && defined(SQLITE_WIN32_HAS_ANSI) |
| 52378 | 52539 | }else{ |
| 52379 | 52540 | attr = osGetFileAttributesA((char*)zConverted); |
| 52380 | 52541 | #endif |
| 52381 | 52542 | } |
| 52382 | 52543 | return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY); |
| | @@ -52388,10 +52549,16 @@ |
| 52388 | 52549 | const char *zFilename, /* Name of file to check */ |
| 52389 | 52550 | int flags, /* Type of test to make on this file */ |
| 52390 | 52551 | int *pResOut /* OUT: Result */ |
| 52391 | 52552 | ); |
| 52392 | 52553 | |
| 52554 | +/* |
| 52555 | +** The Windows version of xAccess() accepts an extra bit in the flags |
| 52556 | +** parameter that prevents an anti-virus retry loop. |
| 52557 | +*/ |
| 52558 | +#define NORETRY 0x4000 |
| 52559 | + |
| 52393 | 52560 | /* |
| 52394 | 52561 | ** Open a file. |
| 52395 | 52562 | */ |
| 52396 | 52563 | static int winOpen( |
| 52397 | 52564 | sqlite3_vfs *pVfs, /* Used to get maximum path length and AppData */ |
| | @@ -52412,10 +52579,11 @@ |
| 52412 | 52579 | winVfsAppData *pAppData; |
| 52413 | 52580 | winFile *pFile = (winFile*)id; |
| 52414 | 52581 | void *zConverted; /* Filename in OS encoding */ |
| 52415 | 52582 | const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ |
| 52416 | 52583 | int cnt = 0; |
| 52584 | + int isRO = 0; /* file is known to be accessible readonly */ |
| 52417 | 52585 | |
| 52418 | 52586 | /* If argument zPath is a NULL pointer, this function is required to open |
| 52419 | 52587 | ** a temporary file. Use this buffer to store the file name in. |
| 52420 | 52588 | */ |
| 52421 | 52589 | char *zTmpname = 0; /* For temporary filename, if necessary. */ |
| | @@ -52576,13 +52744,13 @@ |
| 52576 | 52744 | dwShareMode, |
| 52577 | 52745 | dwCreationDisposition, |
| 52578 | 52746 | &extendedParameters); |
| 52579 | 52747 | if( h!=INVALID_HANDLE_VALUE ) break; |
| 52580 | 52748 | if( isReadWrite ){ |
| 52581 | | - int rc2, isRO = 0; |
| 52749 | + int rc2; |
| 52582 | 52750 | sqlite3BeginBenignMalloc(); |
| 52583 | | - rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO); |
| 52751 | + rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO); |
| 52584 | 52752 | sqlite3EndBenignMalloc(); |
| 52585 | 52753 | if( rc2==SQLITE_OK && isRO ) break; |
| 52586 | 52754 | } |
| 52587 | 52755 | }while( winRetryIoerr(&cnt, &lastErrno) ); |
| 52588 | 52756 | #else |
| | @@ -52593,13 +52761,13 @@ |
| 52593 | 52761 | dwCreationDisposition, |
| 52594 | 52762 | dwFlagsAndAttributes, |
| 52595 | 52763 | NULL); |
| 52596 | 52764 | if( h!=INVALID_HANDLE_VALUE ) break; |
| 52597 | 52765 | if( isReadWrite ){ |
| 52598 | | - int rc2, isRO = 0; |
| 52766 | + int rc2; |
| 52599 | 52767 | sqlite3BeginBenignMalloc(); |
| 52600 | | - rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO); |
| 52768 | + rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO); |
| 52601 | 52769 | sqlite3EndBenignMalloc(); |
| 52602 | 52770 | if( rc2==SQLITE_OK && isRO ) break; |
| 52603 | 52771 | } |
| 52604 | 52772 | }while( winRetryIoerr(&cnt, &lastErrno) ); |
| 52605 | 52773 | #endif |
| | @@ -52613,13 +52781,13 @@ |
| 52613 | 52781 | dwCreationDisposition, |
| 52614 | 52782 | dwFlagsAndAttributes, |
| 52615 | 52783 | NULL); |
| 52616 | 52784 | if( h!=INVALID_HANDLE_VALUE ) break; |
| 52617 | 52785 | if( isReadWrite ){ |
| 52618 | | - int rc2, isRO = 0; |
| 52786 | + int rc2; |
| 52619 | 52787 | sqlite3BeginBenignMalloc(); |
| 52620 | | - rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO); |
| 52788 | + rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO); |
| 52621 | 52789 | sqlite3EndBenignMalloc(); |
| 52622 | 52790 | if( rc2==SQLITE_OK && isRO ) break; |
| 52623 | 52791 | } |
| 52624 | 52792 | }while( winRetryIoerr(&cnt, &lastErrno) ); |
| 52625 | 52793 | } |
| | @@ -52630,11 +52798,11 @@ |
| 52630 | 52798 | dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); |
| 52631 | 52799 | |
| 52632 | 52800 | if( h==INVALID_HANDLE_VALUE ){ |
| 52633 | 52801 | sqlite3_free(zConverted); |
| 52634 | 52802 | sqlite3_free(zTmpname); |
| 52635 | | - if( isReadWrite && !isExclusive ){ |
| 52803 | + if( isReadWrite && isRO && !isExclusive ){ |
| 52636 | 52804 | return winOpen(pVfs, zName, id, |
| 52637 | 52805 | ((flags|SQLITE_OPEN_READONLY) & |
| 52638 | 52806 | ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), |
| 52639 | 52807 | pOutFlags); |
| 52640 | 52808 | }else{ |
| | @@ -52832,11 +53000,17 @@ |
| 52832 | 53000 | ){ |
| 52833 | 53001 | DWORD attr; |
| 52834 | 53002 | int rc = 0; |
| 52835 | 53003 | DWORD lastErrno = 0; |
| 52836 | 53004 | void *zConverted; |
| 53005 | + int noRetry = 0; /* Do not use winRetryIoerr() */ |
| 52837 | 53006 | UNUSED_PARAMETER(pVfs); |
| 53007 | + |
| 53008 | + if( (flags & NORETRY)!=0 ){ |
| 53009 | + noRetry = 1; |
| 53010 | + flags &= ~NORETRY; |
| 53011 | + } |
| 52838 | 53012 | |
| 52839 | 53013 | SimulateIOError( return SQLITE_IOERR_ACCESS; ); |
| 52840 | 53014 | OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n", |
| 52841 | 53015 | zFilename, flags, pResOut)); |
| 52842 | 53016 | |
| | @@ -52856,11 +53030,14 @@ |
| 52856 | 53030 | int cnt = 0; |
| 52857 | 53031 | WIN32_FILE_ATTRIBUTE_DATA sAttrData; |
| 52858 | 53032 | memset(&sAttrData, 0, sizeof(sAttrData)); |
| 52859 | 53033 | while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, |
| 52860 | 53034 | GetFileExInfoStandard, |
| 52861 | | - &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){} |
| 53035 | + &sAttrData)) |
| 53036 | + && !noRetry |
| 53037 | + && winRetryIoerr(&cnt, &lastErrno) |
| 53038 | + ){ /* Loop until true */} |
| 52862 | 53039 | if( rc ){ |
| 52863 | 53040 | /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file |
| 52864 | 53041 | ** as if it does not exist. |
| 52865 | 53042 | */ |
| 52866 | 53043 | if( flags==SQLITE_ACCESS_EXISTS |
| | @@ -52924,10 +53101,11 @@ |
| 52924 | 53101 | const char *zPathname |
| 52925 | 53102 | ){ |
| 52926 | 53103 | return ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ); |
| 52927 | 53104 | } |
| 52928 | 53105 | |
| 53106 | +#ifdef _WIN32 |
| 52929 | 53107 | /* |
| 52930 | 53108 | ** Returns non-zero if the specified path name should be used verbatim. If |
| 52931 | 53109 | ** non-zero is returned from this function, the calling function must simply |
| 52932 | 53110 | ** use the provided path name verbatim -OR- resolve it into a full path name |
| 52933 | 53111 | ** using the GetFullPathName Win32 API function (if available). |
| | @@ -52960,10 +53138,74 @@ |
| 52960 | 53138 | ** If we get to this point, the path name should almost certainly be a purely |
| 52961 | 53139 | ** relative one (i.e. not a UNC name, not absolute, and not volume relative). |
| 52962 | 53140 | */ |
| 52963 | 53141 | return FALSE; |
| 52964 | 53142 | } |
| 53143 | +#endif /* _WIN32 */ |
| 53144 | + |
| 53145 | +#ifdef __CYGWIN__ |
| 53146 | +/* |
| 53147 | +** Simplify a filename into its canonical form |
| 53148 | +** by making the following changes: |
| 53149 | +** |
| 53150 | +** * convert any '/' to '\' (win32) or reverse (Cygwin) |
| 53151 | +** * removing any trailing and duplicate / (except for UNC paths) |
| 53152 | +** * convert /./ into just / |
| 53153 | +** |
| 53154 | +** Changes are made in-place. Return the new name length. |
| 53155 | +** |
| 53156 | +** The original filename is in z[0..]. If the path is shortened, |
| 53157 | +** no-longer used bytes will be written by '\0'. |
| 53158 | +*/ |
| 53159 | +static void winSimplifyName(char *z){ |
| 53160 | + int i, j; |
| 53161 | + for(i=j=0; z[i]; ++i){ |
| 53162 | + if( winIsDirSep(z[i]) ){ |
| 53163 | +#if !defined(SQLITE_TEST) |
| 53164 | + /* Some test-cases assume that "./foo" and "foo" are different */ |
| 53165 | + if( z[i+1]=='.' && winIsDirSep(z[i+2]) ){ |
| 53166 | + ++i; |
| 53167 | + continue; |
| 53168 | + } |
| 53169 | +#endif |
| 53170 | + if( !z[i+1] || (winIsDirSep(z[i+1]) && (i!=0)) ){ |
| 53171 | + continue; |
| 53172 | + } |
| 53173 | + z[j++] = osGetenv?'/':'\\'; |
| 53174 | + }else{ |
| 53175 | + z[j++] = z[i]; |
| 53176 | + } |
| 53177 | + } |
| 53178 | + while(j<i) z[j++] = '\0'; |
| 53179 | +} |
| 53180 | + |
| 53181 | +#define SQLITE_MAX_SYMLINKS 100 |
| 53182 | + |
| 53183 | +static int mkFullPathname( |
| 53184 | + const char *zPath, /* Input path */ |
| 53185 | + char *zOut, /* Output buffer */ |
| 53186 | + int nOut /* Allocated size of buffer zOut */ |
| 53187 | +){ |
| 53188 | + int nPath = sqlite3Strlen30(zPath); |
| 53189 | + int iOff = 0; |
| 53190 | + if( zPath[0]!='/' ){ |
| 53191 | + if( osGetcwd(zOut, nOut-2)==0 ){ |
| 53192 | + return winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)osErrno, "getcwd", zPath); |
| 53193 | + } |
| 53194 | + iOff = sqlite3Strlen30(zOut); |
| 53195 | + zOut[iOff++] = '/'; |
| 53196 | + } |
| 53197 | + if( (iOff+nPath+1)>nOut ){ |
| 53198 | + /* SQLite assumes that xFullPathname() nul-terminates the output buffer |
| 53199 | + ** even if it returns an error. */ |
| 53200 | + zOut[iOff] = '\0'; |
| 53201 | + return SQLITE_CANTOPEN_BKPT; |
| 53202 | + } |
| 53203 | + sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath); |
| 53204 | + return SQLITE_OK; |
| 53205 | +} |
| 53206 | +#endif /* __CYGWIN__ */ |
| 52965 | 53207 | |
| 52966 | 53208 | /* |
| 52967 | 53209 | ** Turn a relative pathname into a full pathname. Write the full |
| 52968 | 53210 | ** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname |
| 52969 | 53211 | ** bytes in size. |
| | @@ -52972,12 +53214,12 @@ |
| 52972 | 53214 | sqlite3_vfs *pVfs, /* Pointer to vfs object */ |
| 52973 | 53215 | const char *zRelative, /* Possibly relative input path */ |
| 52974 | 53216 | int nFull, /* Size of output buffer in bytes */ |
| 52975 | 53217 | char *zFull /* Output buffer */ |
| 52976 | 53218 | ){ |
| 52977 | | -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__) |
| 52978 | | - DWORD nByte; |
| 53219 | +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT |
| 53220 | + int nByte; |
| 52979 | 53221 | void *zConverted; |
| 52980 | 53222 | char *zOut; |
| 52981 | 53223 | #endif |
| 52982 | 53224 | |
| 52983 | 53225 | /* If this path name begins with "/X:" or "\\?\", where "X" is any |
| | @@ -52986,68 +53228,114 @@ |
| 52986 | 53228 | if( zRelative[0]=='/' && (winIsDriveLetterAndColon(zRelative+1) |
| 52987 | 53229 | || winIsLongPathPrefix(zRelative+1)) ){ |
| 52988 | 53230 | zRelative++; |
| 52989 | 53231 | } |
| 52990 | 53232 | |
| 52991 | | -#if defined(__CYGWIN__) |
| 53233 | + SimulateIOError( return SQLITE_ERROR ); |
| 53234 | + |
| 53235 | +#ifdef __CYGWIN__ |
| 53236 | + if( osGetcwd ){ |
| 53237 | + zFull[nFull-1] = '\0'; |
| 53238 | + if( !winIsDriveLetterAndColon(zRelative) || !winIsDirSep(zRelative[2]) ){ |
| 53239 | + int rc = SQLITE_OK; |
| 53240 | + int nLink = 1; /* Number of symbolic links followed so far */ |
| 53241 | + const char *zIn = zRelative; /* Input path for each iteration of loop */ |
| 53242 | + char *zDel = 0; |
| 53243 | + struct stat buf; |
| 53244 | + |
| 53245 | + UNUSED_PARAMETER(pVfs); |
| 53246 | + |
| 53247 | + do { |
| 53248 | + /* Call lstat() on path zIn. Set bLink to true if the path is a symbolic |
| 53249 | + ** link, or false otherwise. */ |
| 53250 | + int bLink = 0; |
| 53251 | + if( osLstat && osReadlink ) { |
| 53252 | + if( osLstat(zIn, &buf)!=0 ){ |
| 53253 | + int myErrno = osErrno; |
| 53254 | + if( myErrno!=ENOENT ){ |
| 53255 | + rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)myErrno, "lstat", zIn); |
| 53256 | + } |
| 53257 | + }else{ |
| 53258 | + bLink = ((buf.st_mode & 0170000) == 0120000); |
| 53259 | + } |
| 53260 | + |
| 53261 | + if( bLink ){ |
| 53262 | + if( zDel==0 ){ |
| 53263 | + zDel = sqlite3MallocZero(nFull); |
| 53264 | + if( zDel==0 ) rc = SQLITE_NOMEM; |
| 53265 | + }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ |
| 53266 | + rc = SQLITE_CANTOPEN_BKPT; |
| 53267 | + } |
| 53268 | + |
| 53269 | + if( rc==SQLITE_OK ){ |
| 53270 | + nByte = osReadlink(zIn, zDel, nFull-1); |
| 53271 | + if( nByte ==(DWORD)-1 ){ |
| 53272 | + rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)osErrno, "readlink", zIn); |
| 53273 | + }else{ |
| 53274 | + if( zDel[0]!='/' ){ |
| 53275 | + int n; |
| 53276 | + for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); |
| 53277 | + if( nByte+n+1>nFull ){ |
| 53278 | + rc = SQLITE_CANTOPEN_BKPT; |
| 53279 | + }else{ |
| 53280 | + memmove(&zDel[n], zDel, nByte+1); |
| 53281 | + memcpy(zDel, zIn, n); |
| 53282 | + nByte += n; |
| 53283 | + } |
| 53284 | + } |
| 53285 | + zDel[nByte] = '\0'; |
| 53286 | + } |
| 53287 | + } |
| 53288 | + |
| 53289 | + zIn = zDel; |
| 53290 | + } |
| 53291 | + } |
| 53292 | + |
| 53293 | + assert( rc!=SQLITE_OK || zIn!=zFull || zIn[0]=='/' ); |
| 53294 | + if( rc==SQLITE_OK && zIn!=zFull ){ |
| 53295 | + rc = mkFullPathname(zIn, zFull, nFull); |
| 53296 | + } |
| 53297 | + if( bLink==0 ) break; |
| 53298 | + zIn = zFull; |
| 53299 | + }while( rc==SQLITE_OK ); |
| 53300 | + |
| 53301 | + sqlite3_free(zDel); |
| 53302 | + winSimplifyName(zFull); |
| 53303 | + return rc; |
| 53304 | + } |
| 53305 | + } |
| 53306 | +#endif /* __CYGWIN__ */ |
| 53307 | +#if 0 /* This doesn't work correctly at all! See: |
| 53308 | + <https://marc.info/?l=sqlite-users&m=139299149416314&w=2> |
| 53309 | +*/ |
| 52992 | 53310 | SimulateIOError( return SQLITE_ERROR ); |
| 52993 | 53311 | UNUSED_PARAMETER(nFull); |
| 52994 | 53312 | assert( nFull>=pVfs->mxPathname ); |
| 52995 | | - if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ |
| 52996 | | - /* |
| 52997 | | - ** NOTE: We are dealing with a relative path name and the data |
| 52998 | | - ** directory has been set. Therefore, use it as the basis |
| 52999 | | - ** for converting the relative path name to an absolute |
| 53000 | | - ** one by prepending the data directory and a slash. |
| 53001 | | - */ |
| 53002 | | - char *zOut = sqlite3MallocZero( 1+(u64)pVfs->mxPathname ); |
| 53003 | | - if( !zOut ){ |
| 53004 | | - return SQLITE_IOERR_NOMEM_BKPT; |
| 53005 | | - } |
| 53006 | | - if( cygwin_conv_path( |
| 53007 | | - (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) | |
| 53008 | | - CCP_RELATIVE, zRelative, zOut, pVfs->mxPathname+1)<0 ){ |
| 53009 | | - sqlite3_free(zOut); |
| 53010 | | - return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno, |
| 53011 | | - "winFullPathname1", zRelative); |
| 53012 | | - }else{ |
| 53013 | | - char *zUtf8 = winConvertToUtf8Filename(zOut); |
| 53014 | | - if( !zUtf8 ){ |
| 53015 | | - sqlite3_free(zOut); |
| 53016 | | - return SQLITE_IOERR_NOMEM_BKPT; |
| 53017 | | - } |
| 53018 | | - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s", |
| 53019 | | - sqlite3_data_directory, winGetDirSep(), zUtf8); |
| 53020 | | - sqlite3_free(zUtf8); |
| 53021 | | - sqlite3_free(zOut); |
| 53022 | | - } |
| 53023 | | - }else{ |
| 53024 | | - char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 ); |
| 53025 | | - if( !zOut ){ |
| 53026 | | - return SQLITE_IOERR_NOMEM_BKPT; |
| 53027 | | - } |
| 53028 | | - if( cygwin_conv_path( |
| 53029 | | - (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A), |
| 53030 | | - zRelative, zOut, pVfs->mxPathname+1)<0 ){ |
| 53031 | | - sqlite3_free(zOut); |
| 53032 | | - return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno, |
| 53033 | | - "winFullPathname2", zRelative); |
| 53034 | | - }else{ |
| 53035 | | - char *zUtf8 = winConvertToUtf8Filename(zOut); |
| 53036 | | - if( !zUtf8 ){ |
| 53037 | | - sqlite3_free(zOut); |
| 53038 | | - return SQLITE_IOERR_NOMEM_BKPT; |
| 53039 | | - } |
| 53040 | | - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8); |
| 53041 | | - sqlite3_free(zUtf8); |
| 53042 | | - sqlite3_free(zOut); |
| 53043 | | - } |
| 53044 | | - } |
| 53045 | | - return SQLITE_OK; |
| 53046 | | -#endif |
| 53047 | | - |
| 53048 | | -#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__) |
| 53313 | + char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 ); |
| 53314 | + if( !zOut ){ |
| 53315 | + return SQLITE_IOERR_NOMEM_BKPT; |
| 53316 | + } |
| 53317 | + if( osCygwin_conv_path( |
| 53318 | + CCP_POSIX_TO_WIN_W, |
| 53319 | + zRelative, zOut, pVfs->mxPathname+1)<0 ){ |
| 53320 | + sqlite3_free(zOut); |
| 53321 | + return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno, |
| 53322 | + "winFullPathname2", zRelative); |
| 53323 | + }else{ |
| 53324 | + char *zUtf8 = winConvertToUtf8Filename(zOut); |
| 53325 | + if( !zUtf8 ){ |
| 53326 | + sqlite3_free(zOut); |
| 53327 | + return SQLITE_IOERR_NOMEM_BKPT; |
| 53328 | + } |
| 53329 | + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8); |
| 53330 | + sqlite3_free(zUtf8); |
| 53331 | + sqlite3_free(zOut); |
| 53332 | + } |
| 53333 | + return SQLITE_OK; |
| 53334 | +#endif |
| 53335 | + |
| 53336 | +#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && defined(_WIN32) |
| 53049 | 53337 | SimulateIOError( return SQLITE_ERROR ); |
| 53050 | 53338 | /* WinCE has no concept of a relative pathname, or so I am told. */ |
| 53051 | 53339 | /* WinRT has no way to convert a relative path to an absolute one. */ |
| 53052 | 53340 | if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ |
| 53053 | 53341 | /* |
| | @@ -53062,11 +53350,12 @@ |
| 53062 | 53350 | sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative); |
| 53063 | 53351 | } |
| 53064 | 53352 | return SQLITE_OK; |
| 53065 | 53353 | #endif |
| 53066 | 53354 | |
| 53067 | | -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__) |
| 53355 | +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT |
| 53356 | +#if defined(_WIN32) |
| 53068 | 53357 | /* It's odd to simulate an io-error here, but really this is just |
| 53069 | 53358 | ** using the io-error infrastructure to test that SQLite handles this |
| 53070 | 53359 | ** function failing. This function could fail if, for example, the |
| 53071 | 53360 | ** current working directory has been unlinked. |
| 53072 | 53361 | */ |
| | @@ -53080,10 +53369,11 @@ |
| 53080 | 53369 | */ |
| 53081 | 53370 | sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s", |
| 53082 | 53371 | sqlite3_data_directory, winGetDirSep(), zRelative); |
| 53083 | 53372 | return SQLITE_OK; |
| 53084 | 53373 | } |
| 53374 | +#endif |
| 53085 | 53375 | zConverted = winConvertFromUtf8Filename(zRelative); |
| 53086 | 53376 | if( zConverted==0 ){ |
| 53087 | 53377 | return SQLITE_IOERR_NOMEM_BKPT; |
| 53088 | 53378 | } |
| 53089 | 53379 | if( osIsNT() ){ |
| | @@ -53092,16 +53382,17 @@ |
| 53092 | 53382 | if( nByte==0 ){ |
| 53093 | 53383 | sqlite3_free(zConverted); |
| 53094 | 53384 | return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), |
| 53095 | 53385 | "winFullPathname1", zRelative); |
| 53096 | 53386 | } |
| 53097 | | - zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) + 3*sizeof(zTemp[0]) ); |
| 53387 | + nByte += 3; |
| 53388 | + zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); |
| 53098 | 53389 | if( zTemp==0 ){ |
| 53099 | 53390 | sqlite3_free(zConverted); |
| 53100 | 53391 | return SQLITE_IOERR_NOMEM_BKPT; |
| 53101 | 53392 | } |
| 53102 | | - nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte+3, zTemp, 0); |
| 53393 | + nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0); |
| 53103 | 53394 | if( nByte==0 ){ |
| 53104 | 53395 | sqlite3_free(zConverted); |
| 53105 | 53396 | sqlite3_free(zTemp); |
| 53106 | 53397 | return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), |
| 53107 | 53398 | "winFullPathname2", zRelative); |
| | @@ -53135,11 +53426,30 @@ |
| 53135 | 53426 | zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI()); |
| 53136 | 53427 | sqlite3_free(zTemp); |
| 53137 | 53428 | } |
| 53138 | 53429 | #endif |
| 53139 | 53430 | if( zOut ){ |
| 53431 | +#ifdef __CYGWIN__ |
| 53432 | + if( memcmp(zOut, "\\\\?\\", 4) ){ |
| 53433 | + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut); |
| 53434 | + }else if( memcmp(zOut+4, "UNC\\", 4) ){ |
| 53435 | + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut+4); |
| 53436 | + }else{ |
| 53437 | + char *p = zOut+6; |
| 53438 | + *p = '\\'; |
| 53439 | + if( osGetcwd ){ |
| 53440 | + /* On Cygwin, UNC paths use forward slashes */ |
| 53441 | + while( *p ){ |
| 53442 | + if( *p=='\\' ) *p = '/'; |
| 53443 | + ++p; |
| 53444 | + } |
| 53445 | + } |
| 53446 | + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut+6); |
| 53447 | + } |
| 53448 | +#else |
| 53140 | 53449 | sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut); |
| 53450 | +#endif /* __CYGWIN__ */ |
| 53141 | 53451 | sqlite3_free(zOut); |
| 53142 | 53452 | return SQLITE_OK; |
| 53143 | 53453 | }else{ |
| 53144 | 53454 | return SQLITE_IOERR_NOMEM_BKPT; |
| 53145 | 53455 | } |
| | @@ -53165,11 +53475,13 @@ |
| 53165 | 53475 | ** Interfaces for opening a shared library, finding entry points |
| 53166 | 53476 | ** within the shared library, and closing the shared library. |
| 53167 | 53477 | */ |
| 53168 | 53478 | static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ |
| 53169 | 53479 | HANDLE h; |
| 53170 | | -#if defined(__CYGWIN__) |
| 53480 | +#if 0 /* This doesn't work correctly at all! See: |
| 53481 | + <https://marc.info/?l=sqlite-users&m=139299149416314&w=2> |
| 53482 | +*/ |
| 53171 | 53483 | int nFull = pVfs->mxPathname+1; |
| 53172 | 53484 | char *zFull = sqlite3MallocZero( nFull ); |
| 53173 | 53485 | void *zConverted = 0; |
| 53174 | 53486 | if( zFull==0 ){ |
| 53175 | 53487 | OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); |
| | @@ -53532,11 +53844,11 @@ |
| 53532 | 53844 | }; |
| 53533 | 53845 | #endif |
| 53534 | 53846 | |
| 53535 | 53847 | /* Double-check that the aSyscall[] array has been constructed |
| 53536 | 53848 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 53537 | | - assert( ArraySize(aSyscall)==82 ); |
| 53849 | + assert( ArraySize(aSyscall)==89 ); |
| 53538 | 53850 | |
| 53539 | 53851 | /* get memory map allocation granularity */ |
| 53540 | 53852 | memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); |
| 53541 | 53853 | #if SQLITE_OS_WINRT |
| 53542 | 53854 | osGetNativeSystemInfo(&winSysInfo); |
| | @@ -66508,14 +66820,12 @@ |
| 66508 | 66820 | s2 = aIn[1]; |
| 66509 | 66821 | }else{ |
| 66510 | 66822 | s1 = s2 = 0; |
| 66511 | 66823 | } |
| 66512 | 66824 | |
| 66513 | | - assert( nByte>=8 ); |
| 66514 | | - assert( (nByte&0x00000007)==0 ); |
| 66515 | | - assert( nByte<=65536 ); |
| 66516 | | - assert( nByte%4==0 ); |
| 66825 | + /* nByte is a multiple of 8 between 8 and 65536 */ |
| 66826 | + assert( nByte>=8 && (nByte&7)==0 && nByte<=65536 ); |
| 66517 | 66827 | |
| 66518 | 66828 | if( !nativeCksum ){ |
| 66519 | 66829 | do { |
| 66520 | 66830 | s1 += BYTESWAP32(aData[0]) + s2; |
| 66521 | 66831 | s2 += BYTESWAP32(aData[1]) + s1; |
| | @@ -147785,10 +148095,11 @@ |
| 147785 | 148095 | } |
| 147786 | 148096 | |
| 147787 | 148097 | multi_select_end: |
| 147788 | 148098 | pDest->iSdst = dest.iSdst; |
| 147789 | 148099 | pDest->nSdst = dest.nSdst; |
| 148100 | + pDest->iSDParm2 = dest.iSDParm2; |
| 147790 | 148101 | if( pDelete ){ |
| 147791 | 148102 | sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pDelete); |
| 147792 | 148103 | } |
| 147793 | 148104 | return rc; |
| 147794 | 148105 | } |
| | @@ -188065,10 +188376,17 @@ |
| 188065 | 188376 | ****************************************************************************** |
| 188066 | 188377 | ** |
| 188067 | 188378 | */ |
| 188068 | 188379 | #ifndef _FTSINT_H |
| 188069 | 188380 | #define _FTSINT_H |
| 188381 | + |
| 188382 | +/* #include <assert.h> */ |
| 188383 | +/* #include <stdlib.h> */ |
| 188384 | +/* #include <stddef.h> */ |
| 188385 | +/* #include <stdio.h> */ |
| 188386 | +/* #include <string.h> */ |
| 188387 | +/* #include <stdarg.h> */ |
| 188070 | 188388 | |
| 188071 | 188389 | #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) |
| 188072 | 188390 | # define NDEBUG 1 |
| 188073 | 188391 | #endif |
| 188074 | 188392 | |
| | @@ -189017,16 +189335,10 @@ |
| 189017 | 189335 | |
| 189018 | 189336 | #if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE) |
| 189019 | 189337 | # define SQLITE_CORE 1 |
| 189020 | 189338 | #endif |
| 189021 | 189339 | |
| 189022 | | -/* #include <assert.h> */ |
| 189023 | | -/* #include <stdlib.h> */ |
| 189024 | | -/* #include <stddef.h> */ |
| 189025 | | -/* #include <stdio.h> */ |
| 189026 | | -/* #include <string.h> */ |
| 189027 | | -/* #include <stdarg.h> */ |
| 189028 | 189340 | |
| 189029 | 189341 | /* #include "fts3.h" */ |
| 189030 | 189342 | #ifndef SQLITE_CORE |
| 189031 | 189343 | /* # include "sqlite3ext.h" */ |
| 189032 | 189344 | SQLITE_EXTENSION_INIT1 |
| | @@ -227533,12 +227845,12 @@ |
| 227533 | 227845 | ){ |
| 227534 | 227846 | if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert && pgno>1 ){ |
| 227535 | 227847 | /* "INSERT INTO dbpage($PGNO,NULL)" causes page number $PGNO and |
| 227536 | 227848 | ** all subsequent pages to be deleted. */ |
| 227537 | 227849 | pTab->iDbTrunc = iDb; |
| 227538 | | - pgno--; |
| 227539 | | - pTab->pgnoTrunc = pgno; |
| 227850 | + pTab->pgnoTrunc = pgno-1; |
| 227851 | + pgno = 1; |
| 227540 | 227852 | }else{ |
| 227541 | 227853 | zErr = "bad page value"; |
| 227542 | 227854 | goto update_fail; |
| 227543 | 227855 | } |
| 227544 | 227856 | } |
| | @@ -241869,11 +242181,12 @@ |
| 241869 | 242181 | sqlite3Fts5ParseError( |
| 241870 | 242182 | pParse, "expected integer, got \"%.*s\"", p->n, p->p |
| 241871 | 242183 | ); |
| 241872 | 242184 | return; |
| 241873 | 242185 | } |
| 241874 | | - nNear = nNear * 10 + (p->p[i] - '0'); |
| 242186 | + if( nNear<214748363 ) nNear = nNear * 10 + (p->p[i] - '0'); |
| 242187 | + /* ^^^^^^^^^^^^^^^--- Prevent integer overflow */ |
| 241875 | 242188 | } |
| 241876 | 242189 | }else{ |
| 241877 | 242190 | nNear = FTS5_DEFAULT_NEARDIST; |
| 241878 | 242191 | } |
| 241879 | 242192 | pNear->nNear = nNear; |
| | @@ -256775,11 +257088,11 @@ |
| 256775 | 257088 | int nArg, /* Number of args */ |
| 256776 | 257089 | sqlite3_value **apUnused /* Function arguments */ |
| 256777 | 257090 | ){ |
| 256778 | 257091 | assert( nArg==0 ); |
| 256779 | 257092 | UNUSED_PARAM2(nArg, apUnused); |
| 256780 | | - sqlite3_result_text(pCtx, "fts5: 2025-03-16 00:13:29 18bda13e197e4b4ec7464b3e70012f71edc05f73d8b14bb48bad452f81c7e185", -1, SQLITE_TRANSIENT); |
| 257093 | + sqlite3_result_text(pCtx, "fts5: 2025-03-27 23:29:25 121f4d97f9a855131859d342bc2ade5f8c34ba7732029ae156d02cec7cb6dd85", -1, SQLITE_TRANSIENT); |
| 256781 | 257094 | } |
| 256782 | 257095 | |
| 256783 | 257096 | /* |
| 256784 | 257097 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 256785 | 257098 | ** |
| 256786 | 257099 | |