| 2 |      1 | /*
 | 
|  |      2 | ** 2008 February 09
 | 
|  |      3 | **
 | 
|  |      4 | ** The author disclaims copyright to this source code.  In place of
 | 
|  |      5 | ** a legal notice, here is a blessing:
 | 
|  |      6 | **
 | 
|  |      7 | **    May you do good and not evil.
 | 
|  |      8 | **    May you find forgiveness for yourself and forgive others.
 | 
|  |      9 | **    May you share freely, never taking more than you give.
 | 
|  |     10 | **
 | 
|  |     11 | ******************************************************************************
 | 
|  |     12 | **
 | 
|  |     13 | ** This file contains code that is specific to windows.
 | 
|  |     14 | */
 | 
|  |     15 | #include "sqliteInt.h"
 | 
|  |     16 | #if OS_SYMBIAN               /* This file is used for symbian only */
 | 
|  |     17 | 
 | 
|  |     18 | #define MAX_PATH 260
 | 
|  |     19 | /*
 | 
|  |     20 | ** A Note About Memory Allocation:
 | 
|  |     21 | **
 | 
|  |     22 | ** This driver uses malloc()/free() directly rather than going through
 | 
|  |     23 | ** the SQLite-wrappers sqlite3_malloc()/sqlite3_free().  Those wrappers
 | 
|  |     24 | ** are designed for use on embedded systems where memory is scarce and
 | 
|  |     25 | ** malloc failures happen frequently.  Win32 does not typically run on
 | 
|  |     26 | ** embedded systems, and when it does the developers normally have bigger
 | 
|  |     27 | ** problems to worry about than running out of memory.  So there is not
 | 
|  |     28 | ** a compelling need to use the wrappers.
 | 
|  |     29 | **
 | 
|  |     30 | ** But there is a good reason to not use the wrappers.  If we use the
 | 
|  |     31 | ** wrappers then we will get simulated malloc() failures within this
 | 
|  |     32 | ** driver.  And that causes all kinds of problems for our tests.  We
 | 
|  |     33 | ** could enhance SQLite to deal with simulated malloc failures within
 | 
|  |     34 | ** the OS driver, but the code to deal with those failure would not
 | 
|  |     35 | ** be exercised on Linux (which does not need to malloc() in the driver)
 | 
|  |     36 | ** and so we would have difficulty writing coverage tests for that
 | 
|  |     37 | ** code.  Better to leave the code out, we think.
 | 
|  |     38 | **
 | 
|  |     39 | ** The point of this discussion is as follows:  When creating a new
 | 
|  |     40 | ** OS layer for an embedded system, if you use this file as an example,
 | 
|  |     41 | ** avoid the use of malloc()/free().  Those routines work ok on windows
 | 
|  |     42 | ** desktops but not so well in embedded systems.
 | 
|  |     43 | */
 | 
|  |     44 | 
 | 
|  |     45 | #include <stdlib.h>
 | 
|  |     46 | #include <string.h>
 | 
|  |     47 | #include <time.h>
 | 
|  |     48 | #include <e32std.h>
 | 
|  |     49 | #include <f32file.h>
 | 
|  |     50 | #include <charconv.h>
 | 
|  |     51 | #include <bautils.h>
 | 
|  |     52 | #include <unistd.h>
 | 
|  |     53 | 
 | 
|  |     54 | /*
 | 
|  |     55 | ** Macros used to determine whether or not to use threads.
 | 
|  |     56 | */
 | 
|  |     57 | #if defined(THREADSAFE) && THREADSAFE
 | 
|  |     58 | # define SQLITE_W32_THREADS 1
 | 
|  |     59 | #endif
 | 
|  |     60 | 
 | 
|  |     61 | /*
 | 
|  |     62 | ** Include code that is common to all os_*.c files
 | 
|  |     63 | */
 | 
|  |     64 | #include "os_common.h"
 | 
|  |     65 | 
 | 
|  |     66 | /*
 | 
|  |     67 | ** The symbianFile structure is a subclass of sqlite3_file* specific to the win32
 | 
|  |     68 | ** portability layer.
 | 
|  |     69 | */
 | 
|  |     70 | 
 | 
|  |     71 | typedef struct symbianFile symbianFile;
 | 
