Home | History | Annotate | Download | only in src
      1 /*
      2 ** 2006 Feb 14
      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 OS/2.
     14 */
     15 
     16 #include "sqliteInt.h"
     17 
     18 #if SQLITE_OS_OS2
     19 
     20 /*
     21 ** A Note About Memory Allocation:
     22 **
     23 ** This driver uses malloc()/free() directly rather than going through
     24 ** the SQLite-wrappers sqlite3_malloc()/sqlite3_free().  Those wrappers
     25 ** are designed for use on embedded systems where memory is scarce and
     26 ** malloc failures happen frequently.  OS/2 does not typically run on
     27 ** embedded systems, and when it does the developers normally have bigger
     28 ** problems to worry about than running out of memory.  So there is not
     29 ** a compelling need to use the wrappers.
     30 **
     31 ** But there is a good reason to not use the wrappers.  If we use the
     32 ** wrappers then we will get simulated malloc() failures within this
     33 ** driver.  And that causes all kinds of problems for our tests.  We
     34 ** could enhance SQLite to deal with simulated malloc failures within
     35 ** the OS driver, but the code to deal with those failure would not
     36 ** be exercised on Linux (which does not need to malloc() in the driver)
     37 ** and so we would have difficulty writing coverage tests for that
     38 ** code.  Better to leave the code out, we think.
     39 **
     40 ** The point of this discussion is as follows:  When creating a new
     41 ** OS layer for an embedded system, if you use this file as an example,
     42 ** avoid the use of malloc()/free().  Those routines work ok on OS/2
     43 ** desktops but not so well in embedded systems.
     44 */
     45 
     46 /*
     47 ** Macros used to determine whether or not to use threads.
     48 */
     49 #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE
     50 # define SQLITE_OS2_THREADS 1
     51 #endif
     52 
     53 /*
     54 ** Include code that is common to all os_*.c files
     55 */
     56 #include "os_common.h"
     57 
     58 /* Forward references */
     59 typedef struct os2File os2File;         /* The file structure */
     60 typedef struct os2ShmNode os2ShmNode;   /* A shared descritive memory node */
     61 typedef struct os2ShmLink os2ShmLink;   /* A connection to shared-memory */
     62 
     63 /*
     64 ** The os2File structure is subclass of sqlite3_file specific for the OS/2
     65 ** protability layer.
     66 */
     67 struct os2File {
     68   const sqlite3_io_methods *pMethod;  /* Always the first entry */
     69   HFILE h;                  /* Handle for accessing the file */
     70   int flags;                /* Flags provided to os2Open() */
     71   int locktype;             /* Type of lock currently held on this file */
     72   int szChunk;              /* Chunk size configured by FCNTL_CHUNK_SIZE */
     73   char *zFullPathCp;        /* Full path name of this file */
     74   os2ShmLink *pShmLink;     /* Instance of shared memory on this file */
     75 };
     76 
     77 #define LOCK_TIMEOUT 10L /* the default locking timeout */
     78 
     79 /*
     80 ** Missing from some versions of the OS/2 toolkit -
     81 ** used to allocate from high memory if possible
     82 */
     83 #ifndef OBJ_ANY
     84 # define OBJ_ANY 0x00000400
     85 #endif
     86 
     87 /*****************************************************************************
     88 ** The next group of routines implement the I/O methods specified
     89 ** by the sqlite3_io_methods object.
     90 ******************************************************************************/
     91 
     92 /*
     93 ** Close a file.
     94 */
     95 static int os2Close( sqlite3_file *id ){
     96   APIRET rc;
     97   os2File *pFile = (os2File*)id;
     98 
     99   assert( id!=0 );
    100   OSTRACE(( "CLOSE %d (%s)\n", pFile->h, pFile->zFullPathCp ));
    101 
    102   rc = DosClose( pFile->h );
    103 
    104   if( pFile->flags & SQLITE_OPEN_DELETEONCLOSE )
    105     DosForceDelete( (PSZ)pFile->zFullPathCp );
    106 
    107   free( pFile->zFullPathCp );
    108   pFile->zFullPathCp = NULL;
    109   pFile->locktype = NO_LOCK;
    110   pFile->h = (HFILE)-1;
    111   pFile->flags = 0;
    112 
    113   OpenCounter( -1 );
    114   return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
    115 }
    116 
    117 /*
    118 ** Read data from a file into a buffer.  Return SQLITE_OK if all
    119 ** bytes were read successfully and SQLITE_IOERR if anything goes
    120 ** wrong.
    121 */
    122 static int os2Read(
    123   sqlite3_file *id,               /* File to read from */
    124   void *pBuf,                     /* Write content into this buffer */
    125   int amt,                        /* Number of bytes to read */
    126   sqlite3_int64 offset            /* Begin reading at this offset */
    127 ){
    128   ULONG fileLocation = 0L;
    129   ULONG got;
    130   os2File *pFile = (os2File*)id;
    131   assert( id!=0 );
    132   SimulateIOError( return SQLITE_IOERR_READ );
    133   OSTRACE(( "READ %d lock=%d\n", pFile->h, pFile->locktype ));
    134   if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){
    135     return SQLITE_IOERR;
    136   }
    137   if( DosRead( pFile->h, pBuf, amt, &got ) != NO_ERROR ){
    138     return SQLITE_IOERR_READ;
    139   }
    140   if( got == (ULONG)amt )
    141     return SQLITE_OK;
    142   else {
    143     /* Unread portions of the input buffer must be zero-filled */
    144     memset(&((char*)pBuf)[got], 0, amt-got);
    145     return SQLITE_IOERR_SHORT_READ;
    146   }
    147 }
    148 
    149 /*
    150 ** Write data from a buffer into a file.  Return SQLITE_OK on success
    151 ** or some other error code on failure.
    152 */
    153 static int os2Write(
    154   sqlite3_file *id,               /* File to write into */
    155   const void *pBuf,               /* The bytes to be written */
    156   int amt,                        /* Number of bytes to write */
    157   sqlite3_int64 offset            /* Offset into the file to begin writing at */
    158 ){
    159   ULONG fileLocation = 0L;
    160   APIRET rc = NO_ERROR;
    161   ULONG wrote;
    162   os2File *pFile = (os2File*)id;
    163   assert( id!=0 );
    164   SimulateIOError( return SQLITE_IOERR_WRITE );
    165   SimulateDiskfullError( return SQLITE_FULL );
    166   OSTRACE(( "WRITE %d lock=%d\n", pFile->h, pFile->locktype ));
    167   if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){
    168     return SQLITE_IOERR;
    169   }
    170   assert( amt>0 );
    171   while( amt > 0 &&
    172          ( rc = DosWrite( pFile->h, (PVOID)pBuf, amt, &wrote ) ) == NO_ERROR &&
    173          wrote > 0
    174   ){
    175     amt -= wrote;
    176     pBuf = &((char*)pBuf)[wrote];
    177   }
    178 
    179   return ( rc != NO_ERROR || amt > (int)wrote ) ? SQLITE_FULL : SQLITE_OK;
    180 }
    181 
    182 /*
    183 ** Truncate an open file to a specified size
    184 */
    185 static int os2Truncate( sqlite3_file *id, i64 nByte ){
    186   APIRET rc;
    187   os2File *pFile = (os2File*)id;
    188   assert( id!=0 );
    189   OSTRACE(( "TRUNCATE %d %lld\n", pFile->h, nByte ));
    190   SimulateIOError( return SQLITE_IOERR_TRUNCATE );
    191 
    192   /* If the user has configured a chunk-size for this file, truncate the
    193   ** file so that it consists of an integer number of chunks (i.e. the
    194   ** actual file size after the operation may be larger than the requested
    195   ** size).
    196   */
    197   if( pFile->szChunk ){
    198     nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
    199   }
    200 
    201   rc = DosSetFileSize( pFile->h, nByte );
    202   return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
    203 }
    204 
    205 #ifdef SQLITE_TEST
    206 /*
    207 ** Count the number of fullsyncs and normal syncs.  This is used to test
    208 ** that syncs and fullsyncs are occuring at the right times.
    209 */
    210 int sqlite3_sync_count = 0;
    211 int sqlite3_fullsync_count = 0;
    212 #endif
    213 
    214 /*
    215 ** Make sure all writes to a particular file are committed to disk.
    216 */
    217 static int os2Sync( sqlite3_file *id, int flags ){
    218   os2File *pFile = (os2File*)id;
    219   OSTRACE(( "SYNC %d lock=%d\n", pFile->h, pFile->locktype ));
    220 #ifdef SQLITE_TEST
    221   if( flags & SQLITE_SYNC_FULL){
    222     sqlite3_fullsync_count++;
    223   }
    224   sqlite3_sync_count++;
    225 #endif
    226   /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
    227   ** no-op
    228   */
    229 #ifdef SQLITE_NO_SYNC
    230   UNUSED_PARAMETER(pFile);
    231   return SQLITE_OK;
    232 #else
    233   return DosResetBuffer( pFile->h ) == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
    234 #endif
    235 }
    236 
    237 /*
    238 ** Determine the current size of a file in bytes
    239 */
    240 static int os2FileSize( sqlite3_file *id, sqlite3_int64 *pSize ){
    241   APIRET rc = NO_ERROR;
    242   FILESTATUS3 fsts3FileInfo;
    243   memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo));
    244   assert( id!=0 );
    245   SimulateIOError( return SQLITE_IOERR_FSTAT );
    246   rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) );
    247   if( rc == NO_ERROR ){
    248     *pSize = fsts3FileInfo.cbFile;
    249     return SQLITE_OK;
    250   }else{
    251     return SQLITE_IOERR_FSTAT;
    252   }
    253 }
    254 
    255 /*
    256 ** Acquire a reader lock.
    257 */
    258 static int getReadLock( os2File *pFile ){
    259   FILELOCK  LockArea,
    260             UnlockArea;
    261   APIRET res;
    262   memset(&LockArea, 0, sizeof(LockArea));
    263   memset(&UnlockArea, 0, sizeof(UnlockArea));
    264   LockArea.lOffset = SHARED_FIRST;
    265   LockArea.lRange = SHARED_SIZE;
    266   UnlockArea.lOffset = 0L;
    267   UnlockArea.lRange = 0L;
    268   res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
    269   OSTRACE(( "GETREADLOCK %d res=%d\n", pFile->h, res ));
    270   return res;
    271 }
    272 
    273 /*
    274 ** Undo a readlock
    275 */
    276 static int unlockReadLock( os2File *id ){
    277   FILELOCK  LockArea,
    278             UnlockArea;
    279   APIRET res;
    280   memset(&LockArea, 0, sizeof(LockArea));
    281   memset(&UnlockArea, 0, sizeof(UnlockArea));
    282   LockArea.lOffset = 0L;
    283   LockArea.lRange = 0L;
    284   UnlockArea.lOffset = SHARED_FIRST;
    285   UnlockArea.lRange = SHARED_SIZE;
    286   res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
    287   OSTRACE(( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res ));
    288   return res;
    289 }
    290 
    291 /*
    292 ** Lock the file with the lock specified by parameter locktype - one
    293 ** of the following:
    294 **
    295 **     (1) SHARED_LOCK
    296 **     (2) RESERVED_LOCK
    297 **     (3) PENDING_LOCK
    298 **     (4) EXCLUSIVE_LOCK
    299 **
    300 ** Sometimes when requesting one lock state, additional lock states
    301 ** are inserted in between.  The locking might fail on one of the later
    302 ** transitions leaving the lock state different from what it started but
    303 ** still short of its goal.  The following chart shows the allowed
    304 ** transitions and the inserted intermediate states:
    305 **
    306 **    UNLOCKED -> SHARED
    307 **    SHARED -> RESERVED
    308 **    SHARED -> (PENDING) -> EXCLUSIVE
    309 **    RESERVED -> (PENDING) -> EXCLUSIVE
    310 **    PENDING -> EXCLUSIVE
    311 **
    312 ** This routine will only increase a lock.  The os2Unlock() routine
    313 ** erases all locks at once and returns us immediately to locking level 0.
    314 ** It is not possible to lower the locking level one step at a time.  You
    315 ** must go straight to locking level 0.
    316 */
    317 static int os2Lock( sqlite3_file *id, int locktype ){
    318   int rc = SQLITE_OK;       /* Return code from subroutines */
    319   APIRET res = NO_ERROR;    /* Result of an OS/2 lock call */
    320   int newLocktype;       /* Set pFile->locktype to this value before exiting */
    321   int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
    322   FILELOCK  LockArea,
    323             UnlockArea;
    324   os2File *pFile = (os2File*)id;
    325   memset(&LockArea, 0, sizeof(LockArea));
    326   memset(&UnlockArea, 0, sizeof(UnlockArea));
    327   assert( pFile!=0 );
    328   OSTRACE(( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype ));
    329 
    330   /* If there is already a lock of this type or more restrictive on the
    331   ** os2File, do nothing. Don't use the end_lock: exit path, as
    332   ** sqlite3_mutex_enter() hasn't been called yet.
    333   */
    334   if( pFile->locktype>=locktype ){
    335     OSTRACE(( "LOCK %d %d ok (already held)\n", pFile->h, locktype ));
    336     return SQLITE_OK;
    337   }
    338 
    339   /* Make sure the locking sequence is correct
    340   */
    341   assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
    342   assert( locktype!=PENDING_LOCK );
    343   assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
    344 
    345   /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
    346   ** a SHARED lock.  If we are acquiring a SHARED lock, the acquisition of
    347   ** the PENDING_LOCK byte is temporary.
    348   */
    349   newLocktype = pFile->locktype;
    350   if( pFile->locktype==NO_LOCK
    351       || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
    352   ){
    353     LockArea.lOffset = PENDING_BYTE;
    354     LockArea.lRange = 1L;
    355     UnlockArea.lOffset = 0L;
    356     UnlockArea.lRange = 0L;
    357 
    358     /* wait longer than LOCK_TIMEOUT here not to have to try multiple times */
    359     res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 100L, 0L );
    360     if( res == NO_ERROR ){
    361       gotPendingLock = 1;
    362       OSTRACE(( "LOCK %d pending lock boolean set.  res=%d\n", pFile->h, res ));
    363     }
    364   }
    365 
    366   /* Acquire a shared lock
    367   */
    368   if( locktype==SHARED_LOCK && res == NO_ERROR ){
    369     assert( pFile->locktype==NO_LOCK );
    370     res = getReadLock(pFile);
    371     if( res == NO_ERROR ){
    372       newLocktype = SHARED_LOCK;
    373     }
    374     OSTRACE(( "LOCK %d acquire shared lock. res=%d\n", pFile->h, res ));
    375   }
    376 
    377   /* Acquire a RESERVED lock
    378   */
    379   if( locktype==RESERVED_LOCK && res == NO_ERROR ){
    380     assert( pFile->locktype==SHARED_LOCK );
    381     LockArea.lOffset = RESERVED_BYTE;
    382     LockArea.lRange = 1L;
    383     UnlockArea.lOffset = 0L;
    384     UnlockArea.lRange = 0L;
    385     res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    386     if( res == NO_ERROR ){
    387       newLocktype = RESERVED_LOCK;
    388     }
    389     OSTRACE(( "LOCK %d acquire reserved lock. res=%d\n", pFile->h, res ));
    390   }
    391 
    392   /* Acquire a PENDING lock
    393   */
    394   if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){
    395     newLocktype = PENDING_LOCK;
    396     gotPendingLock = 0;
    397     OSTRACE(( "LOCK %d acquire pending lock. pending lock boolean unset.\n",
    398                pFile->h ));
    399   }
    400 
    401   /* Acquire an EXCLUSIVE lock
    402   */
    403   if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){
    404     assert( pFile->locktype>=SHARED_LOCK );
    405     res = unlockReadLock(pFile);
    406     OSTRACE(( "unreadlock = %d\n", res ));
    407     LockArea.lOffset = SHARED_FIRST;
    408     LockArea.lRange = SHARED_SIZE;
    409     UnlockArea.lOffset = 0L;
    410     UnlockArea.lRange = 0L;
    411     res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    412     if( res == NO_ERROR ){
    413       newLocktype = EXCLUSIVE_LOCK;
    414     }else{
    415       OSTRACE(( "OS/2 error-code = %d\n", res ));
    416       getReadLock(pFile);
    417     }
    418     OSTRACE(( "LOCK %d acquire exclusive lock.  res=%d\n", pFile->h, res ));
    419   }
    420 
    421   /* If we are holding a PENDING lock that ought to be released, then
    422   ** release it now.
    423   */
    424   if( gotPendingLock && locktype==SHARED_LOCK ){
    425     int r;
    426     LockArea.lOffset = 0L;
    427     LockArea.lRange = 0L;
    428     UnlockArea.lOffset = PENDING_BYTE;
    429     UnlockArea.lRange = 1L;
    430     r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    431     OSTRACE(( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r ));
    432   }
    433 
    434   /* Update the state of the lock has held in the file descriptor then
    435   ** return the appropriate result code.
    436   */
    437   if( res == NO_ERROR ){
    438     rc = SQLITE_OK;
    439   }else{
    440     OSTRACE(( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
    441               locktype, newLocktype ));
    442     rc = SQLITE_BUSY;
    443   }
    444   pFile->locktype = newLocktype;
    445   OSTRACE(( "LOCK %d now %d\n", pFile->h, pFile->locktype ));
    446   return rc;
    447 }
    448 
    449 /*
    450 ** This routine checks if there is a RESERVED lock held on the specified
    451 ** file by this or any other process. If such a lock is held, return
    452 ** non-zero, otherwise zero.
    453 */
    454 static int os2CheckReservedLock( sqlite3_file *id, int *pOut ){
    455   int r = 0;
    456   os2File *pFile = (os2File*)id;
    457   assert( pFile!=0 );
    458   if( pFile->locktype>=RESERVED_LOCK ){
    459     r = 1;
    460     OSTRACE(( "TEST WR-LOCK %d %d (local)\n", pFile->h, r ));
    461   }else{
    462     FILELOCK  LockArea,
    463               UnlockArea;
    464     APIRET rc = NO_ERROR;
    465     memset(&LockArea, 0, sizeof(LockArea));
    466     memset(&UnlockArea, 0, sizeof(UnlockArea));
    467     LockArea.lOffset = RESERVED_BYTE;
    468     LockArea.lRange = 1L;
    469     UnlockArea.lOffset = 0L;
    470     UnlockArea.lRange = 0L;
    471     rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    472     OSTRACE(( "TEST WR-LOCK %d lock reserved byte rc=%d\n", pFile->h, rc ));
    473     if( rc == NO_ERROR ){
    474       APIRET rcu = NO_ERROR; /* return code for unlocking */
    475       LockArea.lOffset = 0L;
    476       LockArea.lRange = 0L;
    477       UnlockArea.lOffset = RESERVED_BYTE;
    478       UnlockArea.lRange = 1L;
    479       rcu = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    480       OSTRACE(( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, rcu ));
    481     }
    482     r = !(rc == NO_ERROR);
    483     OSTRACE(( "TEST WR-LOCK %d %d (remote)\n", pFile->h, r ));
    484   }
    485   *pOut = r;
    486   return SQLITE_OK;
    487 }
    488 
    489 /*
    490 ** Lower the locking level on file descriptor id to locktype.  locktype
    491 ** must be either NO_LOCK or SHARED_LOCK.
    492 **
    493 ** If the locking level of the file descriptor is already at or below
    494 ** the requested locking level, this routine is a no-op.
    495 **
    496 ** It is not possible for this routine to fail if the second argument
    497 ** is NO_LOCK.  If the second argument is SHARED_LOCK then this routine
    498 ** might return SQLITE_IOERR;
    499 */
    500 static int os2Unlock( sqlite3_file *id, int locktype ){
    501   int type;
    502   os2File *pFile = (os2File*)id;
    503   APIRET rc = SQLITE_OK;
    504   APIRET res = NO_ERROR;
    505   FILELOCK  LockArea,
    506             UnlockArea;
    507   memset(&LockArea, 0, sizeof(LockArea));
    508   memset(&UnlockArea, 0, sizeof(UnlockArea));
    509   assert( pFile!=0 );
    510   assert( locktype<=SHARED_LOCK );
    511   OSTRACE(( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype ));
    512   type = pFile->locktype;
    513   if( type>=EXCLUSIVE_LOCK ){
    514     LockArea.lOffset = 0L;
    515     LockArea.lRange = 0L;
    516     UnlockArea.lOffset = SHARED_FIRST;
    517     UnlockArea.lRange = SHARED_SIZE;
    518     res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    519     OSTRACE(( "UNLOCK %d exclusive lock res=%d\n", pFile->h, res ));
    520     if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){
    521       /* This should never happen.  We should always be able to
    522       ** reacquire the read lock */
    523       OSTRACE(( "UNLOCK %d to %d getReadLock() failed\n", pFile->h, locktype ));
    524       rc = SQLITE_IOERR_UNLOCK;
    525     }
    526   }
    527   if( type>=RESERVED_LOCK ){
    528     LockArea.lOffset = 0L;
    529     LockArea.lRange = 0L;
    530     UnlockArea.lOffset = RESERVED_BYTE;
    531     UnlockArea.lRange = 1L;
    532     res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    533     OSTRACE(( "UNLOCK %d reserved res=%d\n", pFile->h, res ));
    534   }
    535   if( locktype==NO_LOCK && type>=SHARED_LOCK ){
    536     res = unlockReadLock(pFile);
    537     OSTRACE(( "UNLOCK %d is %d want %d res=%d\n",
    538               pFile->h, type, locktype, res ));
    539   }
    540   if( type>=PENDING_LOCK ){
    541     LockArea.lOffset = 0L;
    542     LockArea.lRange = 0L;
    543     UnlockArea.lOffset = PENDING_BYTE;
    544     UnlockArea.lRange = 1L;
    545     res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    546     OSTRACE(( "UNLOCK %d pending res=%d\n", pFile->h, res ));
    547   }
    548   pFile->locktype = locktype;
    549   OSTRACE(( "UNLOCK %d now %d\n", pFile->h, pFile->locktype ));
    550   return rc;
    551 }
    552 
    553 /*
    554 ** Control and query of the open file handle.
    555 */
    556 static int os2FileControl(sqlite3_file *id, int op, void *pArg){
    557   switch( op ){
    558     case SQLITE_FCNTL_LOCKSTATE: {
    559       *(int*)pArg = ((os2File*)id)->locktype;
    560       OSTRACE(( "FCNTL_LOCKSTATE %d lock=%d\n",
    561                 ((os2File*)id)->h, ((os2File*)id)->locktype ));
    562       return SQLITE_OK;
    563     }
    564     case SQLITE_FCNTL_CHUNK_SIZE: {
    565       ((os2File*)id)->szChunk = *(int*)pArg;
    566       return SQLITE_OK;
    567     }
    568     case SQLITE_FCNTL_SIZE_HINT: {
    569       sqlite3_int64 sz = *(sqlite3_int64*)pArg;
    570       SimulateIOErrorBenign(1);
    571       os2Truncate(id, sz);
    572       SimulateIOErrorBenign(0);
    573       return SQLITE_OK;
    574     }
    575     case SQLITE_FCNTL_SYNC_OMITTED: {
    576       return SQLITE_OK;
    577     }
    578   }
    579   return SQLITE_NOTFOUND;
    580 }
    581 
    582 /*
    583 ** Return the sector size in bytes of the underlying block device for
    584 ** the specified file. This is almost always 512 bytes, but may be
    585 ** larger for some devices.
    586 **
    587 ** SQLite code assumes this function cannot fail. It also assumes that
    588 ** if two files are created in the same file-system directory (i.e.
    589 ** a database and its journal file) that the sector size will be the
    590 ** same for both.
    591 */
    592 static int os2SectorSize(sqlite3_file *id){
    593   UNUSED_PARAMETER(id);
    594   return SQLITE_DEFAULT_SECTOR_SIZE;
    595 }
    596 
    597 /*
    598 ** Return a vector of device characteristics.
    599 */
    600 static int os2DeviceCharacteristics(sqlite3_file *id){
    601   UNUSED_PARAMETER(id);
    602   return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
    603 }
    604 
    605 
    606 /*
    607 ** Character set conversion objects used by conversion routines.
    608 */
    609 static UconvObject ucUtf8 = NULL; /* convert between UTF-8 and UCS-2 */
    610 static UconvObject uclCp = NULL;  /* convert between local codepage and UCS-2 */
    611 
    612 /*
    613 ** Helper function to initialize the conversion objects from and to UTF-8.
    614 */
    615 static void initUconvObjects( void ){
    616   if( UniCreateUconvObject( UTF_8, &ucUtf8 ) != ULS_SUCCESS )
    617     ucUtf8 = NULL;
    618   if ( UniCreateUconvObject( (UniChar *)L"@path=yes", &uclCp ) != ULS_SUCCESS )
    619     uclCp = NULL;
    620 }
    621 
    622 /*
    623 ** Helper function to free the conversion objects from and to UTF-8.
    624 */
    625 static void freeUconvObjects( void ){
    626   if ( ucUtf8 )
    627     UniFreeUconvObject( ucUtf8 );
    628   if ( uclCp )
    629     UniFreeUconvObject( uclCp );
    630   ucUtf8 = NULL;
    631   uclCp = NULL;
    632 }
    633 
    634 /*
    635 ** Helper function to convert UTF-8 filenames to local OS/2 codepage.
    636 ** The two-step process: first convert the incoming UTF-8 string
    637 ** into UCS-2 and then from UCS-2 to the current codepage.
    638 ** The returned char pointer has to be freed.
    639 */
    640 static char *convertUtf8PathToCp( const char *in ){
    641   UniChar tempPath[CCHMAXPATH];
    642   char *out = (char *)calloc( CCHMAXPATH, 1 );
    643 
    644   if( !out )
    645     return NULL;
    646 
    647   if( !ucUtf8 || !uclCp )
    648     initUconvObjects();
    649 
    650   /* determine string for the conversion of UTF-8 which is CP1208 */
    651   if( UniStrToUcs( ucUtf8, tempPath, (char *)in, CCHMAXPATH ) != ULS_SUCCESS )
    652     return out; /* if conversion fails, return the empty string */
    653 
    654   /* conversion for current codepage which can be used for paths */
    655   UniStrFromUcs( uclCp, out, tempPath, CCHMAXPATH );
    656 
    657   return out;
    658 }
    659 
    660 /*
    661 ** Helper function to convert filenames from local codepage to UTF-8.
    662 ** The two-step process: first convert the incoming codepage-specific
    663 ** string into UCS-2 and then from UCS-2 to the codepage of UTF-8.
    664 ** The returned char pointer has to be freed.
    665 **
    666 ** This function is non-static to be able to use this in shell.c and
    667 ** similar applications that take command line arguments.
    668 */
    669 char *convertCpPathToUtf8( const char *in ){
    670   UniChar tempPath[CCHMAXPATH];
    671   char *out = (char *)calloc( CCHMAXPATH, 1 );
    672 
    673   if( !out )
    674     return NULL;
    675 
    676   if( !ucUtf8 || !uclCp )
    677     initUconvObjects();
    678 
    679   /* conversion for current codepage which can be used for paths */
    680   if( UniStrToUcs( uclCp, tempPath, (char *)in, CCHMAXPATH ) != ULS_SUCCESS )
    681     return out; /* if conversion fails, return the empty string */
    682 
    683   /* determine string for the conversion of UTF-8 which is CP1208 */
    684   UniStrFromUcs( ucUtf8, out, tempPath, CCHMAXPATH );
    685 
    686   return out;
    687 }
    688 
    689 
    690 #ifndef SQLITE_OMIT_WAL
    691 
    692 /*
    693 ** Use main database file for interprocess locking. If un-defined
    694 ** a separate file is created for this purpose. The file will be
    695 ** used only to set file locks. There will be no data written to it.
    696 */
    697 #define SQLITE_OS2_NO_WAL_LOCK_FILE
    698 
    699 #if 0
    700 static void _ERR_TRACE( const char *fmt, ... ) {
    701   va_list  ap;
    702   va_start(ap, fmt);
    703   vfprintf(stderr, fmt, ap);
    704   fflush(stderr);
    705 }
    706 #define ERR_TRACE(rc, msg)        \
    707         if( (rc) != SQLITE_OK ) _ERR_TRACE msg;
    708 #else
    709 #define ERR_TRACE(rc, msg)
    710 #endif
    711 
    712 /*
    713 ** Helper functions to obtain and relinquish the global mutex. The
    714 ** global mutex is used to protect os2ShmNodeList.
    715 **
    716 ** Function os2ShmMutexHeld() is used to assert() that the global mutex
    717 ** is held when required. This function is only used as part of assert()
    718 ** statements. e.g.
    719 **
    720 **   os2ShmEnterMutex()
    721 **     assert( os2ShmMutexHeld() );
    722 **   os2ShmLeaveMutex()
    723 */
    724 static void os2ShmEnterMutex(void){
    725   sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
    726 }
    727 static void os2ShmLeaveMutex(void){
    728   sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
    729 }
    730 #ifdef SQLITE_DEBUG
    731 static int os2ShmMutexHeld(void) {
    732   return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
    733 }
    734 int GetCurrentProcessId(void) {
    735   PPIB pib;
    736   DosGetInfoBlocks(NULL, &pib);
    737   return (int)pib->pib_ulpid;
    738 }
    739 #endif
    740 
    741 /*
    742 ** Object used to represent a the shared memory area for a single log file.
    743 ** When multiple threads all reference the same log-summary, each thread has
    744 ** its own os2File object, but they all point to a single instance of this
    745 ** object.  In other words, each log-summary is opened only once per process.
    746 **
    747 ** os2ShmMutexHeld() must be true when creating or destroying
    748 ** this object or while reading or writing the following fields:
    749 **
    750 **      nRef
    751 **      pNext
    752 **
    753 ** The following fields are read-only after the object is created:
    754 **
    755 **      szRegion
    756 **      hLockFile
    757 **      shmBaseName
    758 **
    759 ** Either os2ShmNode.mutex must be held or os2ShmNode.nRef==0 and
    760 ** os2ShmMutexHeld() is true when reading or writing any other field
    761 ** in this structure.
    762 **
    763 */
    764 struct os2ShmNode {
    765   sqlite3_mutex *mutex;      /* Mutex to access this object */
    766   os2ShmNode *pNext;         /* Next in list of all os2ShmNode objects */
    767 
    768   int szRegion;              /* Size of shared-memory regions */
    769 
    770   int nRegion;               /* Size of array apRegion */
    771   void **apRegion;           /* Array of pointers to shared-memory regions */
    772 
    773   int nRef;                  /* Number of os2ShmLink objects pointing to this */
    774   os2ShmLink *pFirst;        /* First os2ShmLink object pointing to this */
    775 
    776   HFILE hLockFile;           /* File used for inter-process memory locking */
    777   char shmBaseName[1];       /* Name of the memory object !!! must last !!! */
    778 };
    779 
    780 
    781 /*
    782 ** Structure used internally by this VFS to record the state of an
    783 ** open shared memory connection.
    784 **
    785 ** The following fields are initialized when this object is created and
    786 ** are read-only thereafter:
    787 **
    788 **    os2Shm.pShmNode
    789 **    os2Shm.id
    790 **
    791 ** All other fields are read/write.  The os2Shm.pShmNode->mutex must be held
    792 ** while accessing any read/write fields.
    793 */
    794 struct os2ShmLink {
    795   os2ShmNode *pShmNode;      /* The underlying os2ShmNode object */
    796   os2ShmLink *pNext;         /* Next os2Shm with the same os2ShmNode */
    797   u32 sharedMask;            /* Mask of shared locks held */
    798   u32 exclMask;              /* Mask of exclusive locks held */
    799 #ifdef SQLITE_DEBUG
    800   u8 id;                     /* Id of this connection with its os2ShmNode */
    801 #endif
    802 };
    803 
    804 
    805 /*
    806 ** A global list of all os2ShmNode objects.
    807 **
    808 ** The os2ShmMutexHeld() must be true while reading or writing this list.
    809 */
    810 static os2ShmNode *os2ShmNodeList = NULL;
    811 
    812 /*
    813 ** Constants used for locking
    814 */
    815 #ifdef  SQLITE_OS2_NO_WAL_LOCK_FILE
    816 #define OS2_SHM_BASE   (PENDING_BYTE + 0x10000)         /* first lock byte */
    817 #else
    818 #define OS2_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)        /* first lock byte */
    819 #endif
    820 
    821 #define OS2_SHM_DMS    (OS2_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
    822 
    823 /*
    824 ** Apply advisory locks for all n bytes beginning at ofst.
    825 */
    826 #define _SHM_UNLCK  1   /* no lock */
    827 #define _SHM_RDLCK  2   /* shared lock, no wait */
    828 #define _SHM_WRLCK  3   /* exlusive lock, no wait */
    829 #define _SHM_WRLCK_WAIT 4 /* exclusive lock, wait */
    830 static int os2ShmSystemLock(
    831   os2ShmNode *pNode,    /* Apply locks to this open shared-memory segment */
    832   int lockType,         /* _SHM_UNLCK, _SHM_RDLCK, _SHM_WRLCK or _SHM_WRLCK_WAIT */
    833   int ofst,             /* Offset to first byte to be locked/unlocked */
    834   int nByte             /* Number of bytes to lock or unlock */
    835 ){
    836   APIRET rc;
    837   FILELOCK area;
    838   ULONG mode, timeout;
    839 
    840   /* Access to the os2ShmNode object is serialized by the caller */
    841   assert( sqlite3_mutex_held(pNode->mutex) || pNode->nRef==0 );
    842 
    843   mode = 1;     /* shared lock */
    844   timeout = 0;  /* no wait */
    845   area.lOffset = ofst;
    846   area.lRange = nByte;
    847 
    848   switch( lockType ) {
    849     case _SHM_WRLCK_WAIT:
    850       timeout = (ULONG)-1;      /* wait forever */
    851     case _SHM_WRLCK:
    852       mode = 0;                 /* exclusive lock */
    853     case _SHM_RDLCK:
    854       rc = DosSetFileLocks(pNode->hLockFile,
    855                            NULL, &area, timeout, mode);
    856       break;
    857     /* case _SHM_UNLCK: */
    858     default:
    859       rc = DosSetFileLocks(pNode->hLockFile,
    860                            &area, NULL, 0, 0);
    861       break;
    862   }
    863 
    864   OSTRACE(("SHM-LOCK %d %s %s 0x%08lx\n",
    865            pNode->hLockFile,
    866            rc==SQLITE_OK ? "ok" : "failed",
    867            lockType==_SHM_UNLCK ? "Unlock" : "Lock",
    868            rc));
    869 
    870   ERR_TRACE(rc, ("os2ShmSystemLock: %d %s\n", rc, pNode->shmBaseName))
    871 
    872   return ( rc == 0 ) ?  SQLITE_OK : SQLITE_BUSY;
    873 }
    874 
    875 /*
    876 ** Find an os2ShmNode in global list or allocate a new one, if not found.
    877 **
    878 ** This is not a VFS shared-memory method; it is a utility function called
    879 ** by VFS shared-memory methods.
    880 */
    881 static int os2OpenSharedMemory( os2File *fd, int szRegion ) {
    882   os2ShmLink *pLink;
    883   os2ShmNode *pNode;
    884   int cbShmName, rc = SQLITE_OK;
    885   char shmName[CCHMAXPATH + 30];
    886 #ifndef SQLITE_OS2_NO_WAL_LOCK_FILE
    887   ULONG action;
    888 #endif
    889 
    890   /* We need some additional space at the end to append the region number */
    891   cbShmName = sprintf(shmName, "\\SHAREMEM\\%s", fd->zFullPathCp );
    892   if( cbShmName >= CCHMAXPATH-8 )
    893     return SQLITE_IOERR_SHMOPEN;
    894 
    895   /* Replace colon in file name to form a valid shared memory name */
    896   shmName[10+1] = '!';
    897 
    898   /* Allocate link object (we free it later in case of failure) */
    899   pLink = sqlite3_malloc( sizeof(*pLink) );
    900   if( !pLink )
    901     return SQLITE_NOMEM;
    902 
    903   /* Access node list */
    904   os2ShmEnterMutex();
    905 
    906   /* Find node by it's shared memory base name */
    907   for( pNode = os2ShmNodeList;
    908        pNode && stricmp(shmName, pNode->shmBaseName) != 0;
    909        pNode = pNode->pNext )   ;
    910 
    911   /* Not found: allocate a new node */
    912   if( !pNode ) {
    913     pNode = sqlite3_malloc( sizeof(*pNode) + cbShmName );
    914     if( pNode ) {
    915       memset(pNode, 0, sizeof(*pNode) );
    916       pNode->szRegion = szRegion;
    917       pNode->hLockFile = (HFILE)-1;
    918       strcpy(pNode->shmBaseName, shmName);
    919 
    920 #ifdef SQLITE_OS2_NO_WAL_LOCK_FILE
    921       if( DosDupHandle(fd->h, &pNode->hLockFile) != 0 ) {
    922 #else
    923       sprintf(shmName, "%s-lck", fd->zFullPathCp);
    924       if( DosOpen((PSZ)shmName, &pNode->hLockFile, &action, 0, FILE_NORMAL,
    925                   OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
    926                   OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE |
    927                   OPEN_FLAGS_NOINHERIT | OPEN_FLAGS_FAIL_ON_ERROR,
    928                   NULL) != 0 ) {
    929 #endif
    930         sqlite3_free(pNode);
    931         rc = SQLITE_IOERR;
    932       } else {
    933         pNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
    934         if( !pNode->mutex ) {
    935           sqlite3_free(pNode);
    936           rc = SQLITE_NOMEM;
    937         }
    938       }
    939     } else {
    940       rc = SQLITE_NOMEM;
    941     }
    942 
    943     if( rc == SQLITE_OK ) {
    944       pNode->pNext = os2ShmNodeList;
    945       os2ShmNodeList = pNode;
    946     } else {
    947       pNode = NULL;
    948     }
    949   } else if( pNode->szRegion != szRegion ) {
    950     rc = SQLITE_IOERR_SHMSIZE;
    951     pNode = NULL;
    952   }
    953 
    954   if( pNode ) {
    955     sqlite3_mutex_enter(pNode->mutex);
    956 
    957     memset(pLink, 0, sizeof(*pLink));
    958 
    959     pLink->pShmNode = pNode;
    960     pLink->pNext = pNode->pFirst;
    961     pNode->pFirst = pLink;
    962     pNode->nRef++;
    963 
    964     fd->pShmLink = pLink;
    965 
    966     sqlite3_mutex_leave(pNode->mutex);
    967 
    968   } else {
    969     /* Error occured. Free our link object. */
    970     sqlite3_free(pLink);
    971   }
    972 
    973   os2ShmLeaveMutex();
    974 
    975   ERR_TRACE(rc, ("os2OpenSharedMemory: %d  %s\n", rc, fd->zFullPathCp))
    976 
    977   return rc;
    978 }
    979 
    980 /*
    981 ** Purge the os2ShmNodeList list of all entries with nRef==0.
    982 **
    983 ** This is not a VFS shared-memory method; it is a utility function called
    984 ** by VFS shared-memory methods.
    985 */
    986 static void os2PurgeShmNodes( int deleteFlag ) {
    987   os2ShmNode *pNode;
    988   os2ShmNode **ppNode;
    989 
    990   os2ShmEnterMutex();
    991 
    992   ppNode = &os2ShmNodeList;
    993 
    994   while( *ppNode ) {
    995     pNode = *ppNode;
    996 
    997     if( pNode->nRef == 0 ) {
    998       *ppNode = pNode->pNext;
    999 
   1000       if( pNode->apRegion ) {
   1001         /* Prevent other processes from resizing the shared memory */
   1002         os2ShmSystemLock(pNode, _SHM_WRLCK_WAIT, OS2_SHM_DMS, 1);
   1003 
   1004         while( pNode->nRegion-- ) {
   1005 #ifdef SQLITE_DEBUG
   1006           int rc =
   1007 #endif
   1008           DosFreeMem(pNode->apRegion[pNode->nRegion]);
   1009 
   1010           OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n",
   1011                   (int)GetCurrentProcessId(), pNode->nRegion,
   1012                   rc == 0 ? "ok" : "failed"));
   1013         }
   1014 
   1015         /* Allow other processes to resize the shared memory */
   1016         os2ShmSystemLock(pNode, _SHM_UNLCK, OS2_SHM_DMS, 1);
   1017 
   1018         sqlite3_free(pNode->apRegion);
   1019       }
   1020 
   1021       DosClose(pNode->hLockFile);
   1022 
   1023 #ifndef SQLITE_OS2_NO_WAL_LOCK_FILE
   1024       if( deleteFlag ) {
   1025          char fileName[CCHMAXPATH];
   1026          /* Skip "\\SHAREMEM\\" */
   1027          sprintf(fileName, "%s-lck", pNode->shmBaseName + 10);
   1028          /* restore colon */
   1029          fileName[1] = ':';
   1030 
   1031          DosForceDelete(fileName);
   1032       }
   1033 #endif
   1034 
   1035       sqlite3_mutex_free(pNode->mutex);
   1036 
   1037       sqlite3_free(pNode);
   1038 
   1039     } else {
   1040       ppNode = &pNode->pNext;
   1041     }
   1042   }
   1043 
   1044   os2ShmLeaveMutex();
   1045 }
   1046 
   1047 /*
   1048 ** This function is called to obtain a pointer to region iRegion of the
   1049 ** shared-memory associated with the database file id. Shared-memory regions
   1050 ** are numbered starting from zero. Each shared-memory region is szRegion
   1051 ** bytes in size.
   1052 **
   1053 ** If an error occurs, an error code is returned and *pp is set to NULL.
   1054 **
   1055 ** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
   1056 ** region has not been allocated (by any client, including one running in a
   1057 ** separate process), then *pp is set to NULL and SQLITE_OK returned. If
   1058 ** bExtend is non-zero and the requested shared-memory region has not yet
   1059 ** been allocated, it is allocated by this function.
   1060 **
   1061 ** If the shared-memory region has already been allocated or is allocated by
   1062 ** this call as described above, then it is mapped into this processes
   1063 ** address space (if it is not already), *pp is set to point to the mapped
   1064 ** memory and SQLITE_OK returned.
   1065 */
   1066 static int os2ShmMap(
   1067   sqlite3_file *id,               /* Handle open on database file */
   1068   int iRegion,                    /* Region to retrieve */
   1069   int szRegion,                   /* Size of regions */
   1070   int bExtend,                    /* True to extend block if necessary */
   1071   void volatile **pp              /* OUT: Mapped memory */
   1072 ){
   1073   PVOID pvTemp;
   1074   void **apRegion;
   1075   os2ShmNode *pNode;
   1076   int n, rc = SQLITE_OK;
   1077   char shmName[CCHMAXPATH];
   1078   os2File *pFile = (os2File*)id;
   1079 
   1080   *pp = NULL;
   1081 
   1082   if( !pFile->pShmLink )
   1083     rc = os2OpenSharedMemory( pFile, szRegion );
   1084 
   1085   if( rc == SQLITE_OK ) {
   1086     pNode = pFile->pShmLink->pShmNode ;
   1087 
   1088     sqlite3_mutex_enter(pNode->mutex);
   1089 
   1090     assert( szRegion==pNode->szRegion );
   1091 
   1092     /* Unmapped region ? */
   1093     if( iRegion >= pNode->nRegion ) {
   1094       /* Prevent other processes from resizing the shared memory */
   1095       os2ShmSystemLock(pNode, _SHM_WRLCK_WAIT, OS2_SHM_DMS, 1);
   1096 
   1097       apRegion = sqlite3_realloc(
   1098         pNode->apRegion, (iRegion + 1) * sizeof(apRegion[0]));
   1099 
   1100       if( apRegion ) {
   1101         pNode->apRegion = apRegion;
   1102 
   1103         while( pNode->nRegion <= iRegion ) {
   1104           sprintf(shmName, "%s-%u",
   1105                   pNode->shmBaseName, pNode->nRegion);
   1106 
   1107           if( DosGetNamedSharedMem(&pvTemp, (PSZ)shmName,
   1108                 PAG_READ | PAG_WRITE) != NO_ERROR ) {
   1109             if( !bExtend )
   1110               break;
   1111 
   1112             if( DosAllocSharedMem(&pvTemp, (PSZ)shmName, szRegion,
   1113                   PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_ANY) != NO_ERROR &&
   1114                 DosAllocSharedMem(&pvTemp, (PSZ)shmName, szRegion,
   1115                   PAG_READ | PAG_WRITE | PAG_COMMIT) != NO_ERROR ) {
   1116               rc = SQLITE_NOMEM;
   1117               break;
   1118             }
   1119           }
   1120 
   1121           apRegion[pNode->nRegion++] = pvTemp;
   1122         }
   1123 
   1124         /* zero out remaining entries */
   1125         for( n = pNode->nRegion; n <= iRegion; n++ )
   1126           pNode->apRegion[n] = NULL;
   1127 
   1128         /* Return this region (maybe zero) */
   1129         *pp = pNode->apRegion[iRegion];
   1130       } else {
   1131         rc = SQLITE_NOMEM;
   1132       }
   1133 
   1134       /* Allow other processes to resize the shared memory */
   1135       os2ShmSystemLock(pNode, _SHM_UNLCK, OS2_SHM_DMS, 1);
   1136 
   1137     } else {
   1138       /* Region has been mapped previously */
   1139       *pp = pNode->apRegion[iRegion];
   1140     }
   1141 
   1142     sqlite3_mutex_leave(pNode->mutex);
   1143   }
   1144 
   1145   ERR_TRACE(rc, ("os2ShmMap: %s iRgn = %d, szRgn = %d, bExt = %d : %d\n",
   1146                  pFile->zFullPathCp, iRegion, szRegion, bExtend, rc))
   1147 
   1148   return rc;
   1149 }
   1150 
   1151 /*
   1152 ** Close a connection to shared-memory.  Delete the underlying
   1153 ** storage if deleteFlag is true.
   1154 **
   1155 ** If there is no shared memory associated with the connection then this
   1156 ** routine is a harmless no-op.
   1157 */
   1158 static int os2ShmUnmap(
   1159   sqlite3_file *id,               /* The underlying database file */
   1160   int deleteFlag                  /* Delete shared-memory if true */
   1161 ){
   1162   os2File *pFile = (os2File*)id;
   1163   os2ShmLink *pLink = pFile->pShmLink;
   1164 
   1165   if( pLink ) {
   1166     int nRef = -1;
   1167     os2ShmLink **ppLink;
   1168     os2ShmNode *pNode = pLink->pShmNode;
   1169 
   1170     sqlite3_mutex_enter(pNode->mutex);
   1171 
   1172     for( ppLink = &pNode->pFirst;
   1173          *ppLink && *ppLink != pLink;
   1174          ppLink = &(*ppLink)->pNext )   ;
   1175 
   1176     assert(*ppLink);
   1177 
   1178     if( *ppLink ) {
   1179       *ppLink = pLink->pNext;
   1180       nRef = --pNode->nRef;
   1181     } else {
   1182       ERR_TRACE(1, ("os2ShmUnmap: link not found ! %s\n",
   1183                     pNode->shmBaseName))
   1184     }
   1185 
   1186     pFile->pShmLink = NULL;
   1187     sqlite3_free(pLink);
   1188 
   1189     sqlite3_mutex_leave(pNode->mutex);
   1190 
   1191     if( nRef == 0 )
   1192       os2PurgeShmNodes( deleteFlag );
   1193   }
   1194 
   1195   return SQLITE_OK;
   1196 }
   1197 
   1198 /*
   1199 ** Change the lock state for a shared-memory segment.
   1200 **
   1201 ** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
   1202 ** different here than in posix.  In xShmLock(), one can go from unlocked
   1203 ** to shared and back or from unlocked to exclusive and back.  But one may
   1204 ** not go from shared to exclusive or from exclusive to shared.
   1205 */
   1206 static int os2ShmLock(
   1207   sqlite3_file *id,          /* Database file holding the shared memory */
   1208   int ofst,                  /* First lock to acquire or release */
   1209   int n,                     /* Number of locks to acquire or release */
   1210   int flags                  /* What to do with the lock */
   1211 ){
   1212   u32 mask;                             /* Mask of locks to take or release */
   1213   int rc = SQLITE_OK;                   /* Result code */
   1214   os2File *pFile = (os2File*)id;
   1215   os2ShmLink *p = pFile->pShmLink;      /* The shared memory being locked */
   1216   os2ShmLink *pX;                       /* For looping over all siblings */
   1217   os2ShmNode *pShmNode = p->pShmNode;   /* Our node */
   1218 
   1219   assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
   1220   assert( n>=1 );
   1221   assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
   1222        || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
   1223        || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
   1224        || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
   1225   assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
   1226 
   1227   mask = (u32)((1U<<(ofst+n)) - (1U<<ofst));
   1228   assert( n>1 || mask==(1<<ofst) );
   1229 
   1230 
   1231   sqlite3_mutex_enter(pShmNode->mutex);
   1232 
   1233   if( flags & SQLITE_SHM_UNLOCK ){
   1234     u32 allMask = 0; /* Mask of locks held by siblings */
   1235 
   1236     /* See if any siblings hold this same lock */
   1237     for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
   1238       if( pX==p ) continue;
   1239       assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
   1240       allMask |= pX->sharedMask;
   1241     }
   1242 
   1243     /* Unlock the system-level locks */
   1244     if( (mask & allMask)==0 ){
   1245       rc = os2ShmSystemLock(pShmNode, _SHM_UNLCK, ofst+OS2_SHM_BASE, n);
   1246     }else{
   1247       rc = SQLITE_OK;
   1248     }
   1249 
   1250     /* Undo the local locks */
   1251     if( rc==SQLITE_OK ){
   1252       p->exclMask &= ~mask;
   1253       p->sharedMask &= ~mask;
   1254     }
   1255   }else if( flags & SQLITE_SHM_SHARED ){
   1256     u32 allShared = 0;  /* Union of locks held by connections other than "p" */
   1257 
   1258     /* Find out which shared locks are already held by sibling connections.
   1259     ** If any sibling already holds an exclusive lock, go ahead and return
   1260     ** SQLITE_BUSY.
   1261     */
   1262     for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
   1263       if( (pX->exclMask & mask)!=0 ){
   1264         rc = SQLITE_BUSY;
   1265         break;
   1266       }
   1267       allShared |= pX->sharedMask;
   1268     }
   1269 
   1270     /* Get shared locks at the system level, if necessary */
   1271     if( rc==SQLITE_OK ){
   1272       if( (allShared & mask)==0 ){
   1273         rc = os2ShmSystemLock(pShmNode, _SHM_RDLCK, ofst+OS2_SHM_BASE, n);
   1274       }else{
   1275         rc = SQLITE_OK;
   1276       }
   1277     }
   1278 
   1279     /* Get the local shared locks */
   1280     if( rc==SQLITE_OK ){
   1281       p->sharedMask |= mask;
   1282     }
   1283   }else{
   1284     /* Make sure no sibling connections hold locks that will block this
   1285     ** lock.  If any do, return SQLITE_BUSY right away.
   1286     */
   1287     for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
   1288       if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
   1289         rc = SQLITE_BUSY;
   1290         break;
   1291       }
   1292     }
   1293 
   1294     /* Get the exclusive locks at the system level.  Then if successful
   1295     ** also mark the local connection as being locked.
   1296     */
   1297     if( rc==SQLITE_OK ){
   1298       rc = os2ShmSystemLock(pShmNode, _SHM_WRLCK, ofst+OS2_SHM_BASE, n);
   1299       if( rc==SQLITE_OK ){
   1300         assert( (p->sharedMask & mask)==0 );
   1301         p->exclMask |= mask;
   1302       }
   1303     }
   1304   }
   1305 
   1306   sqlite3_mutex_leave(pShmNode->mutex);
   1307 
   1308   OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n",
   1309            p->id, (int)GetCurrentProcessId(), p->sharedMask, p->exclMask,
   1310            rc ? "failed" : "ok"));
   1311 
   1312   ERR_TRACE(rc, ("os2ShmLock: ofst = %d, n = %d, flags = 0x%x -> %d \n",
   1313                  ofst, n, flags, rc))
   1314 
   1315   return rc;
   1316 }
   1317 
   1318 /*
   1319 ** Implement a memory barrier or memory fence on shared memory.
   1320 **
   1321 ** All loads and stores begun before the barrier must complete before
   1322 ** any load or store begun after the barrier.
   1323 */
   1324 static void os2ShmBarrier(
   1325   sqlite3_file *id                /* Database file holding the shared memory */
   1326 ){
   1327   UNUSED_PARAMETER(id);
   1328   os2ShmEnterMutex();
   1329   os2ShmLeaveMutex();
   1330 }
   1331 
   1332 #else
   1333 # define os2ShmMap     0
   1334 # define os2ShmLock    0
   1335 # define os2ShmBarrier 0
   1336 # define os2ShmUnmap   0
   1337 #endif /* #ifndef SQLITE_OMIT_WAL */
   1338 
   1339 
   1340 /*
   1341 ** This vector defines all the methods that can operate on an
   1342 ** sqlite3_file for os2.
   1343 */
   1344 static const sqlite3_io_methods os2IoMethod = {
   1345   2,                              /* iVersion */
   1346   os2Close,                       /* xClose */
   1347   os2Read,                        /* xRead */
   1348   os2Write,                       /* xWrite */
   1349   os2Truncate,                    /* xTruncate */
   1350   os2Sync,                        /* xSync */
   1351   os2FileSize,                    /* xFileSize */
   1352   os2Lock,                        /* xLock */
   1353   os2Unlock,                      /* xUnlock */
   1354   os2CheckReservedLock,           /* xCheckReservedLock */
   1355   os2FileControl,                 /* xFileControl */
   1356   os2SectorSize,                  /* xSectorSize */
   1357   os2DeviceCharacteristics,       /* xDeviceCharacteristics */
   1358   os2ShmMap,                      /* xShmMap */
   1359   os2ShmLock,                     /* xShmLock */
   1360   os2ShmBarrier,                  /* xShmBarrier */
   1361   os2ShmUnmap                     /* xShmUnmap */
   1362 };
   1363 
   1364 
   1365 /***************************************************************************
   1366 ** Here ends the I/O methods that form the sqlite3_io_methods object.
   1367 **
   1368 ** The next block of code implements the VFS methods.
   1369 ****************************************************************************/
   1370 
   1371 /*
   1372 ** Create a temporary file name in zBuf.  zBuf must be big enough to
   1373 ** hold at pVfs->mxPathname characters.
   1374 */
   1375 static int getTempname(int nBuf, char *zBuf ){
   1376   static const char zChars[] =
   1377     "abcdefghijklmnopqrstuvwxyz"
   1378     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   1379     "0123456789";
   1380   int i, j;
   1381   PSZ zTempPathCp;
   1382   char zTempPath[CCHMAXPATH];
   1383   ULONG ulDriveNum, ulDriveMap;
   1384 
   1385   /* It's odd to simulate an io-error here, but really this is just
   1386   ** using the io-error infrastructure to test that SQLite handles this
   1387   ** function failing.
   1388   */
   1389   SimulateIOError( return SQLITE_IOERR );
   1390 
   1391   if( sqlite3_temp_directory ) {
   1392     sqlite3_snprintf(CCHMAXPATH-30, zTempPath, "%s", sqlite3_temp_directory);
   1393   } else if( DosScanEnv( (PSZ)"TEMP",   &zTempPathCp ) == NO_ERROR ||
   1394              DosScanEnv( (PSZ)"TMP",    &zTempPathCp ) == NO_ERROR ||
   1395              DosScanEnv( (PSZ)"TMPDIR", &zTempPathCp ) == NO_ERROR ) {
   1396     char *zTempPathUTF = convertCpPathToUtf8( (char *)zTempPathCp );
   1397     sqlite3_snprintf(CCHMAXPATH-30, zTempPath, "%s", zTempPathUTF);
   1398     free( zTempPathUTF );
   1399   } else if( DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap ) == NO_ERROR ) {
   1400     zTempPath[0] = (char)('A' + ulDriveNum - 1);
   1401     zTempPath[1] = ':';
   1402     zTempPath[2] = '\0';
   1403   } else {
   1404     zTempPath[0] = '\0';
   1405   }
   1406 
   1407   /* Strip off a trailing slashes or backslashes, otherwise we would get *
   1408    * multiple (back)slashes which causes DosOpen() to fail.              *
   1409    * Trailing spaces are not allowed, either.                            */
   1410   j = sqlite3Strlen30(zTempPath);
   1411   while( j > 0 && ( zTempPath[j-1] == '\\' || zTempPath[j-1] == '/' ||
   1412                     zTempPath[j-1] == ' ' ) ){
   1413     j--;
   1414   }
   1415   zTempPath[j] = '\0';
   1416 
   1417   /* We use 20 bytes to randomize the name */
   1418   sqlite3_snprintf(nBuf-22, zBuf,
   1419                    "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
   1420   j = sqlite3Strlen30(zBuf);
   1421   sqlite3_randomness( 20, &zBuf[j] );
   1422   for( i = 0; i < 20; i++, j++ ){
   1423     zBuf[j] = zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
   1424   }
   1425   zBuf[j] = 0;
   1426 
   1427   OSTRACE(( "TEMP FILENAME: %s\n", zBuf ));
   1428   return SQLITE_OK;
   1429 }
   1430 
   1431 
   1432 /*
   1433 ** Turn a relative pathname into a full pathname.  Write the full
   1434 ** pathname into zFull[].  zFull[] will be at least pVfs->mxPathname
   1435 ** bytes in size.
   1436 */
   1437 static int os2FullPathname(
   1438   sqlite3_vfs *pVfs,          /* Pointer to vfs object */
   1439   const char *zRelative,      /* Possibly relative input path */
   1440   int nFull,                  /* Size of output buffer in bytes */
   1441   char *zFull                 /* Output buffer */
   1442 ){
   1443   char *zRelativeCp = convertUtf8PathToCp( zRelative );
   1444   char zFullCp[CCHMAXPATH] = "\0";
   1445   char *zFullUTF;
   1446   APIRET rc = DosQueryPathInfo( (PSZ)zRelativeCp, FIL_QUERYFULLNAME,
   1447                                 zFullCp, CCHMAXPATH );
   1448   free( zRelativeCp );
   1449   zFullUTF = convertCpPathToUtf8( zFullCp );
   1450   sqlite3_snprintf( nFull, zFull, zFullUTF );
   1451   free( zFullUTF );
   1452   return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
   1453 }
   1454 
   1455 
   1456 /*
   1457 ** Open a file.
   1458 */
   1459 static int os2Open(
   1460   sqlite3_vfs *pVfs,            /* Not used */
   1461   const char *zName,            /* Name of the file (UTF-8) */
   1462   sqlite3_file *id,             /* Write the SQLite file handle here */
   1463   int flags,                    /* Open mode flags */
   1464   int *pOutFlags                /* Status return flags */
   1465 ){
   1466   HFILE h;
   1467   ULONG ulOpenFlags = 0;
   1468   ULONG ulOpenMode = 0;
   1469   ULONG ulAction = 0;
   1470   ULONG rc;
   1471   os2File *pFile = (os2File*)id;
   1472   const char *zUtf8Name = zName;
   1473   char *zNameCp;
   1474   char  zTmpname[CCHMAXPATH];
   1475 
   1476   int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
   1477   int isCreate     = (flags & SQLITE_OPEN_CREATE);
   1478   int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
   1479 #ifndef NDEBUG
   1480   int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
   1481   int isReadonly   = (flags & SQLITE_OPEN_READONLY);
   1482   int eType        = (flags & 0xFFFFFF00);
   1483   int isOpenJournal = (isCreate && (
   1484         eType==SQLITE_OPEN_MASTER_JOURNAL
   1485      || eType==SQLITE_OPEN_MAIN_JOURNAL
   1486      || eType==SQLITE_OPEN_WAL
   1487   ));
   1488 #endif
   1489 
   1490   UNUSED_PARAMETER(pVfs);
   1491   assert( id!=0 );
   1492 
   1493   /* Check the following statements are true:
   1494   **
   1495   **   (a) Exactly one of the READWRITE and READONLY flags must be set, and
   1496   **   (b) if CREATE is set, then READWRITE must also be set, and
   1497   **   (c) if EXCLUSIVE is set, then CREATE must also be set.
   1498   **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
   1499   */
   1500   assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
   1501   assert(isCreate==0 || isReadWrite);
   1502   assert(isExclusive==0 || isCreate);
   1503   assert(isDelete==0 || isCreate);
   1504 
   1505   /* The main DB, main journal, WAL file and master journal are never
   1506   ** automatically deleted. Nor are they ever temporary files.  */
   1507   assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
   1508   assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
   1509   assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
   1510   assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
   1511 
   1512   /* Assert that the upper layer has set one of the "file-type" flags. */
   1513   assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB
   1514        || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
   1515        || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL
   1516        || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
   1517   );
   1518 
   1519   memset( pFile, 0, sizeof(*pFile) );
   1520   pFile->h = (HFILE)-1;
   1521 
   1522   /* If the second argument to this function is NULL, generate a
   1523   ** temporary file name to use
   1524   */
   1525   if( !zUtf8Name ){
   1526     assert(isDelete && !isOpenJournal);
   1527     rc = getTempname(CCHMAXPATH, zTmpname);
   1528     if( rc!=SQLITE_OK ){
   1529       return rc;
   1530     }
   1531     zUtf8Name = zTmpname;
   1532   }
   1533 
   1534   if( isReadWrite ){
   1535     ulOpenMode |= OPEN_ACCESS_READWRITE;
   1536   }else{
   1537     ulOpenMode |= OPEN_ACCESS_READONLY;
   1538   }
   1539 
   1540   /* Open in random access mode for possibly better speed.  Allow full
   1541   ** sharing because file locks will provide exclusive access when needed.
   1542   ** The handle should not be inherited by child processes and we don't
   1543   ** want popups from the critical error handler.
   1544   */
   1545   ulOpenMode |= OPEN_FLAGS_RANDOM | OPEN_SHARE_DENYNONE |
   1546                 OPEN_FLAGS_NOINHERIT | OPEN_FLAGS_FAIL_ON_ERROR;
   1547 
   1548   /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
   1549   ** created. SQLite doesn't use it to indicate "exclusive access"
   1550   ** as it is usually understood.
   1551   */
   1552   if( isExclusive ){
   1553     /* Creates a new file, only if it does not already exist. */
   1554     /* If the file exists, it fails. */
   1555     ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
   1556   }else if( isCreate ){
   1557     /* Open existing file, or create if it doesn't exist */
   1558     ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
   1559   }else{
   1560     /* Opens a file, only if it exists. */
   1561     ulOpenFlags |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
   1562   }
   1563 
   1564   zNameCp = convertUtf8PathToCp( zUtf8Name );
   1565   rc = DosOpen( (PSZ)zNameCp,
   1566                 &h,
   1567                 &ulAction,
   1568                 0L,
   1569                 FILE_NORMAL,
   1570                 ulOpenFlags,
   1571                 ulOpenMode,
   1572                 (PEAOP2)NULL );
   1573   free( zNameCp );
   1574 
   1575   if( rc != NO_ERROR ){
   1576     OSTRACE(( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
   1577               rc, zUtf8Name, ulAction, ulOpenFlags, ulOpenMode ));
   1578 
   1579     if( isReadWrite ){
   1580       return os2Open( pVfs, zName, id,
   1581                       ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
   1582                       pOutFlags );
   1583     }else{
   1584       return SQLITE_CANTOPEN;
   1585     }
   1586   }
   1587 
   1588   if( pOutFlags ){
   1589     *pOutFlags = isReadWrite ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
   1590   }
   1591 
   1592   os2FullPathname( pVfs, zUtf8Name, sizeof( zTmpname ), zTmpname );
   1593   pFile->zFullPathCp = convertUtf8PathToCp( zTmpname );
   1594   pFile->pMethod = &os2IoMethod;
   1595   pFile->flags = flags;
   1596   pFile->h = h;
   1597 
   1598   OpenCounter(+1);
   1599   OSTRACE(( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags ));
   1600   return SQLITE_OK;
   1601 }
   1602 
   1603 /*
   1604 ** Delete the named file.
   1605 */
   1606 static int os2Delete(
   1607   sqlite3_vfs *pVfs,                     /* Not used on os2 */
   1608   const char *zFilename,                 /* Name of file to delete */
   1609   int syncDir                            /* Not used on os2 */
   1610 ){
   1611   APIRET rc;
   1612   char *zFilenameCp;
   1613   SimulateIOError( return SQLITE_IOERR_DELETE );
   1614   zFilenameCp = convertUtf8PathToCp( zFilename );
   1615   rc = DosDelete( (PSZ)zFilenameCp );
   1616   free( zFilenameCp );
   1617   OSTRACE(( "DELETE \"%s\"\n", zFilename ));
   1618   return (rc == NO_ERROR ||
   1619           rc == ERROR_FILE_NOT_FOUND ||
   1620           rc == ERROR_PATH_NOT_FOUND ) ? SQLITE_OK : SQLITE_IOERR_DELETE;
   1621 }
   1622 
   1623 /*
   1624 ** Check the existance and status of a file.
   1625 */
   1626 static int os2Access(
   1627   sqlite3_vfs *pVfs,        /* Not used on os2 */
   1628   const char *zFilename,    /* Name of file to check */
   1629   int flags,                /* Type of test to make on this file */
   1630   int *pOut                 /* Write results here */
   1631 ){
   1632   APIRET rc;
   1633   FILESTATUS3 fsts3ConfigInfo;
   1634   char *zFilenameCp;
   1635 
   1636   UNUSED_PARAMETER(pVfs);
   1637   SimulateIOError( return SQLITE_IOERR_ACCESS; );
   1638 
   1639   zFilenameCp = convertUtf8PathToCp( zFilename );
   1640   rc = DosQueryPathInfo( (PSZ)zFilenameCp, FIL_STANDARD,
   1641                          &fsts3ConfigInfo, sizeof(FILESTATUS3) );
   1642   free( zFilenameCp );
   1643   OSTRACE(( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n",
   1644             fsts3ConfigInfo.attrFile, flags, rc ));
   1645 
   1646   switch( flags ){
   1647     case SQLITE_ACCESS_EXISTS:
   1648       /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
   1649       ** as if it does not exist.
   1650       */
   1651       if( fsts3ConfigInfo.cbFile == 0 )
   1652         rc = ERROR_FILE_NOT_FOUND;
   1653       break;
   1654     case SQLITE_ACCESS_READ:
   1655       break;
   1656     case SQLITE_ACCESS_READWRITE:
   1657       if( fsts3ConfigInfo.attrFile & FILE_READONLY )
   1658         rc = ERROR_ACCESS_DENIED;
   1659       break;
   1660     default:
   1661       rc = ERROR_FILE_NOT_FOUND;
   1662       assert( !"Invalid flags argument" );
   1663   }
   1664 
   1665   *pOut = (rc == NO_ERROR);
   1666   OSTRACE(( "ACCESS %s flags %d: rc=%d\n", zFilename, flags, *pOut ));
   1667 
   1668   return SQLITE_OK;
   1669 }
   1670 
   1671 
   1672 #ifndef SQLITE_OMIT_LOAD_EXTENSION
   1673 /*
   1674 ** Interfaces for opening a shared library, finding entry points
   1675 ** within the shared library, and closing the shared library.
   1676 */
   1677 /*
   1678 ** Interfaces for opening a shared library, finding entry points
   1679 ** within the shared library, and closing the shared library.
   1680 */
   1681 static void *os2DlOpen(sqlite3_vfs *pVfs, const char *zFilename){
   1682   HMODULE hmod;
   1683   APIRET rc;
   1684   char *zFilenameCp = convertUtf8PathToCp(zFilename);
   1685   rc = DosLoadModule(NULL, 0, (PSZ)zFilenameCp, &hmod);
   1686   free(zFilenameCp);
   1687   return rc != NO_ERROR ? 0 : (void*)hmod;
   1688 }
   1689 /*
   1690 ** A no-op since the error code is returned on the DosLoadModule call.
   1691 ** os2Dlopen returns zero if DosLoadModule is not successful.
   1692 */
   1693 static void os2DlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
   1694 /* no-op */
   1695 }
   1696 static void (*os2DlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
   1697   PFN pfn;
   1698   APIRET rc;
   1699   rc = DosQueryProcAddr((HMODULE)pHandle, 0L, (PSZ)zSymbol, &pfn);
   1700   if( rc != NO_ERROR ){
   1701     /* if the symbol itself was not found, search again for the same
   1702      * symbol with an extra underscore, that might be needed depending
   1703      * on the calling convention */
   1704     char _zSymbol[256] = "_";
   1705     strncat(_zSymbol, zSymbol, 254);
   1706     rc = DosQueryProcAddr((HMODULE)pHandle, 0L, (PSZ)_zSymbol, &pfn);
   1707   }
   1708   return rc != NO_ERROR ? 0 : (void(*)(void))pfn;
   1709 }
   1710 static void os2DlClose(sqlite3_vfs *pVfs, void *pHandle){
   1711   DosFreeModule((HMODULE)pHandle);
   1712 }
   1713 #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
   1714   #define os2DlOpen 0
   1715   #define os2DlError 0
   1716   #define os2DlSym 0
   1717   #define os2DlClose 0
   1718 #endif
   1719 
   1720 
   1721 /*
   1722 ** Write up to nBuf bytes of randomness into zBuf.
   1723 */
   1724 static int os2Randomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf ){
   1725   int n = 0;
   1726 #if defined(SQLITE_TEST)
   1727   n = nBuf;
   1728   memset(zBuf, 0, nBuf);
   1729 #else
   1730   int i;
   1731   PPIB ppib;
   1732   PTIB ptib;
   1733   DATETIME dt;
   1734   static unsigned c = 0;
   1735   /* Ordered by variation probability */
   1736   static ULONG svIdx[6] = { QSV_MS_COUNT, QSV_TIME_LOW,
   1737                             QSV_MAXPRMEM, QSV_MAXSHMEM,
   1738                             QSV_TOTAVAILMEM, QSV_TOTRESMEM };
   1739 
   1740   /* 8 bytes; timezone and weekday don't increase the randomness much */
   1741   if( (int)sizeof(dt)-3 <= nBuf - n ){
   1742     c += 0x0100;
   1743     DosGetDateTime(&dt);
   1744     dt.year = (USHORT)((dt.year - 1900) | c);
   1745     memcpy(&zBuf[n], &dt, sizeof(dt)-3);
   1746     n += sizeof(dt)-3;
   1747   }
   1748 
   1749   /* 4 bytes; PIDs and TIDs are 16 bit internally, so combine them */
   1750   if( (int)sizeof(ULONG) <= nBuf - n ){
   1751     DosGetInfoBlocks(&ptib, &ppib);
   1752     *(PULONG)&zBuf[n] = MAKELONG(ppib->pib_ulpid,
   1753                                  ptib->tib_ptib2->tib2_ultid);
   1754     n += sizeof(ULONG);
   1755   }
   1756 
   1757   /* Up to 6 * 4 bytes; variables depend on the system state */
   1758   for( i = 0; i < 6 && (int)sizeof(ULONG) <= nBuf - n; i++ ){
   1759     DosQuerySysInfo(svIdx[i], svIdx[i],
   1760                     (PULONG)&zBuf[n], sizeof(ULONG));
   1761     n += sizeof(ULONG);
   1762   }
   1763 #endif
   1764 
   1765   return n;
   1766 }
   1767 
   1768 /*
   1769 ** Sleep for a little while.  Return the amount of time slept.
   1770 ** The argument is the number of microseconds we want to sleep.
   1771 ** The return value is the number of microseconds of sleep actually
   1772 ** requested from the underlying operating system, a number which
   1773 ** might be greater than or equal to the argument, but not less
   1774 ** than the argument.
   1775 */
   1776 static int os2Sleep( sqlite3_vfs *pVfs, int microsec ){
   1777   DosSleep( (microsec/1000) );
   1778   return microsec;
   1779 }
   1780 
   1781 /*
   1782 ** The following variable, if set to a non-zero value, becomes the result
   1783 ** returned from sqlite3OsCurrentTime().  This is used for testing.
   1784 */
   1785 #ifdef SQLITE_TEST
   1786 int sqlite3_current_time = 0;
   1787 #endif
   1788 
   1789 /*
   1790 ** Find the current time (in Universal Coordinated Time).  Write into *piNow
   1791 ** the current time and date as a Julian Day number times 86_400_000.  In
   1792 ** other words, write into *piNow the number of milliseconds since the Julian
   1793 ** epoch of noon in Greenwich on November 24, 4714 B.C according to the
   1794 ** proleptic Gregorian calendar.
   1795 **
   1796 ** On success, return 0.  Return 1 if the time and date cannot be found.
   1797 */
   1798 static int os2CurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
   1799 #ifdef SQLITE_TEST
   1800   static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
   1801 #endif
   1802   int year, month, datepart, timepart;
   1803 
   1804   DATETIME dt;
   1805   DosGetDateTime( &dt );
   1806 
   1807   year = dt.year;
   1808   month = dt.month;
   1809 
   1810   /* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html
   1811   ** http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c
   1812   ** Calculate the Julian days
   1813   */
   1814   datepart = (int)dt.day - 32076 +
   1815     1461*(year + 4800 + (month - 14)/12)/4 +
   1816     367*(month - 2 - (month - 14)/12*12)/12 -
   1817     3*((year + 4900 + (month - 14)/12)/100)/4;
   1818 
   1819   /* Time in milliseconds, hours to noon added */
   1820   timepart = 12*3600*1000 + dt.hundredths*10 + dt.seconds*1000 +
   1821     ((int)dt.minutes + dt.timezone)*60*1000 + dt.hours*3600*1000;
   1822 
   1823   *piNow = (sqlite3_int64)datepart*86400*1000 + timepart;
   1824 
   1825 #ifdef SQLITE_TEST
   1826   if( sqlite3_current_time ){
   1827     *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
   1828   }
   1829 #endif
   1830 
   1831   UNUSED_PARAMETER(pVfs);
   1832   return 0;
   1833 }
   1834 
   1835 /*
   1836 ** Find the current time (in Universal Coordinated Time).  Write the
   1837 ** current time and date as a Julian Day number into *prNow and
   1838 ** return 0.  Return 1 if the time and date cannot be found.
   1839 */
   1840 static int os2CurrentTime( sqlite3_vfs *pVfs, double *prNow ){
   1841   int rc;
   1842   sqlite3_int64 i;
   1843   rc = os2CurrentTimeInt64(pVfs, &i);
   1844   if( !rc ){
   1845     *prNow = i/86400000.0;
   1846   }
   1847   return rc;
   1848 }
   1849 
   1850 /*
   1851 ** The idea is that this function works like a combination of
   1852 ** GetLastError() and FormatMessage() on windows (or errno and
   1853 ** strerror_r() on unix). After an error is returned by an OS
   1854 ** function, SQLite calls this function with zBuf pointing to
   1855 ** a buffer of nBuf bytes. The OS layer should populate the
   1856 ** buffer with a nul-terminated UTF-8 encoded error message
   1857 ** describing the last IO error to have occurred within the calling
   1858 ** thread.
   1859 **
   1860 ** If the error message is too large for the supplied buffer,
   1861 ** it should be truncated. The return value of xGetLastError
   1862 ** is zero if the error message fits in the buffer, or non-zero
   1863 ** otherwise (if the message was truncated). If non-zero is returned,
   1864 ** then it is not necessary to include the nul-terminator character
   1865 ** in the output buffer.
   1866 **
   1867 ** Not supplying an error message will have no adverse effect
   1868 ** on SQLite. It is fine to have an implementation that never
   1869 ** returns an error message:
   1870 **
   1871 **   int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
   1872 **     assert(zBuf[0]=='\0');
   1873 **     return 0;
   1874 **   }
   1875 **
   1876 ** However if an error message is supplied, it will be incorporated
   1877 ** by sqlite into the error message available to the user using
   1878 ** sqlite3_errmsg(), possibly making IO errors easier to debug.
   1879 */
   1880 static int os2GetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
   1881   assert(zBuf[0]=='\0');
   1882   return 0;
   1883 }
   1884 
   1885 /*
   1886 ** Initialize and deinitialize the operating system interface.
   1887 */
   1888 int sqlite3_os_init(void){
   1889   static sqlite3_vfs os2Vfs = {
   1890     3,                 /* iVersion */
   1891     sizeof(os2File),   /* szOsFile */
   1892     CCHMAXPATH,        /* mxPathname */
   1893     0,                 /* pNext */
   1894     "os2",             /* zName */
   1895     0,                 /* pAppData */
   1896 
   1897     os2Open,           /* xOpen */
   1898     os2Delete,         /* xDelete */
   1899     os2Access,         /* xAccess */
   1900     os2FullPathname,   /* xFullPathname */
   1901     os2DlOpen,         /* xDlOpen */
   1902     os2DlError,        /* xDlError */
   1903     os2DlSym,          /* xDlSym */
   1904     os2DlClose,        /* xDlClose */
   1905     os2Randomness,     /* xRandomness */
   1906     os2Sleep,          /* xSleep */
   1907     os2CurrentTime,    /* xCurrentTime */
   1908     os2GetLastError,   /* xGetLastError */
   1909     os2CurrentTimeInt64, /* xCurrentTimeInt64 */
   1910     0,                 /* xSetSystemCall */
   1911     0,                 /* xGetSystemCall */
   1912     0                  /* xNextSystemCall */
   1913   };
   1914   sqlite3_vfs_register(&os2Vfs, 1);
   1915   initUconvObjects();
   1916 /*  sqlite3OSTrace = 1; */
   1917   return SQLITE_OK;
   1918 }
   1919 int sqlite3_os_end(void){
   1920   freeUconvObjects();
   1921   return SQLITE_OK;
   1922 }
   1923 
   1924 #endif /* SQLITE_OS_OS2 */
   1925