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 */
os2Close(sqlite3_file * id)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 */
os2Read(sqlite3_file * id,void * pBuf,int amt,sqlite3_int64 offset)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 */
os2Write(sqlite3_file * id,const void * pBuf,int amt,sqlite3_int64 offset)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 */
os2Truncate(sqlite3_file * id,i64 nByte)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 */
os2Sync(sqlite3_file * id,int flags)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 */
os2FileSize(sqlite3_file * id,sqlite3_int64 * pSize)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 */
getReadLock(os2File * pFile)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 */
unlockReadLock(os2File * id)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 */
os2Lock(sqlite3_file * id,int locktype)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 */
os2CheckReservedLock(sqlite3_file * id,int * pOut)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 */
os2Unlock(sqlite3_file * id,int locktype)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 */
os2FileControl(sqlite3_file * id,int op,void * pArg)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 */
os2SectorSize(sqlite3_file * id)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 */
os2DeviceCharacteristics(sqlite3_file * id)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 */
initUconvObjects(void)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 */
freeUconvObjects(void)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 */
convertUtf8PathToCp(const char * in)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 */
convertCpPathToUtf8(const char * in)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 */
os2ShmEnterMutex(void)724 static void os2ShmEnterMutex(void){
725 sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
726 }
os2ShmLeaveMutex(void)727 static void os2ShmLeaveMutex(void){
728 sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
729 }
730 #ifdef SQLITE_DEBUG
os2ShmMutexHeld(void)731 static int os2ShmMutexHeld(void) {
732 return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
733 }
GetCurrentProcessId(void)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 */
os2ShmSystemLock(os2ShmNode * pNode,int lockType,int ofst,int nByte)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 */
os2OpenSharedMemory(os2File * fd,int szRegion)881 static int os2OpenSharedMemory( os2File *fd, int szRegion ) {
882 os2ShmLink *pLink;
883 os2ShmNode *pNode;
884 int cbShmName, rc = SQLITE_OK;
885 char shmName[CCHMAXPATH + 30];
886 #ifndef SQLITE_OS2_NO_WAL_LOCK_FILE
887 ULONG action;
888 #endif
889
890 /* We need some additional space at the end to append the region number */
891 cbShmName = sprintf(shmName, "\\SHAREMEM\\%s", fd->zFullPathCp );
892 if( cbShmName >= CCHMAXPATH-8 )
893 return SQLITE_IOERR_SHMOPEN;
894
895 /* Replace colon in file name to form a valid shared memory name */
896 shmName[10+1] = '!';
897
898 /* Allocate link object (we free it later in case of failure) */
899 pLink = sqlite3_malloc( sizeof(*pLink) );
900 if( !pLink )
901 return SQLITE_NOMEM;
902
903 /* Access node list */
904 os2ShmEnterMutex();
905
906 /* Find node by it's shared memory base name */
907 for( pNode = os2ShmNodeList;
908 pNode && stricmp(shmName, pNode->shmBaseName) != 0;
909 pNode = pNode->pNext ) ;
910
911 /* Not found: allocate a new node */
912 if( !pNode ) {
913 pNode = sqlite3_malloc( sizeof(*pNode) + cbShmName );
914 if( pNode ) {
915 memset(pNode, 0, sizeof(*pNode) );
916 pNode->szRegion = szRegion;
917 pNode->hLockFile = (HFILE)-1;
918 strcpy(pNode->shmBaseName, shmName);
919
920 #ifdef SQLITE_OS2_NO_WAL_LOCK_FILE
921 if( DosDupHandle(fd->h, &pNode->hLockFile) != 0 ) {
922 #else
923 sprintf(shmName, "%s-lck", fd->zFullPathCp);
924 if( DosOpen((PSZ)shmName, &pNode->hLockFile, &action, 0, FILE_NORMAL,
925 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
926 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE |
927 OPEN_FLAGS_NOINHERIT | OPEN_FLAGS_FAIL_ON_ERROR,
928 NULL) != 0 ) {
929 #endif
930 sqlite3_free(pNode);
931 rc = SQLITE_IOERR;
932 } else {
933 pNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
934 if( !pNode->mutex ) {
935 sqlite3_free(pNode);
936 rc = SQLITE_NOMEM;
937 }
938 }
939 } else {
940 rc = SQLITE_NOMEM;
941 }
942
943 if( rc == SQLITE_OK ) {
944 pNode->pNext = os2ShmNodeList;
945 os2ShmNodeList = pNode;
946 } else {
947 pNode = NULL;
948 }
949 } else if( pNode->szRegion != szRegion ) {
950 rc = SQLITE_IOERR_SHMSIZE;
951 pNode = NULL;
952 }
953
954 if( pNode ) {
955 sqlite3_mutex_enter(pNode->mutex);
956
957 memset(pLink, 0, sizeof(*pLink));
958
959 pLink->pShmNode = pNode;
960 pLink->pNext = pNode->pFirst;
961 pNode->pFirst = pLink;
962 pNode->nRef++;
963
964 fd->pShmLink = pLink;
965
966 sqlite3_mutex_leave(pNode->mutex);
967
968 } else {
969 /* Error occured. Free our link object. */
970 sqlite3_free(pLink);
971 }
972
973 os2ShmLeaveMutex();
974
975 ERR_TRACE(rc, ("os2OpenSharedMemory: %d %s\n", rc, fd->zFullPathCp))
976
977 return rc;
978 }
979
980 /*
981 ** Purge the os2ShmNodeList list of all entries with nRef==0.
982 **
983 ** This is not a VFS shared-memory method; it is a utility function called
984 ** by VFS shared-memory methods.
985 */
986 static void os2PurgeShmNodes( int deleteFlag ) {
987 os2ShmNode *pNode;
988 os2ShmNode **ppNode;
989
990 os2ShmEnterMutex();
991
992 ppNode = &os2ShmNodeList;
993
994 while( *ppNode ) {
995 pNode = *ppNode;
996
997 if( pNode->nRef == 0 ) {
998 *ppNode = pNode->pNext;
999
1000 if( pNode->apRegion ) {
1001 /* Prevent other processes from resizing the shared memory */
1002 os2ShmSystemLock(pNode, _SHM_WRLCK_WAIT, OS2_SHM_DMS, 1);
1003
1004 while( pNode->nRegion-- ) {
1005 #ifdef SQLITE_DEBUG
1006 int rc =
1007 #endif
1008 DosFreeMem(pNode->apRegion[pNode->nRegion]);
1009
1010 OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n",
1011 (int)GetCurrentProcessId(), pNode->nRegion,
1012 rc == 0 ? "ok" : "failed"));
1013 }
1014
1015 /* Allow other processes to resize the shared memory */
1016 os2ShmSystemLock(pNode, _SHM_UNLCK, OS2_SHM_DMS, 1);
1017
1018 sqlite3_free(pNode->apRegion);
1019 }
1020
1021 DosClose(pNode->hLockFile);
1022
1023 #ifndef SQLITE_OS2_NO_WAL_LOCK_FILE
1024 if( deleteFlag ) {
1025 char fileName[CCHMAXPATH];
1026 /* Skip "\\SHAREMEM\\" */
1027 sprintf(fileName, "%s-lck", pNode->shmBaseName + 10);
1028 /* restore colon */
1029 fileName[1] = ':';
1030
1031 DosForceDelete(fileName);
1032 }
1033 #endif
1034
1035 sqlite3_mutex_free(pNode->mutex);
1036
1037 sqlite3_free(pNode);
1038
1039 } else {
1040 ppNode = &pNode->pNext;
1041 }
1042 }
1043
1044 os2ShmLeaveMutex();
1045 }
1046
1047 /*
1048 ** This function is called to obtain a pointer to region iRegion of the
1049 ** shared-memory associated with the database file id. Shared-memory regions
1050 ** are numbered starting from zero. Each shared-memory region is szRegion
1051 ** bytes in size.
1052 **
1053 ** If an error occurs, an error code is returned and *pp is set to NULL.
1054 **
1055 ** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
1056 ** region has not been allocated (by any client, including one running in a
1057 ** separate process), then *pp is set to NULL and SQLITE_OK returned. If
1058 ** bExtend is non-zero and the requested shared-memory region has not yet
1059 ** been allocated, it is allocated by this function.
1060 **
1061 ** If the shared-memory region has already been allocated or is allocated by
1062 ** this call as described above, then it is mapped into this processes
1063 ** address space (if it is not already), *pp is set to point to the mapped
1064 ** memory and SQLITE_OK returned.
1065 */
1066 static int os2ShmMap(
1067 sqlite3_file *id, /* Handle open on database file */
1068 int iRegion, /* Region to retrieve */
1069 int szRegion, /* Size of regions */
1070 int bExtend, /* True to extend block if necessary */
1071 void volatile **pp /* OUT: Mapped memory */
1072 ){
1073 PVOID pvTemp;
1074 void **apRegion;
1075 os2ShmNode *pNode;
1076 int n, rc = SQLITE_OK;
1077 char shmName[CCHMAXPATH];
1078 os2File *pFile = (os2File*)id;
1079
1080 *pp = NULL;
1081
1082 if( !pFile->pShmLink )
1083 rc = os2OpenSharedMemory( pFile, szRegion );
1084
1085 if( rc == SQLITE_OK ) {
1086 pNode = pFile->pShmLink->pShmNode ;
1087
1088 sqlite3_mutex_enter(pNode->mutex);
1089
1090 assert( szRegion==pNode->szRegion );
1091
1092 /* Unmapped region ? */
1093 if( iRegion >= pNode->nRegion ) {
1094 /* Prevent other processes from resizing the shared memory */
1095 os2ShmSystemLock(pNode, _SHM_WRLCK_WAIT, OS2_SHM_DMS, 1);
1096
1097 apRegion = sqlite3_realloc(
1098 pNode->apRegion, (iRegion + 1) * sizeof(apRegion[0]));
1099
1100 if( apRegion ) {
1101 pNode->apRegion = apRegion;
1102
1103 while( pNode->nRegion <= iRegion ) {
1104 sprintf(shmName, "%s-%u",
1105 pNode->shmBaseName, pNode->nRegion);
1106
1107 if( DosGetNamedSharedMem(&pvTemp, (PSZ)shmName,
1108 PAG_READ | PAG_WRITE) != NO_ERROR ) {
1109 if( !bExtend )
1110 break;
1111
1112 if( DosAllocSharedMem(&pvTemp, (PSZ)shmName, szRegion,
1113 PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_ANY) != NO_ERROR &&
1114 DosAllocSharedMem(&pvTemp, (PSZ)shmName, szRegion,
1115 PAG_READ | PAG_WRITE | PAG_COMMIT) != NO_ERROR ) {
1116 rc = SQLITE_NOMEM;
1117 break;
1118 }
1119 }
1120
1121 apRegion[pNode->nRegion++] = pvTemp;
1122 }
1123
1124 /* zero out remaining entries */
1125 for( n = pNode->nRegion; n <= iRegion; n++ )
1126 pNode->apRegion[n] = NULL;
1127
1128 /* Return this region (maybe zero) */
1129 *pp = pNode->apRegion[iRegion];
1130 } else {
1131 rc = SQLITE_NOMEM;
1132 }
1133
1134 /* Allow other processes to resize the shared memory */
1135 os2ShmSystemLock(pNode, _SHM_UNLCK, OS2_SHM_DMS, 1);
1136
1137 } else {
1138 /* Region has been mapped previously */
1139 *pp = pNode->apRegion[iRegion];
1140 }
1141
1142 sqlite3_mutex_leave(pNode->mutex);
1143 }
1144
1145 ERR_TRACE(rc, ("os2ShmMap: %s iRgn = %d, szRgn = %d, bExt = %d : %d\n",
1146 pFile->zFullPathCp, iRegion, szRegion, bExtend, rc))
1147
1148 return rc;
1149 }
1150
1151 /*
1152 ** Close a connection to shared-memory. Delete the underlying
1153 ** storage if deleteFlag is true.
1154 **
1155 ** If there is no shared memory associated with the connection then this
1156 ** routine is a harmless no-op.
1157 */
1158 static int os2ShmUnmap(
1159 sqlite3_file *id, /* The underlying database file */
1160 int deleteFlag /* Delete shared-memory if true */
1161 ){
1162 os2File *pFile = (os2File*)id;
1163 os2ShmLink *pLink = pFile->pShmLink;
1164
1165 if( pLink ) {
1166 int nRef = -1;
1167 os2ShmLink **ppLink;
1168 os2ShmNode *pNode = pLink->pShmNode;
1169
1170 sqlite3_mutex_enter(pNode->mutex);
1171
1172 for( ppLink = &pNode->pFirst;
1173 *ppLink && *ppLink != pLink;
1174 ppLink = &(*ppLink)->pNext ) ;
1175
1176 assert(*ppLink);
1177
1178 if( *ppLink ) {
1179 *ppLink = pLink->pNext;
1180 nRef = --pNode->nRef;
1181 } else {
1182 ERR_TRACE(1, ("os2ShmUnmap: link not found ! %s\n",
1183 pNode->shmBaseName))
1184 }
1185
1186 pFile->pShmLink = NULL;
1187 sqlite3_free(pLink);
1188
1189 sqlite3_mutex_leave(pNode->mutex);
1190
1191 if( nRef == 0 )
1192 os2PurgeShmNodes( deleteFlag );
1193 }
1194
1195 return SQLITE_OK;
1196 }
1197
1198 /*
1199 ** Change the lock state for a shared-memory segment.
1200 **
1201 ** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
1202 ** different here than in posix. In xShmLock(), one can go from unlocked
1203 ** to shared and back or from unlocked to exclusive and back. But one may
1204 ** not go from shared to exclusive or from exclusive to shared.
1205 */
1206 static int os2ShmLock(
1207 sqlite3_file *id, /* Database file holding the shared memory */
1208 int ofst, /* First lock to acquire or release */
1209 int n, /* Number of locks to acquire or release */
1210 int flags /* What to do with the lock */
1211 ){
1212 u32 mask; /* Mask of locks to take or release */
1213 int rc = SQLITE_OK; /* Result code */
1214 os2File *pFile = (os2File*)id;
1215 os2ShmLink *p = pFile->pShmLink; /* The shared memory being locked */
1216 os2ShmLink *pX; /* For looping over all siblings */
1217 os2ShmNode *pShmNode = p->pShmNode; /* Our node */
1218
1219 assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
1220 assert( n>=1 );
1221 assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
1222 || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
1223 || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
1224 || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
1225 assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
1226
1227 mask = (u32)((1U<<(ofst+n)) - (1U<<ofst));
1228 assert( n>1 || mask==(1<<ofst) );
1229
1230
1231 sqlite3_mutex_enter(pShmNode->mutex);
1232
1233 if( flags & SQLITE_SHM_UNLOCK ){
1234 u32 allMask = 0; /* Mask of locks held by siblings */
1235
1236 /* See if any siblings hold this same lock */
1237 for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
1238 if( pX==p ) continue;
1239 assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
1240 allMask |= pX->sharedMask;
1241 }
1242
1243 /* Unlock the system-level locks */
1244 if( (mask & allMask)==0 ){
1245 rc = os2ShmSystemLock(pShmNode, _SHM_UNLCK, ofst+OS2_SHM_BASE, n);
1246 }else{
1247 rc = SQLITE_OK;
1248 }
1249
1250 /* Undo the local locks */
1251 if( rc==SQLITE_OK ){
1252 p->exclMask &= ~mask;
1253 p->sharedMask &= ~mask;
1254 }
1255 }else if( flags & SQLITE_SHM_SHARED ){
1256 u32 allShared = 0; /* Union of locks held by connections other than "p" */
1257
1258 /* Find out which shared locks are already held by sibling connections.
1259 ** If any sibling already holds an exclusive lock, go ahead and return
1260 ** SQLITE_BUSY.
1261 */
1262 for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
1263 if( (pX->exclMask & mask)!=0 ){
1264 rc = SQLITE_BUSY;
1265 break;
1266 }
1267 allShared |= pX->sharedMask;
1268 }
1269
1270 /* Get shared locks at the system level, if necessary */
1271 if( rc==SQLITE_OK ){
1272 if( (allShared & mask)==0 ){
1273 rc = os2ShmSystemLock(pShmNode, _SHM_RDLCK, ofst+OS2_SHM_BASE, n);
1274 }else{
1275 rc = SQLITE_OK;
1276 }
1277 }
1278
1279 /* Get the local shared locks */
1280 if( rc==SQLITE_OK ){
1281 p->sharedMask |= mask;
1282 }
1283 }else{
1284 /* Make sure no sibling connections hold locks that will block this
1285 ** lock. If any do, return SQLITE_BUSY right away.
1286 */
1287 for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
1288 if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
1289 rc = SQLITE_BUSY;
1290 break;
1291 }
1292 }
1293
1294 /* Get the exclusive locks at the system level. Then if successful
1295 ** also mark the local connection as being locked.
1296 */
1297 if( rc==SQLITE_OK ){
1298 rc = os2ShmSystemLock(pShmNode, _SHM_WRLCK, ofst+OS2_SHM_BASE, n);
1299 if( rc==SQLITE_OK ){
1300 assert( (p->sharedMask & mask)==0 );
1301 p->exclMask |= mask;
1302 }
1303 }
1304 }
1305
1306 sqlite3_mutex_leave(pShmNode->mutex);
1307
1308 OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n",
1309 p->id, (int)GetCurrentProcessId(), p->sharedMask, p->exclMask,
1310 rc ? "failed" : "ok"));
1311
1312 ERR_TRACE(rc, ("os2ShmLock: ofst = %d, n = %d, flags = 0x%x -> %d \n",
1313 ofst, n, flags, rc))
1314
1315 return rc;
1316 }
1317
1318 /*
1319 ** Implement a memory barrier or memory fence on shared memory.
1320 **
1321 ** All loads and stores begun before the barrier must complete before
1322 ** any load or store begun after the barrier.
1323 */
1324 static void os2ShmBarrier(
1325 sqlite3_file *id /* Database file holding the shared memory */
1326 ){
1327 UNUSED_PARAMETER(id);
1328 os2ShmEnterMutex();
1329 os2ShmLeaveMutex();
1330 }
1331
1332 #else
1333 # define os2ShmMap 0
1334 # define os2ShmLock 0
1335 # define os2ShmBarrier 0
1336 # define os2ShmUnmap 0
1337 #endif /* #ifndef SQLITE_OMIT_WAL */
1338
1339
1340 /*
1341 ** This vector defines all the methods that can operate on an
1342 ** sqlite3_file for os2.
1343 */
1344 static const sqlite3_io_methods os2IoMethod = {
1345 2, /* iVersion */
1346 os2Close, /* xClose */
1347 os2Read, /* xRead */
1348 os2Write, /* xWrite */
1349 os2Truncate, /* xTruncate */
1350 os2Sync, /* xSync */
1351 os2FileSize, /* xFileSize */
1352 os2Lock, /* xLock */
1353 os2Unlock, /* xUnlock */
1354 os2CheckReservedLock, /* xCheckReservedLock */
1355 os2FileControl, /* xFileControl */
1356 os2SectorSize, /* xSectorSize */
1357 os2DeviceCharacteristics, /* xDeviceCharacteristics */
1358 os2ShmMap, /* xShmMap */
1359 os2ShmLock, /* xShmLock */
1360 os2ShmBarrier, /* xShmBarrier */
1361 os2ShmUnmap /* xShmUnmap */
1362 };
1363
1364
1365 /***************************************************************************
1366 ** Here ends the I/O methods that form the sqlite3_io_methods object.
1367 **
1368 ** The next block of code implements the VFS methods.
1369 ****************************************************************************/
1370
1371 /*
1372 ** Create a temporary file name in zBuf. zBuf must be big enough to
1373 ** hold at pVfs->mxPathname characters.
1374 */
1375 static int getTempname(int nBuf, char *zBuf ){
1376 static const char zChars[] =
1377 "abcdefghijklmnopqrstuvwxyz"
1378 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1379 "0123456789";
1380 int i, j;
1381 PSZ zTempPathCp;
1382 char zTempPath[CCHMAXPATH];
1383 ULONG ulDriveNum, ulDriveMap;
1384
1385 /* It's odd to simulate an io-error here, but really this is just
1386 ** using the io-error infrastructure to test that SQLite handles this
1387 ** function failing.
1388 */
1389 SimulateIOError( return SQLITE_IOERR );
1390
1391 if( sqlite3_temp_directory ) {
1392 sqlite3_snprintf(CCHMAXPATH-30, zTempPath, "%s", sqlite3_temp_directory);
1393 } else if( DosScanEnv( (PSZ)"TEMP", &zTempPathCp ) == NO_ERROR ||
1394 DosScanEnv( (PSZ)"TMP", &zTempPathCp ) == NO_ERROR ||
1395 DosScanEnv( (PSZ)"TMPDIR", &zTempPathCp ) == NO_ERROR ) {
1396 char *zTempPathUTF = convertCpPathToUtf8( (char *)zTempPathCp );
1397 sqlite3_snprintf(CCHMAXPATH-30, zTempPath, "%s", zTempPathUTF);
1398 free( zTempPathUTF );
1399 } else if( DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap ) == NO_ERROR ) {
1400 zTempPath[0] = (char)('A' + ulDriveNum - 1);
1401 zTempPath[1] = ':';
1402 zTempPath[2] = '\0';
1403 } else {
1404 zTempPath[0] = '\0';
1405 }
1406
1407 /* Strip off a trailing slashes or backslashes, otherwise we would get *
1408 * multiple (back)slashes which causes DosOpen() to fail. *
1409 * Trailing spaces are not allowed, either. */
1410 j = sqlite3Strlen30(zTempPath);
1411 while( j > 0 && ( zTempPath[j-1] == '\\' || zTempPath[j-1] == '/' ||
1412 zTempPath[j-1] == ' ' ) ){
1413 j--;
1414 }
1415 zTempPath[j] = '\0';
1416
1417 /* We use 20 bytes to randomize the name */
1418 sqlite3_snprintf(nBuf-22, zBuf,
1419 "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
1420 j = sqlite3Strlen30(zBuf);
1421 sqlite3_randomness( 20, &zBuf[j] );
1422 for( i = 0; i < 20; i++, j++ ){
1423 zBuf[j] = zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
1424 }
1425 zBuf[j] = 0;
1426
1427 OSTRACE(( "TEMP FILENAME: %s\n", zBuf ));
1428 return SQLITE_OK;
1429 }
1430
1431
1432 /*
1433 ** Turn a relative pathname into a full pathname. Write the full
1434 ** pathname into zFull[]. zFull[] will be at least pVfs->mxPathname
1435 ** bytes in size.
1436 */
1437 static int os2FullPathname(
1438 sqlite3_vfs *pVfs, /* Pointer to vfs object */
1439 const char *zRelative, /* Possibly relative input path */
1440 int nFull, /* Size of output buffer in bytes */
1441 char *zFull /* Output buffer */
1442 ){
1443 char *zRelativeCp = convertUtf8PathToCp( zRelative );
1444 char zFullCp[CCHMAXPATH] = "\0";
1445 char *zFullUTF;
1446 APIRET rc = DosQueryPathInfo( (PSZ)zRelativeCp, FIL_QUERYFULLNAME,
1447 zFullCp, CCHMAXPATH );
1448 free( zRelativeCp );
1449 zFullUTF = convertCpPathToUtf8( zFullCp );
1450 sqlite3_snprintf( nFull, zFull, zFullUTF );
1451 free( zFullUTF );
1452 return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
1453 }
1454
1455
1456 /*
1457 ** Open a file.
1458 */
1459 static int os2Open(
1460 sqlite3_vfs *pVfs, /* Not used */
1461 const char *zName, /* Name of the file (UTF-8) */
1462 sqlite3_file *id, /* Write the SQLite file handle here */
1463 int flags, /* Open mode flags */
1464 int *pOutFlags /* Status return flags */
1465 ){
1466 HFILE h;
1467 ULONG ulOpenFlags = 0;
1468 ULONG ulOpenMode = 0;
1469 ULONG ulAction = 0;
1470 ULONG rc;
1471 os2File *pFile = (os2File*)id;
1472 const char *zUtf8Name = zName;
1473 char *zNameCp;
1474 char zTmpname[CCHMAXPATH];
1475
1476 int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
1477 int isCreate = (flags & SQLITE_OPEN_CREATE);
1478 int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
1479 #ifndef NDEBUG
1480 int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
1481 int isReadonly = (flags & SQLITE_OPEN_READONLY);
1482 int eType = (flags & 0xFFFFFF00);
1483 int isOpenJournal = (isCreate && (
1484 eType==SQLITE_OPEN_MASTER_JOURNAL
1485 || eType==SQLITE_OPEN_MAIN_JOURNAL
1486 || eType==SQLITE_OPEN_WAL
1487 ));
1488 #endif
1489
1490 UNUSED_PARAMETER(pVfs);
1491 assert( id!=0 );
1492
1493 /* Check the following statements are true:
1494 **
1495 ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
1496 ** (b) if CREATE is set, then READWRITE must also be set, and
1497 ** (c) if EXCLUSIVE is set, then CREATE must also be set.
1498 ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
1499 */
1500 assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
1501 assert(isCreate==0 || isReadWrite);
1502 assert(isExclusive==0 || isCreate);
1503 assert(isDelete==0 || isCreate);
1504
1505 /* The main DB, main journal, WAL file and master journal are never
1506 ** automatically deleted. Nor are they ever temporary files. */
1507 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
1508 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
1509 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
1510 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
1511
1512 /* Assert that the upper layer has set one of the "file-type" flags. */
1513 assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
1514 || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
1515 || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
1516 || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
1517 );
1518
1519 memset( pFile, 0, sizeof(*pFile) );
1520 pFile->h = (HFILE)-1;
1521
1522 /* If the second argument to this function is NULL, generate a
1523 ** temporary file name to use
1524 */
1525 if( !zUtf8Name ){
1526 assert(isDelete && !isOpenJournal);
1527 rc = getTempname(CCHMAXPATH, zTmpname);
1528 if( rc!=SQLITE_OK ){
1529 return rc;
1530 }
1531 zUtf8Name = zTmpname;
1532 }
1533
1534 if( isReadWrite ){
1535 ulOpenMode |= OPEN_ACCESS_READWRITE;
1536 }else{
1537 ulOpenMode |= OPEN_ACCESS_READONLY;
1538 }
1539
1540 /* Open in random access mode for possibly better speed. Allow full
1541 ** sharing because file locks will provide exclusive access when needed.
1542 ** The handle should not be inherited by child processes and we don't
1543 ** want popups from the critical error handler.
1544 */
1545 ulOpenMode |= OPEN_FLAGS_RANDOM | OPEN_SHARE_DENYNONE |
1546 OPEN_FLAGS_NOINHERIT | OPEN_FLAGS_FAIL_ON_ERROR;
1547
1548 /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
1549 ** created. SQLite doesn't use it to indicate "exclusive access"
1550 ** as it is usually understood.
1551 */
1552 if( isExclusive ){
1553 /* Creates a new file, only if it does not already exist. */
1554 /* If the file exists, it fails. */
1555 ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
1556 }else if( isCreate ){
1557 /* Open existing file, or create if it doesn't exist */
1558 ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1559 }else{
1560 /* Opens a file, only if it exists. */
1561 ulOpenFlags |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1562 }
1563
1564 zNameCp = convertUtf8PathToCp( zUtf8Name );
1565 rc = DosOpen( (PSZ)zNameCp,
1566 &h,
1567 &ulAction,
1568 0L,
1569 FILE_NORMAL,
1570 ulOpenFlags,
1571 ulOpenMode,
1572 (PEAOP2)NULL );
1573 free( zNameCp );
1574
1575 if( rc != NO_ERROR ){
1576 OSTRACE(( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
1577 rc, zUtf8Name, ulAction, ulOpenFlags, ulOpenMode ));
1578
1579 if( isReadWrite ){
1580 return os2Open( pVfs, zName, id,
1581 ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
1582 pOutFlags );
1583 }else{
1584 return SQLITE_CANTOPEN;
1585 }
1586 }
1587
1588 if( pOutFlags ){
1589 *pOutFlags = isReadWrite ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
1590 }
1591
1592 os2FullPathname( pVfs, zUtf8Name, sizeof( zTmpname ), zTmpname );
1593 pFile->zFullPathCp = convertUtf8PathToCp( zTmpname );
1594 pFile->pMethod = &os2IoMethod;
1595 pFile->flags = flags;
1596 pFile->h = h;
1597
1598 OpenCounter(+1);
1599 OSTRACE(( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags ));
1600 return SQLITE_OK;
1601 }
1602
1603 /*
1604 ** Delete the named file.
1605 */
1606 static int os2Delete(
1607 sqlite3_vfs *pVfs, /* Not used on os2 */
1608 const char *zFilename, /* Name of file to delete */
1609 int syncDir /* Not used on os2 */
1610 ){
1611 APIRET rc;
1612 char *zFilenameCp;
1613 SimulateIOError( return SQLITE_IOERR_DELETE );
1614 zFilenameCp = convertUtf8PathToCp( zFilename );
1615 rc = DosDelete( (PSZ)zFilenameCp );
1616 free( zFilenameCp );
1617 OSTRACE(( "DELETE \"%s\"\n", zFilename ));
1618 return (rc == NO_ERROR ||
1619 rc == ERROR_FILE_NOT_FOUND ||
1620 rc == ERROR_PATH_NOT_FOUND ) ? SQLITE_OK : SQLITE_IOERR_DELETE;
1621 }
1622
1623 /*
1624 ** Check the existance and status of a file.
1625 */
1626 static int os2Access(
1627 sqlite3_vfs *pVfs, /* Not used on os2 */
1628 const char *zFilename, /* Name of file to check */
1629 int flags, /* Type of test to make on this file */
1630 int *pOut /* Write results here */
1631 ){
1632 APIRET rc;
1633 FILESTATUS3 fsts3ConfigInfo;
1634 char *zFilenameCp;
1635
1636 UNUSED_PARAMETER(pVfs);
1637 SimulateIOError( return SQLITE_IOERR_ACCESS; );
1638
1639 zFilenameCp = convertUtf8PathToCp( zFilename );
1640 rc = DosQueryPathInfo( (PSZ)zFilenameCp, FIL_STANDARD,
1641 &fsts3ConfigInfo, sizeof(FILESTATUS3) );
1642 free( zFilenameCp );
1643 OSTRACE(( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n",
1644 fsts3ConfigInfo.attrFile, flags, rc ));
1645
1646 switch( flags ){
1647 case SQLITE_ACCESS_EXISTS:
1648 /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
1649 ** as if it does not exist.
1650 */
1651 if( fsts3ConfigInfo.cbFile == 0 )
1652 rc = ERROR_FILE_NOT_FOUND;
1653 break;
1654 case SQLITE_ACCESS_READ:
1655 break;
1656 case SQLITE_ACCESS_READWRITE:
1657 if( fsts3ConfigInfo.attrFile & FILE_READONLY )
1658 rc = ERROR_ACCESS_DENIED;
1659 break;
1660 default:
1661 rc = ERROR_FILE_NOT_FOUND;
1662 assert( !"Invalid flags argument" );
1663 }
1664
1665 *pOut = (rc == NO_ERROR);
1666 OSTRACE(( "ACCESS %s flags %d: rc=%d\n", zFilename, flags, *pOut ));
1667
1668 return SQLITE_OK;
1669 }
1670
1671
1672 #ifndef SQLITE_OMIT_LOAD_EXTENSION
1673 /*
1674 ** Interfaces for opening a shared library, finding entry points
1675 ** within the shared library, and closing the shared library.
1676 */
1677 /*
1678 ** Interfaces for opening a shared library, finding entry points
1679 ** within the shared library, and closing the shared library.
1680 */
1681 static void *os2DlOpen(sqlite3_vfs *pVfs, const char *zFilename){
1682 HMODULE hmod;
1683 APIRET rc;
1684 char *zFilenameCp = convertUtf8PathToCp(zFilename);
1685 rc = DosLoadModule(NULL, 0, (PSZ)zFilenameCp, &hmod);
1686 free(zFilenameCp);
1687 return rc != NO_ERROR ? 0 : (void*)hmod;
1688 }
1689 /*
1690 ** A no-op since the error code is returned on the DosLoadModule call.
1691 ** os2Dlopen returns zero if DosLoadModule is not successful.
1692 */
1693 static void os2DlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
1694 /* no-op */
1695 }
1696 static void (*os2DlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
1697 PFN pfn;
1698 APIRET rc;
1699 rc = DosQueryProcAddr((HMODULE)pHandle, 0L, (PSZ)zSymbol, &pfn);
1700 if( rc != NO_ERROR ){
1701 /* if the symbol itself was not found, search again for the same
1702 * symbol with an extra underscore, that might be needed depending
1703 * on the calling convention */
1704 char _zSymbol[256] = "_";
1705 strncat(_zSymbol, zSymbol, 254);
1706 rc = DosQueryProcAddr((HMODULE)pHandle, 0L, (PSZ)_zSymbol, &pfn);
1707 }
1708 return rc != NO_ERROR ? 0 : (void(*)(void))pfn;
1709 }
1710 static void os2DlClose(sqlite3_vfs *pVfs, void *pHandle){
1711 DosFreeModule((HMODULE)pHandle);
1712 }
1713 #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
1714 #define os2DlOpen 0
1715 #define os2DlError 0
1716 #define os2DlSym 0
1717 #define os2DlClose 0
1718 #endif
1719
1720
1721 /*
1722 ** Write up to nBuf bytes of randomness into zBuf.
1723 */
1724 static int os2Randomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf ){
1725 int n = 0;
1726 #if defined(SQLITE_TEST)
1727 n = nBuf;
1728 memset(zBuf, 0, nBuf);
1729 #else
1730 int i;
1731 PPIB ppib;
1732 PTIB ptib;
1733 DATETIME dt;
1734 static unsigned c = 0;
1735 /* Ordered by variation probability */
1736 static ULONG svIdx[6] = { QSV_MS_COUNT, QSV_TIME_LOW,
1737 QSV_MAXPRMEM, QSV_MAXSHMEM,
1738 QSV_TOTAVAILMEM, QSV_TOTRESMEM };
1739
1740 /* 8 bytes; timezone and weekday don't increase the randomness much */
1741 if( (int)sizeof(dt)-3 <= nBuf - n ){
1742 c += 0x0100;
1743 DosGetDateTime(&dt);
1744 dt.year = (USHORT)((dt.year - 1900) | c);
1745 memcpy(&zBuf[n], &dt, sizeof(dt)-3);
1746 n += sizeof(dt)-3;
1747 }
1748
1749 /* 4 bytes; PIDs and TIDs are 16 bit internally, so combine them */
1750 if( (int)sizeof(ULONG) <= nBuf - n ){
1751 DosGetInfoBlocks(&ptib, &ppib);
1752 *(PULONG)&zBuf[n] = MAKELONG(ppib->pib_ulpid,
1753 ptib->tib_ptib2->tib2_ultid);
1754 n += sizeof(ULONG);
1755 }
1756
1757 /* Up to 6 * 4 bytes; variables depend on the system state */
1758 for( i = 0; i < 6 && (int)sizeof(ULONG) <= nBuf - n; i++ ){
1759 DosQuerySysInfo(svIdx[i], svIdx[i],
1760 (PULONG)&zBuf[n], sizeof(ULONG));
1761 n += sizeof(ULONG);
1762 }
1763 #endif
1764
1765 return n;
1766 }
1767
1768 /*
1769 ** Sleep for a little while. Return the amount of time slept.
1770 ** The argument is the number of microseconds we want to sleep.
1771 ** The return value is the number of microseconds of sleep actually
1772 ** requested from the underlying operating system, a number which
1773 ** might be greater than or equal to the argument, but not less
1774 ** than the argument.
1775 */
1776 static int os2Sleep( sqlite3_vfs *pVfs, int microsec ){
1777 DosSleep( (microsec/1000) );
1778 return microsec;
1779 }
1780
1781 /*
1782 ** The following variable, if set to a non-zero value, becomes the result
1783 ** returned from sqlite3OsCurrentTime(). This is used for testing.
1784 */
1785 #ifdef SQLITE_TEST
1786 int sqlite3_current_time = 0;
1787 #endif
1788
1789 /*
1790 ** Find the current time (in Universal Coordinated Time). Write into *piNow
1791 ** the current time and date as a Julian Day number times 86_400_000. In
1792 ** other words, write into *piNow the number of milliseconds since the Julian
1793 ** epoch of noon in Greenwich on November 24, 4714 B.C according to the
1794 ** proleptic Gregorian calendar.
1795 **
1796 ** On success, return 0. Return 1 if the time and date cannot be found.
1797 */
1798 static int os2CurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
1799 #ifdef SQLITE_TEST
1800 static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
1801 #endif
1802 int year, month, datepart, timepart;
1803
1804 DATETIME dt;
1805 DosGetDateTime( &dt );
1806
1807 year = dt.year;
1808 month = dt.month;
1809
1810 /* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html
1811 ** http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c
1812 ** Calculate the Julian days
1813 */
1814 datepart = (int)dt.day - 32076 +
1815 1461*(year + 4800 + (month - 14)/12)/4 +
1816 367*(month - 2 - (month - 14)/12*12)/12 -
1817 3*((year + 4900 + (month - 14)/12)/100)/4;
1818
1819 /* Time in milliseconds, hours to noon added */
1820 timepart = 12*3600*1000 + dt.hundredths*10 + dt.seconds*1000 +
1821 ((int)dt.minutes + dt.timezone)*60*1000 + dt.hours*3600*1000;
1822
1823 *piNow = (sqlite3_int64)datepart*86400*1000 + timepart;
1824
1825 #ifdef SQLITE_TEST
1826 if( sqlite3_current_time ){
1827 *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
1828 }
1829 #endif
1830
1831 UNUSED_PARAMETER(pVfs);
1832 return 0;
1833 }
1834
1835 /*
1836 ** Find the current time (in Universal Coordinated Time). Write the
1837 ** current time and date as a Julian Day number into *prNow and
1838 ** return 0. Return 1 if the time and date cannot be found.
1839 */
1840 static int os2CurrentTime( sqlite3_vfs *pVfs, double *prNow ){
1841 int rc;
1842 sqlite3_int64 i;
1843 rc = os2CurrentTimeInt64(pVfs, &i);
1844 if( !rc ){
1845 *prNow = i/86400000.0;
1846 }
1847 return rc;
1848 }
1849
1850 /*
1851 ** The idea is that this function works like a combination of
1852 ** GetLastError() and FormatMessage() on windows (or errno and
1853 ** strerror_r() on unix). After an error is returned by an OS
1854 ** function, SQLite calls this function with zBuf pointing to
1855 ** a buffer of nBuf bytes. The OS layer should populate the
1856 ** buffer with a nul-terminated UTF-8 encoded error message
1857 ** describing the last IO error to have occurred within the calling
1858 ** thread.
1859 **
1860 ** If the error message is too large for the supplied buffer,
1861 ** it should be truncated. The return value of xGetLastError
1862 ** is zero if the error message fits in the buffer, or non-zero
1863 ** otherwise (if the message was truncated). If non-zero is returned,
1864 ** then it is not necessary to include the nul-terminator character
1865 ** in the output buffer.
1866 **
1867 ** Not supplying an error message will have no adverse effect
1868 ** on SQLite. It is fine to have an implementation that never
1869 ** returns an error message:
1870 **
1871 ** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
1872 ** assert(zBuf[0]=='\0');
1873 ** return 0;
1874 ** }
1875 **
1876 ** However if an error message is supplied, it will be incorporated
1877 ** by sqlite into the error message available to the user using
1878 ** sqlite3_errmsg(), possibly making IO errors easier to debug.
1879 */
1880 static int os2GetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
1881 assert(zBuf[0]=='\0');
1882 return 0;
1883 }
1884
1885 /*
1886 ** Initialize and deinitialize the operating system interface.
1887 */
1888 int sqlite3_os_init(void){
1889 static sqlite3_vfs os2Vfs = {
1890 3, /* iVersion */
1891 sizeof(os2File), /* szOsFile */
1892 CCHMAXPATH, /* mxPathname */
1893 0, /* pNext */
1894 "os2", /* zName */
1895 0, /* pAppData */
1896
1897 os2Open, /* xOpen */
1898 os2Delete, /* xDelete */
1899 os2Access, /* xAccess */
1900 os2FullPathname, /* xFullPathname */
1901 os2DlOpen, /* xDlOpen */
1902 os2DlError, /* xDlError */
1903 os2DlSym, /* xDlSym */
1904 os2DlClose, /* xDlClose */
1905 os2Randomness, /* xRandomness */
1906 os2Sleep, /* xSleep */
1907 os2CurrentTime, /* xCurrentTime */
1908 os2GetLastError, /* xGetLastError */
1909 os2CurrentTimeInt64, /* xCurrentTimeInt64 */
1910 0, /* xSetSystemCall */
1911 0, /* xGetSystemCall */
1912 0 /* xNextSystemCall */
1913 };
1914 sqlite3_vfs_register(&os2Vfs, 1);
1915 initUconvObjects();
1916 /* sqlite3OSTrace = 1; */
1917 return SQLITE_OK;
1918 }
1919 int sqlite3_os_end(void){
1920 freeUconvObjects();
1921 return SQLITE_OK;
1922 }
1923
1924 #endif /* SQLITE_OS_OS2 */
1925