|  |     72 | struct symbianFile {
 | 
|  |     73 | 	int isOpen;
 | 
|  |     74 |   unsigned char locktype; /* Type of lock currently held on this file */
 | 
|  |     75 |   short sharedLockByte;   /* Randomly chosen byte used as a shared lock */
 | 
|  |     76 |   char fileName[512];
 | 
|  |     77 |   RFs session;
 | 
|  |     78 |   RFile file;
 | 
|  |     79 | };
 | 
|  |     80 | 
 | 
|  |     81 | /*****************************************************************************
 | 
|  |     82 | ** The next group of routines implement the I/O methods specified
 | 
|  |     83 | ** by the sqlite3_io_methods object.
 | 
|  |     84 | ******************************************************************************/
 | 
|  |     85 | 
 | 
|  |     86 | /*
 | 
|  |     87 | ** Close a file.
 | 
|  |     88 | **
 | 
|  |     89 | ** It is reported that an attempt to close a handle might sometimes
 | 
|  |     90 | ** fail.  This is a very unreasonable result, but windows is notorious
 | 
|  |     91 | ** for being unreasonable so I do not doubt that it might happen.  If
 | 
|  |     92 | ** the close fails, we pause for 100 milliseconds and try again.  As
 | 
|  |     93 | ** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
 | 
|  |     94 | ** giving up and returning an error.
 | 
|  |     95 | */
 | 
|  |     96 | #define MX_CLOSE_ATTEMPT 3
 | 
|  |     97 | int winClose(sqlite3_file *id){
 | 
|  |     98 |   int rc, cnt = 0;
 | 
|  |     99 |   symbianFile *pFile = (symbianFile*)id;
 | 
|  |    100 |   pFile->file.Close();
 | 
|  |    101 |   pFile->session.Close();
 | 
|  |    102 |   return SQLITE_OK;
 | 
|  |    103 | }
 | 
|  |    104 | 
 | 
|  |    105 | /*
 | 
|  |    106 | ** Some microsoft compilers lack this definition.
 | 
|  |    107 | */
 | 
|  |    108 | #ifndef INVALID_SET_FILE_POINTER
 | 
|  |    109 | # define INVALID_SET_FILE_POINTER ((DWORD)-1)
 | 
|  |    110 | #endif
 | 
|  |    111 | 
 | 
|  |    112 | /*
 | 
|  |    113 | ** Read data from a file into a buffer.  Return SQLITE_OK if all
 | 
|  |    114 | ** bytes were read successfully and SQLITE_IOERR if anything goes
 | 
|  |    115 | ** wrong.
 | 
|  |    116 | */
 | 
|  |    117 | int winRead(
 | 
|  |    118 |   sqlite3_file *id,          /* File to read from */
 | 
|  |    119 |   void *pBuf,                /* Write content into this buffer */
 | 
|  |    120 |   int amt,                   /* Number of bytes to read */
 | 
|  |    121 |   sqlite3_int64 offset       /* Begin reading at this offset */
 | 
|  |    122 | ){
 | 
|  |    123 |   int rc;
 | 
|  |    124 |   size_t got;
 | 
|  |    125 |   symbianFile *pFile = (symbianFile*)id;
 | 
|  |    126 |   assert( id!=0 );
 | 
|  |    127 |   SimulateIOError(return SQLITE_IOERR_READ);
 | 
|  |    128 |   TInt tOffset = (TInt)offset;
 | 
|  |    129 |   rc = pFile->file.Seek(ESeekStart, tOffset);
 | 
|  |    130 |   if( rc!= KErrNone){
 | 
|  |    131 |     return SQLITE_FULL;
 | 
|  |    132 |   }
 | 
|  |    133 | 
 | 
|  |    134 |   HBufC8* buf = HBufC8::NewL(amt) ;
 | 
|  |    135 |   TPtr8 ptr = buf->Des();
 | 
|  |    136 | 
 | 
|  |    137 |   if (pFile->file.Read(ptr, amt) != KErrNone)
 | 
|  |    138 | 	  {
 | 
|  |    139 | 	    delete buf;
 | 
|  |    140 | 	    return SQLITE_IOERR_READ;
 | 
|  |    141 | 	  }
 | 
|  |    142 | 
 | 
|  |    143 |   got = buf->Length();
 | 
|  |    144 | 
 | 
|  |    145 |   if( got == 0 ){
 | 
|  |    146 | 	  delete buf;
 | 
|  |    147 | 	  TInt size = 0;
 | 
|  |    148 | 	  if (pFile->file.Size(size) != KErrNone) 
 | 
|  |    149 | 	  {
 | 
|  |    150 | 		  return SQLITE_IOERR_READ;
 | 
|  |    151 | 	  }
 | 
|  |    152 | 	  if (size == 0)
 | 
|  |    153 | 	  {
 | 
|  |    154 | 		  return SQLITE_IOERR_SHORT_READ;
 | 
|  |    155 | 	  }
 | 
|  |    156 |     return SQLITE_IOERR_READ;
 | 
|  |    157 |  }
 | 
|  |    158 |   memcpy(pBuf, ptr.Ptr(), got);
 | 
|  |    159 |   delete buf;
 | 
|  |    160 |  if( got == amt ){
 | 
|  |    161 |     return SQLITE_OK;
 | 
|  |    162 |   }else{
 | 
|  |    163 |     memset(&((char*)pBuf)[got], 0, amt-got);
 | 
|  |    164 |     return SQLITE_IOERR_SHORT_READ;
 | 
|  |    165 |   }
 | 
|  |    166 | }
 | 
