1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-10-27 08:52:26 +03:00

Make the OsFile structure opaque with its internal structure known only to

the appropriate os_*.c implementation.  Omit the os_unix.h and os_win.h
include files.  The crash tests are broken by this patch. (CVS 2791)

FossilOrigin-Name: 058f31753871b16b40fe4048e3adcee411e0f87d
This commit is contained in:
drh
2005-11-29 03:13:21 +00:00
parent 9267bdcecd
commit 9cbe635219
14 changed files with 455 additions and 285 deletions

View File

@@ -15,12 +15,82 @@
#include "sqliteInt.h"
#include "os.h"
#if OS_UNIX /* This file is used on unix only */
/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it. If the OS lacks
** large file support, or if the OS is windows, these should be no-ops.
**
** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
** on the compiler command line. This is necessary if you are compiling
** on a recent machine (ex: RedHat 7.2) but you want your code to work
** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
** without this option, LFS is enable. But LFS does not exist in the kernel
** in RedHat 6.0, so the code won't work. Hence, for maximum binary
** portability you should omit LFS.
**
** Similar is true for MacOS. LFS is only supported on MacOS 9 and later.
*/
#ifndef SQLITE_DISABLE_LFS
# define _LARGE_FILE 1
# ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
# endif
# define _LARGEFILE_SOURCE 1
#endif
/*
** standard include files.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
/*
** Macros used to determine whether or not to use threads. The
** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for
** Posix threads and SQLITE_W32_THREADS is defined if we are
** synchronizing using Win32 threads.
*/
#if defined(THREADSAFE) && THREADSAFE
# include <pthread.h>
# define SQLITE_UNIX_THREADS 1
#endif
/*
** Default permissions when creating a new file
*/
#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
#endif
/*
** The OsFile structure is a operating-system dependent representation
** of an open file handle. It is defined differently for each architecture.
**
** This is the definition for Unix.
**
** OsFile.locktype takes one of the values SHARED_LOCK, RESERVED_LOCK,
** PENDING_LOCK or EXCLUSIVE_LOCK.
*/
struct OsFile {
struct openCnt *pOpen; /* Info about all open fd's on this inode */
struct lockInfo *pLock; /* Info about locks on this inode */
int h; /* The file descriptor */
unsigned char locktype; /* The type of lock held on this fd */
unsigned char isOpen; /* True if needs to be closed */
unsigned char fullSync; /* Use F_FULLSYNC if available */
int dirfd; /* File descriptor for the directory */
#ifdef SQLITE_UNIX_THREADS
pthread_t tid; /* The thread authorized to use this OsFile */
#endif
};
/*
** Do not include any of the File I/O interface procedures if the
@@ -82,8 +152,8 @@
** by mistake.
*/
#if defined(SQLITE_UNIX_THREADS) && !defined(SQLITE_ALLOW_XTHREAD_CONNECTIONS)
# define SET_THREADID(X) X->tid = pthread_self()
# define CHECK_THREADID(X) (!pthread_equal(X->tid, pthread_self()))
# define SET_THREADID(X) (X)->tid = pthread_self()
# define CHECK_THREADID(X) (!pthread_equal((X)->tid, pthread_self()))
#else
# define SET_THREADID(X)
# define CHECK_THREADID(X) 0
@@ -493,6 +563,22 @@ static int unixFileExists(const char *zFilename){
return access(zFilename, 0)==0;
}
/*
** Allocate memory for an OsFile. Initialize the new OsFile
** to the value given in pInit and return a pointer to the new
** OsFile. If we run out of memory, close the file and return NULL.
*/
static OsFile *allocateOsFile(OsFile *pInit){
OsFile *pNew;
pNew = sqliteMalloc( sizeof(OsFile) );
if( pNew==0 ){
close(pInit->h);
}else{
*pNew = *pInit;
}
return pNew;
}
/*
** Attempt to open a file for both reading and writing. If that
** fails, try opening it read-only. If the file does not exist,
@@ -508,23 +594,25 @@ static int unixFileExists(const char *zFilename){
*/
static int unixOpenReadWrite(
const char *zFilename,
OsFile *id,
OsFile **pId,
int *pReadonly
){
int rc;
assert( !id->isOpen );
id->dirfd = -1;
SET_THREADID(id);
id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,
OsFile f;
assert( 0==*pId );
f.dirfd = -1;
SET_THREADID(&f);
f.h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,
SQLITE_DEFAULT_FILE_PERMISSIONS);
if( id->h<0 ){
if( f.h<0 ){
#ifdef EISDIR
if( errno==EISDIR ){
return SQLITE_CANTOPEN;
}
#endif
id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
if( id->h<0 ){
f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
if( f.h<0 ){
return SQLITE_CANTOPEN;
}
*pReadonly = 1;
@@ -532,17 +620,21 @@ static int unixOpenReadWrite(
*pReadonly = 0;
}
sqlite3OsEnterMutex();
rc = findLockInfo(id->h, &id->pLock, &id->pOpen);
rc = findLockInfo(f.h, &f.pLock, &f.pOpen);
sqlite3OsLeaveMutex();
if( rc ){
close(id->h);
close(f.h);
return SQLITE_NOMEM;
}
id->locktype = 0;
id->isOpen = 1;
TRACE3("OPEN %-3d %s\n", id->h, zFilename);
OpenCounter(+1);
return SQLITE_OK;
f.locktype = 0;
TRACE3("OPEN %-3d %s\n", f.h, zFilename);
*pId = allocateOsFile(&f);
if( *pId==0 ){
return SQLITE_NOMEM;
}else{
OpenCounter(+1);
return SQLITE_OK;
}
}
@@ -560,36 +652,42 @@ static int unixOpenReadWrite(
**
** On failure, return SQLITE_CANTOPEN.
*/
static int unixOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
static int unixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
int rc;
assert( !id->isOpen );
OsFile f;
assert( 0==*pId );
if( access(zFilename, 0)==0 ){
return SQLITE_CANTOPEN;
}
SET_THREADID(id);
id->dirfd = -1;
id->h = open(zFilename,
SET_THREADID(&f);
f.dirfd = -1;
f.h = open(zFilename,
O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY,
SQLITE_DEFAULT_FILE_PERMISSIONS);
if( id->h<0 ){
if( f.h<0 ){
return SQLITE_CANTOPEN;
}
sqlite3OsEnterMutex();
rc = findLockInfo(id->h, &id->pLock, &id->pOpen);
rc = findLockInfo(f.h, &f.pLock, &f.pOpen);
sqlite3OsLeaveMutex();
if( rc ){
close(id->h);
close(f.h);
unlink(zFilename);
return SQLITE_NOMEM;
}
id->locktype = 0;
id->isOpen = 1;
f.locktype = 0;
if( delFlag ){
unlink(zFilename);
}
TRACE3("OPEN-EX %-3d %s\n", id->h, zFilename);
OpenCounter(+1);
return SQLITE_OK;
TRACE3("OPEN-EX %-3d %s\n", f.h, zFilename);
*pId = allocateOsFile(&f);
if( *pId==0 ){
return SQLITE_NOMEM;
}else{
OpenCounter(+1);
return SQLITE_OK;
}
}
/*
@@ -599,27 +697,33 @@ static int unixOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
**
** On failure, return SQLITE_CANTOPEN.
*/
static int unixOpenReadOnly(const char *zFilename, OsFile *id){
static int unixOpenReadOnly(const char *zFilename, OsFile **pId){
int rc;
assert( !id->isOpen );
SET_THREADID(id);
id->dirfd = -1;
id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
if( id->h<0 ){
OsFile f;
assert( 0==*pId );
SET_THREADID(&f);
f.dirfd = -1;
f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
if( f.h<0 ){
return SQLITE_CANTOPEN;
}
sqlite3OsEnterMutex();
rc = findLockInfo(id->h, &id->pLock, &id->pOpen);
rc = findLockInfo(f.h, &f.pLock, &f.pOpen);
sqlite3OsLeaveMutex();
if( rc ){
close(id->h);
close(f.h);
return SQLITE_NOMEM;
}
id->locktype = 0;
id->isOpen = 1;
TRACE3("OPEN-RO %-3d %s\n", id->h, zFilename);
OpenCounter(+1);
return SQLITE_OK;
f.locktype = 0;
TRACE3("OPEN-RO %-3d %s\n", f.h, zFilename);
*pId = allocateOsFile(&f);
if( *pId==0 ){
return SQLITE_NOMEM;
}else{
OpenCounter(+1);
return SQLITE_OK;
}
}
/*
@@ -631,7 +735,7 @@ static int unixOpenReadOnly(const char *zFilename, OsFile *id){
** 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
** On success, a handle for a previously open file at *id is
** updated with the new directory file descriptor and SQLITE_OK is
** returned.
**
@@ -642,7 +746,7 @@ static int unixOpenDirectory(
const char *zDirname,
OsFile *id
){
if( !id->isOpen ){
if( id==0 ){
/* Do not open the directory if the corresponding file is not already
** open. */
return SQLITE_CANTOPEN;
@@ -727,7 +831,7 @@ static int unixIsDirWritable(char *zBuf){
*/
static int unixRead(OsFile *id, void *pBuf, int amt){
int got;
assert( id->isOpen );
assert( id );
SimulateIOError(SQLITE_IOERR);
TIMER_START;
got = read(id->h, pBuf, amt);
@@ -748,7 +852,7 @@ static int unixRead(OsFile *id, void *pBuf, int amt){
*/
static int unixWrite(OsFile *id, const void *pBuf, int amt){
int wrote = 0;
assert( id->isOpen );
assert( id );
assert( amt>0 );
SimulateIOError(SQLITE_IOERR);
SimulateDiskfullError;
@@ -770,7 +874,7 @@ static int unixWrite(OsFile *id, const void *pBuf, int amt){
** Move the read/write pointer in a file.
*/
static int unixSeek(OsFile *id, i64 offset){
assert( id->isOpen );
assert( id );
SEEK(offset/1024 + 1);
#ifdef SQLITE_TEST
if( offset ) SimulateDiskfullError
@@ -864,7 +968,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
** will not roll back - possibly leading to database corruption.
*/
static int unixSync(OsFile *id, int dataOnly){
assert( id->isOpen );
assert( id );
SimulateIOError(SQLITE_IOERR);
TRACE2("SYNC %-3d\n", id->h);
if( full_fsync(id->h, id->fullSync, dataOnly) ){
@@ -913,7 +1017,7 @@ static int unixSyncDirectory(const char *zDirname){
** Truncate an open file to a specified size
*/
static int unixTruncate(OsFile *id, i64 nByte){
assert( id->isOpen );
assert( id );
SimulateIOError(SQLITE_IOERR);
return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
}
@@ -923,7 +1027,7 @@ static int unixTruncate(OsFile *id, i64 nByte){
*/
static int unixFileSize(OsFile *id, i64 *pSize){
struct stat buf;
assert( id->isOpen );
assert( id );
SimulateIOError(SQLITE_IOERR);
if( fstat(id->h, &buf)!=0 ){
return SQLITE_IOERR;
@@ -941,7 +1045,7 @@ static int unixFileSize(OsFile *id, i64 *pSize){
static int unixCheckReservedLock(OsFile *id){
int r = 0;
assert( id->isOpen );
assert( id );
if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */
@@ -1056,7 +1160,7 @@ static int unixLock(OsFile *id, int locktype){
struct flock lock;
int s;
assert( id->isOpen );
assert( id );
TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", id->h, locktypeName(locktype),
locktypeName(id->locktype), locktypeName(pLock->locktype), pLock->cnt
,getpid() );
@@ -1213,7 +1317,7 @@ static int unixUnlock(OsFile *id, int locktype){
struct flock lock;
int rc = SQLITE_OK;
assert( id->isOpen );
assert( id );
TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype,
id->pLock->locktype, id->pLock->cnt, getpid());
if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
@@ -1291,8 +1395,9 @@ static int unixUnlock(OsFile *id, int locktype){
/*
** Close a file.
*/
static int unixClose(OsFile *id){
if( !id->isOpen ) return SQLITE_OK;
static int unixClose(OsFile **pId){
OsFile *id = *pId;
if( !id ) return SQLITE_OK;
if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
sqlite3Io.xUnlock(id, NO_LOCK);
if( id->dirfd>=0 ) close(id->dirfd);
@@ -1324,6 +1429,8 @@ static int unixClose(OsFile *id){
id->isOpen = 0;
TRACE2("CLOSE %-3d\n", id->h);
OpenCounter(-1);
sqliteFree(id);
*pId = 0;
return SQLITE_OK;
}
@@ -1351,10 +1458,25 @@ static char *unixFullPathname(const char *zRelative){
}
/*
** Make a copy of an OsFile object.
** Change the value of the fullsync flag in the given file descriptor.
*/
static void unixCopyOsFile(OsFile *pDest, OsFile *pSrc){
*pDest = *pSrc;
static void unixSetFullSync(OsFile *id, int v){
id->fullSync = v;
}
/*
** Return the underlying file handle for an OsFile
*/
static int unixFileHandle(OsFile *id){
return id->h;
}
/*
** Return an integer that indices the type of lock currently held
** by this handle. (Used for testing and analysis only.)
*/
static int unixLockState(OsFile *id){
return id->locktype;
}
/*
@@ -1381,7 +1503,9 @@ struct sqlite3IoVtbl sqlite3Io = {
unixLock,
unixUnlock,
unixCheckReservedLock,
unixCopyOsFile,
unixSetFullSync,
unixFileHandle,
unixLockState,
};