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