|  |    167 | 
 | 
|  |    168 | /*
 | 
|  |    169 | ** Write data from a buffer into a file.  Return SQLITE_OK on success
 | 
|  |    170 | ** or some other error code on failure.
 | 
|  |    171 | */
 | 
|  |    172 | int winWrite(
 | 
|  |    173 |   sqlite3_file *id,         /* File to write into */
 | 
|  |    174 |   const void *pBuf,         /* The bytes to be written */
 | 
|  |    175 |   int amt,                  /* Number of bytes to write */
 | 
|  |    176 |   sqlite3_int64 offset      /* Offset into the file to begin writing at */
 | 
|  |    177 | ){
 | 
|  |    178 |   int rc;
 | 
|  |    179 |   symbianFile *pFile = (symbianFile*)id;
 | 
|  |    180 |   assert( id!=0 );
 | 
|  |    181 |   SimulateIOError(return SQLITE_IOERR_WRITE);
 | 
|  |    182 |   SimulateDiskfullError(return SQLITE_FULL);
 | 
|  |    183 |   TInt tOffset = (TInt)offset;
 | 
|  |    184 |   rc = pFile->file.Seek(ESeekStart, tOffset);
 | 
|  |    185 |   if( rc!= KErrNone){
 | 
|  |    186 |     return SQLITE_FULL;
 | 
|  |    187 |   }
 | 
|  |    188 | 
 | 
|  |    189 |   assert( amt>0 );
 | 
|  |    190 |   
 | 
|  |    191 |   rc = SQLITE_OK;
 | 
|  |    192 |   TPtrC8 ptr((TUint8 *)pBuf,amt);
 | 
|  |    193 | 
 | 
|  |    194 |   if (pFile->file.Write(ptr, amt) != KErrNone) rc = SQLITE_FULL;
 | 
|  |    195 | 
 | 
|  |    196 |   return rc;
 | 
|  |    197 | }
 | 
|  |    198 | 
 | 
|  |    199 | /*
 | 
|  |    200 | ** Truncate an open file to a specified size
 | 
|  |    201 | */
 | 
|  |    202 | int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
 | 
|  |    203 |   symbianFile *pFile = (symbianFile*)id;
 | 
|  |    204 | 
 | 
|  |    205 |   if (pFile->file.SetSize(nByte) != KErrNone)
 | 
|  |    206 |   {
 | 
|  |    207 | 	  return SQLITE_IOERR; 
 | 
|  |    208 |   }
 | 
|  |    209 | 
 | 
|  |    210 |   return SQLITE_OK;
 | 
|  |    211 | }
 | 
|  |    212 | 
 | 
|  |    213 | #ifdef SQLITE_TEST
 | 
|  |    214 | /*
 | 
|  |    215 | ** Count the number of fullsyncs and normal syncs.  This is used to test
 | 
|  |    216 | ** that syncs and fullsyncs are occuring at the right times.
 | 
|  |    217 | */
 | 
|  |    218 | int sqlite3_sync_count = 0;
 | 
|  |    219 | int sqlite3_fullsync_count = 0;
 | 
|  |    220 | #endif
 | 
|  |    221 | 
 | 
|  |    222 | /*
 | 
|  |    223 | ** Make sure all writes to a particular file are committed to disk.
 | 
|  |    224 | */
 | 
