The function sqlite3_load_extension() on Cygwin expects a
win32 path, even though it is compiled for Cygwin.
How to reproduce? First create some extension, e.g.:
gcc -shared -o wholenumber.dll ext/misc/wholenumber.c
Then compile the following little program:
================== main.c ================
#include <sqlite3.h>
#include <stdio.h>
void main(int argc, char **argv){
sqlite3 *db;
int rc;
char *zErrMsg = 0;
printf("loading extension: %s\n", argv[1]);
sqlite3_initialize();
sqlite3_open("foo.db", &db);
sqlite3_enable_load_extension(db, 1);
rc = sqlite3_load_extension(db, argv[1], "sqlite3_wholenumber_init",
&zErrMsg);
if( rc!=SQLITE_OK ){
fprintf(stderr, "Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
rc = 1;
}
}
============================================
gcc main.c sqlite3.c
(This produces an executable "a.exe")
Then try:
$ ./a.exe wholenumber.dll
loading extension: wholenumber.dll
This works, but:
$ ./a.exe $PWD/wholenumber.dll
loading extension: /home/nijtmaj/wholenumber.dll
Error: The specified module could not be found.
Hey, this is exactly where the dll is.
$ ./a.exe `cygpath -w /home/nijtmaj/`wholenumber.dll
loading extension: C:\Localdata\cygwin\home\nijtmaj\wholenumber.dll
When using win32 path, it works! That's not correct!
Suggested patch which fixes this is below. Note
that adding 17 lines to the function
winConvertFromUtf8Filename() means that 38 lines
can be removed from the function winGetTempname():
If we teach winConvertFromUtf8Filename() how to
handle cygwin paths, winGetTempname() doesn't
have to do this conversion any more, just deligate it
to winConvertFromUtf8Filename(). The total
amalgamation becomes 21 lines shorter.
If the function cygwin_conv_path() fails for whatever
reason (which should never happen!), the original path
translation is used as fall-back. This simplifies greatly
the error-handling: if there is something wrong with
the path, everything is cleaned up correctly and
handled exactly as before.
I hope this contribution is still in time for SQLite 3.8.4,
and given some time for proper evaluation.
Regards,
Jan Nijtmans
==========================================
Index: src/os_win.c
==================================================================
--- src/os_win.c
+++ src/os_win.c
@@ -4131,10 +4131,27 @@
** function.
*/
static void *winConvertFromUtf8Filename(const char *zFilename){
void *zConverted = 0;
if( osIsNT() ){
+#ifdef __CYGWIN__
+ if( !(winIsDriveLetterAndColon(zFilename)
+ && winIsDirSep(zFilename[2])) ){
+ int nByte = cygwin_conv_path(CCP_POSIX_TO_WIN_W, zFilename, 0, 0);
+ if( nByte>0 ){
+ zConverted = sqlite3MallocZero(nByte);
+ if ( zConverted==0 ){
+ return zConverted;
+ }
+ if( cygwin_conv_path(CCP_POSIX_TO_WIN_W, zFilename,
+ zConverted, nByte)==0 ){
+ return zConverted;
+ }
+ sqlite3_free(zConverted);
+ }
+ }
+#endif
zConverted = winUtf8ToUnicode(zFilename);
}
#ifdef SQLITE_WIN32_HAS_ANSI
else{
zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
@@ -4243,11 +4260,11 @@
/* If the path starts with a drive letter followed by the colon
** character, assume it is already a native Win32 path; otherwise,
** it must be converted to a native Win32 path via the Cygwin API
** prior to using it.
*/
- if( winIsDriveLetterAndColon(zDir) ){
+ if( 1 ){
zConverted = winConvertFromUtf8Filename(zDir);
if( !zConverted ){
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
return SQLITE_IOERR_NOMEM;
@@ -4256,10 +4273,11 @@
sqlite3_snprintf(nMax, zBuf, "%s", zDir);
sqlite3_free(zConverted);
break;
}
sqlite3_free(zConverted);
+#if 0 /* not necessary any more */
}else{
zConverted = sqlite3MallocZero( nMax+1 );
if( !zConverted ){
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
@@ -4290,10 +4308,11 @@
sqlite3_free(zUtf8);
sqlite3_free(zConverted);
break;
}
sqlite3_free(zConverted);
+#endif /* not necessary any more */
}
}
}
#elif !SQLITE_OS_WINRT && !defined(__CYGWIN__)
else if( osIsNT() ){
_______________________________________________
sqlite-users mailing list
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users