Back to index

lightning-sunbird  0.9+nobinonly
os_os2.c
Go to the documentation of this file.
00001 /*
00002 ** 2006 Feb 14
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 ******************************************************************************
00012 **
00013 ** This file contains code that is specific to OS/2.
00014 */
00015 #include "sqliteInt.h"
00016 #include "os.h"
00017 
00018 #if OS_OS2
00019 
00020 /*
00021 ** Macros used to determine whether or not to use threads.
00022 */
00023 #if defined(THREADSAFE) && THREADSAFE
00024 # define SQLITE_OS2_THREADS 1
00025 #endif
00026 
00027 /*
00028 ** Include code that is common to all os_*.c files
00029 */
00030 #include "os_common.h"
00031 
00032 /*
00033 ** The os2File structure is subclass of OsFile specific for the OS/2
00034 ** protability layer.
00035 */
00036 typedef struct os2File os2File;
00037 struct os2File {
00038   IoMethod const *pMethod;  /* Always the first entry */
00039   HFILE h;                  /* Handle for accessing the file */
00040   int delOnClose;           /* True if file is to be deleted on close */
00041   char* pathToDel;          /* Name of file to delete on close */
00042   unsigned char locktype;   /* Type of lock currently held on this file */
00043 };
00044 
00045 /*
00046 ** Do not include any of the File I/O interface procedures if the
00047 ** SQLITE_OMIT_DISKIO macro is defined (indicating that there database
00048 ** will be in-memory only)
00049 */
00050 #ifndef SQLITE_OMIT_DISKIO
00051 
00052 /*
00053 ** Delete the named file
00054 */
00055 int sqlite3Os2Delete( const char *zFilename ){
00056   DosDelete( (PSZ)zFilename );
00057   TRACE2( "DELETE \"%s\"\n", zFilename );
00058   return SQLITE_OK;
00059 }
00060 
00061 /*
00062 ** Return TRUE if the named file exists.
00063 */
00064 int sqlite3Os2FileExists( const char *zFilename ){
00065   FILESTATUS3 fsts3ConfigInfo;
00066   memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo));
00067   return DosQueryPathInfo( (PSZ)zFilename, FIL_STANDARD,
00068         &fsts3ConfigInfo, sizeof(FILESTATUS3) ) == NO_ERROR;
00069 }
00070 
00071 /* Forward declaration */
00072 int allocateOs2File( os2File *pInit, OsFile **pld );
00073 
00074 /*
00075 ** Attempt to open a file for both reading and writing.  If that
00076 ** fails, try opening it read-only.  If the file does not exist,
00077 ** try to create it.
00078 **
00079 ** On success, a handle for the open file is written to *id
00080 ** and *pReadonly is set to 0 if the file was opened for reading and
00081 ** writing or 1 if the file was opened read-only.  The function returns
00082 ** SQLITE_OK.
00083 **
00084 ** On failure, the function returns SQLITE_CANTOPEN and leaves
00085 ** *id and *pReadonly unchanged.
00086 */
00087 int sqlite3Os2OpenReadWrite(
00088   const char *zFilename,
00089   OsFile **pld,
00090   int *pReadonly
00091 ){
00092   os2File  f;
00093   HFILE    hf;
00094   ULONG    ulAction;
00095   APIRET   rc;
00096 
00097   assert( *pld == 0 );
00098   rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L,
00099             FILE_ARCHIVED | FILE_NORMAL,
00100                 OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
00101                 OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
00102                     OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, (PEAOP2)NULL );
00103   if( rc != NO_ERROR ){
00104     rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L,
00105             FILE_ARCHIVED | FILE_NORMAL,
00106                 OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
00107                 OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
00108                         OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY, (PEAOP2)NULL );
00109     if( rc != NO_ERROR ){
00110         return SQLITE_CANTOPEN;
00111     }
00112     *pReadonly = 1;
00113   }
00114   else{
00115     *pReadonly = 0;
00116   }
00117   f.h = hf;
00118   f.locktype = NO_LOCK;
00119   f.delOnClose = 0;
00120   f.pathToDel = NULL;
00121   OpenCounter(+1);
00122   TRACE3( "OPEN R/W %d \"%s\"\n", hf, zFilename );
00123   return allocateOs2File( &f, pld );
00124 }
00125 
00126 
00127 /*
00128 ** Attempt to open a new file for exclusive access by this process.
00129 ** The file will be opened for both reading and writing.  To avoid
00130 ** a potential security problem, we do not allow the file to have
00131 ** previously existed.  Nor do we allow the file to be a symbolic
00132 ** link.
00133 **
00134 ** If delFlag is true, then make arrangements to automatically delete
00135 ** the file when it is closed.
00136 **
00137 ** On success, write the file handle into *id and return SQLITE_OK.
00138 **
00139 ** On failure, return SQLITE_CANTOPEN.
00140 */
00141 int sqlite3Os2OpenExclusive( const char *zFilename, OsFile **pld, int delFlag ){
00142   os2File  f;
00143   HFILE    hf;
00144   ULONG    ulAction;
00145   APIRET   rc;
00146 
00147   assert( *pld == 0 );
00148   rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L, FILE_NORMAL,
00149             OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS,
00150             OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
00151                 OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, (PEAOP2)NULL );
00152   if( rc != NO_ERROR ){
00153     return SQLITE_CANTOPEN;
00154   }
00155 
00156   f.h = hf;
00157   f.locktype = NO_LOCK;
00158   f.delOnClose = delFlag ? 1 : 0;
00159   f.pathToDel = delFlag ? sqlite3OsFullPathname( zFilename ) : NULL;
00160   OpenCounter( +1 );
00161   if( delFlag ) DosForceDelete( sqlite3OsFullPathname( zFilename ) );
00162   TRACE3( "OPEN EX %d \"%s\"\n", hf, sqlite3OsFullPathname ( zFilename ) );
00163   return allocateOs2File( &f, pld );
00164 }
00165 
00166 /*
00167 ** Attempt to open a new file for read-only access.
00168 **
00169 ** On success, write the file handle into *id and return SQLITE_OK.
00170 **
00171 ** On failure, return SQLITE_CANTOPEN.
00172 */
00173 int sqlite3Os2OpenReadOnly( const char *zFilename, OsFile **pld ){
00174   os2File  f;
00175   HFILE    hf;
00176   ULONG    ulAction;
00177   APIRET   rc;
00178 
00179   assert( *pld == 0 );
00180   rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L,
00181             FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
00182             OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
00183                 OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY, (PEAOP2)NULL );
00184   if( rc != NO_ERROR ){
00185     return SQLITE_CANTOPEN;
00186   }
00187   f.h = hf;
00188   f.locktype = NO_LOCK;
00189   f.delOnClose = 0;
00190   f.pathToDel = NULL;
00191   OpenCounter( +1 );
00192   TRACE3( "OPEN RO %d \"%s\"\n", hf, zFilename );
00193   return allocateOs2File( &f, pld );
00194 }
00195 
00196 /*
00197 ** Attempt to open a file descriptor for the directory that contains a
00198 ** file.  This file descriptor can be used to fsync() the directory
00199 ** in order to make sure the creation of a new file is actually written
00200 ** to disk.
00201 **
00202 ** This routine is only meaningful for Unix.  It is a no-op under
00203 ** OS/2 since OS/2 does not support hard links.
00204 **
00205 ** On success, a handle for a previously open file is at *id is
00206 ** updated with the new directory file descriptor and SQLITE_OK is
00207 ** returned.
00208 **
00209 ** On failure, the function returns SQLITE_CANTOPEN and leaves
00210 ** *id unchanged.
00211 */
00212 int os2OpenDirectory(
00213   OsFile *id,
00214   const char *zDirname
00215 ){
00216   return SQLITE_OK;
00217 }
00218 
00219 /*
00220 ** If the following global variable points to a string which is the
00221 ** name of a directory, then that directory will be used to store
00222 ** temporary files.
00223 */
00224 char *sqlite3_temp_directory = 0;
00225 
00226 /*
00227 ** Create a temporary file name in zBuf.  zBuf must be big enough to
00228 ** hold at least SQLITE_TEMPNAME_SIZE characters.
00229 */
00230 int sqlite3Os2TempFileName( char *zBuf ){
00231   static const unsigned char zChars[] =
00232     "abcdefghijklmnopqrstuvwxyz"
00233     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00234     "0123456789";
00235   int i, j;
00236   PSZ zTempPath = 0;
00237   if( DosScanEnv( "TEMP", &zTempPath ) ){
00238     if( DosScanEnv( "TMP", &zTempPath ) ){
00239       if( DosScanEnv( "TMPDIR", &zTempPath ) ){
00240            ULONG ulDriveNum = 0, ulDriveMap = 0;
00241            DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
00242            sprintf( zTempPath, "%c:", (char)( 'A' + ulDriveNum - 1 ) );
00243       }
00244     }
00245   }
00246   for(;;){
00247       sprintf( zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath );
00248       j = strlen( zBuf );
00249       sqlite3Randomness( 15, &zBuf[j] );
00250       for( i = 0; i < 15; i++, j++ ){
00251         zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
00252       }
00253       zBuf[j] = 0;
00254       if( !sqlite3OsFileExists( zBuf ) ) break;
00255   }
00256   TRACE2( "TEMP FILENAME: %s\n", zBuf );
00257   return SQLITE_OK;
00258 }
00259 
00260 /*
00261 ** Close a file.
00262 */
00263 int os2Close( OsFile **pld ){
00264   os2File *pFile;
00265   if( pld && (pFile = (os2File*)*pld)!=0 ){
00266     TRACE2( "CLOSE %d\n", pFile->h );
00267     DosClose( pFile->h );
00268     pFile->locktype = NO_LOCK;
00269     if( pFile->delOnClose != 0 ){
00270         DosForceDelete( pFile->pathToDel );
00271     }
00272     *pld = 0;
00273     OpenCounter( -1 );
00274   }
00275 
00276   return SQLITE_OK;
00277 }
00278 
00279 /*
00280 ** Read data from a file into a buffer.  Return SQLITE_OK if all
00281 ** bytes were read successfully and SQLITE_IOERR if anything goes
00282 ** wrong.
00283 */
00284 int os2Read( OsFile *id, void *pBuf, int amt ){
00285   ULONG got;
00286   assert( id!=0 );
00287   SimulateIOError( SQLITE_IOERR );
00288   TRACE3( "READ %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
00289   DosRead( ((os2File*)id)->h, pBuf, amt, &got );
00290   return (got == (ULONG)amt) ? SQLITE_OK : SQLITE_IOERR;
00291 }
00292 
00293 /*
00294 ** Write data from a buffer into a file.  Return SQLITE_OK on success
00295 ** or some other error code on failure.
00296 */
00297 int os2Write( OsFile *id, const void *pBuf, int amt ){
00298   APIRET rc=NO_ERROR;
00299   ULONG wrote;
00300   assert( id!=0 );
00301   SimulateIOError( SQLITE_IOERR );
00302   SimulateDiskfullError;
00303   TRACE3( "WRITE %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
00304   while( amt > 0 &&
00305       (rc = DosWrite( ((os2File*)id)->h, (PVOID)pBuf, amt, &wrote )) && wrote > 0 ){
00306       amt -= wrote;
00307       pBuf = &((char*)pBuf)[wrote];
00308   }
00309 
00310   return ( rc != NO_ERROR || amt > (int)wrote ) ? SQLITE_FULL : SQLITE_OK;
00311 }
00312 
00313 /*
00314 ** Move the read/write pointer in a file.
00315 */
00316 int os2Seek( OsFile *id, i64 offset ){
00317   APIRET rc;
00318   ULONG filePointer = 0L;
00319   assert( id!=0 );
00320   rc = DosSetFilePtr( ((os2File*)id)->h, offset, FILE_BEGIN, &filePointer );
00321   TRACE3( "SEEK %d %lld\n", ((os2File*)id)->h, offset );
00322   return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
00323 }
00324 
00325 /*
00326 ** Make sure all writes to a particular file are committed to disk.
00327 */
00328 int os2Sync( OsFile *id, int dataOnly ){
00329   assert( id!=0 );
00330   TRACE3( "SYNC %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
00331   return DosResetBuffer( ((os2File*)id)->h ) ? SQLITE_IOERR : SQLITE_OK;
00332 }
00333 
00334 /*
00335 ** Sync the directory zDirname. This is a no-op on operating systems other
00336 ** than UNIX.
00337 */
00338 int sqlite3Os2SyncDirectory( const char *zDirname ){
00339   SimulateIOError( SQLITE_IOERR );
00340   return SQLITE_OK;
00341 }
00342 
00343 /*
00344 ** Truncate an open file to a specified size
00345 */
00346 int os2Truncate( OsFile *id, i64 nByte ){
00347   APIRET rc;
00348   ULONG upperBits = nByte>>32;
00349   assert( id!=0 );
00350   TRACE3( "TRUNCATE %d %lld\n", ((os2File*)id)->h, nByte );
00351   SimulateIOError( SQLITE_IOERR );
00352   rc = DosSetFilePtr( ((os2File*)id)->h, nByte, FILE_BEGIN, &upperBits );
00353   if( rc != NO_ERROR ){
00354     return SQLITE_IOERR;
00355   }
00356   rc = DosSetFilePtr( ((os2File*)id)->h, 0L, FILE_END, &upperBits );
00357   return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
00358 }
00359 
00360 /*
00361 ** Determine the current size of a file in bytes
00362 */
00363 int os2FileSize( OsFile *id, i64 *pSize ){
00364   APIRET rc;
00365   FILESTATUS3 fsts3FileInfo;
00366   memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo));
00367   assert( id!=0 );
00368   SimulateIOError( SQLITE_IOERR );
00369   rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) );
00370   if( rc == NO_ERROR ){
00371     *pSize = fsts3FileInfo.cbFile;
00372     return SQLITE_OK;
00373   }
00374   else{
00375     return SQLITE_IOERR;
00376   }
00377 }
00378 
00379 /*
00380 ** Acquire a reader lock.
00381 */
00382 static int getReadLock( os2File *id ){
00383   FILELOCK  LockArea,
00384             UnlockArea;
00385   memset(&LockArea, 0, sizeof(LockArea));
00386   memset(&UnlockArea, 0, sizeof(UnlockArea));
00387   LockArea.lOffset = SHARED_FIRST;
00388   LockArea.lRange = SHARED_SIZE;
00389   UnlockArea.lOffset = 0L;
00390   UnlockArea.lRange = 0L;
00391   return DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L );
00392 }
00393 
00394 /*
00395 ** Undo a readlock
00396 */
00397 static int unlockReadLock( os2File *id ){
00398   FILELOCK  LockArea,
00399             UnlockArea;
00400   memset(&LockArea, 0, sizeof(LockArea));
00401   memset(&UnlockArea, 0, sizeof(UnlockArea));
00402   LockArea.lOffset = 0L;
00403   LockArea.lRange = 0L;
00404   UnlockArea.lOffset = SHARED_FIRST;
00405   UnlockArea.lRange = SHARED_SIZE;
00406   return DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L );
00407 }
00408 
00409 #ifndef SQLITE_OMIT_PAGER_PRAGMAS
00410 /*
00411 ** Check that a given pathname is a directory and is writable
00412 **
00413 */
00414 int sqlite3Os2IsDirWritable( char *zDirname ){
00415   FILESTATUS3 fsts3ConfigInfo;
00416   APIRET rc = NO_ERROR;
00417   memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo));
00418   if( zDirname==0 ) return 0;
00419   if( strlen(zDirname)>CCHMAXPATH ) return 0;
00420   rc = DosQueryPathInfo( (PSZ)zDirname, FIL_STANDARD, &fsts3ConfigInfo, sizeof(FILESTATUS3) );
00421   if( rc != NO_ERROR ) return 0;
00422   if( (fsts3ConfigInfo.attrFile & FILE_DIRECTORY) != FILE_DIRECTORY ) return 0;
00423 
00424   return 1;
00425 }
00426 #endif /* SQLITE_OMIT_PAGER_PRAGMAS */
00427 
00428 /*
00429 ** Lock the file with the lock specified by parameter locktype - one
00430 ** of the following:
00431 **
00432 **     (1) SHARED_LOCK
00433 **     (2) RESERVED_LOCK
00434 **     (3) PENDING_LOCK
00435 **     (4) EXCLUSIVE_LOCK
00436 **
00437 ** Sometimes when requesting one lock state, additional lock states
00438 ** are inserted in between.  The locking might fail on one of the later
00439 ** transitions leaving the lock state different from what it started but
00440 ** still short of its goal.  The following chart shows the allowed
00441 ** transitions and the inserted intermediate states:
00442 **
00443 **    UNLOCKED -> SHARED
00444 **    SHARED -> RESERVED
00445 **    SHARED -> (PENDING) -> EXCLUSIVE
00446 **    RESERVED -> (PENDING) -> EXCLUSIVE
00447 **    PENDING -> EXCLUSIVE
00448 **
00449 ** This routine will only increase a lock.  The os2Unlock() routine
00450 ** erases all locks at once and returns us immediately to locking level 0.
00451 ** It is not possible to lower the locking level one step at a time.  You
00452 ** must go straight to locking level 0.
00453 */
00454 int os2Lock( OsFile *id, int locktype ){
00455   APIRET rc = SQLITE_OK;    /* Return code from subroutines */
00456   APIRET res = 1;           /* Result of a windows lock call */
00457   int newLocktype;       /* Set id->locktype to this value before exiting */
00458   int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
00459   FILELOCK  LockArea,
00460             UnlockArea;
00461   os2File *pFile = (os2File*)id;
00462   memset(&LockArea, 0, sizeof(LockArea));
00463   memset(&UnlockArea, 0, sizeof(UnlockArea));
00464   assert( pFile!=0 );
00465   TRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype );
00466 
00467   /* If there is already a lock of this type or more restrictive on the
00468   ** OsFile, do nothing. Don't use the end_lock: exit path, as
00469   ** sqlite3OsEnterMutex() hasn't been called yet.
00470   */
00471   if( pFile->locktype>=locktype ){
00472     return SQLITE_OK;
00473   }
00474 
00475   /* Make sure the locking sequence is correct
00476   */
00477   assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
00478   assert( locktype!=PENDING_LOCK );
00479   assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
00480 
00481   /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
00482   ** a SHARED lock.  If we are acquiring a SHARED lock, the acquisition of
00483   ** the PENDING_LOCK byte is temporary.
00484   */
00485   newLocktype = pFile->locktype;
00486   if( pFile->locktype==NO_LOCK
00487    || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
00488   ){
00489     int cnt = 3;
00490 
00491     LockArea.lOffset = PENDING_BYTE;
00492     LockArea.lRange = 1L;
00493     UnlockArea.lOffset = 0L;
00494     UnlockArea.lRange = 0L;
00495 
00496     while( cnt-->0 && (res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L) )!=NO_ERROR ){
00497       /* Try 3 times to get the pending lock.  The pending lock might be
00498       ** held by another reader process who will release it momentarily.
00499       */
00500       TRACE2( "could not get a PENDING lock. cnt=%d\n", cnt );
00501       DosSleep(1);
00502     }
00503     gotPendingLock = res;
00504   }
00505 
00506   /* Acquire a shared lock
00507   */
00508   if( locktype==SHARED_LOCK && res ){
00509     assert( pFile->locktype==NO_LOCK );
00510     res = getReadLock(pFile);
00511     if( res == NO_ERROR ){
00512       newLocktype = SHARED_LOCK;
00513     }
00514   }
00515 
00516   /* Acquire a RESERVED lock
00517   */
00518   if( locktype==RESERVED_LOCK && res ){
00519     assert( pFile->locktype==SHARED_LOCK );
00520     LockArea.lOffset = RESERVED_BYTE;
00521     LockArea.lRange = 1L;
00522     UnlockArea.lOffset = 0L;
00523     UnlockArea.lRange = 0L;
00524     res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
00525     if( res == NO_ERROR ){
00526       newLocktype = RESERVED_LOCK;
00527     }
00528   }
00529 
00530   /* Acquire a PENDING lock
00531   */
00532   if( locktype==EXCLUSIVE_LOCK && res ){
00533     newLocktype = PENDING_LOCK;
00534     gotPendingLock = 0;
00535   }
00536 
00537   /* Acquire an EXCLUSIVE lock
00538   */
00539   if( locktype==EXCLUSIVE_LOCK && res ){
00540     assert( pFile->locktype>=SHARED_LOCK );
00541     res = unlockReadLock(pFile);
00542     TRACE2( "unreadlock = %d\n", res );
00543     LockArea.lOffset = SHARED_FIRST;
00544     LockArea.lRange = SHARED_SIZE;
00545     UnlockArea.lOffset = 0L;
00546     UnlockArea.lRange = 0L;
00547     res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
00548     if( res == NO_ERROR ){
00549       newLocktype = EXCLUSIVE_LOCK;
00550     }else{
00551       TRACE2( "error-code = %d\n", res );
00552     }
00553   }
00554 
00555   /* If we are holding a PENDING lock that ought to be released, then
00556   ** release it now.
00557   */
00558   if( gotPendingLock && locktype==SHARED_LOCK ){
00559     LockArea.lOffset = 0L;
00560     LockArea.lRange = 0L;
00561     UnlockArea.lOffset = PENDING_BYTE;
00562     UnlockArea.lRange = 1L;
00563     DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
00564   }
00565 
00566   /* Update the state of the lock has held in the file descriptor then
00567   ** return the appropriate result code.
00568   */
00569   if( res == NO_ERROR ){
00570     rc = SQLITE_OK;
00571   }else{
00572     TRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
00573            locktype, newLocktype );
00574     rc = SQLITE_BUSY;
00575   }
00576   pFile->locktype = newLocktype;
00577   return rc;
00578 }
00579 
00580 /*
00581 ** This routine checks if there is a RESERVED lock held on the specified
00582 ** file by this or any other process. If such a lock is held, return
00583 ** non-zero, otherwise zero.
00584 */
00585 int os2CheckReservedLock( OsFile *id ){
00586   APIRET rc;
00587   os2File *pFile = (os2File*)id;
00588   assert( pFile!=0 );
00589   if( pFile->locktype>=RESERVED_LOCK ){
00590     rc = 1;
00591     TRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, rc );
00592   }else{
00593     FILELOCK  LockArea,
00594               UnlockArea;
00595     memset(&LockArea, 0, sizeof(LockArea));
00596     memset(&UnlockArea, 0, sizeof(UnlockArea));
00597     LockArea.lOffset = RESERVED_BYTE;
00598     LockArea.lRange = 1L;
00599     UnlockArea.lOffset = 0L;
00600     UnlockArea.lRange = 0L;
00601     rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
00602     if( rc == NO_ERROR ){
00603       LockArea.lOffset = 0L;
00604       LockArea.lRange = 0L;
00605       UnlockArea.lOffset = RESERVED_BYTE;
00606       UnlockArea.lRange = 1L;
00607       rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
00608     }
00609     TRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, rc );
00610   }
00611   return rc;
00612 }
00613 
00614 /*
00615 ** Lower the locking level on file descriptor id to locktype.  locktype
00616 ** must be either NO_LOCK or SHARED_LOCK.
00617 **
00618 ** If the locking level of the file descriptor is already at or below
00619 ** the requested locking level, this routine is a no-op.
00620 **
00621 ** It is not possible for this routine to fail if the second argument
00622 ** is NO_LOCK.  If the second argument is SHARED_LOCK then this routine
00623 ** might return SQLITE_IOERR;
00624 */
00625 int os2Unlock( OsFile *id, int locktype ){
00626   int type;
00627   APIRET rc = SQLITE_OK;
00628   os2File *pFile = (os2File*)id;
00629   FILELOCK  LockArea,
00630             UnlockArea;
00631   memset(&LockArea, 0, sizeof(LockArea));
00632   memset(&UnlockArea, 0, sizeof(UnlockArea));
00633   assert( pFile!=0 );
00634   assert( locktype<=SHARED_LOCK );
00635   TRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype );
00636   type = pFile->locktype;
00637   if( type>=EXCLUSIVE_LOCK ){
00638     LockArea.lOffset = 0L;
00639     LockArea.lRange = 0L;
00640     UnlockArea.lOffset = SHARED_FIRST;
00641     UnlockArea.lRange = SHARED_SIZE;
00642     DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
00643     if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){
00644       /* This should never happen.  We should always be able to
00645       ** reacquire the read lock */
00646       rc = SQLITE_IOERR;
00647     }
00648   }
00649   if( type>=RESERVED_LOCK ){
00650     LockArea.lOffset = 0L;
00651     LockArea.lRange = 0L;
00652     UnlockArea.lOffset = RESERVED_BYTE;
00653     UnlockArea.lRange = 1L;
00654     DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
00655   }
00656   if( locktype==NO_LOCK && type>=SHARED_LOCK ){
00657     unlockReadLock(pFile);
00658   }
00659   if( type>=PENDING_LOCK ){
00660     LockArea.lOffset = 0L;
00661     LockArea.lRange = 0L;
00662     UnlockArea.lOffset = PENDING_BYTE;
00663     UnlockArea.lRange = 1L;
00664     DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
00665   }
00666   pFile->locktype = locktype;
00667   return rc;
00668 }
00669 
00670 /*
00671 ** Turn a relative pathname into a full pathname.  Return a pointer
00672 ** to the full pathname stored in space obtained from sqliteMalloc().
00673 ** The calling function is responsible for freeing this space once it
00674 ** is no longer needed.
00675 */
00676 char *sqlite3Os2FullPathname( const char *zRelative ){
00677   char *zFull = 0;
00678   if( strchr(zRelative, ':') ){
00679     sqlite3SetString( &zFull, zRelative, (char*)0 );
00680   }else{
00681     char zBuff[SQLITE_TEMPNAME_SIZE - 2] = {0};
00682     char zDrive[1] = {0};
00683     ULONG cbzFullLen = SQLITE_TEMPNAME_SIZE;
00684     ULONG ulDriveNum = 0;
00685     ULONG ulDriveMap = 0;
00686     DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
00687     DosQueryCurrentDir( 0L, zBuff, &cbzFullLen );
00688     zFull = sqliteMalloc( cbzFullLen );
00689     sprintf( zDrive, "%c", (char)('A' + ulDriveNum - 1) );
00690     sqlite3SetString( &zFull, zDrive, ":\\", zBuff, "\\", zRelative, (char*)0 );
00691   }
00692   return zFull;
00693 }
00694 
00695 /*
00696 ** The fullSync option is meaningless on os2, or correct me if I'm wrong.  This is a no-op.
00697 ** From os_unix.c: Change the value of the fullsync flag in the given file descriptor.
00698 ** From os_unix.c: ((unixFile*)id)->fullSync = v;
00699 */
00700 static void os2SetFullSync( OsFile *id, int v ){
00701   return;
00702 }
00703 
00704 /*
00705 ** Return the underlying file handle for an OsFile
00706 */
00707 static int os2FileHandle( OsFile *id ){
00708   return (int)((os2File*)id)->h;
00709 }
00710 
00711 /*
00712 ** Return an integer that indices the type of lock currently held
00713 ** by this handle.  (Used for testing and analysis only.)
00714 */
00715 static int os2LockState( OsFile *id ){
00716   return ((os2File*)id)->locktype;
00717 }
00718 
00719 /*
00720 ** This vector defines all the methods that can operate on an OsFile
00721 ** for os2.
00722 */
00723 static const IoMethod sqlite3Os2IoMethod = {
00724   os2Close,
00725   os2OpenDirectory,
00726   os2Read,
00727   os2Write,
00728   os2Seek,
00729   os2Truncate,
00730   os2Sync,
00731   os2SetFullSync,
00732   os2FileHandle,
00733   os2FileSize,
00734   os2Lock,
00735   os2Unlock,
00736   os2LockState,
00737   os2CheckReservedLock,
00738 };
00739 
00740 /*
00741 ** Allocate memory for an OsFile.  Initialize the new OsFile
00742 ** to the value given in pInit and return a pointer to the new
00743 ** OsFile.  If we run out of memory, close the file and return NULL.
00744 */
00745 int allocateOs2File( os2File *pInit, OsFile **pld ){
00746   os2File *pNew;
00747   pNew = sqliteMalloc( sizeof(*pNew) );
00748   if( pNew==0 ){
00749     DosClose( pInit->h );
00750     *pld = 0;
00751     return SQLITE_NOMEM;
00752   }else{
00753     *pNew = *pInit;
00754     pNew->pMethod = &sqlite3Os2IoMethod;
00755     pNew->locktype = NO_LOCK;
00756     *pld = (OsFile*)pNew;
00757     OpenCounter(+1);
00758     return SQLITE_OK;
00759   }
00760 }
00761 
00762 #endif /* SQLITE_OMIT_DISKIO */
00763 /***************************************************************************
00764 ** Everything above deals with file I/O.  Everything that follows deals
00765 ** with other miscellanous aspects of the operating system interface
00766 ****************************************************************************/
00767 
00768 /*
00769 ** Get information to seed the random number generator.  The seed
00770 ** is written into the buffer zBuf[256].  The calling function must
00771 ** supply a sufficiently large buffer.
00772 */
00773 int sqlite3Os2RandomSeed( char *zBuf ){
00774   /* We have to initialize zBuf to prevent valgrind from reporting
00775   ** errors.  The reports issued by valgrind are incorrect - we would
00776   ** prefer that the randomness be increased by making use of the
00777   ** uninitialized space in zBuf - but valgrind errors tend to worry
00778   ** some users.  Rather than argue, it seems easier just to initialize
00779   ** the whole array and silence valgrind, even if that means less randomness
00780   ** in the random seed.
00781   **
00782   ** When testing, initializing zBuf[] to zero is all we do.  That means
00783   ** that we always use the same random number sequence.* This makes the
00784   ** tests repeatable.
00785   */
00786   memset( zBuf, 0, 256 );
00787   DosGetDateTime( (PDATETIME)zBuf );
00788   return SQLITE_OK;
00789 }
00790 
00791 /*
00792 ** Sleep for a little while.  Return the amount of time slept.
00793 */
00794 int sqlite3Os2Sleep( int ms ){
00795   DosSleep( ms );
00796   return ms;
00797 }
00798 
00799 /*
00800 ** Static variables used for thread synchronization
00801 */
00802 static int inMutex = 0;
00803 #ifdef SQLITE_OS2_THREADS
00804 static ULONG mutexOwner;
00805 #endif
00806 
00807 /*
00808 ** The following pair of routines implement mutual exclusion for
00809 ** multi-threaded processes.  Only a single thread is allowed to
00810 ** executed code that is surrounded by EnterMutex() and LeaveMutex().
00811 **
00812 ** SQLite uses only a single Mutex.  There is not much critical
00813 ** code and what little there is executes quickly and without blocking.
00814 */
00815 void sqlite3Os2EnterMutex(){
00816   PTIB ptib;
00817 #ifdef SQLITE_OS2_THREADS
00818   DosEnterCritSec();
00819   DosGetInfoBlocks( &ptib, NULL );
00820   mutexOwner = ptib->tib_ptib2->tib2_ultid;
00821 #endif
00822   assert( !inMutex );
00823   inMutex = 1;
00824 }
00825 void sqlite3Os2LeaveMutex(){
00826   PTIB ptib;
00827   assert( inMutex );
00828   inMutex = 0;
00829 #ifdef SQLITE_OS2_THREADS
00830   DosGetInfoBlocks( &ptib, NULL );
00831   assert( mutexOwner == ptib->tib_ptib2->tib2_ultid );
00832   DosExitCritSec();
00833 #endif
00834 }
00835 
00836 /*
00837 ** Return TRUE if the mutex is currently held.
00838 **
00839 ** If the thisThreadOnly parameter is true, return true if and only if the
00840 ** calling thread holds the mutex.  If the parameter is false, return
00841 ** true if any thread holds the mutex.
00842 */
00843 int sqlite3Os2InMutex( int thisThreadOnly ){
00844 #ifdef SQLITE_OS2_THREADS
00845   PTIB ptib;
00846   DosGetInfoBlocks( &ptib, NULL );
00847   return inMutex>0 && (thisThreadOnly==0 || mutexOwner==ptib->tib_ptib2->tib2_ultid);
00848 #else
00849   return inMutex>0;
00850 #endif
00851 }
00852 
00853 /*
00854 ** The following variable, if set to a non-zero value, becomes the result
00855 ** returned from sqlite3OsCurrentTime().  This is used for testing.
00856 */
00857 #ifdef SQLITE_TEST
00858 int sqlite3_current_time = 0;
00859 #endif
00860 
00861 /*
00862 ** Find the current time (in Universal Coordinated Time).  Write the
00863 ** current time and date as a Julian Day number into *prNow and
00864 ** return 0.  Return 1 if the time and date cannot be found.
00865 */
00866 int sqlite3Os2CurrentTime( double *prNow ){
00867   double now;
00868   USHORT second, minute, hour,
00869          day, month, year;
00870   DATETIME dt;
00871   DosGetDateTime( &dt );
00872   second = (USHORT)dt.seconds;
00873   minute = (USHORT)dt.minutes + dt.timezone;
00874   hour = (USHORT)dt.hours;
00875   day = (USHORT)dt.day;
00876   month = (USHORT)dt.month;
00877   year = (USHORT)dt.year;
00878 
00879   /* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html
00880      http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c */
00881   /* Calculate the Julian days */
00882   now = day - 32076 +
00883     1461*(year + 4800 + (month - 14)/12)/4 +
00884     367*(month - 2 - (month - 14)/12*12)/12 -
00885     3*((year + 4900 + (month - 14)/12)/100)/4;
00886 
00887   /* Add the fractional hours, mins and seconds */
00888   now += (hour + 12.0)/24.0;
00889   now += minute/1440.0;
00890   now += second/86400.0;
00891   *prNow = now;
00892 #ifdef SQLITE_TEST
00893   if( sqlite3_current_time ){
00894     *prNow = sqlite3_current_time/86400.0 + 2440587.5;
00895   }
00896 #endif
00897   return 0;
00898 }
00899 
00900 /*
00901 ** Remember the number of thread-specific-data blocks allocated.
00902 ** Use this to verify that we are not leaking thread-specific-data.
00903 ** Ticket #1601
00904 */
00905 #ifdef SQLITE_TEST
00906 int sqlite3_tsd_count = 0;
00907 # define TSD_COUNTER_INCR InterlockedIncrement( &sqlite3_tsd_count )
00908 # define TSD_COUNTER_DECR InterlockedDecrement( &sqlite3_tsd_count )
00909 #else
00910 # define TSD_COUNTER_INCR  /* no-op */
00911 # define TSD_COUNTER_DECR  /* no-op */
00912 #endif
00913 
00914 /*
00915 ** If called with allocateFlag>1, then return a pointer to thread
00916 ** specific data for the current thread.  Allocate and zero the
00917 ** thread-specific data if it does not already exist necessary.
00918 **
00919 ** If called with allocateFlag==0, then check the current thread
00920 ** specific data.  Return it if it exists.  If it does not exist,
00921 ** then return NULL.
00922 **
00923 ** If called with allocateFlag<0, check to see if the thread specific
00924 ** data is allocated and is all zero.  If it is then deallocate it.
00925 ** Return a pointer to the thread specific data or NULL if it is
00926 ** unallocated or gets deallocated.
00927 */
00928 ThreadData *sqlite3Os2ThreadSpecificData( int allocateFlag ){
00929   static ThreadData **s_ppTsd = NULL;
00930   static const ThreadData zeroData = {0, 0, 0};
00931   ThreadData *pTsd;
00932 
00933   if( !s_ppTsd ){
00934     sqlite3OsEnterMutex();
00935     if( !s_ppTsd ){
00936       PULONG pul;
00937       APIRET rc = DosAllocThreadLocalMemory(1, &pul);
00938       if( rc != NO_ERROR ){
00939         sqlite3OsLeaveMutex();
00940         return 0;
00941       }
00942       s_ppTsd = (ThreadData **)pul;
00943     }
00944     sqlite3OsLeaveMutex();
00945   }
00946   pTsd = *s_ppTsd;
00947   if( allocateFlag>0 ){
00948     if( !pTsd ){
00949       pTsd = sqlite3OsMalloc( sizeof(zeroData) );
00950       if( pTsd ){
00951         *pTsd = zeroData;
00952         *s_ppTsd = pTsd;
00953         TSD_COUNTER_INCR;
00954       }
00955     }
00956   }else if( pTsd!=0 && allocateFlag<0
00957               && memcmp( pTsd, &zeroData, sizeof(ThreadData) )==0 ){
00958     sqlite3OsFree(pTsd);
00959     *s_ppTsd = NULL;
00960     TSD_COUNTER_DECR;
00961     pTsd = 0;
00962   }
00963   return pTsd;
00964 }
00965 #endif /* OS_OS2 */