|  |    225 | int winSync(sqlite3_file *id, int flags){
 | 
|  |    226 |   symbianFile *pFile = (symbianFile*)id;
 | 
|  |    227 |   OSTRACE3("SYNC %d lock=%d\n", pFile->h, pFile->locktype);
 | 
|  |    228 | #ifdef SQLITE_TEST
 | 
|  |    229 |   if( flags & SQLITE_SYNC_FULL ){
 | 
|  |    230 |     sqlite3_fullsync_count++;
 | 
|  |    231 |   }
 | 
|  |    232 |   sqlite3_sync_count++;
 | 
|  |    233 | #endif
 | 
|  |    234 |   TInt error = pFile->file.Flush();
 | 
|  |    235 |   if (error != KErrNone)
 | 
|  |    236 |   {
 | 
|  |    237 |     return SQLITE_IOERR;
 | 
|  |    238 |   }else{
 | 
|  |    239 |     return SQLITE_OK;
 | 
|  |    240 |   }
 | 
|  |    241 | }
 | 
|  |    242 | 
 | 
|  |    243 | /*
 | 
|  |    244 | ** Determine the current size of a file in bytes
 | 
|  |    245 | */
 | 
|  |    246 | int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
 | 
|  |    247 |   symbianFile *pFile = (symbianFile*)id;
 | 
|  |    248 | 
 | 
|  |    249 |   TInt size = 0;
 | 
|  |    250 |   if (pFile->file.Size(size) != KErrNone)
 | 
|  |    251 |   {
 | 
|  |    252 | 	  return SQLITE_IOERR;
 | 
|  |    253 |   }
 | 
|  |    254 | 
 | 
|  |    255 |   *pSize = size;
 | 
|  |    256 | 
 | 
|  |    257 |   return SQLITE_OK;
 | 
|  |    258 | }
 | 
|  |    259 | 
 | 
|  |    260 | 
 | 
|  |    261 | /*
 | 
|  |    262 | ** Lock the file with the lock specified by parameter locktype - one
 | 
|  |    263 | ** of the following:
 | 
|  |    264 | **
 | 
|  |    265 | **     (1) SHARED_LOCK
 | 
|  |    266 | **     (2) RESERVED_LOCK
 | 
|  |    267 | **     (3) PENDING_LOCK
 | 
|  |    268 | **     (4) EXCLUSIVE_LOCK
 | 
|  |    269 | **
 | 
|  |    270 | ** Sometimes when requesting one lock state, additional lock states
 | 
|  |    271 | ** are inserted in between.  The locking might fail on one of the later
 | 
|  |    272 | ** transitions leaving the lock state different from what it started but
 | 
|  |    273 | ** still short of its goal.  The following chart shows the allowed
 | 
|  |    274 | ** transitions and the inserted intermediate states:
 | 
|  |    275 | **
 | 
|  |    276 | **    UNLOCKED -> SHARED
 | 
|  |    277 | **    SHARED -> RESERVED
 | 
|  |    278 | **    SHARED -> (PENDING) -> EXCLUSIVE
 | 
|  |    279 | **    RESERVED -> (PENDING) -> EXCLUSIVE
 | 
|  |    280 | **    PENDING -> EXCLUSIVE
 | 
|  |    281 | **
 | 
|  |    282 | ** This routine will only increase a lock.  The winUnlock() routine
 | 
|  |    283 | ** erases all locks at once and returns us immediately to locking level 0.
 | 
|  |    284 | ** It is not possible to lower the locking level one step at a time.  You
 | 
|  |    285 | ** must go straight to locking level 0.
 | 
|  |    286 | */
 | 
|  |    287 | int winLock(sqlite3_file *id, int locktype){
 | 
|  |    288 |   int rc = SQLITE_OK;    /* Return code from subroutines */
 | 
|  |    289 |   int res = 1;           /* Result of a windows lock call */
 | 
|  |    290 |   int newLocktype;       /* Set pFile->locktype to this value before exiting */
 | 
|  |    291 |   int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
 | 
|  |    292 |   symbianFile *pFile = (symbianFile*)id;
 | 
|  |    293 | 
 | 
|  |    294 |   assert( pFile!=0 );
 | 
|  |    295 |   OSTRACE5("LOCK %d %d was %d(%d)\n",
 | 
|  |    296 |           pFile->h, locktype, pFile->locktype, pFile->sharedLockByte);
 | 
|  |    297 | 
 | 
|  |    298 |   // one smartphone only one application can control the database
 | 
|  |    299 | 
 | 
|  |    300 |   TInt size = 0;
 | 
|  |    301 |   if (pFile->file.Size(size) == KErrNone) return SQLITE_OK;
 | 
|  |    302 | 
 | 
|  |    303 |   return SQLITE_BUSY;
 | 
|  |    304 | }
 | 
