webengine/webkitutils/SqliteSymbian/os_os2.c
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     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 #include "sqliteInt.h"
       
    16 #include "os.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 */
       
    36 typedef struct os2File os2File;
       
    37 struct 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 */
       
    55 int sqlite3Os2Delete( const char *zFilename ){
       
    56   APIRET rc = NO_ERROR;
       
    57 
       
    58   rc = DosDelete( (PSZ)zFilename );
       
    59   TRACE2( "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 */
       
    66 int 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 */
       
    74 int 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 */
       
    89 int 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   TRACE3( "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 */
       
   143 int 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( sqlite3OsFullPathname( zFilename ) );
       
   164   TRACE3( "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 */
       
   175 int 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   TRACE3( "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 */
       
   214 int os2OpenDirectory(
       
   215   OsFile *id,
       
   216   const char *zDirname
       
   217 ){
       
   218   return SQLITE_OK;
       
   219 }
       
   220 
       
   221 /*
       
   222 ** If the following global variable points to a string which is the
       
   223 ** name of a directory, then that directory will be used to store
       
   224 ** temporary files.
       
   225 */
       
   226 char *sqlite3_temp_directory = 0;
       
   227 
       
   228 /*
       
   229 ** Create a temporary file name in zBuf.  zBuf must be big enough to
       
   230 ** hold at least SQLITE_TEMPNAME_SIZE characters.
       
   231 */
       
   232 int sqlite3Os2TempFileName( char *zBuf ){
       
   233   static const unsigned char zChars[] =
       
   234     "abcdefghijklmnopqrstuvwxyz"
       
   235     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
       
   236     "0123456789";
       
   237   int i, j;
       
   238   PSZ zTempPath = 0;
       
   239   if( DosScanEnv( "TEMP", &zTempPath ) ){
       
   240     if( DosScanEnv( "TMP", &zTempPath ) ){
       
   241       if( DosScanEnv( "TMPDIR", &zTempPath ) ){
       
   242            ULONG ulDriveNum = 0, ulDriveMap = 0;
       
   243            DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
       
   244            sprintf( zTempPath, "%c:", (char)( 'A' + ulDriveNum - 1 ) );
       
   245       }
       
   246     }
       
   247   }
       
   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   TRACE2( "TEMP FILENAME: %s\n", zBuf );
       
   259   return SQLITE_OK;
       
   260 }
       
   261 
       
   262 /*
       
   263 ** Close a file.
       
   264 */
       
   265 int os2Close( OsFile **pld ){
       
   266   os2File *pFile;
       
   267   APIRET rc = NO_ERROR;
       
   268   if( pld && (pFile = (os2File*)*pld) != 0 ){
       
   269     TRACE2( "CLOSE %d\n", pFile->h );
       
   270     rc = DosClose( pFile->h );
       
   271     pFile->locktype = NO_LOCK;
       
   272     if( pFile->delOnClose != 0 ){
       
   273         rc = DosForceDelete( 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 */
       
   287 int os2Read( OsFile *id, void *pBuf, int amt ){
       
   288   ULONG got;
       
   289   assert( id!=0 );
       
   290   SimulateIOError( SQLITE_IOERR );
       
   291   TRACE3( "READ %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
       
   292   DosRead( ((os2File*)id)->h, pBuf, amt, &got );
       
   293   return (got == (ULONG)amt) ? SQLITE_OK : SQLITE_IOERR;
       
   294 }
       
   295 
       
   296 /*
       
   297 ** Write data from a buffer into a file.  Return SQLITE_OK on success
       
   298 ** or some other error code on failure.
       
   299 */
       
   300 int os2Write( OsFile *id, const void *pBuf, int amt ){
       
   301   APIRET rc = NO_ERROR;
       
   302   ULONG wrote;
       
   303   assert( id!=0 );
       
   304   SimulateIOError( SQLITE_IOERR );
       
   305   SimulateDiskfullError;
       
   306   TRACE3( "WRITE %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
       
   307   while( amt > 0 &&
       
   308       (rc = DosWrite( ((os2File*)id)->h, (PVOID)pBuf, amt, &wrote )) && wrote > 0 ){
       
   309       amt -= wrote;
       
   310       pBuf = &((char*)pBuf)[wrote];
       
   311   }
       
   312 
       
   313   return ( rc != NO_ERROR || amt > (int)wrote ) ? SQLITE_FULL : SQLITE_OK;
       
   314 }
       
   315 
       
   316 /*
       
   317 ** Move the read/write pointer in a file.
       
   318 */
       
   319 int os2Seek( OsFile *id, i64 offset ){
       
   320   APIRET rc = NO_ERROR;
       
   321   ULONG filePointer = 0L;
       
   322   assert( id!=0 );
       
   323   rc = DosSetFilePtr( ((os2File*)id)->h, offset, FILE_BEGIN, &filePointer );
       
   324   TRACE3( "SEEK %d %lld\n", ((os2File*)id)->h, offset );
       
   325   return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
       
   326 }
       
   327 
       
   328 /*
       
   329 ** Make sure all writes to a particular file are committed to disk.
       
   330 */
       
   331 int os2Sync( OsFile *id, int dataOnly ){
       
   332   assert( id!=0 );
       
   333   TRACE3( "SYNC %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
       
   334   return DosResetBuffer( ((os2File*)id)->h ) == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
       
   335 }
       
   336 
       
   337 /*
       
   338 ** Sync the directory zDirname. This is a no-op on operating systems other
       
   339 ** than UNIX.
       
   340 */
       
   341 int sqlite3Os2SyncDirectory( const char *zDirname ){
       
   342   SimulateIOError( SQLITE_IOERR );
       
   343   return SQLITE_OK;
       
   344 }
       
   345 
       
   346 /*
       
   347 ** Truncate an open file to a specified size
       
   348 */
       
   349 int os2Truncate( OsFile *id, i64 nByte ){
       
   350   APIRET rc = NO_ERROR;
       
   351   ULONG upperBits = nByte>>32;
       
   352   assert( id!=0 );
       
   353   TRACE3( "TRUNCATE %d %lld\n", ((os2File*)id)->h, nByte );
       
   354   SimulateIOError( SQLITE_IOERR );
       
   355   rc = DosSetFilePtr( ((os2File*)id)->h, nByte, FILE_BEGIN, &upperBits );
       
   356   if( rc != NO_ERROR ){
       
   357     return SQLITE_IOERR;
       
   358   }
       
   359   rc = DosSetFilePtr( ((os2File*)id)->h, 0L, FILE_END, &upperBits );
       
   360   return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
       
   361 }
       
   362 
       
   363 /*
       
   364 ** Determine the current size of a file in bytes
       
   365 */
       
   366 int os2FileSize( OsFile *id, i64 *pSize ){
       
   367   APIRET rc = NO_ERROR;
       
   368   FILESTATUS3 fsts3FileInfo;
       
   369   memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo));
       
   370   assert( id!=0 );
       
   371   SimulateIOError( SQLITE_IOERR );
       
   372   rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) );
       
   373   if( rc == NO_ERROR ){
       
   374     *pSize = fsts3FileInfo.cbFile;
       
   375     return SQLITE_OK;
       
   376   }
       
   377   else{
       
   378     return SQLITE_IOERR;
       
   379   }
       
   380 }
       
   381 
       
   382 /*
       
   383 ** Acquire a reader lock.
       
   384 */
       
   385 static int getReadLock( os2File *id ){
       
   386   FILELOCK  LockArea,
       
   387             UnlockArea;
       
   388   memset(&LockArea, 0, sizeof(LockArea));
       
   389   memset(&UnlockArea, 0, sizeof(UnlockArea));
       
   390   LockArea.lOffset = SHARED_FIRST;
       
   391   LockArea.lRange = SHARED_SIZE;
       
   392   UnlockArea.lOffset = 0L;
       
   393   UnlockArea.lRange = 0L;
       
   394   return DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L );
       
   395 }
       
   396 
       
   397 /*
       
   398 ** Undo a readlock
       
   399 */
       
   400 static int unlockReadLock( os2File *id ){
       
   401   FILELOCK  LockArea,
       
   402             UnlockArea;
       
   403   memset(&LockArea, 0, sizeof(LockArea));
       
   404   memset(&UnlockArea, 0, sizeof(UnlockArea));
       
   405   LockArea.lOffset = 0L;
       
   406   LockArea.lRange = 0L;
       
   407   UnlockArea.lOffset = SHARED_FIRST;
       
   408   UnlockArea.lRange = SHARED_SIZE;
       
   409   return DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L );
       
   410 }
       
   411 
       
   412 #ifndef SQLITE_OMIT_PAGER_PRAGMAS
       
   413 /*
       
   414 ** Check that a given pathname is a directory and is writable
       
   415 **
       
   416 */
       
   417 int sqlite3Os2IsDirWritable( char *zDirname ){
       
   418   FILESTATUS3 fsts3ConfigInfo;
       
   419   APIRET rc = NO_ERROR;
       
   420   memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo));
       
   421   if( zDirname==0 ) return 0;
       
   422   if( strlen(zDirname)>CCHMAXPATH ) return 0;
       
   423   rc = DosQueryPathInfo( (PSZ)zDirname, FIL_STANDARD, &fsts3ConfigInfo, sizeof(FILESTATUS3) );
       
   424   if( rc != NO_ERROR ) return 0;
       
   425   if( (fsts3ConfigInfo.attrFile & FILE_DIRECTORY) != FILE_DIRECTORY ) return 0;
       
   426 
       
   427   return 1;
       
   428 }
       
   429 #endif /* SQLITE_OMIT_PAGER_PRAGMAS */
       
   430 
       
   431 /*
       
   432 ** Lock the file with the lock specified by parameter locktype - one
       
   433 ** of the following:
       
   434 **
       
   435 **     (1) SHARED_LOCK
       
   436 **     (2) RESERVED_LOCK
       
   437 **     (3) PENDING_LOCK
       
   438 **     (4) EXCLUSIVE_LOCK
       
   439 **
       
   440 ** Sometimes when requesting one lock state, additional lock states
       
   441 ** are inserted in between.  The locking might fail on one of the later
       
   442 ** transitions leaving the lock state different from what it started but
       
   443 ** still short of its goal.  The following chart shows the allowed
       
   444 ** transitions and the inserted intermediate states:
       
   445 **
       
   446 **    UNLOCKED -> SHARED
       
   447 **    SHARED -> RESERVED
       
   448 **    SHARED -> (PENDING) -> EXCLUSIVE
       
   449 **    RESERVED -> (PENDING) -> EXCLUSIVE
       
   450 **    PENDING -> EXCLUSIVE
       
   451 **
       
   452 ** This routine will only increase a lock.  The os2Unlock() routine
       
   453 ** erases all locks at once and returns us immediately to locking level 0.
       
   454 ** It is not possible to lower the locking level one step at a time.  You
       
   455 ** must go straight to locking level 0.
       
   456 */
       
   457 int os2Lock( OsFile *id, int locktype ){
       
   458   APIRET rc = SQLITE_OK;    /* Return code from subroutines */
       
   459   APIRET res = NO_ERROR;    /* Result of an OS/2 lock call */
       
   460   int newLocktype;       /* Set id->locktype to this value before exiting */
       
   461   int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
       
   462   FILELOCK  LockArea,
       
   463             UnlockArea;
       
   464   os2File *pFile = (os2File*)id;
       
   465   memset(&LockArea, 0, sizeof(LockArea));
       
   466   memset(&UnlockArea, 0, sizeof(UnlockArea));
       
   467   assert( pFile!=0 );
       
   468   TRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype );
       
   469 
       
   470   /* If there is already a lock of this type or more restrictive on the
       
   471   ** OsFile, do nothing. Don't use the end_lock: exit path, as
       
   472   ** sqlite3OsEnterMutex() hasn't been called yet.
       
   473   */
       
   474   if( pFile->locktype>=locktype ){
       
   475     return SQLITE_OK;
       
   476   }
       
   477 
       
   478   /* Make sure the locking sequence is correct
       
   479   */
       
   480   assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
       
   481   assert( locktype!=PENDING_LOCK );
       
   482   assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
       
   483 
       
   484   /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
       
   485   ** a SHARED lock.  If we are acquiring a SHARED lock, the acquisition of
       
   486   ** the PENDING_LOCK byte is temporary.
       
   487   */
       
   488   newLocktype = pFile->locktype;
       
   489   if( pFile->locktype==NO_LOCK
       
   490    || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
       
   491   ){
       
   492     int cnt = 3;
       
   493 
       
   494     LockArea.lOffset = PENDING_BYTE;
       
   495     LockArea.lRange = 1L;
       
   496     UnlockArea.lOffset = 0L;
       
   497     UnlockArea.lRange = 0L;
       
   498 
       
   499     while( cnt-->0 && (res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L) )!=NO_ERROR ){
       
   500       /* Try 3 times to get the pending lock.  The pending lock might be
       
   501       ** held by another reader process who will release it momentarily.
       
   502       */
       
   503       TRACE2( "could not get a PENDING lock. cnt=%d\n", cnt );
       
   504       DosSleep(1);
       
   505     }
       
   506     gotPendingLock = res;
       
   507   }
       
   508 
       
   509   /* Acquire a shared lock
       
   510   */
       
   511   if( locktype==SHARED_LOCK && res ){
       
   512     assert( pFile->locktype==NO_LOCK );
       
   513     res = getReadLock(pFile);
       
   514     if( res == NO_ERROR ){
       
   515       newLocktype = SHARED_LOCK;
       
   516     }
       
   517   }
       
   518 
       
   519   /* Acquire a RESERVED lock
       
   520   */
       
   521   if( locktype==RESERVED_LOCK && res ){
       
   522     assert( pFile->locktype==SHARED_LOCK );
       
   523     LockArea.lOffset = RESERVED_BYTE;
       
   524     LockArea.lRange = 1L;
       
   525     UnlockArea.lOffset = 0L;
       
   526     UnlockArea.lRange = 0L;
       
   527     res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
       
   528     if( res == NO_ERROR ){
       
   529       newLocktype = RESERVED_LOCK;
       
   530     }
       
   531   }
       
   532 
       
   533   /* Acquire a PENDING lock
       
   534   */
       
   535   if( locktype==EXCLUSIVE_LOCK && res ){
       
   536     newLocktype = PENDING_LOCK;
       
   537     gotPendingLock = 0;
       
   538   }
       
   539 
       
   540   /* Acquire an EXCLUSIVE lock
       
   541   */
       
   542   if( locktype==EXCLUSIVE_LOCK && res ){
       
   543     assert( pFile->locktype>=SHARED_LOCK );
       
   544     res = unlockReadLock(pFile);
       
   545     TRACE2( "unreadlock = %d\n", res );
       
   546     LockArea.lOffset = SHARED_FIRST;
       
   547     LockArea.lRange = SHARED_SIZE;
       
   548     UnlockArea.lOffset = 0L;
       
   549     UnlockArea.lRange = 0L;
       
   550     res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
       
   551     if( res == NO_ERROR ){
       
   552       newLocktype = EXCLUSIVE_LOCK;
       
   553     }else{
       
   554       TRACE2( "error-code = %d\n", res );
       
   555     }
       
   556   }
       
   557 
       
   558   /* If we are holding a PENDING lock that ought to be released, then
       
   559   ** release it now.
       
   560   */
       
   561   if( gotPendingLock && locktype==SHARED_LOCK ){
       
   562     LockArea.lOffset = 0L;
       
   563     LockArea.lRange = 0L;
       
   564     UnlockArea.lOffset = PENDING_BYTE;
       
   565     UnlockArea.lRange = 1L;
       
   566     DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
       
   567   }
       
   568 
       
   569   /* Update the state of the lock has held in the file descriptor then
       
   570   ** return the appropriate result code.
       
   571   */
       
   572   if( res == NO_ERROR ){
       
   573     rc = SQLITE_OK;
       
   574   }else{
       
   575     TRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
       
   576            locktype, newLocktype );
       
   577     rc = SQLITE_BUSY;
       
   578   }
       
   579   pFile->locktype = newLocktype;
       
   580   return rc;
       
   581 }
       
   582 
       
   583 /*
       
   584 ** This routine checks if there is a RESERVED lock held on the specified
       
   585 ** file by this or any other process. If such a lock is held, return
       
   586 ** non-zero, otherwise zero.
       
   587 */
       
   588 int os2CheckReservedLock( OsFile *id ){
       
   589   APIRET rc = NO_ERROR;
       
   590   os2File *pFile = (os2File*)id;
       
   591   assert( pFile!=0 );
       
   592   if( pFile->locktype>=RESERVED_LOCK ){
       
   593     rc = 1;
       
   594     TRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, rc );
       
   595   }else{
       
   596     FILELOCK  LockArea,
       
   597               UnlockArea;
       
   598     memset(&LockArea, 0, sizeof(LockArea));
       
   599     memset(&UnlockArea, 0, sizeof(UnlockArea));
       
   600     LockArea.lOffset = RESERVED_BYTE;
       
   601     LockArea.lRange = 1L;
       
   602     UnlockArea.lOffset = 0L;
       
   603     UnlockArea.lRange = 0L;
       
   604     rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
       
   605     if( rc == NO_ERROR ){
       
   606       LockArea.lOffset = 0L;
       
   607       LockArea.lRange = 0L;
       
   608       UnlockArea.lOffset = RESERVED_BYTE;
       
   609       UnlockArea.lRange = 1L;
       
   610       rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
       
   611     }
       
   612     TRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, rc );
       
   613   }
       
   614   return rc;
       
   615 }
       
   616 
       
   617 /*
       
   618 ** Lower the locking level on file descriptor id to locktype.  locktype
       
   619 ** must be either NO_LOCK or SHARED_LOCK.
       
   620 **
       
   621 ** If the locking level of the file descriptor is already at or below
       
   622 ** the requested locking level, this routine is a no-op.
       
   623 **
       
   624 ** It is not possible for this routine to fail if the second argument
       
   625 ** is NO_LOCK.  If the second argument is SHARED_LOCK then this routine
       
   626 ** might return SQLITE_IOERR;
       
   627 */
       
   628 int os2Unlock( OsFile *id, int locktype ){
       
   629   int type;
       
   630   APIRET rc = SQLITE_OK;
       
   631   os2File *pFile = (os2File*)id;
       
   632   FILELOCK  LockArea,
       
   633             UnlockArea;
       
   634   memset(&LockArea, 0, sizeof(LockArea));
       
   635   memset(&UnlockArea, 0, sizeof(UnlockArea));
       
   636   assert( pFile!=0 );
       
   637   assert( locktype<=SHARED_LOCK );
       
   638   TRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype );
       
   639   type = pFile->locktype;
       
   640   if( type>=EXCLUSIVE_LOCK ){
       
   641     LockArea.lOffset = 0L;
       
   642     LockArea.lRange = 0L;
       
   643     UnlockArea.lOffset = SHARED_FIRST;
       
   644     UnlockArea.lRange = SHARED_SIZE;
       
   645     DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
       
   646     if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){
       
   647       /* This should never happen.  We should always be able to
       
   648       ** reacquire the read lock */
       
   649       rc = SQLITE_IOERR;
       
   650     }
       
   651   }
       
   652   if( type>=RESERVED_LOCK ){
       
   653     LockArea.lOffset = 0L;
       
   654     LockArea.lRange = 0L;
       
   655     UnlockArea.lOffset = RESERVED_BYTE;
       
   656     UnlockArea.lRange = 1L;
       
   657     DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
       
   658   }
       
   659   if( locktype==NO_LOCK && type>=SHARED_LOCK ){
       
   660     unlockReadLock(pFile);
       
   661   }
       
   662   if( type>=PENDING_LOCK ){
       
   663     LockArea.lOffset = 0L;
       
   664     LockArea.lRange = 0L;
       
   665     UnlockArea.lOffset = PENDING_BYTE;
       
   666     UnlockArea.lRange = 1L;
       
   667     DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
       
   668   }
       
   669   pFile->locktype = locktype;
       
   670   return rc;
       
   671 }
       
   672 
       
   673 /*
       
   674 ** Turn a relative pathname into a full pathname.  Return a pointer
       
   675 ** to the full pathname stored in space obtained from sqliteMalloc().
       
   676 ** The calling function is responsible for freeing this space once it
       
   677 ** is no longer needed.
       
   678 */
       
   679 char *sqlite3Os2FullPathname( const char *zRelative ){
       
   680   char *zFull = 0;
       
   681   if( strchr(zRelative, ':') ){
       
   682     sqlite3SetString( &zFull, zRelative, (char*)0 );
       
   683   }else{
       
   684     char zBuff[SQLITE_TEMPNAME_SIZE - 2] = {0};
       
   685     char zDrive[1] = {0};
       
   686     ULONG cbzFullLen = SQLITE_TEMPNAME_SIZE;
       
   687     ULONG ulDriveNum = 0;
       
   688     ULONG ulDriveMap = 0;
       
   689     DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
       
   690     DosQueryCurrentDir( 0L, zBuff, &cbzFullLen );
       
   691     zFull = sqliteMalloc( cbzFullLen );
       
   692     sprintf( zDrive, "%c", (char)('A' + ulDriveNum - 1) );
       
   693     sqlite3SetString( &zFull, zDrive, ":\\", zBuff, "\\", zRelative, (char*)0 );
       
   694   }
       
   695   return zFull;
       
   696 }
       
   697 
       
   698 /*
       
   699 ** The fullSync option is meaningless on os2, or correct me if I'm wrong.  This is a no-op.
       
   700 ** From os_unix.c: Change the value of the fullsync flag in the given file descriptor.
       
   701 ** From os_unix.c: ((unixFile*)id)->fullSync = v;
       
   702 */
       
   703 static void os2SetFullSync( OsFile *id, int v ){
       
   704   return;
       
   705 }
       
   706 
       
   707 /*
       
   708 ** Return the underlying file handle for an OsFile
       
   709 */
       
   710 static int os2FileHandle( OsFile *id ){
       
   711   return (int)((os2File*)id)->h;
       
   712 }
       
   713 
       
   714 /*
       
   715 ** Return an integer that indices the type of lock currently held
       
   716 ** by this handle.  (Used for testing and analysis only.)
       
   717 */
       
   718 static int os2LockState( OsFile *id ){
       
   719   return ((os2File*)id)->locktype;
       
   720 }
       
   721 
       
   722 /*
       
   723 ** This vector defines all the methods that can operate on an OsFile
       
   724 ** for os2.
       
   725 */
       
   726 static const IoMethod sqlite3Os2IoMethod = {
       
   727   os2Close,
       
   728   os2OpenDirectory,
       
   729   os2Read,
       
   730   os2Write,
       
   731   os2Seek,
       
   732   os2Truncate,
       
   733   os2Sync,
       
   734   os2SetFullSync,
       
   735   os2FileHandle,
       
   736   os2FileSize,
       
   737   os2Lock,
       
   738   os2Unlock,
       
   739   os2LockState,
       
   740   os2CheckReservedLock,
       
   741 };
       
   742 
       
   743 /*
       
   744 ** Allocate memory for an OsFile.  Initialize the new OsFile
       
   745 ** to the value given in pInit and return a pointer to the new
       
   746 ** OsFile.  If we run out of memory, close the file and return NULL.
       
   747 */
       
   748 int allocateOs2File( os2File *pInit, OsFile **pld ){
       
   749   os2File *pNew;
       
   750   pNew = sqliteMalloc( sizeof(*pNew) );
       
   751   if( pNew==0 ){
       
   752     DosClose( pInit->h );
       
   753     *pld = 0;
       
   754     return SQLITE_NOMEM;
       
   755   }else{
       
   756     *pNew = *pInit;
       
   757     pNew->pMethod = &sqlite3Os2IoMethod;
       
   758     pNew->locktype = NO_LOCK;
       
   759     *pld = (OsFile*)pNew;
       
   760     OpenCounter(+1);
       
   761     return SQLITE_OK;
       
   762   }
       
   763 }
       
   764 
       
   765 #endif /* SQLITE_OMIT_DISKIO */
       
   766 /***************************************************************************
       
   767 ** Everything above deals with file I/O.  Everything that follows deals
       
   768 ** with other miscellanous aspects of the operating system interface
       
   769 ****************************************************************************/
       
   770 
       
   771 /*
       
   772 ** Get information to seed the random number generator.  The seed
       
   773 ** is written into the buffer zBuf[256].  The calling function must
       
   774 ** supply a sufficiently large buffer.
       
   775 */
       
   776 int sqlite3Os2RandomSeed( char *zBuf ){
       
   777   /* We have to initialize zBuf to prevent valgrind from reporting
       
   778   ** errors.  The reports issued by valgrind are incorrect - we would
       
   779   ** prefer that the randomness be increased by making use of the
       
   780   ** uninitialized space in zBuf - but valgrind errors tend to worry
       
   781   ** some users.  Rather than argue, it seems easier just to initialize
       
   782   ** the whole array and silence valgrind, even if that means less randomness
       
   783   ** in the random seed.
       
   784   **
       
   785   ** When testing, initializing zBuf[] to zero is all we do.  That means
       
   786   ** that we always use the same random number sequence. This makes the
       
   787   ** tests repeatable.
       
   788   */
       
   789   memset( zBuf, 0, 256 );
       
   790   DosGetDateTime( (PDATETIME)zBuf );
       
   791   return SQLITE_OK;
       
   792 }
       
   793 
       
   794 /*
       
   795 ** Sleep for a little while.  Return the amount of time slept.
       
   796 */
       
   797 int sqlite3Os2Sleep( int ms ){
       
   798   DosSleep( ms );
       
   799   return ms;
       
   800 }
       
   801 
       
   802 /*
       
   803 ** Static variables used for thread synchronization
       
   804 */
       
   805 static int inMutex = 0;
       
   806 #ifdef SQLITE_OS2_THREADS
       
   807 static ULONG mutexOwner;
       
   808 #endif
       
   809 
       
   810 /*
       
   811 ** The following pair of routines implement mutual exclusion for
       
   812 ** multi-threaded processes.  Only a single thread is allowed to
       
   813 ** executed code that is surrounded by EnterMutex() and LeaveMutex().
       
   814 **
       
   815 ** SQLite uses only a single Mutex.  There is not much critical
       
   816 ** code and what little there is executes quickly and without blocking.
       
   817 */
       
   818 void sqlite3Os2EnterMutex(){
       
   819   PTIB ptib;
       
   820 #ifdef SQLITE_OS2_THREADS
       
   821   DosEnterCritSec();
       
   822   DosGetInfoBlocks( &ptib, NULL );
       
   823   mutexOwner = ptib->tib_ptib2->tib2_ultid;
       
   824 #endif
       
   825   assert( !inMutex );
       
   826   inMutex = 1;
       
   827 }
       
   828 void sqlite3Os2LeaveMutex(){
       
   829   PTIB ptib;
       
   830   assert( inMutex );
       
   831   inMutex = 0;
       
   832 #ifdef SQLITE_OS2_THREADS
       
   833   DosGetInfoBlocks( &ptib, NULL );
       
   834   assert( mutexOwner == ptib->tib_ptib2->tib2_ultid );
       
   835   DosExitCritSec();
       
   836 #endif
       
   837 }
       
   838 
       
   839 /*
       
   840 ** Return TRUE if the mutex is currently held.
       
   841 **
       
   842 ** If the thisThreadOnly parameter is true, return true if and only if the
       
   843 ** calling thread holds the mutex.  If the parameter is false, return
       
   844 ** true if any thread holds the mutex.
       
   845 */
       
   846 int sqlite3Os2InMutex( int thisThreadOnly ){
       
   847 #ifdef SQLITE_OS2_THREADS
       
   848   PTIB ptib;
       
   849   DosGetInfoBlocks( &ptib, NULL );
       
   850   return inMutex>0 && (thisThreadOnly==0 || mutexOwner==ptib->tib_ptib2->tib2_ultid);
       
   851 #else
       
   852   return inMutex>0;
       
   853 #endif
       
   854 }
       
   855 
       
   856 /*
       
   857 ** The following variable, if set to a non-zero value, becomes the result
       
   858 ** returned from sqlite3OsCurrentTime().  This is used for testing.
       
   859 */
       
   860 #ifdef SQLITE_TEST
       
   861 int sqlite3_current_time = 0;
       
   862 #endif
       
   863 
       
   864 /*
       
   865 ** Find the current time (in Universal Coordinated Time).  Write the
       
   866 ** current time and date as a Julian Day number into *prNow and
       
   867 ** return 0.  Return 1 if the time and date cannot be found.
       
   868 */
       
   869 int sqlite3Os2CurrentTime( double *prNow ){
       
   870   double now;
       
   871   USHORT second, minute, hour,
       
   872          day, month, year;
       
   873   DATETIME dt;
       
   874   DosGetDateTime( &dt );
       
   875   second = (USHORT)dt.seconds;
       
   876   minute = (USHORT)dt.minutes + dt.timezone;
       
   877   hour = (USHORT)dt.hours;
       
   878   day = (USHORT)dt.day;
       
   879   month = (USHORT)dt.month;
       
   880   year = (USHORT)dt.year;
       
   881 
       
   882   /* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html
       
   883      http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c */
       
   884   /* Calculate the Julian days */
       
   885   now = day - 32076 +
       
   886     1461*(year + 4800 + (month - 14)/12)/4 +
       
   887     367*(month - 2 - (month - 14)/12*12)/12 -
       
   888     3*((year + 4900 + (month - 14)/12)/100)/4;
       
   889 
       
   890   /* Add the fractional hours, mins and seconds */
       
   891   now += (hour + 12.0)/24.0;
       
   892   now += minute/1440.0;
       
   893   now += second/86400.0;
       
   894   *prNow = now;
       
   895 #ifdef SQLITE_TEST
       
   896   if( sqlite3_current_time ){
       
   897     *prNow = sqlite3_current_time/86400.0 + 2440587.5;
       
   898   }
       
   899 #endif
       
   900   return 0;
       
   901 }
       
   902 
       
   903 /*
       
   904 ** Remember the number of thread-specific-data blocks allocated.
       
   905 ** Use this to verify that we are not leaking thread-specific-data.
       
   906 ** Ticket #1601
       
   907 */
       
   908 #ifdef SQLITE_TEST
       
   909 int sqlite3_tsd_count = 0;
       
   910 # define TSD_COUNTER_INCR InterlockedIncrement( &sqlite3_tsd_count )
       
   911 # define TSD_COUNTER_DECR InterlockedDecrement( &sqlite3_tsd_count )
       
   912 #else
       
   913 # define TSD_COUNTER_INCR  /* no-op */
       
   914 # define TSD_COUNTER_DECR  /* no-op */
       
   915 #endif
       
   916 
       
   917 /*
       
   918 ** If called with allocateFlag>1, then return a pointer to thread
       
   919 ** specific data for the current thread.  Allocate and zero the
       
   920 ** thread-specific data if it does not already exist necessary.
       
   921 **
       
   922 ** If called with allocateFlag==0, then check the current thread
       
   923 ** specific data.  Return it if it exists.  If it does not exist,
       
   924 ** then return NULL.
       
   925 **
       
   926 ** If called with allocateFlag<0, check to see if the thread specific
       
   927 ** data is allocated and is all zero.  If it is then deallocate it.
       
   928 ** Return a pointer to the thread specific data or NULL if it is
       
   929 ** unallocated or gets deallocated.
       
   930 */
       
   931 ThreadData *sqlite3Os2ThreadSpecificData( int allocateFlag ){
       
   932   static ThreadData **s_ppTsd = NULL;
       
   933   static const ThreadData zeroData = {0, 0, 0};
       
   934   ThreadData *pTsd;
       
   935 
       
   936   if( !s_ppTsd ){
       
   937     sqlite3OsEnterMutex();
       
   938     if( !s_ppTsd ){
       
   939       PULONG pul;
       
   940       APIRET rc = DosAllocThreadLocalMemory(1, &pul);
       
   941       if( rc != NO_ERROR ){
       
   942         sqlite3OsLeaveMutex();
       
   943         return 0;
       
   944       }
       
   945       s_ppTsd = (ThreadData **)pul;
       
   946     }
       
   947     sqlite3OsLeaveMutex();
       
   948   }
       
   949   pTsd = *s_ppTsd;
       
   950   if( allocateFlag>0 ){
       
   951     if( !pTsd ){
       
   952       pTsd = sqlite3OsMalloc( sizeof(zeroData) );
       
   953       if( pTsd ){
       
   954         *pTsd = zeroData;
       
   955         *s_ppTsd = pTsd;
       
   956         TSD_COUNTER_INCR;
       
   957       }
       
   958     }
       
   959   }else if( pTsd!=0 && allocateFlag<0
       
   960               && memcmp( pTsd, &zeroData, sizeof(ThreadData) )==0 ){
       
   961     sqlite3OsFree(pTsd);
       
   962     *s_ppTsd = NULL;
       
   963     TSD_COUNTER_DECR;
       
   964     pTsd = 0;
       
   965   }
       
   966   return pTsd;
       
   967 }
       
   968 #endif /* OS_OS2 */