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 */
59typedef struct os2File os2File;         /* The file structure */
60typedef struct os2ShmNode os2ShmNode;   /* A shared descritive memory node */
61typedef 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*/
67struct 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*/
95static 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*/
122static 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*/
153static 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*/
185static 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*/
210int sqlite3_sync_count = 0;
211int sqlite3_fullsync_count = 0;
212#endif
213
214/*
215** Make sure all writes to a particular file are committed to disk.
216*/
217static 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*/
240static 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*/
258static 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*/
276static 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*/
317static 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*/
454static 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*/
500static 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*/
556static 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*/
592static 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*/
600static 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*/
609static UconvObject ucUtf8 = NULL; /* convert between UTF-8 and UCS-2 */
610static 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*/
615static 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*/
625static 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*/
640static 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*/
669char *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
700static 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*/
724static void os2ShmEnterMutex(void){
725  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
726}
727static void os2ShmLeaveMutex(void){
728  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
729}
730#ifdef SQLITE_DEBUG
731static int os2ShmMutexHeld(void) {
732  return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
733}
734int 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*/
764struct 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*/
794struct 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*/
810static 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 */
830static 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*/
881static 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*/
986static 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*/
1066static 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*/
1158static 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*/
1206static 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*/
1324static 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*/
1344static 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*/
1375static 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*/
1437static 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*/
1459static 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*/
1606static 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*/
1626static 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*/
1681static 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*/
1693static void os2DlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
1694/* no-op */
1695}
1696static 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}
1710static 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*/
1724static 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*/
1776static 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
1786int 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*/
1798static 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*/
1840static 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*/
1880static 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*/
1888int 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}
1919int sqlite3_os_end(void){
1920  freeUconvObjects();
1921  return SQLITE_OK;
1922}
1923
1924#endif /* SQLITE_OS_OS2 */
1925