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

--
robUx4 on blog <http://robux4.blogspot.com/>
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

Reply via email to