- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / sqlite / src / src / os_os2.c
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 */