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

📄 os_unix.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    if( errno==EISDIR ){      return SQLITE_CANTOPEN;    }#endif    id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);    if( id->h<0 ){      return SQLITE_CANTOPEN;     }    *pReadonly = 1;  }else{    *pReadonly = 0;  }  sqlite3OsEnterMutex();  rc = findLockInfo(id->h, &id->pLock, &id->pOpen);  sqlite3OsLeaveMutex();  if( rc ){    close(id->h);    return SQLITE_NOMEM;  }  id->locktype = 0;  id->isOpen = 1;  TRACE3("OPEN    %-3d %s\n", id->h, zFilename);  OpenCounter(+1);  return SQLITE_OK;}/*** 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 sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){  int rc;  assert( !id->isOpen );  if( access(zFilename, 0)==0 ){    return SQLITE_CANTOPEN;  }  id->dirfd = -1;  id->h = open(zFilename,                O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600);  if( id->h<0 ){    return SQLITE_CANTOPEN;  }  sqlite3OsEnterMutex();  rc = findLockInfo(id->h, &id->pLock, &id->pOpen);  sqlite3OsLeaveMutex();  if( rc ){    close(id->h);    unlink(zFilename);    return SQLITE_NOMEM;  }  id->locktype = 0;  id->isOpen = 1;  if( delFlag ){    unlink(zFilename);  }  TRACE3("OPEN-EX %-3d %s\n", id->h, zFilename);  OpenCounter(+1);  return SQLITE_OK;}/*** 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 sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){  int rc;  assert( !id->isOpen );  id->dirfd = -1;  id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);  if( id->h<0 ){    return SQLITE_CANTOPEN;  }  sqlite3OsEnterMutex();  rc = findLockInfo(id->h, &id->pLock, &id->pOpen);  sqlite3OsLeaveMutex();  if( rc ){    close(id->h);    return SQLITE_NOMEM;  }  id->locktype = 0;  id->isOpen = 1;  TRACE3("OPEN-RO %-3d %s\n", id->h, zFilename);  OpenCounter(+1);  return SQLITE_OK;}/*** 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 is 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.*/int sqlite3OsOpenDirectory(  const char *zDirname,  OsFile *id){  if( !id->isOpen ){    /* Do not open the directory if the corresponding file is not already    ** open. */    return SQLITE_CANTOPEN;  }  assert( id->dirfd<0 );  id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0);  if( id->dirfd<0 ){    return SQLITE_CANTOPEN;   }  TRACE3("OPENDIR %-3d %s\n", id->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.*/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 sqlite3OsTempFileName(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; }#ifndef SQLITE_OMIT_PAGER_PRAGMAS/*** Check that a given pathname is a directory and is writable ***/int sqlite3OsIsDirWritable(char *zBuf){  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;  return 1;}#endif /* SQLITE_OMIT_PAGER_PRAGMAS *//*** Read data from a file into a buffer.  Return SQLITE_OK if all** bytes were read successfully and SQLITE_IOERR if anything goes** wrong.*/int sqlite3OsRead(OsFile *id, void *pBuf, int amt){  int got;  assert( id->isOpen );  SimulateIOError(SQLITE_IOERR);  TIMER_START;  got = read(id->h, pBuf, amt);  TIMER_END;  TRACE5("READ    %-3d %5d %7d %d\n", id->h, got, last_page, TIMER_ELAPSED);  SEEK(0);  /* if( got<0 ) got = 0; */  if( got==amt ){    return SQLITE_OK;  }else{    return SQLITE_IOERR;  }}/*** Write data from a buffer into a file.  Return SQLITE_OK on success** or some other error code on failure.*/int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){  int wrote = 0;  assert( id->isOpen );  assert( amt>0 );  SimulateIOError(SQLITE_IOERR);  SimulateDiskfullError;  TIMER_START;  while( amt>0 && (wrote = write(id->h, pBuf, amt))>0 ){    amt -= wrote;    pBuf = &((char*)pBuf)[wrote];  }  TIMER_END;  TRACE5("WRITE   %-3d %5d %7d %d\n", 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.*/int sqlite3OsSeek(OsFile *id, i64 offset){  assert( id->isOpen );  SEEK(offset/1024 + 1);  lseek(id->h, offset, SEEK_SET);  return SQLITE_OK;}#ifdef SQLITE_TEST/*** Count the number of fullsyncs and normal syncs.  This is used to test** that syncs and fullsyncs are occuring at the right times.*/int sqlite3_sync_count = 0;int sqlite3_fullsync_count = 0;#endif/*** The fsync() system call does not work as advertised on many** unix systems.  The following procedure is an attempt to make** it work better.**** The SQLITE_NO_SYNC macro disables all fsync()s.  This is useful** for testing when we want to run through the test suite quickly.** You are strongly advised *not* to deploy with SQLITE_NO_SYNC** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash** or power failure will likely corrupt the database file.*/static int full_fsync(int fd, int fullSync){  int rc;  /* Record the number of times that we do a normal fsync() and   ** FULLSYNC.  This is used during testing to verify that this procedure  ** gets called with the correct arguments.  */#ifdef SQLITE_TEST  if( fullSync ) sqlite3_fullsync_count++;  sqlite3_sync_count++;#endif  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a  ** no-op  */#ifdef SQLITE_NO_SYNC  rc = SQLITE_OK;#else#ifdef F_FULLFSYNC  if( fullSync ){    rc = fcntl(fd, F_FULLFSYNC, 0);  }else{    rc = 1;  }  /* If the FULLSYNC failed, try to do a normal fsync() */  if( rc ) rc = fsync(fd);#else  rc = fsync(fd);#endif /* defined(F_FULLFSYNC) */#endif /* defined(SQLITE_NO_SYNC) */  return rc;}/*** 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 sqlite3OsSync(OsFile *id){  assert( id->isOpen );  SimulateIOError(SQLITE_IOERR);  TRACE2("SYNC    %-3d\n", id->h);  if( full_fsync(id->h, id->fullSync) ){    return SQLITE_IOERR;  }  if( id->dirfd>=0 ){    TRACE2("DIRSYNC %-3d\n", id->dirfd);    full_fsync(id->dirfd, id->fullSync);    close(id->dirfd);  /* Only need to sync once, so close the directory */    id->dirfd = -1;    /* when we are done. */  }  return SQLITE_OK;}/*** Sync the directory zDirname. This is a no-op on operating systems other** than UNIX.**** This is used to make sure the master journal file has truely been deleted** before making changes to individual journals on a multi-database commit.** The F_FULLFSYNC option is not needed here.*/int sqlite3OsSyncDirectory(const char *zDirname){  int fd;  int r;  SimulateIOError(SQLITE_IOERR);  fd = open(zDirname, O_RDONLY|O_BINARY, 0);  TRACE3("DIRSYNC %-3d (%s)\n", fd, zDirname);  if( fd<0 ){    return SQLITE_CANTOPEN;   }  r = fsync(fd);  close(fd);  return ((r==0)?SQLITE_OK:SQLITE_IOERR);}/*** Truncate an open file to a specified size*/int sqlite3OsTruncate(OsFile *id, i64 nByte){  assert( id->isOpen );  SimulateIOError(SQLITE_IOERR);  return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;}/*** Determine the current size of a file in bytes*/int sqlite3OsFileSize(OsFile *id, i64 *pSize){  struct stat buf;  assert( id->isOpen );  SimulateIOError(SQLITE_IOERR);  if( fstat(id->h, &buf)!=0 ){    return SQLITE_IOERR;  }  *pSize = buf.st_size;  return SQLITE_OK;}/*** This routine checks if there is a RESERVED lock held on the specified** file by this or any other process. If such a lock is held, return** non-zero.  If the file is unlocked or holds only SHARED locks, then** return zero.*/int sqlite3OsCheckReservedLock(OsFile *id){  int r = 0;  assert( id->isOpen );  sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */  /* Check if a thread in this process holds such a lock */  if( id->pLock->locktype>SHARED_LOCK ){    r = 1;  }  /* Otherwise see if some other process holds it.  */  if( !r ){    struct flock lock;    lock.l_whence = SEEK_SET;    lock.l_start = RESERVED_BYTE;    lock.l_len = 1;    lock.l_type = F_WRLCK;    fcntl(id->h, F_GETLK, &lock);    if( lock.l_type!=F_UNLCK ){      r = 1;    }  }    sqlite3OsLeaveMutex();  TRACE3("TEST WR-LOCK %d %d\n", id->h, r);  return r;}#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/*** Lock the file with the lock specified by parameter locktype - one** of the following:****     (1) SHARED_LOCK**     (2) RESERVED_LOCK**     (3) PENDING_LOCK**     (4) EXCLUSIVE_LOCK**** Sometimes when requesting one lock state, additional lock states** are inserted in between.  The locking might fail on one of the later** transitions leaving the lock state different from what it started but

⌨️ 快捷键说明

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