blob: 1dcf4b6729f6dbda7f3e7f5f155035c38bae8bc3 [file] [log] [blame]
drh60a1e4b2006-06-03 18:02:15 +00001/*
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*/
pweilbacher4fffb4f2006-12-22 20:33:13 +000015
16#if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY)
17/* os2safe.h has to be included before os2.h, needed for high mem */
18#include <os2safe.h>
19#endif
20
drh60a1e4b2006-06-03 18:02:15 +000021#include "sqliteInt.h"
22#include "os.h"
23
24#if OS_OS2
25
26/*
27** Macros used to determine whether or not to use threads.
28*/
29#if defined(THREADSAFE) && THREADSAFE
30# define SQLITE_OS2_THREADS 1
31#endif
32
33/*
34** Include code that is common to all os_*.c files
35*/
36#include "os_common.h"
37
38/*
39** The os2File structure is subclass of OsFile specific for the OS/2
40** protability layer.
41*/
42typedef struct os2File os2File;
43struct os2File {
44 IoMethod const *pMethod; /* Always the first entry */
45 HFILE h; /* Handle for accessing the file */
46 int delOnClose; /* True if file is to be deleted on close */
47 char* pathToDel; /* Name of file to delete on close */
48 unsigned char locktype; /* Type of lock currently held on this file */
49};
50
51/*
52** Do not include any of the File I/O interface procedures if the
53** SQLITE_OMIT_DISKIO macro is defined (indicating that there database
54** will be in-memory only)
55*/
56#ifndef SQLITE_OMIT_DISKIO
57
58/*
59** Delete the named file
60*/
61int sqlite3Os2Delete( const char *zFilename ){
pweilbacher04bd0c12006-06-24 12:38:59 +000062 APIRET rc = NO_ERROR;
63
64 rc = DosDelete( (PSZ)zFilename );
drh4f0c5872007-03-26 22:05:01 +000065 OSTRACE2( "DELETE \"%s\"\n", zFilename );
pweilbacher04bd0c12006-06-24 12:38:59 +000066 return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
drh60a1e4b2006-06-03 18:02:15 +000067}
68
69/*
70** Return TRUE if the named file exists.
71*/
72int sqlite3Os2FileExists( const char *zFilename ){
73 FILESTATUS3 fsts3ConfigInfo;
74 memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo));
75 return DosQueryPathInfo( (PSZ)zFilename, FIL_STANDARD,
76 &fsts3ConfigInfo, sizeof(FILESTATUS3) ) == NO_ERROR;
77}
78
79/* Forward declaration */
80int allocateOs2File( os2File *pInit, OsFile **pld );
81
82/*
83** Attempt to open a file for both reading and writing. If that
84** fails, try opening it read-only. If the file does not exist,
85** try to create it.
86**
87** On success, a handle for the open file is written to *id
88** and *pReadonly is set to 0 if the file was opened for reading and
89** writing or 1 if the file was opened read-only. The function returns
90** SQLITE_OK.
91**
92** On failure, the function returns SQLITE_CANTOPEN and leaves
93** *id and *pReadonly unchanged.
94*/
95int sqlite3Os2OpenReadWrite(
96 const char *zFilename,
97 OsFile **pld,
98 int *pReadonly
99){
100 os2File f;
101 HFILE hf;
102 ULONG ulAction;
pweilbacher04bd0c12006-06-24 12:38:59 +0000103 APIRET rc = NO_ERROR;
drh60a1e4b2006-06-03 18:02:15 +0000104
105 assert( *pld == 0 );
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_DENYNONE | OPEN_ACCESS_READWRITE, (PEAOP2)NULL );
111 if( rc != NO_ERROR ){
112 rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L,
113 FILE_ARCHIVED | FILE_NORMAL,
114 OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
115 OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
116 OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY, (PEAOP2)NULL );
117 if( rc != NO_ERROR ){
118 return SQLITE_CANTOPEN;
119 }
120 *pReadonly = 1;
121 }
122 else{
123 *pReadonly = 0;
124 }
125 f.h = hf;
126 f.locktype = NO_LOCK;
127 f.delOnClose = 0;
128 f.pathToDel = NULL;
129 OpenCounter(+1);
drh4f0c5872007-03-26 22:05:01 +0000130 OSTRACE3( "OPEN R/W %d \"%s\"\n", hf, zFilename );
drh60a1e4b2006-06-03 18:02:15 +0000131 return allocateOs2File( &f, pld );
132}
133
134
135/*
136** Attempt to open a new file for exclusive access by this process.
137** The file will be opened for both reading and writing. To avoid
138** a potential security problem, we do not allow the file to have
139** previously existed. Nor do we allow the file to be a symbolic
140** link.
141**
142** If delFlag is true, then make arrangements to automatically delete
143** the file when it is closed.
144**
145** On success, write the file handle into *id and return SQLITE_OK.
146**
147** On failure, return SQLITE_CANTOPEN.
148*/
149int sqlite3Os2OpenExclusive( const char *zFilename, OsFile **pld, int delFlag ){
150 os2File f;
151 HFILE hf;
152 ULONG ulAction;
pweilbacher04bd0c12006-06-24 12:38:59 +0000153 APIRET rc = NO_ERROR;
drh60a1e4b2006-06-03 18:02:15 +0000154
155 assert( *pld == 0 );
156 rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L, FILE_NORMAL,
157 OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS,
158 OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
159 OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, (PEAOP2)NULL );
160 if( rc != NO_ERROR ){
161 return SQLITE_CANTOPEN;
162 }
163
164 f.h = hf;
165 f.locktype = NO_LOCK;
166 f.delOnClose = delFlag ? 1 : 0;
167 f.pathToDel = delFlag ? sqlite3OsFullPathname( zFilename ) : NULL;
168 OpenCounter( +1 );
169 if( delFlag ) DosForceDelete( sqlite3OsFullPathname( zFilename ) );
drh4f0c5872007-03-26 22:05:01 +0000170 OSTRACE3( "OPEN EX %d \"%s\"\n", hf, sqlite3OsFullPathname ( zFilename ) );
drh60a1e4b2006-06-03 18:02:15 +0000171 return allocateOs2File( &f, pld );
172}
173
174/*
175** Attempt to open a new file for read-only access.
176**
177** On success, write the file handle into *id and return SQLITE_OK.
178**
179** On failure, return SQLITE_CANTOPEN.
180*/
181int sqlite3Os2OpenReadOnly( const char *zFilename, OsFile **pld ){
182 os2File f;
183 HFILE hf;
184 ULONG ulAction;
pweilbacher04bd0c12006-06-24 12:38:59 +0000185 APIRET rc = NO_ERROR;
drh60a1e4b2006-06-03 18:02:15 +0000186
187 assert( *pld == 0 );
188 rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L,
189 FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
190 OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
191 OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY, (PEAOP2)NULL );
192 if( rc != NO_ERROR ){
193 return SQLITE_CANTOPEN;
194 }
195 f.h = hf;
196 f.locktype = NO_LOCK;
197 f.delOnClose = 0;
198 f.pathToDel = NULL;
199 OpenCounter( +1 );
drh4f0c5872007-03-26 22:05:01 +0000200 OSTRACE3( "OPEN RO %d \"%s\"\n", hf, zFilename );
drh60a1e4b2006-06-03 18:02:15 +0000201 return allocateOs2File( &f, pld );
202}
203
204/*
205** Attempt to open a file descriptor for the directory that contains a
206** file. This file descriptor can be used to fsync() the directory
207** in order to make sure the creation of a new file is actually written
208** to disk.
209**
210** This routine is only meaningful for Unix. It is a no-op under
211** OS/2 since OS/2 does not support hard links.
212**
213** On success, a handle for a previously open file is at *id is
214** updated with the new directory file descriptor and SQLITE_OK is
215** returned.
216**
217** On failure, the function returns SQLITE_CANTOPEN and leaves
218** *id unchanged.
219*/
220int os2OpenDirectory(
221 OsFile *id,
222 const char *zDirname
223){
224 return SQLITE_OK;
225}
226
227/*
228** If the following global variable points to a string which is the
229** name of a directory, then that directory will be used to store
230** temporary files.
231*/
232char *sqlite3_temp_directory = 0;
233
234/*
235** Create a temporary file name in zBuf. zBuf must be big enough to
236** hold at least SQLITE_TEMPNAME_SIZE characters.
237*/
238int sqlite3Os2TempFileName( char *zBuf ){
239 static const unsigned char zChars[] =
240 "abcdefghijklmnopqrstuvwxyz"
241 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
242 "0123456789";
243 int i, j;
244 PSZ zTempPath = 0;
245 if( DosScanEnv( "TEMP", &zTempPath ) ){
246 if( DosScanEnv( "TMP", &zTempPath ) ){
247 if( DosScanEnv( "TMPDIR", &zTempPath ) ){
248 ULONG ulDriveNum = 0, ulDriveMap = 0;
249 DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
250 sprintf( zTempPath, "%c:", (char)( 'A' + ulDriveNum - 1 ) );
251 }
252 }
253 }
254 for(;;){
255 sprintf( zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath );
256 j = strlen( zBuf );
257 sqlite3Randomness( 15, &zBuf[j] );
258 for( i = 0; i < 15; i++, j++ ){
259 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
260 }
261 zBuf[j] = 0;
262 if( !sqlite3OsFileExists( zBuf ) ) break;
263 }
drh4f0c5872007-03-26 22:05:01 +0000264 OSTRACE2( "TEMP FILENAME: %s\n", zBuf );
drh60a1e4b2006-06-03 18:02:15 +0000265 return SQLITE_OK;
266}
267
268/*
269** Close a file.
270*/
271int os2Close( OsFile **pld ){
272 os2File *pFile;
pweilbacher04bd0c12006-06-24 12:38:59 +0000273 APIRET rc = NO_ERROR;
274 if( pld && (pFile = (os2File*)*pld) != 0 ){
drh4f0c5872007-03-26 22:05:01 +0000275 OSTRACE2( "CLOSE %d\n", pFile->h );
pweilbacher04bd0c12006-06-24 12:38:59 +0000276 rc = DosClose( pFile->h );
drh60a1e4b2006-06-03 18:02:15 +0000277 pFile->locktype = NO_LOCK;
278 if( pFile->delOnClose != 0 ){
pweilbacher04bd0c12006-06-24 12:38:59 +0000279 rc = DosForceDelete( pFile->pathToDel );
drh60a1e4b2006-06-03 18:02:15 +0000280 }
281 *pld = 0;
282 OpenCounter( -1 );
283 }
284
pweilbacher04bd0c12006-06-24 12:38:59 +0000285 return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
drh60a1e4b2006-06-03 18:02:15 +0000286}
287
288/*
289** Read data from a file into a buffer. Return SQLITE_OK if all
290** bytes were read successfully and SQLITE_IOERR if anything goes
291** wrong.
292*/
293int os2Read( OsFile *id, void *pBuf, int amt ){
294 ULONG got;
295 assert( id!=0 );
drh59685932006-09-14 13:47:11 +0000296 SimulateIOError( return SQLITE_IOERR );
drh4f0c5872007-03-26 22:05:01 +0000297 OSTRACE3( "READ %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
drh60a1e4b2006-06-03 18:02:15 +0000298 DosRead( ((os2File*)id)->h, pBuf, amt, &got );
pweilbacher4a53cdb2007-01-28 21:12:13 +0000299 if (got == (ULONG)amt)
300 return SQLITE_OK;
301 else if (got < 0)
302 return SQLITE_IOERR_READ;
303 else {
304 memset(&((char*)pBuf)[got], 0, amt-got);
305 return SQLITE_IOERR_SHORT_READ;
306 }
drh60a1e4b2006-06-03 18:02:15 +0000307}
308
309/*
310** Write data from a buffer into a file. Return SQLITE_OK on success
311** or some other error code on failure.
312*/
313int os2Write( OsFile *id, const void *pBuf, int amt ){
pweilbacher04bd0c12006-06-24 12:38:59 +0000314 APIRET rc = NO_ERROR;
drh60a1e4b2006-06-03 18:02:15 +0000315 ULONG wrote;
316 assert( id!=0 );
drh59685932006-09-14 13:47:11 +0000317 SimulateIOError( return SQLITE_IOERR );
318 SimulateDiskfullError( return SQLITE_FULL );
drh4f0c5872007-03-26 22:05:01 +0000319 OSTRACE3( "WRITE %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
drh60a1e4b2006-06-03 18:02:15 +0000320 while( amt > 0 &&
321 (rc = DosWrite( ((os2File*)id)->h, (PVOID)pBuf, amt, &wrote )) && wrote > 0 ){
322 amt -= wrote;
323 pBuf = &((char*)pBuf)[wrote];
324 }
325
326 return ( rc != NO_ERROR || amt > (int)wrote ) ? SQLITE_FULL : SQLITE_OK;
327}
328
329/*
330** Move the read/write pointer in a file.
331*/
332int os2Seek( OsFile *id, i64 offset ){
pweilbacher04bd0c12006-06-24 12:38:59 +0000333 APIRET rc = NO_ERROR;
drh60a1e4b2006-06-03 18:02:15 +0000334 ULONG filePointer = 0L;
335 assert( id!=0 );
336 rc = DosSetFilePtr( ((os2File*)id)->h, offset, FILE_BEGIN, &filePointer );
drh4f0c5872007-03-26 22:05:01 +0000337 OSTRACE3( "SEEK %d %lld\n", ((os2File*)id)->h, offset );
drh60a1e4b2006-06-03 18:02:15 +0000338 return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
339}
340
341/*
342** Make sure all writes to a particular file are committed to disk.
343*/
344int os2Sync( OsFile *id, int dataOnly ){
345 assert( id!=0 );
drh4f0c5872007-03-26 22:05:01 +0000346 OSTRACE3( "SYNC %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
pweilbacher04bd0c12006-06-24 12:38:59 +0000347 return DosResetBuffer( ((os2File*)id)->h ) == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
drh60a1e4b2006-06-03 18:02:15 +0000348}
349
350/*
351** Sync the directory zDirname. This is a no-op on operating systems other
352** than UNIX.
353*/
354int sqlite3Os2SyncDirectory( const char *zDirname ){
drh59685932006-09-14 13:47:11 +0000355 SimulateIOError( return SQLITE_IOERR );
drh60a1e4b2006-06-03 18:02:15 +0000356 return SQLITE_OK;
357}
358
359/*
360** Truncate an open file to a specified size
361*/
362int os2Truncate( OsFile *id, i64 nByte ){
pweilbacher04bd0c12006-06-24 12:38:59 +0000363 APIRET rc = NO_ERROR;
drh60a1e4b2006-06-03 18:02:15 +0000364 ULONG upperBits = nByte>>32;
365 assert( id!=0 );
drh4f0c5872007-03-26 22:05:01 +0000366 OSTRACE3( "TRUNCATE %d %lld\n", ((os2File*)id)->h, nByte );
drh59685932006-09-14 13:47:11 +0000367 SimulateIOError( return SQLITE_IOERR );
drh60a1e4b2006-06-03 18:02:15 +0000368 rc = DosSetFilePtr( ((os2File*)id)->h, nByte, FILE_BEGIN, &upperBits );
369 if( rc != NO_ERROR ){
370 return SQLITE_IOERR;
371 }
372 rc = DosSetFilePtr( ((os2File*)id)->h, 0L, FILE_END, &upperBits );
373 return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
374}
375
376/*
377** Determine the current size of a file in bytes
378*/
379int os2FileSize( OsFile *id, i64 *pSize ){
pweilbacher04bd0c12006-06-24 12:38:59 +0000380 APIRET rc = NO_ERROR;
drh60a1e4b2006-06-03 18:02:15 +0000381 FILESTATUS3 fsts3FileInfo;
382 memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo));
383 assert( id!=0 );
drh59685932006-09-14 13:47:11 +0000384 SimulateIOError( return SQLITE_IOERR );
drh60a1e4b2006-06-03 18:02:15 +0000385 rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) );
386 if( rc == NO_ERROR ){
387 *pSize = fsts3FileInfo.cbFile;
388 return SQLITE_OK;
389 }
390 else{
391 return SQLITE_IOERR;
392 }
393}
394
395/*
396** Acquire a reader lock.
397*/
398static int getReadLock( os2File *id ){
399 FILELOCK LockArea,
400 UnlockArea;
401 memset(&LockArea, 0, sizeof(LockArea));
402 memset(&UnlockArea, 0, sizeof(UnlockArea));
403 LockArea.lOffset = SHARED_FIRST;
404 LockArea.lRange = SHARED_SIZE;
405 UnlockArea.lOffset = 0L;
406 UnlockArea.lRange = 0L;
407 return DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L );
408}
409
410/*
411** Undo a readlock
412*/
413static int unlockReadLock( os2File *id ){
414 FILELOCK LockArea,
415 UnlockArea;
416 memset(&LockArea, 0, sizeof(LockArea));
417 memset(&UnlockArea, 0, sizeof(UnlockArea));
418 LockArea.lOffset = 0L;
419 LockArea.lRange = 0L;
420 UnlockArea.lOffset = SHARED_FIRST;
421 UnlockArea.lRange = SHARED_SIZE;
422 return DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L );
423}
424
425#ifndef SQLITE_OMIT_PAGER_PRAGMAS
426/*
427** Check that a given pathname is a directory and is writable
428**
429*/
430int sqlite3Os2IsDirWritable( char *zDirname ){
431 FILESTATUS3 fsts3ConfigInfo;
432 APIRET rc = NO_ERROR;
433 memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo));
434 if( zDirname==0 ) return 0;
435 if( strlen(zDirname)>CCHMAXPATH ) return 0;
436 rc = DosQueryPathInfo( (PSZ)zDirname, FIL_STANDARD, &fsts3ConfigInfo, sizeof(FILESTATUS3) );
437 if( rc != NO_ERROR ) return 0;
438 if( (fsts3ConfigInfo.attrFile & FILE_DIRECTORY) != FILE_DIRECTORY ) return 0;
439
440 return 1;
441}
442#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
443
444/*
445** Lock the file with the lock specified by parameter locktype - one
446** of the following:
447**
448** (1) SHARED_LOCK
449** (2) RESERVED_LOCK
450** (3) PENDING_LOCK
451** (4) EXCLUSIVE_LOCK
452**
453** Sometimes when requesting one lock state, additional lock states
454** are inserted in between. The locking might fail on one of the later
455** transitions leaving the lock state different from what it started but
456** still short of its goal. The following chart shows the allowed
457** transitions and the inserted intermediate states:
458**
459** UNLOCKED -> SHARED
460** SHARED -> RESERVED
461** SHARED -> (PENDING) -> EXCLUSIVE
462** RESERVED -> (PENDING) -> EXCLUSIVE
463** PENDING -> EXCLUSIVE
464**
465** This routine will only increase a lock. The os2Unlock() routine
466** erases all locks at once and returns us immediately to locking level 0.
467** It is not possible to lower the locking level one step at a time. You
468** must go straight to locking level 0.
469*/
470int os2Lock( OsFile *id, int locktype ){
471 APIRET rc = SQLITE_OK; /* Return code from subroutines */
pweilbacher04bd0c12006-06-24 12:38:59 +0000472 APIRET res = NO_ERROR; /* Result of an OS/2 lock call */
drh60a1e4b2006-06-03 18:02:15 +0000473 int newLocktype; /* Set id->locktype to this value before exiting */
474 int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
475 FILELOCK LockArea,
476 UnlockArea;
477 os2File *pFile = (os2File*)id;
478 memset(&LockArea, 0, sizeof(LockArea));
479 memset(&UnlockArea, 0, sizeof(UnlockArea));
480 assert( pFile!=0 );
drh4f0c5872007-03-26 22:05:01 +0000481 OSTRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype );
drh60a1e4b2006-06-03 18:02:15 +0000482
483 /* If there is already a lock of this type or more restrictive on the
484 ** OsFile, do nothing. Don't use the end_lock: exit path, as
485 ** sqlite3OsEnterMutex() hasn't been called yet.
486 */
487 if( pFile->locktype>=locktype ){
488 return SQLITE_OK;
489 }
490
491 /* Make sure the locking sequence is correct
492 */
493 assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
494 assert( locktype!=PENDING_LOCK );
495 assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
496
497 /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
498 ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
499 ** the PENDING_LOCK byte is temporary.
500 */
501 newLocktype = pFile->locktype;
502 if( pFile->locktype==NO_LOCK
503 || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
504 ){
505 int cnt = 3;
506
507 LockArea.lOffset = PENDING_BYTE;
508 LockArea.lRange = 1L;
509 UnlockArea.lOffset = 0L;
510 UnlockArea.lRange = 0L;
511
512 while( cnt-->0 && (res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L) )!=NO_ERROR ){
513 /* Try 3 times to get the pending lock. The pending lock might be
514 ** held by another reader process who will release it momentarily.
515 */
drh4f0c5872007-03-26 22:05:01 +0000516 OSTRACE2( "could not get a PENDING lock. cnt=%d\n", cnt );
drh60a1e4b2006-06-03 18:02:15 +0000517 DosSleep(1);
518 }
519 gotPendingLock = res;
520 }
521
522 /* Acquire a shared lock
523 */
524 if( locktype==SHARED_LOCK && res ){
525 assert( pFile->locktype==NO_LOCK );
526 res = getReadLock(pFile);
527 if( res == NO_ERROR ){
528 newLocktype = SHARED_LOCK;
529 }
530 }
531
532 /* Acquire a RESERVED lock
533 */
534 if( locktype==RESERVED_LOCK && res ){
535 assert( pFile->locktype==SHARED_LOCK );
536 LockArea.lOffset = RESERVED_BYTE;
537 LockArea.lRange = 1L;
538 UnlockArea.lOffset = 0L;
539 UnlockArea.lRange = 0L;
540 res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
541 if( res == NO_ERROR ){
542 newLocktype = RESERVED_LOCK;
543 }
544 }
545
546 /* Acquire a PENDING lock
547 */
548 if( locktype==EXCLUSIVE_LOCK && res ){
549 newLocktype = PENDING_LOCK;
550 gotPendingLock = 0;
551 }
552
553 /* Acquire an EXCLUSIVE lock
554 */
555 if( locktype==EXCLUSIVE_LOCK && res ){
556 assert( pFile->locktype>=SHARED_LOCK );
557 res = unlockReadLock(pFile);
drh4f0c5872007-03-26 22:05:01 +0000558 OSTRACE2( "unreadlock = %d\n", res );
drh60a1e4b2006-06-03 18:02:15 +0000559 LockArea.lOffset = SHARED_FIRST;
560 LockArea.lRange = SHARED_SIZE;
561 UnlockArea.lOffset = 0L;
562 UnlockArea.lRange = 0L;
563 res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
564 if( res == NO_ERROR ){
565 newLocktype = EXCLUSIVE_LOCK;
566 }else{
drh4f0c5872007-03-26 22:05:01 +0000567 OSTRACE2( "error-code = %d\n", res );
drh60a1e4b2006-06-03 18:02:15 +0000568 }
569 }
570
571 /* If we are holding a PENDING lock that ought to be released, then
572 ** release it now.
573 */
574 if( gotPendingLock && locktype==SHARED_LOCK ){
575 LockArea.lOffset = 0L;
576 LockArea.lRange = 0L;
577 UnlockArea.lOffset = PENDING_BYTE;
578 UnlockArea.lRange = 1L;
579 DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
580 }
581
582 /* Update the state of the lock has held in the file descriptor then
583 ** return the appropriate result code.
584 */
585 if( res == NO_ERROR ){
586 rc = SQLITE_OK;
587 }else{
drh4f0c5872007-03-26 22:05:01 +0000588 OSTRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
drh60a1e4b2006-06-03 18:02:15 +0000589 locktype, newLocktype );
590 rc = SQLITE_BUSY;
591 }
592 pFile->locktype = newLocktype;
593 return rc;
594}
595
596/*
597** This routine checks if there is a RESERVED lock held on the specified
598** file by this or any other process. If such a lock is held, return
599** non-zero, otherwise zero.
600*/
601int os2CheckReservedLock( OsFile *id ){
pweilbacher04bd0c12006-06-24 12:38:59 +0000602 APIRET rc = NO_ERROR;
drh60a1e4b2006-06-03 18:02:15 +0000603 os2File *pFile = (os2File*)id;
604 assert( pFile!=0 );
605 if( pFile->locktype>=RESERVED_LOCK ){
606 rc = 1;
drh4f0c5872007-03-26 22:05:01 +0000607 OSTRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, rc );
drh60a1e4b2006-06-03 18:02:15 +0000608 }else{
609 FILELOCK LockArea,
610 UnlockArea;
611 memset(&LockArea, 0, sizeof(LockArea));
612 memset(&UnlockArea, 0, sizeof(UnlockArea));
613 LockArea.lOffset = RESERVED_BYTE;
614 LockArea.lRange = 1L;
615 UnlockArea.lOffset = 0L;
616 UnlockArea.lRange = 0L;
617 rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
618 if( rc == NO_ERROR ){
619 LockArea.lOffset = 0L;
620 LockArea.lRange = 0L;
621 UnlockArea.lOffset = RESERVED_BYTE;
622 UnlockArea.lRange = 1L;
623 rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
624 }
drh4f0c5872007-03-26 22:05:01 +0000625 OSTRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, rc );
drh60a1e4b2006-06-03 18:02:15 +0000626 }
627 return rc;
628}
629
630/*
631** Lower the locking level on file descriptor id to locktype. locktype
632** must be either NO_LOCK or SHARED_LOCK.
633**
634** If the locking level of the file descriptor is already at or below
635** the requested locking level, this routine is a no-op.
636**
637** It is not possible for this routine to fail if the second argument
638** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
639** might return SQLITE_IOERR;
640*/
641int os2Unlock( OsFile *id, int locktype ){
642 int type;
643 APIRET rc = SQLITE_OK;
644 os2File *pFile = (os2File*)id;
645 FILELOCK LockArea,
646 UnlockArea;
647 memset(&LockArea, 0, sizeof(LockArea));
648 memset(&UnlockArea, 0, sizeof(UnlockArea));
649 assert( pFile!=0 );
650 assert( locktype<=SHARED_LOCK );
drh4f0c5872007-03-26 22:05:01 +0000651 OSTRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype );
drh60a1e4b2006-06-03 18:02:15 +0000652 type = pFile->locktype;
653 if( type>=EXCLUSIVE_LOCK ){
654 LockArea.lOffset = 0L;
655 LockArea.lRange = 0L;
656 UnlockArea.lOffset = SHARED_FIRST;
657 UnlockArea.lRange = SHARED_SIZE;
658 DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
659 if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){
660 /* This should never happen. We should always be able to
661 ** reacquire the read lock */
662 rc = SQLITE_IOERR;
663 }
664 }
665 if( type>=RESERVED_LOCK ){
666 LockArea.lOffset = 0L;
667 LockArea.lRange = 0L;
668 UnlockArea.lOffset = RESERVED_BYTE;
669 UnlockArea.lRange = 1L;
670 DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
671 }
672 if( locktype==NO_LOCK && type>=SHARED_LOCK ){
673 unlockReadLock(pFile);
674 }
675 if( type>=PENDING_LOCK ){
676 LockArea.lOffset = 0L;
677 LockArea.lRange = 0L;
678 UnlockArea.lOffset = PENDING_BYTE;
679 UnlockArea.lRange = 1L;
680 DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
681 }
682 pFile->locktype = locktype;
683 return rc;
684}
685
686/*
687** Turn a relative pathname into a full pathname. Return a pointer
688** to the full pathname stored in space obtained from sqliteMalloc().
689** The calling function is responsible for freeing this space once it
690** is no longer needed.
691*/
692char *sqlite3Os2FullPathname( const char *zRelative ){
693 char *zFull = 0;
694 if( strchr(zRelative, ':') ){
695 sqlite3SetString( &zFull, zRelative, (char*)0 );
696 }else{
697 char zBuff[SQLITE_TEMPNAME_SIZE - 2] = {0};
698 char zDrive[1] = {0};
699 ULONG cbzFullLen = SQLITE_TEMPNAME_SIZE;
700 ULONG ulDriveNum = 0;
701 ULONG ulDriveMap = 0;
702 DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
703 DosQueryCurrentDir( 0L, zBuff, &cbzFullLen );
704 zFull = sqliteMalloc( cbzFullLen );
705 sprintf( zDrive, "%c", (char)('A' + ulDriveNum - 1) );
706 sqlite3SetString( &zFull, zDrive, ":\\", zBuff, "\\", zRelative, (char*)0 );
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/*
danielk1977a3d4c882007-03-23 10:08:38 +0000736** 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 PAGER_SECTOR_SIZE;
747}
748
749/*
drh60a1e4b2006-06-03 18:02:15 +0000750** 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,
danielk1977a3d4c882007-03-23 10:08:38 +0000768 os2SectorSize,
drh60a1e4b2006-06-03 18:02:15 +0000769};
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
drh761df872006-12-21 01:29:22 +0000799#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){
pweilbacher5fecee12007-01-28 21:42:08 +0000805 UCHAR loadErr[256];
806 HMODULE hmod;
807 APIRET rc;
808 rc = DosLoadModule(loadErr, sizeof(loadErr), zFilename, &hmod);
809 if (rc != NO_ERROR) return 0;
810 return (void*)hmod;
drh761df872006-12-21 01:29:22 +0000811}
812void *sqlite3Os2Dlsym(void *pHandle, const char *zSymbol){
pweilbacher5fecee12007-01-28 21:42:08 +0000813 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 pfn;
drh761df872006-12-21 01:29:22 +0000826}
827int sqlite3Os2Dlclose(void *pHandle){
pweilbacher5fecee12007-01-28 21:42:08 +0000828 return DosFreeModule((HMODULE)pHandle);
drh761df872006-12-21 01:29:22 +0000829}
830#endif /* SQLITE_OMIT_LOAD_EXTENSION */
831
832
drh60a1e4b2006-06-03 18:02:15 +0000833/*
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
pweilbacher04bd0c12006-06-24 12:38:59 +0000848 ** that we always use the same random number sequence. This makes the
drh60a1e4b2006-06-03 18:02:15 +0000849 ** 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 PTIB ptib;
882#ifdef SQLITE_OS2_THREADS
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 PTIB ptib;
892 assert( inMutex );
893 inMutex = 0;
894#ifdef SQLITE_OS2_THREADS
895 DosGetInfoBlocks( &ptib, NULL );
896 assert( mutexOwner == ptib->tib_ptib2->tib2_ultid );
897 DosExitCritSec();
898#endif
899}
900
901/*
902** Return TRUE if the mutex is currently held.
903**
904** If the thisThreadOnly parameter is true, return true if and only if the
905** calling thread holds the mutex. If the parameter is false, return
906** true if any thread holds the mutex.
907*/
908int sqlite3Os2InMutex( int thisThreadOnly ){
909#ifdef SQLITE_OS2_THREADS
910 PTIB ptib;
911 DosGetInfoBlocks( &ptib, NULL );
912 return inMutex>0 && (thisThreadOnly==0 || mutexOwner==ptib->tib_ptib2->tib2_ultid);
913#else
914 return inMutex>0;
915#endif
916}
917
918/*
919** The following variable, if set to a non-zero value, becomes the result
920** returned from sqlite3OsCurrentTime(). This is used for testing.
921*/
922#ifdef SQLITE_TEST
923int sqlite3_current_time = 0;
924#endif
925
926/*
927** Find the current time (in Universal Coordinated Time). Write the
928** current time and date as a Julian Day number into *prNow and
929** return 0. Return 1 if the time and date cannot be found.
930*/
931int sqlite3Os2CurrentTime( double *prNow ){
932 double now;
933 USHORT second, minute, hour,
934 day, month, year;
935 DATETIME dt;
936 DosGetDateTime( &dt );
937 second = (USHORT)dt.seconds;
938 minute = (USHORT)dt.minutes + dt.timezone;
939 hour = (USHORT)dt.hours;
940 day = (USHORT)dt.day;
941 month = (USHORT)dt.month;
942 year = (USHORT)dt.year;
943
944 /* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html
945 http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c */
946 /* Calculate the Julian days */
947 now = day - 32076 +
948 1461*(year + 4800 + (month - 14)/12)/4 +
949 367*(month - 2 - (month - 14)/12*12)/12 -
950 3*((year + 4900 + (month - 14)/12)/100)/4;
951
952 /* Add the fractional hours, mins and seconds */
953 now += (hour + 12.0)/24.0;
954 now += minute/1440.0;
955 now += second/86400.0;
956 *prNow = now;
957#ifdef SQLITE_TEST
958 if( sqlite3_current_time ){
959 *prNow = sqlite3_current_time/86400.0 + 2440587.5;
960 }
961#endif
962 return 0;
963}
964
965/*
966** Remember the number of thread-specific-data blocks allocated.
967** Use this to verify that we are not leaking thread-specific-data.
968** Ticket #1601
969*/
970#ifdef SQLITE_TEST
971int sqlite3_tsd_count = 0;
972# define TSD_COUNTER_INCR InterlockedIncrement( &sqlite3_tsd_count )
973# define TSD_COUNTER_DECR InterlockedDecrement( &sqlite3_tsd_count )
974#else
975# define TSD_COUNTER_INCR /* no-op */
976# define TSD_COUNTER_DECR /* no-op */
977#endif
978
979/*
980** If called with allocateFlag>1, then return a pointer to thread
981** specific data for the current thread. Allocate and zero the
982** thread-specific data if it does not already exist necessary.
983**
984** If called with allocateFlag==0, then check the current thread
985** specific data. Return it if it exists. If it does not exist,
986** then return NULL.
987**
988** If called with allocateFlag<0, check to see if the thread specific
989** data is allocated and is all zero. If it is then deallocate it.
990** Return a pointer to the thread specific data or NULL if it is
991** unallocated or gets deallocated.
992*/
993ThreadData *sqlite3Os2ThreadSpecificData( int allocateFlag ){
994 static ThreadData **s_ppTsd = NULL;
995 static const ThreadData zeroData = {0, 0, 0};
996 ThreadData *pTsd;
997
998 if( !s_ppTsd ){
999 sqlite3OsEnterMutex();
1000 if( !s_ppTsd ){
1001 PULONG pul;
1002 APIRET rc = DosAllocThreadLocalMemory(1, &pul);
1003 if( rc != NO_ERROR ){
1004 sqlite3OsLeaveMutex();
1005 return 0;
1006 }
1007 s_ppTsd = (ThreadData **)pul;
1008 }
1009 sqlite3OsLeaveMutex();
1010 }
1011 pTsd = *s_ppTsd;
1012 if( allocateFlag>0 ){
1013 if( !pTsd ){
1014 pTsd = sqlite3OsMalloc( sizeof(zeroData) );
1015 if( pTsd ){
1016 *pTsd = zeroData;
1017 *s_ppTsd = pTsd;
1018 TSD_COUNTER_INCR;
1019 }
1020 }
1021 }else if( pTsd!=0 && allocateFlag<0
1022 && memcmp( pTsd, &zeroData, sizeof(ThreadData) )==0 ){
1023 sqlite3OsFree(pTsd);
1024 *s_ppTsd = NULL;
1025 TSD_COUNTER_DECR;
1026 pTsd = 0;
1027 }
1028 return pTsd;
1029}
1030#endif /* OS_OS2 */