|  |    305 | 
 | 
|  |    306 | /*
 | 
|  |    307 | ** This routine checks if there is a RESERVED lock held on the specified
 | 
|  |    308 | ** file by this or any other process. If such a lock is held, return
 | 
|  |    309 | ** non-zero, otherwise zero.
 | 
|  |    310 | */
 | 
|  |    311 | int winCheckReservedLock(sqlite3_file *id){
 | 
|  |    312 |   int rc;
 | 
|  |    313 |   symbianFile *pFile = (symbianFile*)id;
 | 
|  |    314 |   assert( pFile!=0 );
 | 
|  |    315 |   if( pFile->locktype>=RESERVED_LOCK ){
 | 
|  |    316 |     rc = 1;
 | 
|  |    317 |     OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
 | 
|  |    318 |   }else{
 | 
|  |    319 | 	  TInt size = 0;
 | 
|  |    320 | 	  if (pFile->file.Size(size) == KErrNone) rc = 1;
 | 
|  |    321 |     OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc);
 | 
|  |    322 |   }
 | 
|  |    323 |   return rc;
 | 
|  |    324 | }
 | 
|  |    325 | 
 | 
|  |    326 | /*
 | 
|  |    327 | ** Lower the locking level on file descriptor id to locktype.  locktype
 | 
|  |    328 | ** must be either NO_LOCK or SHARED_LOCK.
 | 
|  |    329 | **
 | 
|  |    330 | ** If the locking level of the file descriptor is already at or below
 | 
|  |    331 | ** the requested locking level, this routine is a no-op.
 | 
|  |    332 | **
 | 
|  |    333 | ** It is not possible for this routine to fail if the second argument
 | 
|  |    334 | ** is NO_LOCK.  If the second argument is SHARED_LOCK then this routine
 | 
|  |    335 | ** might return SQLITE_IOERR;
 | 
|  |    336 | */
 | 
|  |    337 | int winUnlock(sqlite3_file *id, int locktype){
 | 
|  |    338 |   int type;
 | 
|  |    339 |   symbianFile *pFile = (symbianFile*)id;
 | 
|  |    340 |   int rc = SQLITE_OK;
 | 
|  |    341 |   assert( pFile!=0 );
 | 
|  |    342 |   return rc;
 | 
|  |    343 | }
 | 
|  |    344 | 
 | 
|  |    345 | /*
 | 
|  |    346 | ** Control and query of the open file handle.
 | 
|  |    347 | */
 | 
|  |    348 | int winFileControl(sqlite3_file *id, int op, void *pArg){
 | 
|  |    349 |   switch( op ){
 | 
|  |    350 |     case SQLITE_FCNTL_LOCKSTATE: {
 | 
|  |    351 |       *(int*)pArg = ((symbianFile*)id)->locktype;
 | 
|  |    352 |       return SQLITE_OK;
 | 
|  |    353 |     }
 | 
|  |    354 |   }
 | 
|  |    355 |   return SQLITE_ERROR;
 | 
|  |    356 | }
 | 
|  |    357 | 
 | 
|  |    358 | /*
 | 
|  |    359 | ** Return the sector size in bytes of the underlying block device for
 | 
|  |    360 | ** the specified file. This is almost always 512 bytes, but may be
 | 
|  |    361 | ** larger for some devices.
 | 
|  |    362 | **
 | 
|  |    363 | ** SQLite code assumes this function cannot fail. It also assumes that
 | 
|  |    364 | ** if two files are created in the same file-system directory (i.e.
 | 
|  |    365 | ** a database and its journal file) that the sector size will be the
 | 
|  |    366 | ** same for both.
 | 
|  |    367 | */
 | 
|  |    368 | int winSectorSize(sqlite3_file *id){
 | 
|  |    369 |   return SQLITE_DEFAULT_SECTOR_SIZE;
 | 
|  |    370 | }
 | 
|  |    371 | 
 | 
|  |    372 | /*
 | 
|  |    373 | ** Return a vector of device characteristics.
 | 
|  |    374 | */
 | 
|  |    375 | int winDeviceCharacteristics(sqlite3_file *id){
 | 
|  |    376 |   return 0;
 | 
|  |    377 | }
 | 
|  |    378 | 
 | 
|  |    379 | 
 | 
