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

📄 os_unix.c

📁 sqlite嵌入式数据库源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*** Release a openCnt structure previously allocated by findLockInfo().*/static void releaseOpenCnt(struct openCnt *pOpen){  assert( sqlite3OsInMutex(1) );  pOpen->nRef--;  if( pOpen->nRef==0 ){    sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);    free(pOpen->aPending);    sqlite3ThreadSafeFree(pOpen);  }}/*** Given a file descriptor, locate lockInfo and openCnt structures that** describes that file descriptor.  Create new ones if necessary.  The** return values might be uninitialized if an error occurs.**** Return the number of errors.*/static int findLockInfo(  int fd,                      /* The file descriptor used in the key */  struct lockInfo **ppLock,    /* Return the lockInfo structure here */  struct openCnt **ppOpen      /* Return the openCnt structure here */){  int rc;  struct lockKey key1;  struct openKey key2;  struct stat statbuf;  struct lockInfo *pLock;  struct openCnt *pOpen;  rc = fstat(fd, &statbuf);  if( rc!=0 ) return 1;  assert( sqlite3OsInMutex(1) );  memset(&key1, 0, sizeof(key1));  key1.dev = statbuf.st_dev;  key1.ino = statbuf.st_ino;#ifdef SQLITE_UNIX_THREADS  if( threadsOverrideEachOthersLocks<0 ){    testThreadLockingBehavior(fd);  }  key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self();#endif  memset(&key2, 0, sizeof(key2));  key2.dev = statbuf.st_dev;  key2.ino = statbuf.st_ino;  pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1));  if( pLock==0 ){    struct lockInfo *pOld;    pLock = sqlite3ThreadSafeMalloc( sizeof(*pLock) );    if( pLock==0 ){      rc = 1;      goto exit_findlockinfo;    }    pLock->key = key1;    pLock->nRef = 1;    pLock->cnt = 0;    pLock->locktype = 0;    pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);    if( pOld!=0 ){      assert( pOld==pLock );      sqlite3ThreadSafeFree(pLock);      rc = 1;      goto exit_findlockinfo;    }  }else{    pLock->nRef++;  }  *ppLock = pLock;  if( ppOpen!=0 ){    pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2));    if( pOpen==0 ){      struct openCnt *pOld;      pOpen = sqlite3ThreadSafeMalloc( sizeof(*pOpen) );      if( pOpen==0 ){        releaseLockInfo(pLock);        rc = 1;        goto exit_findlockinfo;      }      pOpen->key = key2;      pOpen->nRef = 1;      pOpen->nLock = 0;      pOpen->nPending = 0;      pOpen->aPending = 0;      pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen);      if( pOld!=0 ){        assert( pOld==pOpen );        sqlite3ThreadSafeFree(pOpen);        releaseLockInfo(pLock);        rc = 1;        goto exit_findlockinfo;      }    }else{      pOpen->nRef++;    }    *ppOpen = pOpen;  }exit_findlockinfo:  return rc;}#ifdef SQLITE_DEBUG/*** Helper function for printing out trace information from debugging** binaries. This returns the string represetation of the supplied** integer lock-type.*/static const char *locktypeName(int locktype){  switch( locktype ){  case NO_LOCK: return "NONE";  case SHARED_LOCK: return "SHARED";  case RESERVED_LOCK: return "RESERVED";  case PENDING_LOCK: return "PENDING";  case EXCLUSIVE_LOCK: return "EXCLUSIVE";  }  return "ERROR";}#endif/*** If we are currently in a different thread than the thread that the** unixFile argument belongs to, then transfer ownership of the unixFile** over to the current thread.**** A unixFile is only owned by a thread on systems where one thread is** unable to override locks created by a different thread.  RedHat9 is** an example of such a system.**** Ownership transfer is only allowed if the unixFile is currently unlocked.** If the unixFile is locked and an ownership is wrong, then return** SQLITE_MISUSE.  SQLITE_OK is returned if everything works.*/#ifdef SQLITE_UNIX_THREADSstatic int transferOwnership(unixFile *pFile){  int rc;  pthread_t hSelf;  if( threadsOverrideEachOthersLocks ){    /* Ownership transfers not needed on this system */    return SQLITE_OK;  }  hSelf = pthread_self();  if( pthread_equal(pFile->tid, hSelf) ){    /* We are still in the same thread */    TRACE1("No-transfer, same thread\n");    return SQLITE_OK;  }  if( pFile->locktype!=NO_LOCK ){    /* We cannot change ownership while we are holding a lock! */    return SQLITE_MISUSE;  }  TRACE4("Transfer ownership of %d from %d to %d\n", pFile->h,pFile->tid,hSelf);  pFile->tid = hSelf;  releaseLockInfo(pFile->pLock);  rc = findLockInfo(pFile->h, &pFile->pLock, 0);  TRACE5("LOCK    %d is now %s(%s,%d)\n", pFile->h,     locktypeName(pFile->locktype),     locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);  return rc;}#else  /* On single-threaded builds, ownership transfer is a no-op */# define transferOwnership(X) SQLITE_OK#endif/*** Delete the named file*/int sqlite3UnixDelete(const char *zFilename){  unlink(zFilename);  return SQLITE_OK;}/*** Return TRUE if the named file exists.*/int sqlite3UnixFileExists(const char *zFilename){  return access(zFilename, 0)==0;}/* Forward declaration */static int allocateUnixFile(unixFile *pInit, OsFile **pId);/*** Attempt to open a file for both reading and writing.  If that** fails, try opening it read-only.  If the file does not exist,** try to create it.**** On success, a handle for the open file is written to *id** and *pReadonly is set to 0 if the file was opened for reading and** writing or 1 if the file was opened read-only.  The function returns** SQLITE_OK.**** On failure, the function returns SQLITE_CANTOPEN and leaves** *id and *pReadonly unchanged.*/int sqlite3UnixOpenReadWrite(  const char *zFilename,  OsFile **pId,  int *pReadonly){  int rc;  unixFile f;  CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadWrite, zFilename, pId, pReadonly);  assert( 0==*pId );  f.h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,                          SQLITE_DEFAULT_FILE_PERMISSIONS);  if( f.h<0 ){#ifdef EISDIR    if( errno==EISDIR ){      return SQLITE_CANTOPEN;    }#endif    f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);    if( f.h<0 ){      return SQLITE_CANTOPEN;     }    *pReadonly = 1;  }else{    *pReadonly = 0;  }  sqlite3OsEnterMutex();  rc = findLockInfo(f.h, &f.pLock, &f.pOpen);  sqlite3OsLeaveMutex();  if( rc ){    close(f.h);    return SQLITE_NOMEM;  }  TRACE3("OPEN    %-3d %s\n", f.h, zFilename);  return allocateUnixFile(&f, pId);}/*** Attempt to open a new file for exclusive access by this process.** The file will be opened for both reading and writing.  To avoid** a potential security problem, we do not allow the file to have** previously existed.  Nor do we allow the file to be a symbolic** link.**** If delFlag is true, then make arrangements to automatically delete** the file when it is closed.**** On success, write the file handle into *id and return SQLITE_OK.**** On failure, return SQLITE_CANTOPEN.*/int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){  int rc;  unixFile f;  CRASH_TEST_OVERRIDE(sqlite3CrashOpenExclusive, zFilename, pId, delFlag);  assert( 0==*pId );  f.h = open(zFilename,                O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY,                SQLITE_DEFAULT_FILE_PERMISSIONS);  if( f.h<0 ){    return SQLITE_CANTOPEN;  }  sqlite3OsEnterMutex();  rc = findLockInfo(f.h, &f.pLock, &f.pOpen);  sqlite3OsLeaveMutex();  if( rc ){    close(f.h);    unlink(zFilename);    return SQLITE_NOMEM;  }  if( delFlag ){    unlink(zFilename);  }  TRACE3("OPEN-EX %-3d %s\n", f.h, zFilename);  return allocateUnixFile(&f, pId);}/*** Attempt to open a new file for read-only access.**** On success, write the file handle into *id and return SQLITE_OK.**** On failure, return SQLITE_CANTOPEN.*/int sqlite3UnixOpenReadOnly(const char *zFilename, OsFile **pId){  int rc;  unixFile f;  CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadOnly, zFilename, pId, 0);  assert( 0==*pId );  f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);  if( f.h<0 ){    return SQLITE_CANTOPEN;  }  sqlite3OsEnterMutex();  rc = findLockInfo(f.h, &f.pLock, &f.pOpen);  sqlite3OsLeaveMutex();  if( rc ){    close(f.h);    return SQLITE_NOMEM;  }  TRACE3("OPEN-RO %-3d %s\n", f.h, zFilename);  return allocateUnixFile(&f, pId);}/*** Attempt to open a file descriptor for the directory that contains a** file.  This file descriptor can be used to fsync() the directory** in order to make sure the creation of a new file is actually written** to disk.**** This routine is only meaningful for Unix.  It is a no-op under** windows since windows does not support hard links.**** On success, a handle for a previously open file at *id is** updated with the new directory file descriptor and SQLITE_OK is** returned.**** On failure, the function returns SQLITE_CANTOPEN and leaves** *id unchanged.*/static int unixOpenDirectory(  OsFile *id,  const char *zDirname){  unixFile *pFile = (unixFile*)id;  if( pFile==0 ){    /* Do not open the directory if the corresponding file is not already    ** open. */    return SQLITE_CANTOPEN;  }  SET_THREADID(pFile);  assert( pFile->dirfd<0 );  pFile->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0);  if( pFile->dirfd<0 ){    return SQLITE_CANTOPEN;   }  TRACE3("OPENDIR %-3d %s\n", pFile->dirfd, zDirname);  return SQLITE_OK;}/*** If the following global variable points to a string which is the** name of a directory, then that directory will be used to store** temporary files.**** See also the "PRAGMA temp_store_directory" SQL command.*/char *sqlite3_temp_directory = 0;/*** Create a temporary file name in zBuf.  zBuf must be big enough to** hold at least SQLITE_TEMPNAME_SIZE characters.*/int sqlite3UnixTempFileName(char *zBuf){  static const char *azDirs[] = {     0,     "/var/tmp",     "/usr/tmp",     "/tmp",     ".",  };  static const unsigned char zChars[] =    "abcdefghijklmnopqrstuvwxyz"    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"    "0123456789";  int i, j;  struct stat buf;  const char *zDir = ".";  azDirs[0] = sqlite3_temp_directory;  for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){    if( azDirs[i]==0 ) continue;    if( stat(azDirs[i], &buf) ) continue;    if( !S_ISDIR(buf.st_mode) ) continue;    if( access(azDirs[i], 07) ) continue;    zDir = azDirs[i];    break;  }  do{    sprintf(zBuf, "%s/"TEMP_FILE_PREFIX, zDir);    j = strlen(zBuf);    sqlite3Randomness(15, &zBuf[j]);    for(i=0; i<15; i++, j++){      zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];    }    zBuf[j] = 0;  }while( access(zBuf,0)==0 );  return SQLITE_OK; }/*** Check that a given pathname is a directory and is writable ***/int sqlite3UnixIsDirWritable(char *zBuf){#ifndef SQLITE_OMIT_PAGER_PRAGMAS  struct stat buf;  if( zBuf==0 ) return 0;  if( zBuf[0]==0 ) return 0;  if( stat(zBuf, &buf) ) return 0;  if( !S_ISDIR(buf.st_mode) ) return 0;  if( access(zBuf, 07) ) return 0;#endif /* SQLITE_OMIT_PAGER_PRAGMAS */  return 1;}/*** Seek to the offset in id->offset then read cnt bytes into pBuf.** Return the number of bytes actually read.  Update the offset.*/static int seekAndRead(unixFile *id, void *pBuf, int cnt){  int got;#ifdef USE_PREAD  got = pread(id->h, pBuf, cnt, id->offset);#else  lseek(id->h, id->offset, SEEK_SET);  got = read(id->h, pBuf, cnt);#endif  if( got>0 ){    id->offset += got;  }  return got;}/*** Read data from a file into a buffer.  Return SQLITE_OK if all** bytes were read successfully and SQLITE_IOERR if anything goes** wrong.*/static int unixRead(OsFile *id, void *pBuf, int amt){  int got;  assert( id );  SimulateIOError(SQLITE_IOERR);  TIMER_START;  got = seekAndRead((unixFile*)id, pBuf, amt);  TIMER_END;  TRACE5("READ    %-3d %5d %7d %d\n", ((unixFile*)id)->h, got,          last_page, TIMER_ELAPSED);  SEEK(0);  /* if( got<0 ) got = 0; */  if( got==amt ){    return SQLITE_OK;  }else{    return SQLITE_IOERR;  }}/*** Seek to the offset in id->offset then read cnt bytes into pBuf.** Return the number of bytes actually read.  Update the offset.*/static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){  int got;#ifdef USE_PREAD  got = pwrite(id->h, pBuf, cnt, id->offset);#else  lseek(id->h, id->offset, SEEK_SET);  got = write(id->h, pBuf, cnt);#endif  if( got>0 ){    id->offset += got;  }  return got;}/*** Write data from a buffer into a file.  Return SQLITE_OK on success** or some other error code on failure.*/static int unixWrite(OsFile *id, const void *pBuf, int amt){  int wrote = 0;  assert( id );  assert( amt>0 );  SimulateIOError(SQLITE_IOERR);  SimulateDiskfullError;  TIMER_START;  while( amt>0 && (wrote = seekAndWrite((unixFile*)id, pBuf, amt))>0 ){    amt -= wrote;    pBuf = &((char*)pBuf)[wrote];  }  TIMER_END;  TRACE5("WRITE   %-3d %5d %7d %d\n", ((unixFile*)id)->h, wrote,          last_page, TIMER_ELAPSED);  SEEK(0);  if( amt>0 ){    return SQLITE_FULL;  }  return SQLITE_OK;}/*** Move the read/write pointer in a file.*/static int unixSeek(OsFile *id, i64 offset){  assert( id );  SEEK(offset/1024 + 1);#ifdef SQLITE_TEST  if( offset ) SimulateDiskfullError#endif

⌨️ 快捷键说明

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