⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os.c

📁 sqlite源码wince移植版
💻 C
📖 第 1 页 / 共 5 页
字号:
# else    wrote = amt;    oserr = FSWrite(id->refNum, &wrote, pBuf);# endif    if( wrote == 0 || oserr != noErr)      break;    amt -= wrote;    pBuf = &((char*)pBuf)[wrote];  }  if( oserr != noErr || amt>wrote ){    return SQLITE_FULL;  }  return SQLITE_OK;#endif}/*** Move the read/write pointer in a file.*/int sqliteOsSeek(OsFile *id, off_t offset){  SEEK(offset/1024 + 1);#if OS_UNIX  lseek(id->fd, offset, SEEK_SET);  return SQLITE_OK;#endif#if OS_WIN  {    LONG upperBits = offset>>32;    LONG lowerBits = offset & 0xffffffff;    DWORD rc;    rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN);    /* TRACE3("SEEK rc=0x%x upper=0x%x\n", rc, upperBits); */  }  return SQLITE_OK;#endif#if OS_MAC  {    off_t curSize;    if( sqliteOsFileSize(id, &curSize) != SQLITE_OK ){      return SQLITE_IOERR;    }    if( offset >= curSize ){      if( sqliteOsTruncate(id, offset+1) != SQLITE_OK ){        return SQLITE_IOERR;      }    }# ifdef _LARGE_FILE    if( FSSetForkPosition(id->refNum, fsFromStart, offset) != noErr ){# else    if( SetFPos(id->refNum, fsFromStart, offset) != noErr ){# endif      return SQLITE_IOERR;    }else{      return SQLITE_OK;    }  }#endif}/*** Make sure all writes to a particular file are committed to disk.**** Under Unix, also make sure that the directory entry for the file** has been created by fsync-ing the directory that contains the file.** If we do not do this and we encounter a power failure, the directory** entry for the journal might not exist after we reboot.  The next** SQLite to access the file will not know that the journal exists (because** the directory entry for the journal was never created) and the transaction** will not roll back - possibly leading to database corruption.*/int sqliteOsSync(OsFile *id){#if OS_UNIX  SimulateIOError(SQLITE_IOERR);  TRACE2("SYNC    %-3d\n", id->fd);  if( fsync(id->fd) ){    return SQLITE_IOERR;  }else{    if( id->dirfd>=0 ){      TRACE2("DIRSYNC %-3d\n", id->dirfd);      fsync(id->dirfd);      close(id->dirfd);  /* Only need to sync once, so close the directory */      id->dirfd = -1;    /* when we are done. */    }    return SQLITE_OK;  }#endif#if OS_WIN  if( FlushFileBuffers(id->h) ){    return SQLITE_OK;  }else{    return SQLITE_IOERR;  }#endif#if OS_MAC# ifdef _LARGE_FILE  if( FSFlushFork(id->refNum) != noErr ){# else  ParamBlockRec params;  memset(&params, 0, sizeof(ParamBlockRec));  params.ioParam.ioRefNum = id->refNum;  if( PBFlushFileSync(&params) != noErr ){# endif    return SQLITE_IOERR;  }else{    return SQLITE_OK;  }#endif}/*** Truncate an open file to a specified size*/int sqliteOsTruncate(OsFile *id, off_t nByte){  SimulateIOError(SQLITE_IOERR);#if OS_UNIX  return ftruncate(id->fd, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;#endif#if OS_WIN  {    LONG upperBits = nByte>>32;    SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN);    SetEndOfFile(id->h);  }  return SQLITE_OK;#endif#if OS_MAC# ifdef _LARGE_FILE  if( FSSetForkSize(id->refNum, fsFromStart, nByte) != noErr){# else  if( SetEOF(id->refNum, nByte) != noErr ){# endif    return SQLITE_IOERR;  }else{    return SQLITE_OK;  }#endif}/*** Determine the current size of a file in bytes*/int sqliteOsFileSize(OsFile *id, off_t *pSize){#if OS_UNIX  struct stat buf;  SimulateIOError(SQLITE_IOERR);  if( fstat(id->fd, &buf)!=0 ){    return SQLITE_IOERR;  }  *pSize = buf.st_size;  return SQLITE_OK;#endif#if OS_WIN  DWORD upperBits, lowerBits;  SimulateIOError(SQLITE_IOERR);  lowerBits = GetFileSize(id->h, &upperBits);  *pSize = (((off_t)upperBits)<<32) + lowerBits;  return SQLITE_OK;#endif#if OS_MAC# ifdef _LARGE_FILE  if( FSGetForkSize(id->refNum, pSize) != noErr){# else  if( GetEOF(id->refNum, pSize) != noErr ){# endif    return SQLITE_IOERR;  }else{    return SQLITE_OK;  }#endif}#if OS_WIN/*** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.** Return false (zero) for Win95, Win98, or WinME.**** Here is an interesting observation:  Win95, Win98, and WinME lack** the LockFileEx() API.  But we can still statically link against that** API as long as we don't call it win running Win95/98/ME.  A call to** this routine is used to determine if the host is Win95/98/ME or** WinNT/2K/XP so that we will know whether or not we can safely call** the LockFileEx() API.*/int isNT(void){  static int osType = 0;   /* 0=unknown 1=win95 2=winNT */# ifndef _WIN32_WCE  if( osType==0 ){    OSVERSIONINFO sInfo;    sInfo.dwOSVersionInfoSize = sizeof(sInfo);    GetVersionEx(&sInfo);    osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;  }# endif  return osType==2;}#endif/*** Windows file locking notes:  [similar issues apply to MacOS]**** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because** those functions are not available.  So we use only LockFile() and** UnlockFile().**** LockFile() prevents not just writing but also reading by other processes.** (This is a design error on the part of Windows, but there is nothing** we can do about that.)  So the region used for locking is at the** end of the file where it is unlikely to ever interfere with an** actual read attempt.**** A database read lock is obtained by locking a single randomly-chosen ** byte out of a specific range of bytes. The lock byte is obtained at ** random so two separate readers can probably access the file at the ** same time, unless they are unlucky and choose the same lock byte.** A database write lock is obtained by locking all bytes in the range.** There can only be one writer.**** A lock is obtained on the first byte of the lock range before acquiring** either a read lock or a write lock.  This prevents two processes from** attempting to get a lock at a same time.  The semantics of ** sqliteOsReadLock() require that if there is already a write lock, that** lock is converted into a read lock atomically.  The lock on the first** byte allows us to drop the old write lock and get the read lock without** another process jumping into the middle and messing us up.  The same** argument applies to sqliteOsWriteLock().**** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,** which means we can use reader/writer locks.  When reader writer locks** are used, the lock is placed on the same range of bytes that is used** for probabilistic locking in Win95/98/ME.  Hence, the locking scheme** will support two or more Win95 readers or two or more WinNT readers.** But a single Win95 reader will lock out all WinNT readers and a single** WinNT reader will lock out all other Win95 readers.**** Note: On MacOS we use the resource fork for locking.**** The following #defines specify the range of bytes used for locking.** N_LOCKBYTE is the number of bytes available for doing the locking.** The first byte used to hold the lock while the lock is changing does** not count toward this number.  FIRST_LOCKBYTE is the address of** the first byte in the range of bytes used for locking.*/#define N_LOCKBYTE       10239#if OS_MAC# define FIRST_LOCKBYTE   (0x000fffff - N_LOCKBYTE)#else# define FIRST_LOCKBYTE   (0xffffffff - N_LOCKBYTE)#endif/*** Change the status of the lock on the file "id" to be a readlock.** If the file was write locked, then this reduces the lock to a read.** If the file was read locked, then this acquires a new read lock.**** Return SQLITE_OK on success and SQLITE_BUSY on failure.  If this** library was compiled with large file support (LFS) but LFS is not** available on the host, then an SQLITE_NOLFS is returned.*/int sqliteOsReadLock(OsFile *id){#if OS_UNIX  int rc;  sqliteOsEnterMutex();  if( id->pLock->cnt>0 ){    if( !id->locked ){      id->pLock->cnt++;      id->locked = 1;      id->pOpen->nLock++;    }    rc = SQLITE_OK;  }else if( id->locked || id->pLock->cnt==0 ){    struct flock lock;    int s;    lock.l_type = F_RDLCK;    lock.l_whence = SEEK_SET;    lock.l_start = lock.l_len = 0L;    s = fcntl(id->fd, F_SETLK, &lock);    if( s!=0 ){      rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;    }else{      rc = SQLITE_OK;      if( !id->locked ){        id->pOpen->nLock++;        id->locked = 1;      }      id->pLock->cnt = 1;    }  }else{    rc = SQLITE_BUSY;  }  sqliteOsLeaveMutex();  return rc;#endif#if OS_WIN# ifndef _WIN32_WCE  int rc;  if( id->locked>0 ){    rc = SQLITE_OK;  }else{    int lk;    int res;    int cnt = 100;    sqliteRandomness(sizeof(lk), &lk);    lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;    while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){      Sleep(1);    }    if( res ){      UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);      if( isNT() ){        OVERLAPPED ovlp;        ovlp.Offset = FIRST_LOCKBYTE+1;        ovlp.OffsetHigh = 0;        ovlp.hEvent = 0;        res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY,                           0, N_LOCKBYTE, 0, &ovlp);      }else{        res = LockFile(id->h, FIRST_LOCKBYTE+lk, 0, 1, 0);      }      UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);    }    if( res ){      id->locked = lk;      rc = SQLITE_OK;    }else{      rc = SQLITE_BUSY;    }  }  return rc;# else  // if already read locked, return success  if ( id->locked > 0 )    return SQLITE_OK;  // If file not shared, always success  if ( id->hMux == 0 )  {     id->locked = 1;     return SQLITE_OK;  }#  ifndef SQLITE_WCE_OMIT_FILELOCK  // Lock file for all processes  if ( ! wceport_LockFileMutex(id->hMux) )     return SQLITE_BUSY;  // if file is write locked, release semaphore to a single reader state  if ( id->locked < 0 )  {     BOOL res = ReleaseSemaphore( id->hSem, MAX_FILE_READERS-1, NULL );     // Update lock status and release file mutex lock     id->locked = 1;     ReleaseMutex( id->hMux );     // this can only fail on a program bug or operating sistem error     // what should we do if that happens ?     assert( res != FALSE );     return SQLITE_OK;  }  // not locked yet, try to decrement semaphore  if ( ! wceport_DecrementSemaphore(id->hSem) )  {	// Write-locked by other thread, or maximum readers reached     ReleaseMutex( id->hMux );     return SQLITE_BUSY;  }  id->locked = 1;  ReleaseMutex( id->hMux );  return SQLITE_OK;#  else // SQLITE_WCE_OMIT_FILELOCK  id->locked = 1;  return SQLITE_OK;#  endif // SQLITE_OMIT_FILELOCK# endif#endif#if OS_MAC  int rc;  if( id->locked>0 || id->refNumRF == -1 ){    rc = SQLITE_OK;  }else{    int lk;    OSErr res;    int cnt = 5;    ParamBlockRec params;    sqliteRandomness(sizeof(lk), &lk);    lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;    memset(&params, 0, sizeof(params));    params.ioParam.ioRefNum = id->refNumRF;    params.ioParam.ioPosMode = fsFromStart;    params.ioParam.ioPosOffset = FIRST_LOCKBYTE;    params.ioParam.ioReqCount = 1;    while( cnt-->0 && (res = PBLockRangeSync(&params))!=noErr ){      UInt32 finalTicks;      Delay(1, &finalTicks); /* 1/60 sec */    }    if( res == noErr ){      params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;      params.ioParam.ioReqCount = N_LOCKBYTE;      PBUnlockRangeSync(&params);      params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk;      params.ioParam.ioReqCount = 1;      res = PBLockRangeSync(&params);      params.ioParam.ioPosOffset = FIRST_LOCKBYTE;      params.ioParam.ioReqCount = 1;      PBUnlockRangeSync(&params);    }    if( res == noErr ){      id->locked = lk;      rc = SQLITE_OK;    }else{      rc = SQLITE_BUSY;    }  }  return rc;#endif}/*** Change the lock status to be an exclusive or write lock.  Return** SQLITE_OK on success and SQLITE_BUSY on a failure.  If this** library was compiled with large file support (LFS) but LFS is not** available on the host, then an SQLITE_NOLFS is returned.*/int sqliteOsWriteLock(OsFile *id){#if OS_UNIX  int rc;  sqliteOsEnterMutex();  if( id->pLock->cnt==0 || (id->pLock->cnt==1 && id->locked==1) ){    struct flock lock;    int s;    lock.l_type = F_WRLCK;    lock.l_whence = SEEK_SET;    lock.l_start = lock.l_len = 0L;    s = fcntl(id->fd, F_SETLK, &lock);    if( s!=0 ){      rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;    }else{      rc = SQLITE_OK;      if( !id->locked ){        id->pOpen->nLock++;        id->locked = 1;      }      id->pLock->cnt = -1;    }  }else{    rc = SQLITE_BUSY;  }  sqliteOsLeaveMutex();  return rc;#endif#if OS_WIN# ifndef _WIN32_WCE  int rc;  if( id->locked<0 ){    rc = SQLITE_OK;  }else{    int res;    int cnt = 100;    while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){      Sleep(1);    }    if( res ){      if( id->locked>0 ){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -