diff options
Diffstat (limited to 'src/os_win.c')
-rw-r--r-- | src/os_win.c | 313 |
1 files changed, 106 insertions, 207 deletions
diff --git a/src/os_win.c b/src/os_win.c index 0dd56af58..623e30104 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -2722,7 +2722,11 @@ static int winHandleLockTimeout( if( res==WAIT_OBJECT_0 ){ ret = TRUE; }else if( res==WAIT_TIMEOUT ){ +#if SQLITE_ENABLE_SETLK_TIMEOUT==1 rc = SQLITE_BUSY_TIMEOUT; +#else + rc = SQLITE_BUSY; +#endif }else{ /* Some other error has occurred */ rc = SQLITE_IOERR_LOCK; @@ -3986,6 +3990,103 @@ static int winDeviceCharacteristics(sqlite3_file *id){ */ static SYSTEM_INFO winSysInfo; +/* +** Convert a UTF-8 filename into whatever form the underlying +** operating system wants filenames in. Space to hold the result +** is obtained from malloc and must be freed by the calling +** function +** +** On Cygwin, 3 possible input forms are accepted: +** - If the filename starts with "<drive>:/" or "<drive>:\", +** it is converted to UTF-16 as-is. +** - If the filename contains '/', it is assumed to be a +** Cygwin absolute path, it is converted to a win32 +** absolute path in UTF-16. +** - Otherwise it must be a filename only, the win32 filename +** is returned in UTF-16. +** Note: If the function cygwin_conv_path() fails, only +** UTF-8 -> UTF-16 conversion will be done. This can only +** happen when the file path >32k, in which case winUtf8ToUnicode() +** will fail too. +*/ +static void *winConvertFromUtf8Filename(const char *zFilename){ + void *zConverted = 0; + if( osIsNT() ){ +#ifdef __CYGWIN__ + int nChar; + LPWSTR zWideFilename; + + if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename) + && winIsDirSep(zFilename[2])) ){ + i64 nByte; + int convertflag = CCP_POSIX_TO_WIN_W; + if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE; + nByte = (i64)osCygwin_conv_path(convertflag, + zFilename, 0, 0); + if( nByte>0 ){ + zConverted = sqlite3MallocZero(12+(u64)nByte); + if ( zConverted==0 ){ + return zConverted; + } + zWideFilename = zConverted; + /* Filenames should be prefixed, except when converted + * full path already starts with "\\?\". */ + if( osCygwin_conv_path(convertflag, zFilename, + zWideFilename+4, nByte)==0 ){ + if( (convertflag&CCP_RELATIVE) ){ + memmove(zWideFilename, zWideFilename+4, nByte); + }else if( memcmp(zWideFilename+4, L"\\\\", 4) ){ + memcpy(zWideFilename, L"\\\\?\\", 8); + }else if( zWideFilename[6]!='?' ){ + memmove(zWideFilename+6, zWideFilename+4, nByte); + memcpy(zWideFilename, L"\\\\?\\UNC", 14); + }else{ + memmove(zWideFilename, zWideFilename+4, nByte); + } + return zConverted; + } + sqlite3_free(zConverted); + } + } + nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); + if( nChar==0 ){ + return 0; + } + zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+12 ); + if( zWideFilename==0 ){ + return 0; + } + nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, + zWideFilename, nChar); + if( nChar==0 ){ + sqlite3_free(zWideFilename); + zWideFilename = 0; + }else if( nChar>MAX_PATH + && winIsDriveLetterAndColon(zFilename) + && winIsDirSep(zFilename[2]) ){ + memmove(zWideFilename+4, zWideFilename, nChar*sizeof(WCHAR)); + zWideFilename[2] = '\\'; + memcpy(zWideFilename, L"\\\\?\\", 8); + }else if( nChar>MAX_PATH + && winIsDirSep(zFilename[0]) && winIsDirSep(zFilename[1]) + && zFilename[2] != '?' ){ + memmove(zWideFilename+6, zWideFilename, nChar*sizeof(WCHAR)); + memcpy(zWideFilename, L"\\\\?\\UNC", 14); + } + zConverted = zWideFilename; +#else + zConverted = winUtf8ToUnicode(zFilename); +#endif /* __CYGWIN__ */ + } +#if defined(SQLITE_WIN32_HAS_ANSI) && defined(_WIN32) + else{ + zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); + } +#endif + /* caller will handle out of memory */ + return zConverted; +} + #ifndef SQLITE_OMIT_WAL /* @@ -4181,103 +4282,6 @@ static int winLockSharedMemory(winShmNode *pShmNode, DWORD nMs){ /* -** Convert a UTF-8 filename into whatever form the underlying -** operating system wants filenames in. Space to hold the result -** is obtained from malloc and must be freed by the calling -** function -** -** On Cygwin, 3 possible input forms are accepted: -** - If the filename starts with "<drive>:/" or "<drive>:\", -** it is converted to UTF-16 as-is. -** - If the filename contains '/', it is assumed to be a -** Cygwin absolute path, it is converted to a win32 -** absolute path in UTF-16. -** - Otherwise it must be a filename only, the win32 filename -** is returned in UTF-16. -** Note: If the function cygwin_conv_path() fails, only -** UTF-8 -> UTF-16 conversion will be done. This can only -** happen when the file path >32k, in which case winUtf8ToUnicode() -** will fail too. -*/ -static void *winConvertFromUtf8Filename(const char *zFilename){ - void *zConverted = 0; - if( osIsNT() ){ -#ifdef __CYGWIN__ - int nChar; - LPWSTR zWideFilename; - - if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename) - && winIsDirSep(zFilename[2])) ){ - int nByte; - int convertflag = CCP_POSIX_TO_WIN_W; - if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE; - nByte = (int)osCygwin_conv_path(convertflag, - zFilename, 0, 0); - if( nByte>0 ){ - zConverted = sqlite3MallocZero(nByte+12); - if ( zConverted==0 ){ - return zConverted; - } - zWideFilename = zConverted; - /* Filenames should be prefixed, except when converted - * full path already starts with "\\?\". */ - if( osCygwin_conv_path(convertflag, zFilename, - zWideFilename+4, nByte)==0 ){ - if( (convertflag&CCP_RELATIVE) ){ - memmove(zWideFilename, zWideFilename+4, nByte); - }else if( memcmp(zWideFilename+4, L"\\\\", 4) ){ - memcpy(zWideFilename, L"\\\\?\\", 8); - }else if( zWideFilename[6]!='?' ){ - memmove(zWideFilename+6, zWideFilename+4, nByte); - memcpy(zWideFilename, L"\\\\?\\UNC", 14); - }else{ - memmove(zWideFilename, zWideFilename+4, nByte); - } - return zConverted; - } - sqlite3_free(zConverted); - } - } - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); - if( nChar==0 ){ - return 0; - } - zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+12 ); - if( zWideFilename==0 ){ - return 0; - } - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, - zWideFilename, nChar); - if( nChar==0 ){ - sqlite3_free(zWideFilename); - zWideFilename = 0; - }else if( nChar>MAX_PATH - && winIsDriveLetterAndColon(zFilename) - && winIsDirSep(zFilename[2]) ){ - memmove(zWideFilename+4, zWideFilename, nChar*sizeof(WCHAR)); - zWideFilename[2] = '\\'; - memcpy(zWideFilename, L"\\\\?\\", 8); - }else if( nChar>MAX_PATH - && winIsDirSep(zFilename[0]) && winIsDirSep(zFilename[1]) - && zFilename[2] != '?' ){ - memmove(zWideFilename+6, zWideFilename, nChar*sizeof(WCHAR)); - memcpy(zWideFilename, L"\\\\?\\UNC", 14); - } - zConverted = zWideFilename; -#else - zConverted = winUtf8ToUnicode(zFilename); -#endif /* __CYGWIN__ */ - } -#if defined(SQLITE_WIN32_HAS_ANSI) && defined(_WIN32) - else{ - zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); - } -#endif - /* caller will handle out of memory */ - return zConverted; -} - -/* ** This function is used to open a handle on a *-shm file. ** ** If SQLITE_ENABLE_SETLK_TIMEOUT is defined at build time, then the file @@ -4533,21 +4537,20 @@ static int winShmLock( /* Check that, if this to be a blocking lock, no locks that occur later ** in the following list than the lock being obtained are already held: ** - ** 1. Checkpointer lock (ofst==1). - ** 2. Write lock (ofst==0). - ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK). + ** 1. Recovery lock (ofst==2). + ** 2. Checkpointer lock (ofst==1). + ** 3. Write lock (ofst==0). + ** 4. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK). ** ** In other words, if this is a blocking lock, none of the locks that ** occur later in the above list than the lock being obtained may be ** held. - ** - ** It is not permitted to block on the RECOVER lock. */ #if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG) { u16 lockMask = (p->exclMask|p->sharedMask); assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( - (ofst!=2) /* not RECOVER */ + (ofst!=2 || lockMask==0) && (ofst!=1 || lockMask==0 || lockMask==2) && (ofst!=0 || lockMask<3) && (ofst<3 || lockMask<(1<<ofst)) @@ -5097,27 +5100,6 @@ static winVfsAppData winNolockAppData = { ** sqlite3_vfs object. */ -#if 0 /* No longer necessary */ -/* -** Convert a filename from whatever the underlying operating system -** supports for filenames into UTF-8. Space to hold the result is -** obtained from malloc and must be freed by the calling function. -*/ -static char *winConvertToUtf8Filename(const void *zFilename){ - char *zConverted = 0; - if( osIsNT() ){ - zConverted = winUnicodeToUtf8(zFilename); - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI()); - } -#endif - /* caller will handle out of memory */ - return zConverted; -} -#endif - /* ** This function returns non-zero if the specified UTF-8 string buffer ** ends with a directory separator character or one was successfully @@ -5257,42 +5239,6 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ break; } sqlite3_free(zConverted); -#if 0 /* No longer necessary */ - }else{ - zConverted = sqlite3MallocZero( nMax+1 ); - if( !zConverted ){ - sqlite3_free(zBuf); - OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM_BKPT; - } - if( osCygwin_conv_path( - CCP_POSIX_TO_WIN_W, zDir, - zConverted, nMax+1)<0 ){ - sqlite3_free(zConverted); - sqlite3_free(zBuf); - OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n")); - return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno, - "winGetTempname2", zDir); - } - if( winIsDir(zConverted) ){ - /* At this point, we know the candidate directory exists and should - ** be used. However, we may need to convert the string containing - ** its name into UTF-8 (i.e. if it is UTF-16 right now). - */ - char *zUtf8 = winConvertToUtf8Filename(zConverted); - if( !zUtf8 ){ - sqlite3_free(zConverted); - sqlite3_free(zBuf); - OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM_BKPT; - } - sqlite3_snprintf(nMax, zBuf, "%s", zUtf8); - sqlite3_free(zUtf8); - sqlite3_free(zConverted); - break; - } - sqlite3_free(zConverted); -#endif /* No longer necessary */ } } } @@ -6191,34 +6137,6 @@ static int winFullPathnameNoMutex( } } #endif /* __CYGWIN__ */ -#if 0 /* This doesn't work correctly at all! See: - <https://marc.info/?l=sqlite-users&m=139299149416314&w=2> -*/ - SimulateIOError( return SQLITE_ERROR ); - UNUSED_PARAMETER(nFull); - assert( nFull>=pVfs->mxPathname ); - char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 ); - if( !zOut ){ - return SQLITE_IOERR_NOMEM_BKPT; - } - if( osCygwin_conv_path( - CCP_POSIX_TO_WIN_W, - zRelative, zOut, pVfs->mxPathname+1)<0 ){ - sqlite3_free(zOut); - return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno, - "winFullPathname2", zRelative); - }else{ - char *zUtf8 = winConvertToUtf8Filename(zOut); - if( !zUtf8 ){ - sqlite3_free(zOut); - return SQLITE_IOERR_NOMEM_BKPT; - } - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8); - sqlite3_free(zUtf8); - sqlite3_free(zOut); - } - return SQLITE_OK; -#endif #if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && defined(_WIN32) SimulateIOError( return SQLITE_ERROR ); @@ -6364,27 +6282,8 @@ static int winFullPathname( */ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ HANDLE h; -#if 0 /* This doesn't work correctly at all! See: - <https://marc.info/?l=sqlite-users&m=139299149416314&w=2> -*/ - int nFull = pVfs->mxPathname+1; - char *zFull = sqlite3MallocZero( nFull ); - void *zConverted = 0; - if( zFull==0 ){ - OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); - return 0; - } - if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){ - sqlite3_free(zFull); - OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); - return 0; - } - zConverted = winConvertFromUtf8Filename(zFull); - sqlite3_free(zFull); -#else void *zConverted = winConvertFromUtf8Filename(zFilename); UNUSED_PARAMETER(pVfs); -#endif if( zConverted==0 ){ OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); return 0; |