|  |    380 | /***************************************************************************
 | 
|  |    381 | ** Here ends the I/O methods that form the sqlite3_io_methods object.
 | 
|  |    382 | **
 | 
|  |    383 | ** The next block of code implements the VFS methods.
 | 
|  |    384 | ****************************************************************************/
 | 
|  |    385 | 
 | 
|  |    386 | void ConvertToUnicode(RFs session, TDes16& aUnicode, const char *str)
 | 
|  |    387 | {
 | 
|  |    388 |   CCnvCharacterSetConverter *converter = CCnvCharacterSetConverter::NewL();
 | 
|  |    389 |   converter->PrepareToConvertToOrFromL(KCharacterSetIdentifierUtf8, session);
 | 
|  |    390 |   
 | 
|  |    391 |   TPtrC8 ptr((const unsigned char*)str);
 | 
|  |    392 | 
 | 
|  |    393 |   int state = CCnvCharacterSetConverter::KStateDefault;
 | 
|  |    394 |   converter->ConvertToUnicode(aUnicode, ptr, state);
 | 
|  |    395 |   delete converter;
 | 
|  |    396 | }
 | 
|  |    397 | 
 | 
|  |    398 | /*
 | 
|  |    399 | ** Open a file.
 | 
|  |    400 | */
 | 
|  |    401 | int winOpen(
 | 
|  |    402 |   sqlite3_vfs *pVfs,        /* Not used */
 | 
|  |    403 |   const char *zName,        /* Name of the file (UTF-8) */
 | 
|  |    404 |   sqlite3_file *id,         /* Write the SQLite file handle here */
 | 
|  |    405 |   int flags,                /* Open mode flags */
 | 
|  |    406 |   int *pOutFlags            /* Status return flags */
 | 
|  |    407 | ){
 | 
|  |    408 |   symbianFile *pFile = (symbianFile*)id;
 | 
|  |    409 |   TBuf16<MAX_PATH> filename;
 | 
|  |    410 | 
 | 
|  |    411 |   pFile->isOpen = 0;
 | 
|  |    412 |   memset(pFile, 0, sizeof(*pFile));
 | 
|  |    413 |   strcpy(pFile->fileName, zName);
 | 
|  |    414 |   pFile->session.Connect();
 | 
|  |    415 | 
 | 
|  |    416 |   ConvertToUnicode(pFile->session, filename, zName);
 | 
|  |    417 | 
 | 
|  |    418 |   int ret = 0;
 | 
|  |    419 |   if( flags & SQLITE_OPEN_CREATE ){
 | 
|  |    420 |     if (BaflUtils::FileExists(pFile->session, filename) == 1)
 | 
|  |    421 |     	{
 | 
|  |    422 |   	  ret = pFile->file.Open(pFile->session, filename, EFileStream | EFileWrite);
 | 
|  |    423 |     	}
 | 
|  |    424 |     else
 | 
|  |    425 |     	{
 | 
|  |    426 |     	ret = pFile->file.Create(pFile->session, filename, EFileStream | EFileWrite);
 | 
|  |    427 |     	}
 | 
|  |    428 |   }
 | 
|  |    429 |   else
 | 
|  |    430 |   if( flags & SQLITE_OPEN_READWRITE ){
 | 
|  |    431 | 	  ret = pFile->file.Open(pFile->session, filename, EFileStream | EFileWrite);
 | 
|  |    432 |   }else{
 | 
|  |    433 | 	ret = pFile->file.Open(pFile->session, filename, EFileStream | EFileRead);
 | 
|  |    434 |   }
 | 
|  |    435 | 
 | 
|  |    436 |   OpenCounter(+1);
 | 
|  |    437 | 
 | 
|  |    438 |   if (ret != KErrNone)
 | 
|  |    439 |   {
 | 
|  |    440 | 	  return SQLITE_IOERR;
 | 
|  |    441 |   }
 | 
|  |    442 | 
 | 
|  |    443 |   pFile->isOpen = 1;
 | 
|  |    444 |   return SQLITE_OK;
 | 
|  |    445 | }
 | 
|  |    446 | 
 | 
|  |    447 | /*
 | 
|  |    448 | ** Delete the named file.
 | 
|  |    449 | **
 | 
|  |    450 | ** Note that windows does not allow a file to be deleted if some other
 | 
|  |    451 | ** process has it open.  Sometimes a virus scanner or indexing program
 | 
|  |    452 | ** will open a journal file shortly after it is created in order to do
 | 
|  |    453 | ** whatever does.  While this other process is holding the
 | 
|  |    454 | ** file open, we will be unable to delete it.  To work around this
 | 
|  |    455 | ** problem, we delay 100 milliseconds and try to delete again.  Up
 | 
|  |    456 | ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
 | 
|  |    457 | ** up and returning an error.
 | 
|  |    458 | */
 | 
