aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/sqlite/win32/os_os2.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/sqlite/win32/os_os2.c')
-rwxr-xr-xlibraries/sqlite/win32/os_os2.c1032
1 files changed, 0 insertions, 1032 deletions
diff --git a/libraries/sqlite/win32/os_os2.c b/libraries/sqlite/win32/os_os2.c
deleted file mode 100755
index c4fbe66..0000000
--- a/libraries/sqlite/win32/os_os2.c
+++ /dev/null
@@ -1,1032 +0,0 @@
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 OS_OS2
19
20/*
21** Macros used to determine whether or not to use threads.
22*/
23#if defined(THREADSAFE) && THREADSAFE
24# define SQLITE_OS2_THREADS 1
25#endif
26
27/*
28** Include code that is common to all os_*.c files
29*/
30#include "os_common.h"
31
32/*
33** The os2File structure is subclass of OsFile specific for the OS/2
34** protability layer.
35*/
36typedef struct os2File os2File;
37struct os2File {
38 IoMethod const *pMethod; /* Always the first entry */
39 HFILE h; /* Handle for accessing the file */
40 int delOnClose; /* True if file is to be deleted on close */
41 char* pathToDel; /* Name of file to delete on close */
42 unsigned char locktype; /* Type of lock currently held on this file */
43};
44
45/*
46** Do not include any of the File I/O interface procedures if the
47** SQLITE_OMIT_DISKIO macro is defined (indicating that there database
48** will be in-memory only)
49*/
50#ifndef SQLITE_OMIT_DISKIO
51
52/*
53** Delete the named file
54*/
55int sqlite3Os2Delete( const char *zFilename ){
56 APIRET rc = NO_ERROR;
57
58 rc = DosDelete( (PSZ)zFilename );
59 OSTRACE2( "DELETE \"%s\"\n", zFilename );
60 return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
61}
62
63/*
64** Return TRUE if the named file exists.
65*/
66int sqlite3Os2FileExists( const char *zFilename ){
67 FILESTATUS3 fsts3ConfigInfo;
68 memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo));
69 return DosQueryPathInfo( (PSZ)zFilename, FIL_STANDARD,
70 &fsts3ConfigInfo, sizeof(FILESTATUS3) ) == NO_ERROR;
71}
72
73/* Forward declaration */
74int allocateOs2File( os2File *pInit, OsFile **pld );
75
76/*
77** Attempt to open a file for both reading and writing. If that
78** fails, try opening it read-only. If the file does not exist,
79** try to create it.
80**
81** On success, a handle for the open file is written to *id
82** and *pReadonly is set to 0 if the file was opened for reading and
83** writing or 1 if the file was opened read-only. The function returns
84** SQLITE_OK.
85**
86** On failure, the function returns SQLITE_CANTOPEN and leaves
87** *id and *pReadonly unchanged.
88*/
89int sqlite3Os2OpenReadWrite(
90 const char *zFilename,
91 OsFile **pld,
92 int *pReadonly
93){
94 os2File f;
95 HFILE hf;
96 ULONG ulAction;
97 APIRET rc = NO_ERROR;
98
99 assert( *pld == 0 );
100 rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L,
101 FILE_ARCHIVED | FILE_NORMAL,
102 OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
103 OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
104 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, (PEAOP2)NULL );
105 if( rc != NO_ERROR ){
106 rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L,
107 FILE_ARCHIVED | FILE_NORMAL,
108 OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
109 OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
110 OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY, (PEAOP2)NULL );
111 if( rc != NO_ERROR ){
112 return SQLITE_CANTOPEN;
113 }
114 *pReadonly = 1;
115 }
116 else{
117 *pReadonly = 0;
118 }
119 f.h = hf;
120 f.locktype = NO_LOCK;
121 f.delOnClose = 0;
122 f.pathToDel = NULL;
123 OpenCounter(+1);
124 OSTRACE3( "OPEN R/W %d \"%s\"\n", hf, zFilename );
125 return allocateOs2File( &f, pld );
126}
127
128
129/*
130** Attempt to open a new file for exclusive access by this process.
131** The file will be opened for both reading and writing. To avoid
132** a potential security problem, we do not allow the file to have
133** previously existed. Nor do we allow the file to be a symbolic
134** link.
135**
136** If delFlag is true, then make arrangements to automatically delete
137** the file when it is closed.
138**
139** On success, write the file handle into *id and return SQLITE_OK.
140**
141** On failure, return SQLITE_CANTOPEN.
142*/
143int sqlite3Os2OpenExclusive( const char *zFilename, OsFile **pld, int delFlag ){
144 os2File f;
145 HFILE hf;
146 ULONG ulAction;
147 APIRET rc = NO_ERROR;
148
149 assert( *pld == 0 );
150 rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L, FILE_NORMAL,
151 OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS,
152 OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
153 OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, (PEAOP2)NULL );
154 if( rc != NO_ERROR ){
155 return SQLITE_CANTOPEN;
156 }
157
158 f.h = hf;
159 f.locktype = NO_LOCK;
160 f.delOnClose = delFlag ? 1 : 0;
161 f.pathToDel = delFlag ? sqlite3OsFullPathname( zFilename ) : NULL;
162 OpenCounter( +1 );
163 if( delFlag ) DosForceDelete( (PSZ)sqlite3OsFullPathname( zFilename ) );
164 OSTRACE3( "OPEN EX %d \"%s\"\n", hf, sqlite3OsFullPathname ( zFilename ) );
165 return allocateOs2File( &f, pld );
166}
167
168/*
169** Attempt to open a new file for read-only access.
170**
171** On success, write the file handle into *id and return SQLITE_OK.
172**
173** On failure, return SQLITE_CANTOPEN.
174*/
175int sqlite3Os2OpenReadOnly( const char *zFilename, OsFile **pld ){
176 os2File f;
177 HFILE hf;
178 ULONG ulAction;
179 APIRET rc = NO_ERROR;
180
181 assert( *pld == 0 );
182 rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L,
183 FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
184 OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
185 OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY, (PEAOP2)NULL );
186 if( rc != NO_ERROR ){
187 return SQLITE_CANTOPEN;
188 }
189 f.h = hf;
190 f.locktype = NO_LOCK;
191 f.delOnClose = 0;
192 f.pathToDel = NULL;
193 OpenCounter( +1 );
194 OSTRACE3( "OPEN RO %d \"%s\"\n", hf, zFilename );
195 return allocateOs2File( &f, pld );
196}
197
198/*
199** Attempt to open a file descriptor for the directory that contains a
200** file. This file descriptor can be used to fsync() the directory
201** in order to make sure the creation of a new file is actually written
202** to disk.
203**
204** This routine is only meaningful for Unix. It is a no-op under
205** OS/2 since OS/2 does not support hard links.
206**
207** On success, a handle for a previously open file is at *id is
208** updated with the new directory file descriptor and SQLITE_OK is
209** returned.
210**
211** On failure, the function returns SQLITE_CANTOPEN and leaves
212** *id unchanged.
213*/
214int os2OpenDirectory(
215 OsFile *id,
216 const char *zDirname
217){
218 return SQLITE_OK;
219}
220
221/*
222** Create a temporary file name in zBuf. zBuf must be big enough to
223** hold at least SQLITE_TEMPNAME_SIZE characters.
224*/
225int sqlite3Os2TempFileName( char *zBuf ){
226 static const unsigned char zChars[] =
227 "abcdefghijklmnopqrstuvwxyz"
228 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
229 "0123456789";
230 int i, j;
231 PSZ zTempPath = 0;
232 if( DosScanEnv( (PSZ)"TEMP", &zTempPath ) ){
233 if( DosScanEnv( (PSZ)"TMP", &zTempPath ) ){
234 if( DosScanEnv( (PSZ)"TMPDIR", &zTempPath ) ){
235 ULONG ulDriveNum = 0, ulDriveMap = 0;
236 DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
237 sprintf( (char*)zTempPath, "%c:", (char)( 'A' + ulDriveNum - 1 ) );
238 }
239 }
240 }
241 /* strip off a trailing slashes or backslashes, otherwise we would get *
242 * multiple (back)slashes which causes DosOpen() to fail */
243 j = strlen(zTempPath);
244 while( j > 0 && zTempPath[j-1] == '\\' || zTempPath[j-1] == '/' ){
245 j--;
246 }
247 zTempPath[j] = '\0';
248 for(;;){
249 sprintf( zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath );
250 j = strlen( zBuf );
251 sqlite3Randomness( 15, &zBuf[j] );
252 for( i = 0; i < 15; i++, j++ ){
253 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
254 }
255 zBuf[j] = 0;
256 if( !sqlite3OsFileExists( zBuf ) ) break;
257 }
258 OSTRACE2( "TEMP FILENAME: %s\n", zBuf );
259 return SQLITE_OK;
260}
261
262/*
263** Close a file.
264*/
265int os2Close( OsFile **pld ){
266 os2File *pFile;
267 APIRET rc = NO_ERROR;
268 if( pld && (pFile = (os2File*)*pld) != 0 ){
269 OSTRACE2( "CLOSE %d\n", pFile->h );
270 rc = DosClose( pFile->h );
271 pFile->locktype = NO_LOCK;
272 if( pFile->delOnClose != 0 ){
273 rc = DosForceDelete( (PSZ)pFile->pathToDel );
274 }
275 *pld = 0;
276 OpenCounter( -1 );
277 }
278
279 return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
280}
281
282/*
283** Read data from a file into a buffer. Return SQLITE_OK if all
284** bytes were read successfully and SQLITE_IOERR if anything goes
285** wrong.
286*/
287int os2Read( OsFile *id, void *pBuf, int amt ){
288 ULONG got;
289 assert( id!=0 );
290 SimulateIOError( return SQLITE_IOERR );
291 OSTRACE3( "READ %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
292 DosRead( ((os2File*)id)->h, pBuf, amt, &got );
293 if (got == (ULONG)amt)
294 return SQLITE_OK;
295 else if (got == 0)
296 return SQLITE_IOERR_READ;
297 else {
298 memset(&((char*)pBuf)[got], 0, amt-got);
299 return SQLITE_IOERR_SHORT_READ;
300 }
301}
302
303/*
304** Write data from a buffer into a file. Return SQLITE_OK on success
305** or some other error code on failure.
306*/
307int os2Write( OsFile *id, const void *pBuf, int amt ){
308 APIRET rc = NO_ERROR;
309 ULONG wrote;
310 assert( id!=0 );
311 SimulateIOError( return SQLITE_IOERR );
312 SimulateDiskfullError( return SQLITE_FULL );
313 OSTRACE3( "WRITE %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
314 while( amt > 0 &&
315 (rc = DosWrite( ((os2File*)id)->h, (PVOID)pBuf, amt, &wrote )) && wrote > 0 ){
316 amt -= wrote;
317 pBuf = &((char*)pBuf)[wrote];
318 }
319
320 return ( rc != NO_ERROR || amt > (int)wrote ) ? SQLITE_FULL : SQLITE_OK;
321}
322
323/*
324** Move the read/write pointer in a file.
325*/
326int os2Seek( OsFile *id, i64 offset ){
327 APIRET rc = NO_ERROR;
328 ULONG filePointer = 0L;
329 assert( id!=0 );
330 rc = DosSetFilePtr( ((os2File*)id)->h, offset, FILE_BEGIN, &filePointer );
331 OSTRACE3( "SEEK %d %lld\n", ((os2File*)id)->h, offset );
332 return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
333}
334
335/*
336** Make sure all writes to a particular file are committed to disk.
337*/
338int os2Sync( OsFile *id, int dataOnly ){
339 assert( id!=0 );
340 OSTRACE3( "SYNC %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
341 return DosResetBuffer( ((os2File*)id)->h ) == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
342}
343
344/*
345** Sync the directory zDirname. This is a no-op on operating systems other
346** than UNIX.
347*/
348int sqlite3Os2SyncDirectory( const char *zDirname ){
349 SimulateIOError( return SQLITE_IOERR );
350 return SQLITE_OK;
351}
352
353/*
354** Truncate an open file to a specified size
355*/
356int os2Truncate( OsFile *id, i64 nByte ){
357 APIRET rc = NO_ERROR;
358 ULONG upperBits = nByte>>32;
359 assert( id!=0 );
360 OSTRACE3( "TRUNCATE %d %lld\n", ((os2File*)id)->h, nByte );
361 SimulateIOError( return SQLITE_IOERR );
362 rc = DosSetFilePtr( ((os2File*)id)->h, nByte, FILE_BEGIN, &upperBits );
363 if( rc != NO_ERROR ){
364 return SQLITE_IOERR;
365 }
366 rc = DosSetFilePtr( ((os2File*)id)->h, 0L, FILE_END, &upperBits );
367 return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
368}
369
370/*
371** Determine the current size of a file in bytes
372*/
373int os2FileSize( OsFile *id, i64 *pSize ){
374 APIRET rc = NO_ERROR;
375 FILESTATUS3 fsts3FileInfo;
376 memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo));
377 assert( id!=0 );
378 SimulateIOError( return SQLITE_IOERR );
379 rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) );
380 if( rc == NO_ERROR ){
381 *pSize = fsts3FileInfo.cbFile;
382 return SQLITE_OK;
383 }
384 else{
385 return SQLITE_IOERR;
386 }
387}
388
389/*
390** Acquire a reader lock.
391*/
392static int getReadLock( os2File *id ){
393 FILELOCK LockArea,
394 UnlockArea;
395 memset(&LockArea, 0, sizeof(LockArea));
396 memset(&UnlockArea, 0, sizeof(UnlockArea));
397 LockArea.lOffset = SHARED_FIRST;
398 LockArea.lRange = SHARED_SIZE;
399 UnlockArea.lOffset = 0L;
400 UnlockArea.lRange = 0L;
401 return DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L );
402}
403
404/*
405** Undo a readlock
406*/
407static int unlockReadLock( os2File *id ){
408 FILELOCK LockArea,
409 UnlockArea;
410 memset(&LockArea, 0, sizeof(LockArea));
411 memset(&UnlockArea, 0, sizeof(UnlockArea));
412 LockArea.lOffset = 0L;
413 LockArea.lRange = 0L;
414 UnlockArea.lOffset = SHARED_FIRST;
415 UnlockArea.lRange = SHARED_SIZE;
416 return DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L );
417}
418
419#ifndef SQLITE_OMIT_PAGER_PRAGMAS
420/*
421** Check that a given pathname is a directory and is writable
422**
423*/
424int sqlite3Os2IsDirWritable( char *zDirname ){
425 FILESTATUS3 fsts3ConfigInfo;
426 APIRET rc = NO_ERROR;
427 memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo));
428 if( zDirname==0 ) return 0;
429 if( strlen(zDirname)>CCHMAXPATH ) return 0;
430 rc = DosQueryPathInfo( (PSZ)zDirname, FIL_STANDARD, &fsts3ConfigInfo, sizeof(FILESTATUS3) );
431 if( rc != NO_ERROR ) return 0;
432 if( (fsts3ConfigInfo.attrFile & FILE_DIRECTORY) != FILE_DIRECTORY ) return 0;
433
434 return 1;
435}
436#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
437
438/*
439** Lock the file with the lock specified by parameter locktype - one
440** of the following:
441**
442** (1) SHARED_LOCK
443** (2) RESERVED_LOCK
444** (3) PENDING_LOCK
445** (4) EXCLUSIVE_LOCK
446**
447** Sometimes when requesting one lock state, additional lock states
448** are inserted in between. The locking might fail on one of the later
449** transitions leaving the lock state different from what it started but
450** still short of its goal. The following chart shows the allowed
451** transitions and the inserted intermediate states:
452**
453** UNLOCKED -> SHARED
454** SHARED -> RESERVED
455** SHARED -> (PENDING) -> EXCLUSIVE
456** RESERVED -> (PENDING) -> EXCLUSIVE
457** PENDING -> EXCLUSIVE
458**
459** This routine will only increase a lock. The os2Unlock() routine
460** erases all locks at once and returns us immediately to locking level 0.
461** It is not possible to lower the locking level one step at a time. You
462** must go straight to locking level 0.
463*/
464int os2Lock( OsFile *id, int locktype ){
465 APIRET rc = SQLITE_OK; /* Return code from subroutines */
466 APIRET res = NO_ERROR; /* Result of an OS/2 lock call */
467 int newLocktype; /* Set id->locktype to this value before exiting */
468 int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
469 FILELOCK LockArea,
470 UnlockArea;
471 os2File *pFile = (os2File*)id;
472 memset(&LockArea, 0, sizeof(LockArea));
473 memset(&UnlockArea, 0, sizeof(UnlockArea));
474 assert( pFile!=0 );
475 OSTRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype );
476
477 /* If there is already a lock of this type or more restrictive on the
478 ** OsFile, do nothing. Don't use the end_lock: exit path, as
479 ** sqlite3OsEnterMutex() hasn't been called yet.
480 */
481 if( pFile->locktype>=locktype ){
482 return SQLITE_OK;
483 }
484
485 /* Make sure the locking sequence is correct
486 */
487 assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
488 assert( locktype!=PENDING_LOCK );
489 assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
490
491 /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
492 ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
493 ** the PENDING_LOCK byte is temporary.
494 */
495 newLocktype = pFile->locktype;
496 if( pFile->locktype==NO_LOCK
497 || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
498 ){
499 int cnt = 3;
500
501 LockArea.lOffset = PENDING_BYTE;
502 LockArea.lRange = 1L;
503 UnlockArea.lOffset = 0L;
504 UnlockArea.lRange = 0L;
505
506 while( cnt-->0 && (res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L) )!=NO_ERROR ){
507 /* Try 3 times to get the pending lock. The pending lock might be
508 ** held by another reader process who will release it momentarily.
509 */
510 OSTRACE2( "could not get a PENDING lock. cnt=%d\n", cnt );
511 DosSleep(1);
512 }
513 gotPendingLock = res;
514 }
515
516 /* Acquire a shared lock
517 */
518 if( locktype==SHARED_LOCK && res ){
519 assert( pFile->locktype==NO_LOCK );
520 res = getReadLock(pFile);
521 if( res == NO_ERROR ){
522 newLocktype = SHARED_LOCK;
523 }
524 }
525
526 /* Acquire a RESERVED lock
527 */
528 if( locktype==RESERVED_LOCK && res ){
529 assert( pFile->locktype==SHARED_LOCK );
530 LockArea.lOffset = RESERVED_BYTE;
531 LockArea.lRange = 1L;
532 UnlockArea.lOffset = 0L;
533 UnlockArea.lRange = 0L;
534 res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
535 if( res == NO_ERROR ){
536 newLocktype = RESERVED_LOCK;
537 }
538 }
539
540 /* Acquire a PENDING lock
541 */
542 if( locktype==EXCLUSIVE_LOCK && res ){
543 newLocktype = PENDING_LOCK;
544 gotPendingLock = 0;
545 }
546
547 /* Acquire an EXCLUSIVE lock
548 */
549 if( locktype==EXCLUSIVE_LOCK && res ){
550 assert( pFile->locktype>=SHARED_LOCK );
551 res = unlockReadLock(pFile);
552 OSTRACE2( "unreadlock = %d\n", res );
553 LockArea.lOffset = SHARED_FIRST;
554 LockArea.lRange = SHARED_SIZE;
555 UnlockArea.lOffset = 0L;
556 UnlockArea.lRange = 0L;
557 res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
558 if( res == NO_ERROR ){
559 newLocktype = EXCLUSIVE_LOCK;
560 }else{
561 OSTRACE2( "error-code = %d\n", res );
562 }
563 }
564
565 /* If we are holding a PENDING lock that ought to be released, then
566 ** release it now.
567 */
568 if( gotPendingLock && locktype==SHARED_LOCK ){
569 LockArea.lOffset = 0L;
570 LockArea.lRange = 0L;
571 UnlockArea.lOffset = PENDING_BYTE;
572 UnlockArea.lRange = 1L;
573 DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
574 }
575
576 /* Update the state of the lock has held in the file descriptor then
577 ** return the appropriate result code.
578 */
579 if( res == NO_ERROR ){
580 rc = SQLITE_OK;
581 }else{
582 OSTRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
583 locktype, newLocktype );
584 rc = SQLITE_BUSY;
585 }
586 pFile->locktype = newLocktype;
587 return rc;
588}
589
590/*
591** This routine checks if there is a RESERVED lock held on the specified
592** file by this or any other process. If such a lock is held, return
593** non-zero, otherwise zero.
594*/
595int os2CheckReservedLock( OsFile *id ){
596 APIRET rc = NO_ERROR;
597 os2File *pFile = (os2File*)id;
598 assert( pFile!=0 );
599 if( pFile->locktype>=RESERVED_LOCK ){
600 rc = 1;
601 OSTRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, rc );
602 }else{
603 FILELOCK LockArea,
604 UnlockArea;
605 memset(&LockArea, 0, sizeof(LockArea));
606 memset(&UnlockArea, 0, sizeof(UnlockArea));
607 LockArea.lOffset = RESERVED_BYTE;
608 LockArea.lRange = 1L;
609 UnlockArea.lOffset = 0L;
610 UnlockArea.lRange = 0L;
611 rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
612 if( rc == NO_ERROR ){
613 LockArea.lOffset = 0L;
614 LockArea.lRange = 0L;
615 UnlockArea.lOffset = RESERVED_BYTE;
616 UnlockArea.lRange = 1L;
617 rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
618 }
619 OSTRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, rc );
620 }
621 return rc;
622}
623
624/*
625** Lower the locking level on file descriptor id to locktype. locktype
626** must be either NO_LOCK or SHARED_LOCK.
627**
628** If the locking level of the file descriptor is already at or below
629** the requested locking level, this routine is a no-op.
630**
631** It is not possible for this routine to fail if the second argument
632** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
633** might return SQLITE_IOERR;
634*/
635int os2Unlock( OsFile *id, int locktype ){
636 int type;
637 APIRET rc = SQLITE_OK;
638 os2File *pFile = (os2File*)id;
639 FILELOCK LockArea,
640 UnlockArea;
641 memset(&LockArea, 0, sizeof(LockArea));
642 memset(&UnlockArea, 0, sizeof(UnlockArea));
643 assert( pFile!=0 );
644 assert( locktype<=SHARED_LOCK );
645 OSTRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype );
646 type = pFile->locktype;
647 if( type>=EXCLUSIVE_LOCK ){
648 LockArea.lOffset = 0L;
649 LockArea.lRange = 0L;
650 UnlockArea.lOffset = SHARED_FIRST;
651 UnlockArea.lRange = SHARED_SIZE;
652 DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
653 if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){
654 /* This should never happen. We should always be able to
655 ** reacquire the read lock */
656 rc = SQLITE_IOERR;
657 }
658 }
659 if( type>=RESERVED_LOCK ){
660 LockArea.lOffset = 0L;
661 LockArea.lRange = 0L;
662 UnlockArea.lOffset = RESERVED_BYTE;
663 UnlockArea.lRange = 1L;
664 DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
665 }
666 if( locktype==NO_LOCK && type>=SHARED_LOCK ){
667 unlockReadLock(pFile);
668 }
669 if( type>=PENDING_LOCK ){
670 LockArea.lOffset = 0L;
671 LockArea.lRange = 0L;
672 UnlockArea.lOffset = PENDING_BYTE;
673 UnlockArea.lRange = 1L;
674 DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
675 }
676 pFile->locktype = locktype;
677 return rc;
678}
679
680/*
681** Turn a relative pathname into a full pathname. Return a pointer
682** to the full pathname stored in space obtained from sqliteMalloc().
683** The calling function is responsible for freeing this space once it
684** is no longer needed.
685*/
686char *sqlite3Os2FullPathname( const char *zRelative ){
687 char *zFull = 0;
688 if( strchr(zRelative, ':') ){
689 sqlite3SetString( &zFull, zRelative, (char*)0 );
690 }else{
691 ULONG ulDriveNum = 0;
692 ULONG ulDriveMap = 0;
693 ULONG cbzBufLen = SQLITE_TEMPNAME_SIZE;
694 char zDrive[2];
695 char *zBuff;
696
697 zBuff = sqliteMalloc( cbzBufLen );
698 if( zBuff != 0 ){
699 DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
700 if( DosQueryCurrentDir( ulDriveNum, (PBYTE)zBuff, &cbzBufLen ) == NO_ERROR ){
701 sprintf( zDrive, "%c", (char)('A' + ulDriveNum - 1) );
702 sqlite3SetString( &zFull, zDrive, ":\\", zBuff,
703 "\\", zRelative, (char*)0 );
704 }
705 sqliteFree( zBuff );
706 }
707 }
708 return zFull;
709}
710
711/*
712** The fullSync option is meaningless on os2, or correct me if I'm wrong. This is a no-op.
713** From os_unix.c: Change the value of the fullsync flag in the given file descriptor.
714** From os_unix.c: ((unixFile*)id)->fullSync = v;
715*/
716static void os2SetFullSync( OsFile *id, int v ){
717 return;
718}
719
720/*
721** Return the underlying file handle for an OsFile
722*/
723static int os2FileHandle( OsFile *id ){
724 return (int)((os2File*)id)->h;
725}
726
727/*
728** Return an integer that indices the type of lock currently held
729** by this handle. (Used for testing and analysis only.)
730*/
731static int os2LockState( OsFile *id ){
732 return ((os2File*)id)->locktype;
733}
734
735/*
736** Return the sector size in bytes of the underlying block device for
737** the specified file. This is almost always 512 bytes, but may be
738** larger for some devices.
739**
740** SQLite code assumes this function cannot fail. It also assumes that
741** if two files are created in the same file-system directory (i.e.
742** a database and it's journal file) that the sector size will be the
743** same for both.
744*/
745static int os2SectorSize(OsFile *id){
746 return SQLITE_DEFAULT_SECTOR_SIZE;
747}
748
749/*
750** This vector defines all the methods that can operate on an OsFile
751** for os2.
752*/
753static const IoMethod sqlite3Os2IoMethod = {
754 os2Close,
755 os2OpenDirectory,
756 os2Read,
757 os2Write,
758 os2Seek,
759 os2Truncate,
760 os2Sync,
761 os2SetFullSync,
762 os2FileHandle,
763 os2FileSize,
764 os2Lock,
765 os2Unlock,
766 os2LockState,
767 os2CheckReservedLock,
768 os2SectorSize,
769};
770
771/*
772** Allocate memory for an OsFile. Initialize the new OsFile
773** to the value given in pInit and return a pointer to the new
774** OsFile. If we run out of memory, close the file and return NULL.
775*/
776int allocateOs2File( os2File *pInit, OsFile **pld ){
777 os2File *pNew;
778 pNew = sqliteMalloc( sizeof(*pNew) );
779 if( pNew==0 ){
780 DosClose( pInit->h );
781 *pld = 0;
782 return SQLITE_NOMEM;
783 }else{
784 *pNew = *pInit;
785 pNew->pMethod = &sqlite3Os2IoMethod;
786 pNew->locktype = NO_LOCK;
787 *pld = (OsFile*)pNew;
788 OpenCounter(+1);
789 return SQLITE_OK;
790 }
791}
792
793#endif /* SQLITE_OMIT_DISKIO */
794/***************************************************************************
795** Everything above deals with file I/O. Everything that follows deals
796** with other miscellanous aspects of the operating system interface
797****************************************************************************/
798
799#ifndef SQLITE_OMIT_LOAD_EXTENSION
800/*
801** Interfaces for opening a shared library, finding entry points
802** within the shared library, and closing the shared library.
803*/
804void *sqlite3Os2Dlopen(const char *zFilename){
805 UCHAR loadErr[256];
806 HMODULE hmod;
807 APIRET rc;
808 rc = DosLoadModule((PSZ)loadErr, sizeof(loadErr), zFilename, &hmod);
809 if (rc != NO_ERROR) return 0;
810 return (void*)hmod;
811}
812void *sqlite3Os2Dlsym(void *pHandle, const char *zSymbol){
813 PFN pfn;
814 APIRET rc;
815 rc = DosQueryProcAddr((HMODULE)pHandle, 0L, zSymbol, &pfn);
816 if (rc != NO_ERROR) {
817 /* if the symbol itself was not found, search again for the same
818 * symbol with an extra underscore, that might be needed depending
819 * on the calling convention */
820 char _zSymbol[256] = "_";
821 strncat(_zSymbol, zSymbol, 255);
822 rc = DosQueryProcAddr((HMODULE)pHandle, 0L, _zSymbol, &pfn);
823 }
824 if (rc != NO_ERROR) return 0;
825 return (void *)pfn;
826}
827int sqlite3Os2Dlclose(void *pHandle){
828 return DosFreeModule((HMODULE)pHandle);
829}
830#endif /* SQLITE_OMIT_LOAD_EXTENSION */
831
832
833/*
834** Get information to seed the random number generator. The seed
835** is written into the buffer zBuf[256]. The calling function must
836** supply a sufficiently large buffer.
837*/
838int sqlite3Os2RandomSeed( char *zBuf ){
839 /* We have to initialize zBuf to prevent valgrind from reporting
840 ** errors. The reports issued by valgrind are incorrect - we would
841 ** prefer that the randomness be increased by making use of the
842 ** uninitialized space in zBuf - but valgrind errors tend to worry
843 ** some users. Rather than argue, it seems easier just to initialize
844 ** the whole array and silence valgrind, even if that means less randomness
845 ** in the random seed.
846 **
847 ** When testing, initializing zBuf[] to zero is all we do. That means
848 ** that we always use the same random number sequence. This makes the
849 ** tests repeatable.
850 */
851 memset( zBuf, 0, 256 );
852 DosGetDateTime( (PDATETIME)zBuf );
853 return SQLITE_OK;
854}
855
856/*
857** Sleep for a little while. Return the amount of time slept.
858*/
859int sqlite3Os2Sleep( int ms ){
860 DosSleep( ms );
861 return ms;
862}
863
864/*
865** Static variables used for thread synchronization
866*/
867static int inMutex = 0;
868#ifdef SQLITE_OS2_THREADS
869static ULONG mutexOwner;
870#endif
871
872/*
873** The following pair of routines implement mutual exclusion for
874** multi-threaded processes. Only a single thread is allowed to
875** executed code that is surrounded by EnterMutex() and LeaveMutex().
876**
877** SQLite uses only a single Mutex. There is not much critical
878** code and what little there is executes quickly and without blocking.
879*/
880void sqlite3Os2EnterMutex(){
881#ifdef SQLITE_OS2_THREADS
882 PTIB ptib;
883 DosEnterCritSec();
884 DosGetInfoBlocks( &ptib, NULL );
885 mutexOwner = ptib->tib_ptib2->tib2_ultid;
886#endif
887 assert( !inMutex );
888 inMutex = 1;
889}
890void sqlite3Os2LeaveMutex(){
891#ifdef SQLITE_OS2_THREADS
892 PTIB ptib;
893#endif
894 assert( inMutex );
895 inMutex = 0;
896#ifdef SQLITE_OS2_THREADS
897 DosGetInfoBlocks( &ptib, NULL );
898 assert( mutexOwner == ptib->tib_ptib2->tib2_ultid );
899 DosExitCritSec();
900#endif
901}
902
903/*
904** Return TRUE if the mutex is currently held.
905**
906** If the thisThreadOnly parameter is true, return true if and only if the
907** calling thread holds the mutex. If the parameter is false, return
908** true if any thread holds the mutex.
909*/
910int sqlite3Os2InMutex( int thisThreadOnly ){
911#ifdef SQLITE_OS2_THREADS
912 PTIB ptib;
913 DosGetInfoBlocks( &ptib, NULL );
914 return inMutex>0 && (thisThreadOnly==0 || mutexOwner==ptib->tib_ptib2->tib2_ultid);
915#else
916 return inMutex>0;
917#endif
918}
919
920/*
921** The following variable, if set to a non-zero value, becomes the result
922** returned from sqlite3OsCurrentTime(). This is used for testing.
923*/
924#ifdef SQLITE_TEST
925int sqlite3_current_time = 0;
926#endif
927
928/*
929** Find the current time (in Universal Coordinated Time). Write the
930** current time and date as a Julian Day number into *prNow and
931** return 0. Return 1 if the time and date cannot be found.
932*/
933int sqlite3Os2CurrentTime( double *prNow ){
934 double now;
935 USHORT second, minute, hour,
936 day, month, year;
937 DATETIME dt;
938 DosGetDateTime( &dt );
939 second = (USHORT)dt.seconds;
940 minute = (USHORT)dt.minutes + dt.timezone;
941 hour = (USHORT)dt.hours;
942 day = (USHORT)dt.day;
943 month = (USHORT)dt.month;
944 year = (USHORT)dt.year;
945
946 /* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html
947 http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c */
948 /* Calculate the Julian days */
949 now = day - 32076 +
950 1461*(year + 4800 + (month - 14)/12)/4 +
951 367*(month - 2 - (month - 14)/12*12)/12 -
952 3*((year + 4900 + (month - 14)/12)/100)/4;
953
954 /* Add the fractional hours, mins and seconds */
955 now += (hour + 12.0)/24.0;
956 now += minute/1440.0;
957 now += second/86400.0;
958 *prNow = now;
959#ifdef SQLITE_TEST
960 if( sqlite3_current_time ){
961 *prNow = sqlite3_current_time/86400.0 + 2440587.5;
962 }
963#endif
964 return 0;
965}
966
967/*
968** Remember the number of thread-specific-data blocks allocated.
969** Use this to verify that we are not leaking thread-specific-data.
970** Ticket #1601
971*/
972#ifdef SQLITE_TEST
973int sqlite3_tsd_count = 0;
974# define TSD_COUNTER_INCR InterlockedIncrement( &sqlite3_tsd_count )
975# define TSD_COUNTER_DECR InterlockedDecrement( &sqlite3_tsd_count )
976#else
977# define TSD_COUNTER_INCR /* no-op */
978# define TSD_COUNTER_DECR /* no-op */
979#endif
980
981/*
982** If called with allocateFlag>1, then return a pointer to thread
983** specific data for the current thread. Allocate and zero the
984** thread-specific data if it does not already exist necessary.
985**
986** If called with allocateFlag==0, then check the current thread
987** specific data. Return it if it exists. If it does not exist,
988** then return NULL.
989**
990** If called with allocateFlag<0, check to see if the thread specific
991** data is allocated and is all zero. If it is then deallocate it.
992** Return a pointer to the thread specific data or NULL if it is
993** unallocated or gets deallocated.
994*/
995ThreadData *sqlite3Os2ThreadSpecificData( int allocateFlag ){
996 static ThreadData **s_ppTsd = NULL;
997 static const ThreadData zeroData = {0, 0, 0};
998 ThreadData *pTsd;
999
1000 if( !s_ppTsd ){
1001 sqlite3OsEnterMutex();
1002 if( !s_ppTsd ){
1003 PULONG pul;
1004 APIRET rc = DosAllocThreadLocalMemory(1, &pul);
1005 if( rc != NO_ERROR ){
1006 sqlite3OsLeaveMutex();
1007 return 0;
1008 }
1009 s_ppTsd = (ThreadData **)pul;
1010 }
1011 sqlite3OsLeaveMutex();
1012 }
1013 pTsd = *s_ppTsd;
1014 if( allocateFlag>0 ){
1015 if( !pTsd ){
1016 pTsd = sqlite3OsMalloc( sizeof(zeroData) );
1017 if( pTsd ){
1018 *pTsd = zeroData;
1019 *s_ppTsd = pTsd;
1020 TSD_COUNTER_INCR;
1021 }
1022 }
1023 }else if( pTsd!=0 && allocateFlag<0
1024 && memcmp( pTsd, &zeroData, sizeof(ThreadData) )==0 ){
1025 sqlite3OsFree(pTsd);
1026 *s_ppTsd = NULL;
1027 TSD_COUNTER_DECR;
1028 pTsd = 0;
1029 }
1030 return pTsd;
1031}
1032#endif /* OS_OS2 */