Hi,
I do not now if you found it but there is another port of sqlite to
WinCE. You can find it at http://sqlite-wince.sourceforge.net/.
Would it be possible if your port and the sf port could be merged
together in main line src tree?
Regards Simon
On sre, 2006-01-04 at 10:13 -1000, Steve Lhomme wrote:
> Hi everyone,
>
> I'm a happy user of SQlite for a project I just started to make a
> multimedia database (a bit like the DB in iTunes). The idea is to make
> it as cross-platform as possible and free.
>
> I tried to make it work under Windows CE but run into a few problems
> when compiling with Embedded Visual C++ 4. Although WinCE has a very
> similar API to Windows, it lacks some of the features.
>
> - only the unicode API is present, so I disabled all the xxxA() API calls
>
> - localtime() is defined but doesn't exist, so I coded one with the
> existing API
>
> - LockFile(Ex) and UnlockFile(Ex) are not supported, only the Ex API is
> available on WinCE 5 but I need bigger support so I just made the code
> blank on WinCE. Is there any drawback to that ?
>
> - FILE_ATTRIBUTE_TEMPORARY and FILE_FLAG_DELETE_ON_CLOSE are not
> supported for CreateFile. So I removed the flags for WinCE. But that
> means I have to delete the auto-deleting files on close. I modified the
> API to do that when calling sqlite3OsClose(). I realise changing the API
> is not so good, so calling sqlite3OsDelete() where the close is called
> could be a better option.
>
> All of the changes are included in the following patch.
>
> Steve
>
> priloga plain text document (WinCE.patch)
> Index: os.h
> ===================================================================
> --- os.h (revision 1)
> +++ os.h (working copy)
> @@ -182,7 +182,7 @@
> int sqlite3OsSyncDirectory(const char*);
> int sqlite3OsTempFileName(char*);
> int sqlite3OsIsDirWritable(char*);
> -int sqlite3OsClose(OsFile*);
> +int sqlite3OsClose(OsFile*, const char*);
> int sqlite3OsRead(OsFile*, void*, int amt);
> int sqlite3OsWrite(OsFile*, const void*, int amt);
> int sqlite3OsSeek(OsFile*, i64 offset);
> Index: os_unix.c
> ===================================================================
> --- os_unix.c (revision 1)
> +++ os_unix.c (working copy)
> @@ -1278,7 +1278,7 @@
> /*
> ** Close a file.
> */
> -int sqlite3OsClose(OsFile *id){
> +int sqlite3OsClose(OsFile *id, const char*){
> if( !id->isOpen ) return SQLITE_OK;
> if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
> sqlite3OsUnlock(id, NO_LOCK);
> Index: os_win.c
> ===================================================================
> --- os_win.c (revision 1)
> +++ os_win.c (working copy)
> @@ -33,6 +33,64 @@
> ** Include code that is common to all os_*.c files
> */
> #include "os_common.h"
> +
> +#if defined(_WIN32_WCE)
> +#include <time.h>
> +struct tm * __cdecl localtime(const time_t *t)
> +{
> + static struct tm y;
> + FILETIME uTm, lTm;
> + SYSTEMTIME pTm;
> + uTm.dwLowDateTime = *t & 0xFFFFFFFF;
> + uTm.dwHighDateTime= *t >> 32;
> + FileTimeToLocalFileTime(&uTm,&lTm);
> + FileTimeToSystemTime(&lTm,&pTm);
> + y.tm_year = pTm.wYear - 1900;
> + y.tm_mon = pTm.wMonth - 1;
> + y.tm_wday = pTm.wDayOfWeek;
> + y.tm_mday = pTm.wDay;
> + y.tm_hour = pTm.wHour;
> + y.tm_min = pTm.wMinute;
> + y.tm_sec = pTm.wSecond;
> + return &y;
> +}
> +
> +#ifndef LOCKFILE_EXCLUSIVE_LOCK
> +#define LockFileEx(a,b,c,d,e,f) (1)
> +#define UnlockFileEx(a,b,c,d,e) (1)
> +#endif
> +
> +BOOL LockFile(
> + HANDLE hFile,
> + DWORD dwFileOffsetLow,
> + DWORD dwFileOffsetHigh,
> + DWORD nNumberOfBytesToLockLow,
> + DWORD nNumberOfBytesToLockHigh
> +)
> +{
> + OVERLAPPED ovlp;
> + ovlp.Offset = dwFileOffsetLow;
> + ovlp.OffsetHigh = dwFileOffsetHigh;
> + ovlp.hEvent = 0;
> + return LockFileEx(hFile,
> LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 0,
> nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, &ovlp);
> +}
> +
> +
> +BOOL UnlockFile(
> + HANDLE hFile,
> + DWORD dwFileOffsetLow,
> + DWORD dwFileOffsetHigh,
> + DWORD nNumberOfBytesToUnlockLow,
> + DWORD nNumberOfBytesToUnlockHigh
> +)
> +{
> + OVERLAPPED ovlp;
> + ovlp.Offset = dwFileOffsetLow;
> + ovlp.OffsetHigh = dwFileOffsetHigh;
> + ovlp.hEvent = 0;
> + return UnlockFileEx(hFile, 0, nNumberOfBytesToUnlockLow,
> nNumberOfBytesToUnlockHigh, &ovlp);
> +}
> +#endif
>
> /*
> ** Do not include any of the File I/O interface procedures if the
> @@ -66,14 +124,18 @@
> ** WinNT/2K/XP so that we will know whether or not we can safely call
> ** the LockFileEx() API.
> */
> -static int isNT(void){
> +static int isNT(void){
> +#if !defined(_WIN32_WCE)
> if( sqlite3_os_type==0 ){
> OSVERSIONINFO sInfo;
> sInfo.dwOSVersionInfoSize = sizeof(sInfo);
> GetVersionEx(&sInfo);
> sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
> }
> - return sqlite3_os_type==2;
> + return sqlite3_os_type==2;
> +#else
> + return 1;
> +#endif
> }
>
> /*
> @@ -131,9 +193,11 @@
> if( zWide ){
> DeleteFileW(zWide);
> sqliteFree(zWide);
> +#if !defined(_WIN32_WCE)
> }else{
> DeleteFileA(zFilename);
> - }
> +#endif
> + }
> TRACE2("DELETE \"%s\"\n", zFilename);
> return SQLITE_OK;
> }
> @@ -147,8 +211,10 @@
> if( zWide ){
> exists = GetFileAttributesW(zWide) != 0xffffffff;
> sqliteFree(zWide);
> +#if !defined(_WIN32_WCE)
> }else{
> - exists = GetFileAttributesA(zFilename) != 0xffffffff;
> + exists = GetFileAttributesA(zFilename) != 0xffffffff;
> +#endif
> }
> return exists;
> }
> @@ -201,6 +267,7 @@
> *pReadonly = 0;
> }
> sqliteFree(zWide);
> +#if !defined(_WIN32_WCE)
> }else{
> h = CreateFileA(zFilename,
> GENERIC_READ | GENERIC_WRITE,
> @@ -225,7 +292,8 @@
> *pReadonly = 1;
> }else{
> *pReadonly = 0;
> - }
> + }
> +#endif
> }
> id->h = h;
> id->locktype = NO_LOCK;
> @@ -257,8 +325,12 @@
> WCHAR *zWide = utf8ToUnicode(zFilename);
> assert( !id->isOpen );
> if( delFlag ){
> - fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
> - | FILE_FLAG_DELETE_ON_CLOSE;
> +#if defined(_WIN32_WCE)
> + fileflags = FILE_FLAG_RANDOM_ACCESS;
> +#else
> + fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
> + | FILE_FLAG_DELETE_ON_CLOSE;
> +#endif
> }else{
> fileflags = FILE_FLAG_RANDOM_ACCESS;
> }
> @@ -271,7 +343,11 @@
> fileflags,
> NULL
> );
> +#if defined(_WIN32_WCE)
> + SetFileAttributes(zWide, FILE_ATTRIBUTE_TEMPORARY);
> +#endif
> sqliteFree(zWide);
> +#if !defined(_WIN32_WCE)
> }else{
> h = CreateFileA(zFilename,
> GENERIC_READ | GENERIC_WRITE,
> @@ -280,9 +356,10 @@
> CREATE_ALWAYS,
> fileflags,
> NULL
> - );
> + );
> +#endif
> }
> - if( h==INVALID_HANDLE_VALUE ){
> + if( h==INVALID_HANDLE_VALUE ){
> return SQLITE_CANTOPEN;
> }
> id->h = h;
> @@ -315,6 +392,7 @@
> NULL
> );
> sqliteFree(zWide);
> +#if !defined(_WIN32_WCE)
> }else{
> h = CreateFileA(zFilename,
> GENERIC_READ,
> @@ -323,7 +401,8 @@
> OPEN_EXISTING,
> FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
> NULL
> - );
> + );
> +#endif
> }
> if( h==INVALID_HANDLE_VALUE ){
> return SQLITE_CANTOPEN;
> @@ -381,7 +460,11 @@
> if( sqlite3_temp_directory ){
> strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30);
> zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
> - }else if( isNT() ){
> +#if !defined(_WIN32_WCE)
> + }else if( !isNT() ){
> + GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath);
> +#endif
> + }else{
> char *zMulti;
> WCHAR zWidePath[SQLITE_TEMPNAME_SIZE];
> GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath);
> @@ -391,8 +474,6 @@
> zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
> sqliteFree(zMulti);
> }
> - }else{
> - GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath);
> }
> for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
> zTempPath[i] = 0;
> @@ -413,11 +494,18 @@
> /*
> ** Close a file.
> */
> -int sqlite3OsClose(OsFile *id){
> +int sqlite3OsClose(OsFile *id, const char *FilePath){
> if( id->isOpen ){
> TRACE2("CLOSE %d\n", id->h);
> CloseHandle(id->h);
> - OpenCounter(-1);
> + OpenCounter(-1);
> +#if defined(_WIN32_WCE)
> + {
> + WCHAR *path = utf8ToUnicode(FilePath);
> + DeleteFile(path);
> + sqliteFree(path);
> + }
> +#endif
> id->isOpen = 0;
> }
> return SQLITE_OK;
> @@ -556,7 +644,7 @@
> int lk;
> sqlite3Randomness(sizeof(lk), &lk);
> id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
> - res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0);
> + res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0);
> }
> return res;
> }
> @@ -565,12 +653,12 @@
> ** Undo a readlock
> */
> static int unlockReadLock(OsFile *id){
> - int res;
> + int res;
> if( isNT() ){
> res = UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
> }else{
> res = UnlockFile(id->h, SHARED_FIRST + id->sharedLockByte, 0, 1, 0);
> - }
> + }
> return res;
> }
>
> @@ -588,8 +676,10 @@
> if( zWide ){
> fileAttr = GetFileAttributesW(zWide);
> sqliteFree(zWide);
> +#if !defined(_WIN32_WCE)
> }else{
> - fileAttr = GetFileAttributesA(zDirname);
> + fileAttr = GetFileAttributesA(zDirname);
> +#endif
> }
> if( fileAttr == 0xffffffff ) return 0;
> if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){
> @@ -800,7 +890,7 @@
> */
> char *sqlite3OsFullPathname(const char *zRelative){
> char *zNotUsed;
> - char *zFull;
> + char *zFull=0;
> WCHAR *zWide;
> int nByte;
> #ifdef __CYGWIN__
> @@ -808,7 +898,7 @@
> zFull = sqliteMalloc( nByte );
> if( zFull==0 ) return 0;
> if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0;
> -#else
> +#elif !defined(_WIN32_WCE)
> zWide = utf8ToUnicode(zRelative);
> if( zWide ){
> WCHAR *zTemp, *zNotUsedW;
> @@ -823,8 +913,13 @@
> nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1;
> zFull = sqliteMalloc( nByte*sizeof(zFull[0]) );
> if( zFull==0 ) return 0;
> - GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed);
> + GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed);
> }
> +#else
> + nByte = strlen(zRelative)+1;
> + zFull = sqliteMalloc(nByte);
> + if (zFull)
> + memcpy(zFull,zRelative,nByte);
> #endif
> return zFull;
> }
> @@ -919,14 +1014,20 @@
> ** Find the current time (in Universal Coordinated Time). Write the
> ** current time and date as a Julian Day number into *prNow and
> ** return 0. Return 1 if the time and date cannot be found.
> -*/
> +*/
> int sqlite3OsCurrentTime(double *prNow){
> FILETIME ft;
> /* FILETIME structure is a 64-bit value representing the number of
> 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
> */
> double now;
> - GetSystemTimeAsFileTime( &ft );
> +#if defined(_WIN32_WCE)
> + SYSTEMTIME time;
> + GetSystemTime(&time);
> + SystemTimeToFileTime(&time,&ft);
> +#else
> + GetSystemTimeAsFileTime( &ft );
> +#endif
> now = ((double)ft.dwHighDateTime) * 4294967296.0;
> *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
> #ifdef SQLITE_TEST
> @@ -935,6 +1036,6 @@
> }
> #endif
> return 0;
> -}
> +}
>
> #endif /* OS_WIN */
> Index: pager.c
> ===================================================================
> --- pager.c (revision 1)
> +++ pager.c (working copy)
> @@ -907,11 +907,11 @@
> }
> sqlite3pager_stmt_commit(pPager);
> if( pPager->stmtOpen ){
> - sqlite3OsClose(&pPager->stfd);
> + sqlite3OsClose(&pPager->stfd, pPager->zFilename);
> pPager->stmtOpen = 0;
> }
> if( pPager->journalOpen ){
> - sqlite3OsClose(&pPager->jfd);
> + sqlite3OsClose(&pPager->jfd, pPager->tempFile?pPager->zFilename:NULL);
> pPager->journalOpen = 0;
> sqlite3OsDelete(pPager->zJournal);
> sqliteFree( pPager->aInJournal );
> @@ -1128,7 +1128,7 @@
> }
>
> rc = readMasterJournal(&journal, &zMasterPtr);
> - sqlite3OsClose(&journal);
> + sqlite3OsClose(&journal, NULL);
> if( rc!=SQLITE_OK ){
> goto delmaster_out;
> }
> @@ -1151,7 +1151,7 @@
> sqliteFree(zMasterJournal);
> }
> if( master_open ){
> - sqlite3OsClose(&master);
> + sqlite3OsClose(&master, NULL);
> }
> return rc;
> }
> @@ -1633,18 +1633,18 @@
> }
> }
> if( !zFullPathname ){
> - sqlite3OsClose(&fd);
> + sqlite3OsClose(&fd, zFilename);
> return SQLITE_NOMEM;
> }
> if( rc!=SQLITE_OK ){
> - sqlite3OsClose(&fd);
> + sqlite3OsClose(&fd, zFilename);
> sqliteFree(zFullPathname);
> return rc;
> }
> nameLen = strlen(zFullPathname);
> pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 );
> if( pPager==0 ){
> - sqlite3OsClose(&fd);
> + sqlite3OsClose(&fd, zFilename);
> sqliteFree(zFullPathname);
> return SQLITE_NOMEM;
> }
> @@ -2002,13 +2002,13 @@
> TRACE2("CLOSE %d\n", PAGERID(pPager));
> assert( pPager->errMask || (pPager->journalOpen==0 && pPager->stmtOpen==0)
> );
> if( pPager->journalOpen ){
> - sqlite3OsClose(&pPager->jfd);
> + sqlite3OsClose(&pPager->jfd, pPager->tempFile?pPager->zJournal:NULL);
> }
> sqliteFree(pPager->aInJournal);
> if( pPager->stmtOpen ){
> - sqlite3OsClose(&pPager->stfd);
> + sqlite3OsClose(&pPager->stfd, pPager->zFilename);
> }
> - sqlite3OsClose(&pPager->fd);
> + sqlite3OsClose(&pPager->fd, NULL);
> /* Temp files are automatically deleted by the OS
> ** if( pPager->tempFile ){
> ** sqlite3OsDelete(pPager->zFilename);
> Index: vdbeaux.c
> ===================================================================
> --- vdbeaux.c (revision 1)
> +++ vdbeaux.c (working copy)
> @@ -1003,7 +1003,7 @@
> }
> rc = sqlite3OsWrite(&master, zFile, strlen(zFile)+1);
> if( rc!=SQLITE_OK ){
> - sqlite3OsClose(&master);
> + sqlite3OsClose(&master, 0);
> sqlite3OsDelete(zMaster);
> sqliteFree(zMaster);
> return rc;
> @@ -1019,7 +1019,7 @@
> rc = sqlite3OsOpenDirectory(zMainFile, &master);
> if( rc!=SQLITE_OK ||
> (needSync && (rc=sqlite3OsSync(&master,0))!=SQLITE_OK) ){
> - sqlite3OsClose(&master);
> + sqlite3OsClose(&master, 0);
> sqlite3OsDelete(zMaster);
> sqliteFree(zMaster);
> return rc;
> @@ -1040,13 +1040,13 @@
> if( pBt && sqlite3BtreeIsInTrans(pBt) ){
> rc = sqlite3BtreeSync(pBt, zMaster);
> if( rc!=SQLITE_OK ){
> - sqlite3OsClose(&master);
> + sqlite3OsClose(&master, 0);
> sqliteFree(zMaster);
> return rc;
> }
> }
> }
> - sqlite3OsClose(&master);
> + sqlite3OsClose(&master, 0);
>
> /* Delete the master journal file. This commits the transaction. After
> ** doing this the directory is synced again before any individual