|  |    459 | #define MX_DELETION_ATTEMPTS 5
 | 
|  |    460 | int winDelete(
 | 
|  |    461 |   sqlite3_vfs *pVfs,          /* Not used on win32 */
 | 
|  |    462 |   const char *zFilename,      /* Name of file to delete */
 | 
|  |    463 |   int syncDir                 /* Not used on win32 */
 | 
|  |    464 | ){
 | 
|  |    465 |   SimulateIOError(return SQLITE_IOERR_DELETE);
 | 
|  |    466 |   TBuf16<MAX_PATH> filename;
 | 
|  |    467 | 
 | 
|  |    468 |   RFs session;
 | 
|  |    469 |   session.Connect();
 | 
|  |    470 |   ConvertToUnicode(session, filename, zFilename);
 | 
|  |    471 |   BaflUtils::DeleteFile(session, filename);
 | 
|  |    472 |   OSTRACE2("DELETE \"%s\"\n", zFilename);
 | 
|  |    473 |   session.Close();
 | 
|  |    474 |   return SQLITE_OK;
 | 
|  |    475 | }
 | 
|  |    476 | 
 | 
|  |    477 | /*
 | 
|  |    478 | ** Check the existance and status of a file.
 | 
|  |    479 | */
 | 
|  |    480 | int winAccess(
 | 
|  |    481 |   sqlite3_vfs *pVfs,         /* Not used on win32 */
 | 
|  |    482 |   const char *zFilename,     /* Name of file to check */
 | 
|  |    483 |   int flags                  /* Type of test to make on this file */
 | 
|  |    484 | ){
 | 
|  |    485 |   TBuf16<MAX_PATH> filename;
 | 
|  |    486 | 
 | 
|  |    487 |   RFs session;
 | 
|  |    488 |   session.Connect();
 | 
|  |    489 |   ConvertToUnicode(session, filename, zFilename);
 | 
|  |    490 |   int ret = BaflUtils::FileExists(session, filename);
 | 
|  |    491 |   session.Close();
 | 
|  |    492 | 
 | 
|  |    493 |   return ret;
 | 
|  |    494 | }
 | 
|  |    495 | 
 | 
|  |    496 | 
 | 
|  |    497 | /*
 | 
|  |    498 | ** Create a temporary file name in zBuf.  zBuf must be big enough to
 | 
|  |    499 | ** hold at pVfs->mxPathname characters.
 | 
|  |    500 | */
 | 
|  |    501 | int winGetTempname(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
 | 
|  |    502 |   static char zChars[] =
 | 
|  |    503 |     "abcdefghijklmnopqrstuvwxyz"
 | 
|  |    504 |     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 | 
|  |    505 |     "0123456789";
 | 
|  |    506 |   int i, j;
 | 
|  |    507 |   char zTempPath[MAX_PATH+1];
 | 
|  |    508 |   if( sqlite3_temp_directory ){
 | 
|  |    509 |     sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
 | 
|  |    510 |   }
 | 
|  |    511 |   else
 | 
|  |    512 |   {
 | 
|  |    513 |   }
 | 
|  |    514 |   
 | 
|  |    515 |   for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
 | 
|  |    516 |   zTempPath[i] = 0;
 | 
|  |    517 |   sqlite3_snprintf(nBuf-30, zBuf,
 | 
|  |    518 |                    "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
 | 
|  |    519 |   j = strlen(zBuf);
 | 
|  |    520 |   sqlite3Randomness(20, &zBuf[j]);
 | 
|  |    521 |   for(i=0; i<20; i++, j++){
 | 
|  |    522 |     zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
 | 
|  |    523 |   }
 | 
|  |    524 |   zBuf[j] = 0;
 | 
|  |    525 |   OSTRACE2("TEMP FILENAME: %s\n", zBuf);
 | 
|  |    526 |   return SQLITE_OK; 
 | 
|  |    527 | }
 | 
|  |    528 | 
 | 
|  |    529 | /*
 | 
|  |    530 | ** Turn a relative pathname into a full pathname.  Write the full
 | 
|  |    531 | ** pathname into zOut[].  zOut[] will be at least pVfs->mxPathname
 | 
|  |    532 | ** bytes in size.
 | 
|  |    533 | */
 | 
|  |    534 | int winFullPathname(
 | 
|  |    535 |   sqlite3_vfs *pVfs,            /* Pointer to vfs object */
 | 
|  |    536 |   const char *zRelative,        /* Possibly relative input path */
 | 
|  |    537 |   int nFull,                    /* Size of output buffer in bytes */
 | 
|  |    538 |   char *zFull                   /* Output buffer */
 | 
|  |    539 | ){
 | 
|  |    540 | 
 | 
|  |    541 |   /* WinCE has no concept of a relative pathname, or so I am told. */
 | 
|  |    542 |   sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative);
 | 
|  |    543 |   return SQLITE_OK;
 | 
|  |    544 | }
 | 
|  |    545 | 
 | 
|  |    546 |   #define winDlOpen  0
 | 
|  |    547 |   #define winDlError 0
 | 
|  |    548 |   #define winDlSym   0
 | 
|  |    549 |   #define winDlClose 0
 | 
|  |    550 | 
 | 
|  |    551 | 
 | 
|  |    552 | /*
 | 
|  |    553 | ** Write up to nBuf bytes of randomness into zBuf.
 | 
|  |    554 | */
 | 
|  |    555 | int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
 | 
|  |    556 | 
 | 
|  |    557 | 	int i;
 | 
|  |    558 | 	for (i=0; i<nBuf; ++i)
 | 
|  |    559 | 	{
 | 
|  |    560 | 		zBuf[i] = rand() % 255;
 | 
|  |    561 | 	}
 | 
|  |    562 | 	return nBuf;
 | 
|  |    563 | }
 | 
|  |    564 | 
 | 
|  |    565 | 
 | 
|  |    566 | /*
 | 
|  |    567 | ** Sleep for a little while.  Return the amount of time slept.
 | 
|  |    568 | */
 | 
|  |    569 | int winSleep(sqlite3_vfs *pVfs, int microsec){
 | 
|  |    570 | 	return sleep(microsec / 1000);
 | 
|  |    571 | }
 | 
|  |    572 | 
 | 
|  |    573 | /*
 | 
|  |    574 | ** The following variable, if set to a non-zero value, becomes the result
 | 
|  |    575 | ** returned from sqlite3OsCurrentTime().  This is used for testing.
 | 
|  |    576 | */
 | 
|  |    577 | #ifdef SQLITE_TEST
 | 
|  |    578 | int sqlite3_current_time = 0;
 | 
|  |    579 | #endif
 | 
|  |    580 | 
 | 
|  |    581 | /*
 | 
|  |    582 | ** Find the current time (in Universal Coordinated Time).  Write the
 | 
|  |    583 | ** current time and date as a Julian Day number into *prNow and
 | 
|  |    584 | ** return 0.  Return 1 if the time and date cannot be found.
 | 
|  |    585 | */
 | 
|  |    586 | int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
 | 
|  |    587 |   double now;
 | 
|  |    588 | 
 | 
|  |    589 |   now = time(NULL);
 | 
|  |    590 |   *prNow = now;
 | 
|  |    591 | 
 | 
|  |    592 |   return 0;
 | 
|  |    593 | }
 | 
|  |    594 | 
 | 
|  |    595 | 
 | 
|  |    596 | /*
 | 
|  |    597 | ** Return a pointer to the sqlite3DefaultVfs structure.   We use
 | 
|  |    598 | ** a function rather than give the structure global scope because
 | 
|  |    599 | ** some compilers (MSVC) do not allow forward declarations of
 | 
|  |    600 | ** initialized structures.
 | 
|  |    601 | */
 | 
|  |    602 | sqlite3_vfs *sqlite3OsDefaultVfs(void){
 | 
|  |    603 |   static sqlite3_vfs winVfs = {
 | 
|  |    604 |     1,                 /* iVersion */
 | 
|  |    605 |     -1,   /* szOsFile */
 | 
|  |    606 |     MAX_PATH,          /* mxPathname */
 | 
|  |    607 |     0,                 /* pNext */
 | 
|  |    608 |     "symbian",           /* zName */
 | 
|  |    609 |     0,                 /* pAppData */
 | 
|  |    610 |     };
 | 
|  |    611 |   
 | 
|  |    612 |   winVfs.szOsFile = sizeof(symbianFile);
 | 
|  |    613 |   return &winVfs;
 | 
|  |    614 | }
 | 
|  |    615 | 
 | 
|  |    616 | #endif /* OS_SYMBIAN */
 |