]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Make the OsFile structure opaque with its internal structure known only to
authordrh <drh@noemail.net>
Tue, 29 Nov 2005 03:13:21 +0000 (03:13 +0000)
committerdrh <drh@noemail.net>
Tue, 29 Nov 2005 03:13:21 +0000 (03:13 +0000)
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

14 files changed:
Makefile.in
main.mk
manifest
manifest.uuid
src/expr.c
src/os.h
src/os_unix.c
src/os_win.c
src/pager.c
src/test1.c
src/test2.c
src/test6.c
src/vdbeaux.c
test/attach.test

index 1d67c30350979cf0e8a593cfc7cf0555e10819eb..3505149f6a904e7d02f87b5a7fdf9845cb597f8c 100644 (file)
@@ -205,8 +205,6 @@ HDR = \
    opcodes.h \
    $(TOP)/src/os.h \
    $(TOP)/src/os_common.h \
-   $(TOP)/src/os_unix.h \
-   $(TOP)/src/os_win.h \
    $(TOP)/src/sqliteInt.h  \
    $(TOP)/src/vdbe.h \
    parse.h
diff --git a/main.mk b/main.mk
index e6b6ea98806523d0a486a206ec76a5e52dbb2515..c903354daeb98642a67dce3bb6704e4e82d48849 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -147,8 +147,6 @@ HDR = \
    opcodes.h \
    $(TOP)/src/os.h \
    $(TOP)/src/os_common.h \
-   $(TOP)/src/os_unix.h \
-   $(TOP)/src/os_win.h \
    $(TOP)/src/sqliteInt.h  \
    $(TOP)/src/vdbe.h \
    parse.h
index 4ee323f0aa746c97e5e5978292fb0cb25c2d486c..40df7438611d298830db43d2291217790bb27d7e 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,6 +1,6 @@
-C Replace\sa\scall\sto\ssprintf()\swith\ssqlite3MPrintf()\ssince\son\ssome\sembedded\nplatforms,\ssprintf()\sis\sbusted.\s\sNeed\sto\sgo\sthrough\sand\sdo\ssimilar\sreplacements\nelsewhere\sin\sthe\scode.\s(CVS\s2790)
-D 2005-11-28T12:36:36
-F Makefile.in 28a2772cd9e03ba758c2a052813092cdb9da73bf
+C Make\sthe\sOsFile\sstructure\sopaque\swith\sits\sinternal\sstructure\sknown\sonly\sto\nthe\sappropriate\sos_*.c\simplementation.\s\sOmit\sthe\sos_unix.h\sand\sos_win.h\ninclude\sfiles.\s\sThe\scrash\stests\sare\sbroken\sby\sthis\spatch.\s(CVS\s2791)
+D 2005-11-29T03:13:21
+F Makefile.in eac4c98a32a0eae9d6bb2779ac74bbb5441758d3
 F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
 F VERSION b818cce180263e590a00ad4509a713892c3eecea
@@ -19,7 +19,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
 F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
 F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
-F main.mk 1cf8c00ee4439d3332a2da771fe168ed8420c2d7
+F main.mk 76d9e7bcebea556f0db40811b9273d6b704df88e
 F mkdll.sh 5ec23622515d5bf8969404e80cfb5e220ddf0512
 F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
 F mkopcodeh.awk 071dbba4eaf56c8d643baf4604a043af35683316
@@ -42,7 +42,7 @@ F src/complete.c 4de937dfdd4c79a501772ab2035b26082f337a79
 F src/date.c 7444b0900a28da77e57e3337a636873cff0ae940
 F src/delete.c 29dac493f4d83b05f91233b116827c133bcdab72
 F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
-F src/expr.c b18a7dc6ebff2351abf35ff914465e2341038d34
+F src/expr.c 80ceb8c7d15dd53985831f0b4c660b3c3df796a3
 F src/func.c 7d81dccd9c440c6c4e761056333e629192814af0
 F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863
 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
@@ -50,15 +50,15 @@ F src/insert.c da031c3ed8e1675fac891990095d277c2ba6e205
 F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b
 F src/main.c 97bb830cdbd378d1f87469618471f52d9d263d09
 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
-F src/os.h 70da8a43e03190a981d02bdc7cef1eb9ad1db4ad
+F src/os.h a429c3534c1179ce925c120b3ce9b82543a9873a
 F src/os_common.h d74a11728ad2444b6b695b94c28c06881f049e49
 F src/os_test.c 49833426101f99aee4bb5f6a44b7c4b2029fda1c
 F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3
-F src/os_unix.c 09f174975fe054ed73117ee17c5650f55773fbe3
+F src/os_unix.c 02b6a1c7e7a646da10f41f8ed3364a2a1c33c135
 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
-F src/os_win.c a3762efcc6eebbf8a38d25ff80e0e510ec7afead
+F src/os_win.c f18626e44669e12fba9948dd98934ab4b46c343c
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c 309d473c01b5e2b355fc3c8adce2a36df16c43a3
+F src/pager.c 18cc5b274a0df28dc9145da522a6e281f80b925f
 F src/pager.h e7b41ce8e7b5f629d456708b7ad9a8c8ede37140
 F src/parse.y e4d57c2fd5cc02f19822ec41f6dc2bfc9bc85609
 F src/pragma.c e278b3f722379ab9d630a1569ac05f586f01f4db
@@ -71,12 +71,12 @@ F src/sqlite.h.in 8e648e1f386e4509f2f96c09ded7c07b0df0c9a2
 F src/sqliteInt.h 4148c9778e350014c2e27b332d7a2ef7278fe62e
 F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316
 F src/tclsqlite.c a497c3adfd2c85da6a934331ec0041e47884fbcb
-F src/test1.c 415c9c4571bf9ecbec3a7bba3c4338efd83fc137
-F src/test2.c 360cfa7fe17a4fe67f6d19699cd6d59fca4ff09f
+F src/test1.c c2c307a4cbbf4670f43a7b4b144dce866d1d701f
+F src/test2.c 02d639d515ddf99a3bbc00f640d8544ecb925a9b
 F src/test3.c f4e6a16a602091696619a1171bda25c0e3df49f7
 F src/test4.c a8fd681e139e1c61f22a77d07fc3a99cb28fff3f
 F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5
-F src/test6.c d8501501dbd257b88b3ecfa5c46d5e2ac230e0f9
+F src/test6.c 0543cf075a0cfcc2f83a0810cb2a93d57a7eb602
 F src/tokenize.c bdb79702217af49eba44c2a3b4f5fc7bd9ed2917
 F src/trigger.c aea0283a3ef729a3e9c8dc5dc1a11c9fcc0a12a7
 F src/update.c fec7665138ccf2a2133f11dcd24c1134c6b33526
@@ -87,7 +87,7 @@ F src/vdbe.c 88a85e681522e82e14c8d08adacccbe4e96dd1c9
 F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13
 F src/vdbeInt.h 0055c37eccbf3a189fd893a90f8eb6a5fa60c871
 F src/vdbeapi.c 85bbe1d0243a89655433d60711b4bd71979b59cd
-F src/vdbeaux.c 3dca9c04c07dda17f0cb06b3a552e1e23106232f
+F src/vdbeaux.c 09b9bcfed1101b53b433e5d0d7b80943bdf3d1b2
 F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
 F src/vdbemem.c cd9609c1e7f71ec76d9840c84c3a57ebfa6539cf
 F src/where.c a9fed5a5b549f5dae1aa95dc9463cd1f35efa0f1
@@ -98,7 +98,7 @@ F test/alter2.test 60ba0a7057dc71ad630a1cc7c487104346849d50
 F test/alter3.test d4eecd8dbd008d0e66f1c201fa6dc2edca853c38
 F test/altermalloc.test 6e1f404ec021eb2ba6582e3c77b0a35cf206b7af
 F test/analyze.test 2f55535aa335785db1a2f97d3f3831c16c09f8b0
-F test/attach.test f320e98bcca68d100cab7666a0c9a93ac5f236bd
+F test/attach.test dae07fa1554b618b9cc4c7bc349b3bc1a532180e
 F test/attach2.test 3396c012a39ddf7ba6b528d80bd79554168aa115
 F test/attach3.test 63013383adc4380af69779f34f4af19bd49f7cbe
 F test/attachmalloc.test cdb26c42850f04698377ccec05f5fa89d987837c
@@ -323,7 +323,7 @@ F www/tclsqlite.tcl ddcf912ea48695603c8ed7efb29f0812ef8d1b49
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 7e7cfce0f8ed2a6e04747736a2c68484f447cdfb
-R 34f591d26adade3953279102265da94b
+P 1b4f2d89bbe833359cefcea580783fd92aa7b8ab
+R 167d41b6779a94a69e79f7db1fd9daa9
 U drh
-Z a721118f67e524e11c01a78c05611f0f
+Z 717f7b44d42f5a1bd0daf8e23da32026
index 77360b68cf43c2c5720759315e3adad3b6a8ba32..71074c1ab49b32b0a8961d2ebd272cc07e7e9084 100644 (file)
@@ -1 +1 @@
-1b4f2d89bbe833359cefcea580783fd92aa7b8ab
\ No newline at end of file
+058f31753871b16b40fe4048e3adcee411e0f87d
\ No newline at end of file
index 24def4f39f066c137419a7834dfc36249b288a1b..50edb902dcbda3a8e31136b12c1a7e75bc1e61bd 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.239 2005/11/28 12:36:36 drh Exp $
+** $Id: expr.c,v 1.240 2005/11/29 03:13:22 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1274,17 +1274,16 @@ struct QueryCoder {
 
 
 /*
-** Generate code for subqueries and IN operators.
+** Generate code for scalar subqueries used as an expression
+** and IN operators.  Examples:
 **
-** IN operators comes in two forms:
+**     (SELECT a FROM b)          -- subquery
+**     EXISTS (SELECT a FROM b)   -- EXISTS subquery
+**     x IN (4,5,11)              -- IN operator with list on right-hand side
+**     x IN (SELECT a FROM b)     -- IN operator with subquery on the right
 **
-**           expr IN (exprlist)
-** and
-**           expr IN (SELECT ...)
-**
-** The first form is handled by creating a set holding the list
-** of allowed values.  The second form causes the SELECT to generate 
-** a temporary table.
+** The pExpr parameter describes the expression that contains the IN
+** operator or subquery.
 */
 #ifndef SQLITE_OMIT_SUBQUERY
 void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
index 5db9fa4581f1de1583f36cc01d217e92601d1e71..412273b5f42012f409e7e41cb2ff7272cf635730 100644 (file)
--- a/src/os.h
+++ b/src/os.h
 #endif
 
 /*
-** Invoke the appropriate operating-system specific header file.
+** The OsFile object describes an open disk file in an OS-dependent way.
 */
-#if OS_ALT
-# include "os_alt.h"
-#endif
-#if OS_UNIX
-# include "os_unix.h"
-#endif
-#if OS_WIN
-# include "os_win.h"
-#endif
+typedef struct OsFile OsFile;
 
-/* os_other.c and os_other.h are not delivered with SQLite.  These files
-** are place-holders that can be filled in by third-party developers to
-** implement backends to their on proprietary operating systems.
+/*
+** Define the maximum size of a temporary filename
 */
-#if OS_OTHER
-# include "os_other.h"
+#if OS_WIN
+# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
+#else
+# define SQLITE_TEMPNAME_SIZE 200
 #endif
 
 /* If the SET_FULLSYNC macro is not defined above, then make it
@@ -179,14 +172,14 @@ extern unsigned int sqlite3_pending_byte;
 extern struct sqlite3IoVtbl {
   int (*xDelete)(const char*);
   int (*xFileExists)(const char*);
-  int (*xOpenReadWrite)(const char*, OsFile*, int*);
-  int (*xOpenExclusive)(const char*, OsFile*, int);
-  int (*xOpenReadOnly)(const char*, OsFile*);
+  int (*xOpenReadWrite)(const char*, OsFile**, int*);
+  int (*xOpenExclusive)(const char*, OsFile**, int);
+  int (*xOpenReadOnly)(const char*, OsFile**);
   int (*xOpenDirectory)(const char*, OsFile*);
   int (*xSyncDirectory)(const char*);
   int (*xTempFileName)(char*);
   int (*xIsDirWritable)(char*);
-  int (*xClose)(OsFile*);
+  int (*xClose)(OsFile**);
   int (*xRead)(OsFile*, void*, int amt);
   int (*xWrite)(OsFile*, const void*, int amt);
   int (*xSeek)(OsFile*, i64 offset);
@@ -197,7 +190,9 @@ extern struct sqlite3IoVtbl {
   int (*xLock)(OsFile*, int);
   int (*xUnlock)(OsFile*, int);
   int (*xCheckReservedLock)(OsFile *id);
-  void (*xCopyOsFile)(OsFile *pDest, OsFile *pSrc);
+  void (*xSetFullSync)(OsFile *id, int setting);
+  int (*xFileHandle)(OsFile *id);
+  int (*xLockState)(OsFile *id);
 } sqlite3Io;
 
 /* The interface for file I/O is above.  Other miscellaneous functions
index b6ef2081f88c12b1f6006d15c699b074726285a1..cf855277009cb5f536570e852b3a1fa07e25e335 100644 (file)
 #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
 ** 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 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 void unixCopyOsFile(OsFile *pDest, OsFile *pSrc){
-  *pDest = *pSrc;
+static int unixLockState(OsFile *id){
+  return id->locktype;
 }
 
 /*
@@ -1381,7 +1503,9 @@ struct sqlite3IoVtbl sqlite3Io = {
   unixLock,
   unixUnlock,
   unixCheckReservedLock,
-  unixCopyOsFile,
+  unixSetFullSync,
+  unixFileHandle,
+  unixLockState,
 };
 
 
index 45ff7af62e338d94c70c778558ce3d9b5b1f799d..e1833b766ac5d9ed26e2991c6150bf4e5c98aba7 100644 (file)
@@ -16,6 +16,7 @@
 #include "os.h"
 #if OS_WIN               /* This file is used for windows only */
 
+#include <windows.h>
 #include <winbase.h>
 
 #ifdef __CYGWIN__
 */
 #include "os_common.h"
 
+/*
+** The OsFile structure is a operating-system independing representation
+** of an open file handle.  It is defined differently for each architecture.
+**
+** This is the definition for Win32.
+*/
+struct OsFile {
+  HANDLE h;               /* Handle for accessing the file */
+  unsigned char locktype; /* Type of lock currently held on this file */
+  short sharedLockByte;   /* Randomly chosen byte used as a shared lock */
+};
+
+
+
 /*
 ** Do not include any of the File I/O interface procedures if the
 ** SQLITE_OMIT_DISKIO macro is defined (indicating that there database
@@ -153,6 +168,23 @@ static int winFileExists(const char *zFilename){
   return exists;
 }
 
+
+/*
+** 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 ){
+    CloseHandle(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,
@@ -168,12 +200,13 @@ static int winFileExists(const char *zFilename){
 */
 static int winOpenReadWrite(
   const char *zFilename,
-  OsFile *id,
+  OsFile **pId,
   int *pReadonly
 ){
+  OsFile f;
   HANDLE h;
   WCHAR *zWide = utf8ToUnicode(zFilename);
-  assert( !id->isOpen );
+  assert( *pId==0 );
   if( zWide ){
     h = CreateFileW(zWide,
        GENERIC_READ | GENERIC_WRITE,
@@ -227,13 +260,17 @@ static int winOpenReadWrite(
       *pReadonly = 0;
     }
   }
-  id->h = h;
-  id->locktype = NO_LOCK;
-  id->sharedLockByte = 0;
-  id->isOpen = 1;
-  OpenCounter(+1);
+  f.h = h;
+  f.locktype = NO_LOCK;
+  f.sharedLockByte = 0;
   TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename);
-  return SQLITE_OK;
+  *pId = allocateOsFile(&f);
+  if( *pId==0 ){
+    return SQLITE_NOMEM;
+  }else{
+    OpenCounter(+1);
+    return SQLITE_OK;
+  }
 }
 
 
@@ -251,11 +288,12 @@ static int winOpenReadWrite(
 **
 ** On failure, return SQLITE_CANTOPEN.
 */
-static int winOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
+static int winOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
+  OsFile f;
   HANDLE h;
   int fileflags;
   WCHAR *zWide = utf8ToUnicode(zFilename);
-  assert( !id->isOpen );
+  assert( *pId == 0 );
   if( delFlag ){
     fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS 
                      | FILE_FLAG_DELETE_ON_CLOSE;
@@ -285,13 +323,17 @@ static int winOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
   if( h==INVALID_HANDLE_VALUE ){
     return SQLITE_CANTOPEN;
   }
-  id->h = h;
-  id->locktype = NO_LOCK;
-  id->sharedLockByte = 0;
-  id->isOpen = 1;
-  OpenCounter(+1);
+  f.h = h;
+  f.locktype = NO_LOCK;
+  f.sharedLockByte = 0;
   TRACE3("OPEN EX %d \"%s\"\n", h, zFilename);
-  return SQLITE_OK;
+  *pId = allocateOsFile(&f);
+  if( *pId==0 ){
+    return SQLITE_NOMEM;
+  }else{
+    OpenCounter(+1);
+    return SQLITE_OK;
+  }
 }
 
 /*
@@ -301,10 +343,11 @@ static int winOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
 **
 ** On failure, return SQLITE_CANTOPEN.
 */
-static int winOpenReadOnly(const char *zFilename, OsFile *id){
+static int winOpenReadOnly(const char *zFilename, OsFile **pId){
+  OsFile f;
   HANDLE h;
   WCHAR *zWide = utf8ToUnicode(zFilename);
-  assert( !id->isOpen );
+  assert( *pId==0 );
   if( zWide ){
     h = CreateFileW(zWide,
        GENERIC_READ,
@@ -328,13 +371,17 @@ static int winOpenReadOnly(const char *zFilename, OsFile *id){
   if( h==INVALID_HANDLE_VALUE ){
     return SQLITE_CANTOPEN;
   }
-  id->h = h;
-  id->locktype = NO_LOCK;
-  id->sharedLockByte = 0;
-  id->isOpen = 1;
-  OpenCounter(+1);
+  f.h = h;
+  f.locktype = NO_LOCK;
+  f.sharedLockByte = 0;
   TRACE3("OPEN RO %d \"%s\"\n", h, zFilename);
-  return SQLITE_OK;
+  *pId = allocateOsFile(&f);
+  if( *pId==0 ){
+    return SQLITE_NOMEM;
+  }else{
+    OpenCounter(+1);
+    return SQLITE_OK;
+  }
 }
 
 /*
@@ -413,12 +460,13 @@ static int winTempFileName(char *zBuf){
 /*
 ** Close a file.
 */
-static int winClose(OsFile *id){
-  if( id->isOpen ){
-    TRACE2("CLOSE %d\n", id->h);
-    CloseHandle(id->h);
+static int winClose(OsFile **pId){
+  if( *pId ){
+    TRACE2("CLOSE %d\n", (*pId)->h);
+    CloseHandle((*pId)->h);
     OpenCounter(-1);
-    id->isOpen = 0;
+    sqliteFree(*pId);
+    *pId = 0;
   }
   return SQLITE_OK;
 }
@@ -430,7 +478,7 @@ static int winClose(OsFile *id){
 */
 static int winRead(OsFile *id, void *pBuf, int amt){
   DWORD got;
-  assert( id->isOpen );
+  assert( id!=0 );
   SimulateIOError(SQLITE_IOERR);
   TRACE3("READ %d lock=%d\n", id->h, id->locktype);
   if( !ReadFile(id->h, pBuf, amt, &got, 0) ){
@@ -450,7 +498,7 @@ static int winRead(OsFile *id, void *pBuf, int amt){
 static int winWrite(OsFile *id, const void *pBuf, int amt){
   int rc = 0;
   DWORD wrote;
-  assert( id->isOpen );
+  assert( id!=0 );
   SimulateIOError(SQLITE_IOERR);
   SimulateDiskfullError;
   TRACE3("WRITE %d lock=%d\n", id->h, id->locktype);
@@ -479,7 +527,7 @@ static int winSeek(OsFile *id, i64 offset){
   LONG upperBits = offset>>32;
   LONG lowerBits = offset & 0xffffffff;
   DWORD rc;
-  assert( id->isOpen );
+  assert( id!=0 );
 #ifdef SQLITE_TEST
   if( offset ) SimulateDiskfullError
 #endif
@@ -496,7 +544,7 @@ static int winSeek(OsFile *id, i64 offset){
 ** Make sure all writes to a particular file are committed to disk.
 */
 static int winSync(OsFile *id, int dataOnly){
-  assert( id->isOpen );
+  assert( id!=0 );
   TRACE3("SYNC %d lock=%d\n", id->h, id->locktype);
   if( FlushFileBuffers(id->h) ){
     return SQLITE_OK;
@@ -519,7 +567,7 @@ static int winSyncDirectory(const char *zDirname){
 */
 static int winTruncate(OsFile *id, i64 nByte){
   LONG upperBits = nByte>>32;
-  assert( id->isOpen );
+  assert( id!=0 );
   TRACE3("TRUNCATE %d %lld\n", id->h, nByte);
   SimulateIOError(SQLITE_IOERR);
   SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN);
@@ -532,7 +580,7 @@ static int winTruncate(OsFile *id, i64 nByte){
 */
 static int winFileSize(OsFile *id, i64 *pSize){
   DWORD upperBits, lowerBits;
-  assert( id->isOpen );
+  assert( id!=0 );
   SimulateIOError(SQLITE_IOERR);
   lowerBits = GetFileSize(id->h, &upperBits);
   *pSize = (((i64)upperBits)<<32) + lowerBits;
@@ -631,7 +679,7 @@ static int winLock(OsFile *id, int locktype){
   int newLocktype;       /* Set id->locktype to this value before exiting */
   int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
 
-  assert( id->isOpen );
+  assert( id!=0 );
   TRACE5("LOCK %d %d was %d(%d)\n",
           id->h, locktype, id->locktype, id->sharedLockByte);
 
@@ -737,7 +785,7 @@ static int winLock(OsFile *id, int locktype){
 */
 static int winCheckReservedLock(OsFile *id){
   int rc;
-  assert( id->isOpen );
+  assert( id!=0 );
   if( id->locktype>=RESERVED_LOCK ){
     rc = 1;
     TRACE3("TEST WR-LOCK %d %d (local)\n", id->h, rc);
@@ -766,7 +814,7 @@ static int winCheckReservedLock(OsFile *id){
 static int winUnlock(OsFile *id, int locktype){
   int type;
   int rc = SQLITE_OK;
-  assert( id->isOpen );
+  assert( id!=0 );
   assert( locktype<=SHARED_LOCK );
   TRACE5("UNLOCK %d to %d was %d(%d)\n", id->h, locktype,
           id->locktype, id->sharedLockByte);
@@ -830,10 +878,25 @@ static char *winFullPathname(const char *zRelative){
 }
 
 /*
-** Make a copy of an OsFile object.
+** The fullSync option is meaningless on windows.   This is a no-op.
+*/
+static void winSetFullSync(OsFile *id, int v){
+  return;
+}
+
+/*
+** Return the underlying file handle for an OsFile
+*/
+static int winFileHandle(OsFile *id){
+  return (int)id->h;
+}
+
+/*
+** Return an integer that indices the type of lock currently held
+** by this handle.  (Used for testing and analysis only.)
 */
-static void winCopyOsFile(OsFile *pDest, OsFile *pSrc){
-  *pDest = *pSrc;
+static int winLockState(OsFile *id){
+  return id->locktype;
 }
 
 
@@ -861,7 +924,9 @@ struct sqlite3IoVtbl sqlite3Io = {
   winLock,
   winUnlock,
   winCheckReservedLock,
-  winCopyOsFile,
+  winSetFullSync,
+  winFileHandle,
+  winLockState,
 };
 
 #endif /* SQLITE_OMIT_DISKIO */
index 17a5c31925533d4674e1d0cb9bb333fa1466721e..1b6dc8846dabfdc5c679073a321d1f5aa42ff2b5 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.220 2005/11/26 03:51:19 drh Exp $
+** @(#) $Id: pager.c,v 1.221 2005/11/29 03:13:22 drh Exp $
 */
 #ifndef SQLITE_OMIT_DISKIO
 #include "sqliteInt.h"
@@ -52,8 +52,8 @@
 ** associated file-descriptor is returned. FILEHANDLEID() takes an OsFile
 ** struct as it's argument.
 */
-#define PAGERID(p) (p->fd.h)
-#define FILEHANDLEID(fd) (fd.h)
+#define PAGERID(p) FILEHANDLEID(&(p)->fd)
+#define FILEHANDLEID(fd) (sqlite3Io.xFileHandle(&fd))
 
 /*
 ** The page cache as a whole is always in one of the following
@@ -262,8 +262,8 @@ struct Pager {
   char *zFilename;            /* Name of the database file */
   char *zJournal;             /* Name of the journal file */
   char *zDirectory;           /* Directory hold database and journal files */
-  OsFile fd, jfd;             /* File descriptors for database and journal */
-  OsFile stfd;                /* File descriptor for the statement subjournal*/
+  OsFile *fd, *jfd;           /* File descriptors for database and journal */
+  OsFile *stfd;               /* File descriptor for the statement subjournal*/
   BusyHandler *pBusyHandler;  /* Pointer to sqlite.busyHandler */
   PgHdr *pFirst, *pLast;      /* List of free pages */
   PgHdr *pFirstSynced;        /* First free page with PgHdr.needSync==0 */
@@ -590,7 +590,7 @@ static int seekJournalHdr(Pager *pPager){
   assert( offset>=c );
   assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
   pPager->journalOff = offset;
-  return sqlite3Io.xSeek(&pPager->jfd, pPager->journalOff);
+  return sqlite3Io.xSeek(pPager->jfd, pPager->journalOff);
 }
 
 /*
@@ -626,33 +626,33 @@ static int writeJournalHdr(Pager *pPager){
   ** Actually maybe the whole journal header should be delayed until that
   ** point. Think about this.
   */
-  rc = sqlite3Io.xWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
+  rc = sqlite3Io.xWrite(pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
 
   if( rc==SQLITE_OK ){
     /* The nRec Field. 0xFFFFFFFF for no-sync journals. */
-    rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0);
+    rc = write32bits(pPager->jfd, pPager->noSync ? 0xffffffff : 0);
   }
   if( rc==SQLITE_OK ){
     /* The random check-hash initialiser */ 
     sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
-    rc = write32bits(&pPager->jfd, pPager->cksumInit);
+    rc = write32bits(pPager->jfd, pPager->cksumInit);
   }
   if( rc==SQLITE_OK ){
     /* The initial database size */
-    rc = write32bits(&pPager->jfd, pPager->dbSize);
+    rc = write32bits(pPager->jfd, pPager->dbSize);
   }
   if( rc==SQLITE_OK ){
     /* The assumed sector size for this process */
-    rc = write32bits(&pPager->jfd, pPager->sectorSize);
+    rc = write32bits(pPager->jfd, pPager->sectorSize);
   }
 
   /* The journal header has been written successfully. Seek the journal
   ** file descriptor to the end of the journal header sector.
   */
   if( rc==SQLITE_OK ){
-    rc = sqlite3Io.xSeek(&pPager->jfd, pPager->journalOff-1);
+    rc = sqlite3Io.xSeek(pPager->jfd, pPager->journalOff-1);
     if( rc==SQLITE_OK ){
-      rc = sqlite3Io.xWrite(&pPager->jfd, "\000", 1);
+      rc = sqlite3Io.xWrite(pPager->jfd, "\000", 1);
     }
   }
   return rc;
@@ -690,20 +690,20 @@ static int readJournalHdr(
     return SQLITE_DONE;
   }
 
-  rc = sqlite3Io.xRead(&pPager->jfd, aMagic, sizeof(aMagic));
+  rc = sqlite3Io.xRead(pPager->jfd, aMagic, sizeof(aMagic));
   if( rc ) return rc;
 
   if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
     return SQLITE_DONE;
   }
 
-  rc = read32bits(&pPager->jfd, pNRec);
+  rc = read32bits(pPager->jfd, pNRec);
   if( rc ) return rc;
 
-  rc = read32bits(&pPager->jfd, &pPager->cksumInit);
+  rc = read32bits(pPager->jfd, &pPager->cksumInit);
   if( rc ) return rc;
 
-  rc = read32bits(&pPager->jfd, pDbSize);
+  rc = read32bits(pPager->jfd, pDbSize);
   if( rc ) return rc;
 
   /* Update the assumed sector-size to match the value used by 
@@ -712,11 +712,11 @@ static int readJournalHdr(
   ** is being called from within pager_playback(). The local value
   ** of Pager.sectorSize is restored at the end of that routine.
   */
-  rc = read32bits(&pPager->jfd, (u32 *)&pPager->sectorSize);
+  rc = read32bits(pPager->jfd, (u32 *)&pPager->sectorSize);
   if( rc ) return rc;
 
   pPager->journalOff += JOURNAL_HDR_SZ(pPager);
-  rc = sqlite3Io.xSeek(&pPager->jfd, pPager->journalOff);
+  rc = sqlite3Io.xSeek(pPager->jfd, pPager->journalOff);
   return rc;
 }
 
@@ -761,19 +761,19 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
   }
   pPager->journalOff += (len+20);
 
-  rc = write32bits(&pPager->jfd, PAGER_MJ_PGNO(pPager));
+  rc = write32bits(pPager->jfd, PAGER_MJ_PGNO(pPager));
   if( rc!=SQLITE_OK ) return rc;
 
-  rc = sqlite3Io.xWrite(&pPager->jfd, zMaster, len);
+  rc = sqlite3Io.xWrite(pPager->jfd, zMaster, len);
   if( rc!=SQLITE_OK ) return rc;
 
-  rc = write32bits(&pPager->jfd, len);
+  rc = write32bits(pPager->jfd, len);
   if( rc!=SQLITE_OK ) return rc;
 
-  rc = write32bits(&pPager->jfd, cksum);
+  rc = write32bits(pPager->jfd, cksum);
   if( rc!=SQLITE_OK ) return rc;
 
-  rc = sqlite3Io.xWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
+  rc = sqlite3Io.xWrite(pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
   pPager->needSync = !pPager->noSync;
   return rc;
 }
@@ -851,7 +851,7 @@ static void pager_reset(Pager *pPager){
   if( pPager->state>=PAGER_RESERVED ){
     sqlite3pager_rollback(pPager);
   }
-  sqlite3Io.xUnlock(&pPager->fd, NO_LOCK);
+  sqlite3Io.xUnlock(pPager->fd, NO_LOCK);
   pPager->state = PAGER_UNLOCK;
   pPager->dbSize = -1;
   pPager->nRef = 0;
@@ -923,7 +923,7 @@ static int pager_unwritelock(Pager *pPager){
     assert( pPager->aInJournal==0 );
     assert( pPager->dirtyCache==0 || pPager->useJournal==0 );
   }
-  rc = sqlite3Io.xUnlock(&pPager->fd, SHARED_LOCK);
+  rc = sqlite3Io.xUnlock(pPager->fd, SHARED_LOCK);
   pPager->state = PAGER_SHARED;
   pPager->origDbSize = 0;
   pPager->setMaster = 0;
@@ -978,7 +978,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
   /* useCksum should be true for the main journal and false for
   ** statement journals.  Verify that this is always the case
   */
-  assert( jfd == (useCksum ? &pPager->jfd : &pPager->stfd) );
+  assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) );
 
 
   rc = read32bits(jfd, &pgno);
@@ -1033,9 +1033,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
   assert( pPager->state>=PAGER_EXCLUSIVE || pPg!=0 );
   TRACE3("PLAYBACK %d page %d\n", PAGERID(pPager), pgno);
   if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){
-    rc = sqlite3Io.xSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
+    rc = sqlite3Io.xSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize);
     if( rc==SQLITE_OK ){
-      rc = sqlite3Io.xWrite(&pPager->fd, aData, pPager->pageSize);
+      rc = sqlite3Io.xWrite(pPager->fd, aData, pPager->pageSize);
     }
     if( pPg ) pPg->dirty = 0;
   }
@@ -1075,18 +1075,17 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
 static int pager_delmaster(const char *zMaster){
   int rc;
   int master_open = 0;
-  OsFile master;
+  OsFile *master = 0;
   char *zMasterJournal = 0; /* Contents of master journal file */
   i64 nMasterJournal;       /* Size of master journal file */
 
   /* Open the master journal file exclusively in case some other process
   ** is running this routine also. Not that it makes too much difference.
   */
-  memset(&master, 0, sizeof(master));
   rc = sqlite3Io.xOpenReadOnly(zMaster, &master);
   if( rc!=SQLITE_OK ) goto delmaster_out;
   master_open = 1;
-  rc = sqlite3Io.xFileSize(&master, &nMasterJournal);
+  rc = sqlite3Io.xFileSize(master, &nMasterJournal);
   if( rc!=SQLITE_OK ) goto delmaster_out;
 
   if( nMasterJournal>0 ){
@@ -1101,7 +1100,7 @@ static int pager_delmaster(const char *zMaster){
       rc = SQLITE_NOMEM;
       goto delmaster_out;
     }
-    rc = sqlite3Io.xRead(&master, zMasterJournal, nMasterJournal);
+    rc = sqlite3Io.xRead(master, zMasterJournal, nMasterJournal);
     if( rc!=SQLITE_OK ) goto delmaster_out;
 
     zJournal = zMasterJournal;
@@ -1111,16 +1110,15 @@ static int pager_delmaster(const char *zMaster){
         ** Open it and check if it points at the master journal. If
         ** so, return without deleting the master journal file.
         */
-        OsFile journal;
+        OsFile *journal = 0;
         int c;
 
-        memset(&journal, 0, sizeof(journal));
         rc = sqlite3Io.xOpenReadOnly(zJournal, &journal);
         if( rc!=SQLITE_OK ){
           goto delmaster_out;
         }
 
-        rc = readMasterJournal(&journal, &zMasterPtr);
+        rc = readMasterJournal(journal, &zMasterPtr);
         sqlite3Io.xClose(&journal);
         if( rc!=SQLITE_OK ){
           goto delmaster_out;
@@ -1165,9 +1163,9 @@ static int pager_reload_cache(Pager *pPager){
     char zBuf[SQLITE_MAX_PAGE_SIZE];
     if( !pPg->dirty ) continue;
     if( (int)pPg->pgno <= pPager->origDbSize ){
-      rc = sqlite3Io.xSeek(&pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1));
+      rc = sqlite3Io.xSeek(pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1));
       if( rc==SQLITE_OK ){
-        rc = sqlite3Io.xRead(&pPager->fd, zBuf, pPager->pageSize);
+        rc = sqlite3Io.xRead(pPager->fd, zBuf, pPager->pageSize);
       }
       TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
       if( rc ) break;
@@ -1198,7 +1196,7 @@ static int pager_reload_cache(Pager *pPager){
 */
 static int pager_truncate(Pager *pPager, int nPage){
   assert( pPager->state>=PAGER_EXCLUSIVE );
-  return sqlite3Io.xTruncate(&pPager->fd, pPager->pageSize*(i64)nPage);
+  return sqlite3Io.xTruncate(pPager->fd, pPager->pageSize*(i64)nPage);
 }
 
 /*
@@ -1266,7 +1264,7 @@ static int pager_playback(Pager *pPager){
   ** the journal is empty.
   */
   assert( pPager->journalOpen );
-  rc = sqlite3Io.xFileSize(&pPager->jfd, &szJ);
+  rc = sqlite3Io.xFileSize(pPager->jfd, &szJ);
   if( rc!=SQLITE_OK ){
     goto end_playback;
   }
@@ -1276,7 +1274,7 @@ static int pager_playback(Pager *pPager){
   ** present on disk, then the journal is not hot and does not need to be
   ** played back.
   */
-  rc = readMasterJournal(&pPager->jfd, &zMaster);
+  rc = readMasterJournal(pPager->jfd, &zMaster);
   assert( rc!=SQLITE_DONE );
   if( rc!=SQLITE_OK || (zMaster && !sqlite3Io.xFileExists(zMaster)) ){
     sqliteFree(zMaster);
@@ -1284,7 +1282,7 @@ static int pager_playback(Pager *pPager){
     if( rc==SQLITE_DONE ) rc = SQLITE_OK;
     goto end_playback;
   }
-  sqlite3Io.xSeek(&pPager->jfd, 0);
+  sqlite3Io.xSeek(pPager->jfd, 0);
   pPager->journalOff = 0;
 
   /* This loop terminates either when the readJournalHdr() call returns
@@ -1327,13 +1325,13 @@ static int pager_playback(Pager *pPager){
       pPager->dbSize = mxPg;
     }
 
-    /* rc = sqlite3Io.xSeek(&pPager->jfd, JOURNAL_HDR_SZ(pPager)); */
+    /* rc = sqlite3Io.xSeek(pPager->jfd, JOURNAL_HDR_SZ(pPager)); */
     if( rc!=SQLITE_OK ) goto end_playback;
   
     /* Copy original pages out of the journal and back into the database file.
     */
     for(i=0; i<nRec; i++){
-      rc = pager_playback_one_page(pPager, &pPager->jfd, 1);
+      rc = pager_playback_one_page(pPager, pPager->jfd, 1);
       if( rc!=SQLITE_OK ){
         if( rc==SQLITE_DONE ){
           rc = SQLITE_OK;
@@ -1400,7 +1398,7 @@ static int pager_stmt_playback(Pager *pPager){
 #ifndef NDEBUG 
   {
     i64 os_szJ;
-    rc = sqlite3Io.xFileSize(&pPager->jfd, &os_szJ);
+    rc = sqlite3Io.xFileSize(pPager->jfd, &os_szJ);
     if( rc!=SQLITE_OK ) return rc;
     assert( szJ==os_szJ );
   }
@@ -1426,7 +1424,7 @@ static int pager_stmt_playback(Pager *pPager){
   /* Figure out how many records are in the statement journal.
   */
   assert( pPager->stmtInUse && pPager->journalOpen );
-  sqlite3Io.xSeek(&pPager->stfd, 0);
+  sqlite3Io.xSeek(pPager->stfd, 0);
   nRec = pPager->stmtNRec;
   
   /* Copy original pages out of the statement journal and back into the
@@ -1435,7 +1433,7 @@ static int pager_stmt_playback(Pager *pPager){
   ** journals.
   */
   for(i=nRec-1; i>=0; i--){
-    rc = pager_playback_one_page(pPager, &pPager->stfd, 0);
+    rc = pager_playback_one_page(pPager, pPager->stfd, 0);
     assert( rc!=SQLITE_DONE );
     if( rc!=SQLITE_OK ) goto end_stmt_playback;
   }
@@ -1448,7 +1446,7 @@ static int pager_stmt_playback(Pager *pPager){
   ** If it is not zero, then Pager.stmtHdrOff is the offset to the start
   ** of the first journal header written during this statement transaction.
   */
-  rc = sqlite3Io.xSeek(&pPager->jfd, pPager->stmtJSize);
+  rc = sqlite3Io.xSeek(pPager->jfd, pPager->stmtJSize);
   if( rc!=SQLITE_OK ){
     goto end_stmt_playback;
   }
@@ -1456,7 +1454,7 @@ static int pager_stmt_playback(Pager *pPager){
   pPager->cksumInit = pPager->stmtCksum;
   assert( JOURNAL_HDR_SZ(pPager)<(pPager->pageSize+8) );
   while( pPager->journalOff <= (hdrOff-(pPager->pageSize+8)) ){
-    rc = pager_playback_one_page(pPager, &pPager->jfd, 1);
+    rc = pager_playback_one_page(pPager, pPager->jfd, 1);
     assert( rc!=SQLITE_DONE );
     if( rc!=SQLITE_OK ) goto end_stmt_playback;
   }
@@ -1473,7 +1471,7 @@ static int pager_stmt_playback(Pager *pPager){
       nRec = (szJ - pPager->journalOff) / (pPager->pageSize+8);
     }
     for(i=nRec-1; i>=0 && pPager->journalOff < szJ; i--){
-      rc = pager_playback_one_page(pPager, &pPager->jfd, 1);
+      rc = pager_playback_one_page(pPager, pPager->jfd, 1);
       assert( rc!=SQLITE_DONE );
       if( rc!=SQLITE_OK ) goto end_stmt_playback;
     }
@@ -1553,14 +1551,14 @@ int sqlite3_opentemp_count = 0;
 ** The OS will automatically delete the temporary file when it is
 ** closed.
 */
-static int sqlite3pager_opentemp(char *zFile, OsFile *fd){
+static int sqlite3pager_opentemp(char *zFile, OsFile **pFd){
   int cnt = 8;
   int rc;
   sqlite3_opentemp_count++;  /* Used for testing and analysis only */
   do{
     cnt--;
     sqlite3Io.xTempFileName(zFile);
-    rc = sqlite3Io.xOpenExclusive(zFile, fd, 1);
+    rc = sqlite3Io.xOpenExclusive(zFile, pFd, 1);
   }while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM );
   return rc;
 }
@@ -1588,7 +1586,7 @@ int sqlite3pager_open(
   Pager *pPager;
   char *zFullPathname = 0;
   int nameLen;
-  OsFile fd;
+  OsFile *fd;
   int rc = SQLITE_OK;
   int i;
   int tempFile = 0;
@@ -1652,7 +1650,7 @@ int sqlite3pager_open(
   strcpy(pPager->zJournal, zFullPathname);
   sqliteFree(zFullPathname);
   strcpy(&pPager->zJournal[nameLen], "-journal");
-  sqlite3Io.xCopyOsFile(&pPager->fd,&fd);
+  pPager->fd = fd;
   pPager->journalOpen = 0;
   pPager->useJournal = useJournal && !memDb;
   pPager->noReadlock = noReadlock && readOnly;
@@ -1763,8 +1761,8 @@ void enable_simulated_io_errors(void){
 void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){
   memset(pDest, 0, N);
   if( MEMDB==0 ){
-    sqlite3Io.xSeek(&pPager->fd, 0);
-    sqlite3Io.xRead(&pPager->fd, pDest, N);
+    sqlite3Io.xSeek(pPager->fd, 0);
+    sqlite3Io.xRead(pPager->fd, pDest, N);
     clear_simulated_io_error();
   }
 }
@@ -1784,7 +1782,7 @@ int sqlite3pager_pagecount(Pager *pPager){
   if( pPager->dbSize>=0 ){
     n = pPager->dbSize;
   } else {
-    if( sqlite3Io.xFileSize(&pPager->fd, &n)!=SQLITE_OK ){
+    if( sqlite3Io.xFileSize(pPager->fd, &n)!=SQLITE_OK ){
       pPager->errMask |= PAGER_ERR_DISK;
       return 0;
     }
@@ -1916,7 +1914,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
     rc = SQLITE_OK;
   }else{
     do {
-      rc = sqlite3Io.xLock(&pPager->fd, locktype);
+      rc = sqlite3Io.xLock(pPager->fd, locktype);
     }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) );
     if( rc==SQLITE_OK ){
       pPager->state = locktype;
@@ -1984,14 +1982,14 @@ int sqlite3pager_close(Pager *pPager){
       sqlite3pager_rollback(pPager);
       enable_simulated_io_errors();
       if( !MEMDB ){
-        sqlite3Io.xUnlock(&pPager->fd, NO_LOCK);
+        sqlite3Io.xUnlock(pPager->fd, NO_LOCK);
       }
       assert( pPager->errMask || pPager->journalOpen==0 );
       break;
     }
     case PAGER_SHARED: {
       if( !MEMDB ){
-        sqlite3Io.xUnlock(&pPager->fd, NO_LOCK);
+        sqlite3Io.xUnlock(pPager->fd, NO_LOCK);
       }
       break;
     }
@@ -2133,7 +2131,7 @@ static int syncJournal(Pager *pPager){
         ** with the nRec computed from the size of the journal file.
         */
         i64 jSz;
-        rc = sqlite3Io.xFileSize(&pPager->jfd, &jSz);
+        rc = sqlite3Io.xFileSize(pPager->jfd, &jSz);
         if( rc!=0 ) return rc;
         assert( pPager->journalOff==jSz );
       }
@@ -2146,20 +2144,20 @@ static int syncJournal(Pager *pPager){
         */
         if( pPager->fullSync ){
           TRACE2("SYNC journal of %d\n", PAGERID(pPager));
-          rc = sqlite3Io.xSync(&pPager->jfd, 0);
+          rc = sqlite3Io.xSync(pPager->jfd, 0);
           if( rc!=0 ) return rc;
         }
-        rc = sqlite3Io.xSeek(&pPager->jfd,
+        rc = sqlite3Io.xSeek(pPager->jfd,
                            pPager->journalHdr + sizeof(aJournalMagic));
         if( rc ) return rc;
-        rc = write32bits(&pPager->jfd, pPager->nRec);
+        rc = write32bits(pPager->jfd, pPager->nRec);
         if( rc ) return rc;
 
-        rc = sqlite3Io.xSeek(&pPager->jfd, pPager->journalOff);
+        rc = sqlite3Io.xSeek(pPager->jfd, pPager->journalOff);
         if( rc ) return rc;
       }
       TRACE2("SYNC journal of %d\n", PAGERID(pPager));
-      rc = sqlite3Io.xSync(&pPager->jfd, pPager->fullSync);
+      rc = sqlite3Io.xSync(pPager->jfd, pPager->fullSync);
       if( rc!=0 ) return rc;
       pPager->journalStarted = 1;
     }
@@ -2224,7 +2222,7 @@ static int pager_write_pagelist(PgHdr *pList){
 
   while( pList ){
     assert( pList->dirty );
-    rc = sqlite3Io.xSeek(&pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize);
+    rc = sqlite3Io.xSeek(pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize);
     if( rc ) return rc;
     /* If there are dirty pages in the page cache with page numbers greater
     ** than Pager.dbSize, this means sqlite3pager_truncate() was called to
@@ -2234,7 +2232,7 @@ static int pager_write_pagelist(PgHdr *pList){
     if( pList->pgno<=pPager->dbSize ){
       CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
       TRACE3("STORE %d page %d\n", PAGERID(pPager), pList->pgno);
-      rc = sqlite3Io.xWrite(&pPager->fd, PGHDR_TO_DATA(pList),
+      rc = sqlite3Io.xWrite(pPager->fd, PGHDR_TO_DATA(pList),
                              pPager->pageSize);
       CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0);
       TEST_INCR(pPager->nWrite);
@@ -2282,7 +2280,7 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
 static int hasHotJournal(Pager *pPager){
   if( !pPager->useJournal ) return 0;
   if( !sqlite3Io.xFileExists(pPager->zJournal) ) return 0;
-  if( sqlite3Io.xCheckReservedLock(&pPager->fd) ) return 0;
+  if( sqlite3Io.xCheckReservedLock(pPager->fd) ) return 0;
   if( sqlite3pager_pagecount(pPager)==0 ){
     sqlite3Io.xDelete(pPager->zJournal);
     return 0;
@@ -2361,9 +2359,9 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
        ** second process will get to this point in the code and fail to
        ** obtain it's own EXCLUSIVE lock on the database file.
        */
-       rc = sqlite3Io.xLock(&pPager->fd, EXCLUSIVE_LOCK);
+       rc = sqlite3Io.xLock(pPager->fd, EXCLUSIVE_LOCK);
        if( rc!=SQLITE_OK ){
-         sqlite3Io.xUnlock(&pPager->fd, NO_LOCK);
+         sqlite3Io.xUnlock(pPager->fd, NO_LOCK);
          pPager->state = PAGER_UNLOCK;
          return rc;
        }
@@ -2379,7 +2377,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
        */
        rc = sqlite3Io.xOpenReadOnly(pPager->zJournal, &pPager->jfd);
        if( rc!=SQLITE_OK ){
-         sqlite3Io.xUnlock(&pPager->fd, NO_LOCK);
+         sqlite3Io.xUnlock(pPager->fd, NO_LOCK);
          pPager->state = PAGER_UNLOCK;
          return SQLITE_BUSY;
        }
@@ -2536,16 +2534,16 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
     }else{
       int rc;
       assert( MEMDB==0 );
-      rc = sqlite3Io.xSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
+      rc = sqlite3Io.xSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize);
       if( rc==SQLITE_OK ){
-        rc = sqlite3Io.xRead(&pPager->fd, PGHDR_TO_DATA(pPg),
+        rc = sqlite3Io.xRead(pPager->fd, PGHDR_TO_DATA(pPg),
                               pPager->pageSize);
       }
       TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
       CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
       if( rc!=SQLITE_OK ){
         i64 fileSize;
-        if( sqlite3Io.xFileSize(&pPager->fd,&fileSize)!=SQLITE_OK
+        if( sqlite3Io.xFileSize(pPager->fd,&fileSize)!=SQLITE_OK
                || fileSize>=pgno*pPager->pageSize ){
           sqlite3pager_unref(PGHDR_TO_DATA(pPg));
           return rc;
@@ -2675,9 +2673,9 @@ static int pager_open_journal(Pager *pPager){
   if( rc!=SQLITE_OK ){
     goto failed_to_open_journal;
   }
-  SET_FULLSYNC(pPager->jfd, pPager->fullSync);
-  SET_FULLSYNC(pPager->fd, pPager->fullSync);
-  sqlite3Io.xOpenDirectory(pPager->zDirectory, &pPager->jfd);
+  sqlite3Io.xSetFullSync(pPager->jfd, pPager->fullSync);
+  sqlite3Io.xSetFullSync(pPager->fd, pPager->fullSync);
+  sqlite3Io.xOpenDirectory(pPager->zDirectory, pPager->jfd);
   pPager->journalOpen = 1;
   pPager->journalStarted = 0;
   pPager->needSync = 0;
@@ -2705,7 +2703,7 @@ static int pager_open_journal(Pager *pPager){
 failed_to_open_journal:
   sqliteFree(pPager->aInJournal);
   pPager->aInJournal = 0;
-  sqlite3Io.xUnlock(&pPager->fd, NO_LOCK);
+  sqlite3Io.xUnlock(pPager->fd, NO_LOCK);
   pPager->state = PAGER_UNLOCK;
   return rc;
 }
@@ -2749,7 +2747,7 @@ int sqlite3pager_begin(void *pData, int exFlag){
       pPager->state = PAGER_EXCLUSIVE;
       pPager->origDbSize = pPager->dbSize;
     }else{
-      rc = sqlite3Io.xLock(&pPager->fd, RESERVED_LOCK);
+      rc = sqlite3Io.xLock(pPager->fd, RESERVED_LOCK);
       if( rc==SQLITE_OK ){
         pPager->state = PAGER_RESERVED;
         if( exFlag ){
@@ -2860,7 +2858,7 @@ int sqlite3pager_write(void *pData){
           store32bits(cksum, pPg, pPager->pageSize);
           szPg = pPager->pageSize+8;
           store32bits(pPg->pgno, pPg, -4);
-          rc = sqlite3Io.xWrite(&pPager->jfd, &((char*)pData)[-4], szPg);
+          rc = sqlite3Io.xWrite(pPager->jfd, &((char*)pData)[-4], szPg);
           pPager->journalOff += szPg;
           TRACE4("JOURNAL %d page %d needSync=%d\n",
                   PAGERID(pPager), pPg->pgno, pPg->needSync);
@@ -2909,7 +2907,7 @@ int sqlite3pager_write(void *pData){
       }else{
         store32bits(pPg->pgno, pPg, -4);
         CODEC(pPager, pData, pPg->pgno, 7);
-        rc = sqlite3Io.xWrite(&pPager->stfd,((char*)pData)-4,
+        rc = sqlite3Io.xWrite(pPager->stfd,((char*)pData)-4,
                                pPager->pageSize+4);
         TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
         CODEC(pPager, pData, pPg->pgno, 0);
@@ -3272,11 +3270,11 @@ int sqlite3pager_stmt_begin(Pager *pPager){
   assert( pPager->journalOpen );
   pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 );
   if( pPager->aInStmt==0 ){
-    sqlite3Io.xLock(&pPager->fd, SHARED_LOCK);
+    sqlite3Io.xLock(pPager->fd, SHARED_LOCK);
     return SQLITE_NOMEM;
   }
 #ifndef NDEBUG
-  rc = sqlite3Io.xFileSize(&pPager->jfd, &pPager->stmtJSize);
+  rc = sqlite3Io.xFileSize(pPager->jfd, &pPager->stmtJSize);
   if( rc ) goto stmt_begin_failed;
   assert( pPager->stmtJSize == pPager->journalOff );
 #endif
@@ -3309,8 +3307,8 @@ int sqlite3pager_stmt_commit(Pager *pPager){
     PgHdr *pPg, *pNext;
     TRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
     if( !MEMDB ){
-      sqlite3Io.xSeek(&pPager->stfd, 0);
-      /* sqlite3Io.xTruncate(&pPager->stfd, 0); */
+      sqlite3Io.xSeek(pPager->stfd, 0);
+      /* sqlite3Io.xTruncate(pPager->stfd, 0); */
       sqliteFree( pPager->aInStmt );
       pPager->aInStmt = 0;
     }
@@ -3513,7 +3511,7 @@ int sqlite3pager_sync(Pager *pPager, const char *zMaster, Pgno nTrunc){
 
     /* Sync the database file. */
     if( !pPager->noSync ){
-      rc = sqlite3Io.xSync(&pPager->fd, 0);
+      rc = sqlite3Io.xSync(pPager->fd, 0);
     }
 
     pPager->state = PAGER_SYNCED;
@@ -3627,11 +3625,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){
 ** PENDING_LOCK, or EXCLUSIVE_LOCK.
 */
 int sqlite3pager_lockstate(Pager *pPager){
-#ifdef OS_TEST
-  return pPager->fd->fd.locktype;
-#else
-  return pPager->fd.locktype;
-#endif
+  return sqlite3Io.xLockState(pPager->fd);
 }
 #endif
 
index 402ff8c42ce0dfb2b826b6c1a56223bc99ff5ad3..870b729d02b24ead892bcf0fcdbc1b6f2fc22213 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.166 2005/11/26 00:25:03 drh Exp $
+** $Id: test1.c,v 1.167 2005/11/29 03:13:22 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -2429,7 +2429,7 @@ static int test_sqlite3OsOpenReadWrite(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
-  OsFile * pFile;
+  OsFile *pFile;
   int rc;
   int dummy;
   char zBuf[100];
@@ -2440,10 +2440,8 @@ static int test_sqlite3OsOpenReadWrite(
     return TCL_ERROR;
   }
 
-  pFile = sqliteMalloc(sizeof(OsFile));
-  rc = sqlite3Io.xOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy);
+  rc = sqlite3Io.xOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy);
   if( rc!=SQLITE_OK ){
-    sqliteFree(pFile);
     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
     return TCL_ERROR;
   }
@@ -2461,7 +2459,7 @@ static int test_sqlite3OsClose(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
-  OsFile * pFile;
+  OsFile *pFile;
   int rc;
 
   if( objc!=2 ){
@@ -2473,12 +2471,11 @@ static int test_sqlite3OsClose(
   if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
     return TCL_ERROR;
   }
-  rc = sqlite3Io.xClose(pFile);
+  rc = sqlite3Io.xClose(&pFile);
   if( rc!=SQLITE_OK ){
     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
     return TCL_ERROR;
   }
-  sqliteFree(pFile);
   return TCL_OK;
 }
 
index bb02af5da49e2b10b714bb6bf1e201a1bd9086cb..39e91489749360273887b08509d3773dc99a011e 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test2.c,v 1.36 2005/11/26 00:25:04 drh Exp $
+** $Id: test2.c,v 1.37 2005/11/29 03:13:22 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -524,7 +524,7 @@ static int fake_big_file(
   int rc;
   int n;
   i64 offset;
-  OsFile fd;
+  OsFile *fd = 0;
   int readOnly = 0;
   if( argc!=3 ){
     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
@@ -532,7 +532,6 @@ static int fake_big_file(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
-  memset(&fd, 0, sizeof(fd));
   rc = sqlite3Io.xOpenReadWrite(argv[2], &fd, &readOnly);
   if( rc ){
     Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0);
@@ -540,12 +539,12 @@ static int fake_big_file(
   }
   offset = n;
   offset *= 1024*1024;
-  rc = sqlite3Io.xSeek(&fd, offset);
+  rc = sqlite3Io.xSeek(fd, offset);
   if( rc ){
     Tcl_AppendResult(interp, "seek failed: ", errorName(rc), 0);
     return TCL_ERROR;
   }
-  rc = sqlite3Io.xWrite(&fd, "Hello, World!", 14);
+  rc = sqlite3Io.xWrite(fd, "Hello, World!", 14);
   sqlite3Io.xClose(&fd);
   if( rc ){
     Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0);
index 414480ba0ad82c4fb9f731dedd8c4de05a0fd521..3407ff2b50c338ab277c7531ee5bd4a5730b6c14 100644 (file)
@@ -18,6 +18,7 @@
 #include "sqliteInt.h"
 #include "os.h"
 #include "tcl.h"
+#if 0
 
 /*
 ** A copy of the original sqlite3Io structure
 static struct sqlite3IoVtbl origIo;
 
 /*
-** The pAux part of OsFile points to this structure.
+** The OsFile structure for the crash-test backend.  The pBase field
+** points to an OsFile structure for the native backend.
 */
-typedef struct OsTestFile OsTestFile;
-struct OsTestFile {
+struct OsFile {
   u8 **apBlk;         /* Array of blocks that have been written to. */
   int nBlk;           /* Size of apBlock. */
   int nMaxWrite;      /* Largest offset written to. */
   char *zName;        /* File name */
   OsFile *pBase;      /* Base class */
-  OsTestFile *pNext;  /* Next in a list of them all */
+  OsFile *pNext;      /* Next in a list of them all */
 };
 
 /*
@@ -102,9 +103,8 @@ static OsTestFile *pAllFiles = 0;
 /*
 ** Initialise the os_test.c specific fields of pFile.
 */
-static void initFile(OsFile *id, char const *zName){
-  OsTestFile *pFile = sqliteMalloc(sizeof(OsTestFile) + strlen(zName)+1);
-  id->pAux = pFile;
+static void initFile(OsFile **pId, char const *zName){
+  OsFile *pFile = *pId = sqliteMalloc(sizeof(OsFile) + strlen(zName)+1);
   pFile->nMaxWrite = 0; 
   pFile->nBlk = 0; 
   pFile->apBlk = 0; 
@@ -120,11 +120,11 @@ static void initFile(OsFile *id, char const *zName){
 ** and unlink the structure from the pAllFiles list.
 */
 static void closeFile(OsFile *id){
-  OsTestFile *pFile = (OsTestFile*)id->pAux;
+  OsFile *pFile = id;
   if( pFile==pAllFiles ){
     pAllFiles = pFile->pNext;
   }else{
-    OsTestFile *p;
+    OsFile *p;
     for(p=pAllFiles; p->pNext!=pFile; p=p->pNext ){
       assert( p );
     }
@@ -137,14 +137,14 @@ static void closeFile(OsFile *id){
 ** Return the current seek offset from the start of the file. This
 ** is unix-only code.
 */
-static i64 osTell(OsTestFile *pFile){
+static i64 osTell(OsFile *pFile){
   return lseek(pFile->pBase->h, 0, SEEK_CUR);
 }
 
 /*
 ** Load block 'blk' into the cache of pFile.
 */
-static int cacheBlock(OsTestFile *pFile, int blk){
+static int cacheBlock(OsFile *pFile, int blk){
   if( blk>=pFile->nBlk ){
     int n = ((pFile->nBlk * 2) + 100 + blk);
     /* if( pFile->nBlk==0 ){ printf("DIRTY %s\n", pFile->zName); } */
@@ -184,7 +184,7 @@ static int cacheBlock(OsTestFile *pFile, int blk){
 ** Write the cache of pFile to disk. If crash is non-zero, randomly
 ** skip blocks when writing. The cache is deleted before returning.
 */
-static int writeCache2(OsTestFile *pFile, int crash){
+static int writeCache2(OsFile *pFile, int crash){
   int i;
   int nMax = pFile->nMaxWrite;
   i64 offset;
@@ -249,7 +249,7 @@ printf("Writing block %d of %s\n", i, pFile->zName);
 /*
 ** Write the cache to disk.
 */
-static int writeCache(OsTestFile *pFile){
+static int writeCache(OsFile *pFile){
   if( pFile->apBlk ){
     int c = crashRequired(pFile->zName);
     if( c ){
@@ -275,8 +275,8 @@ static int crashClose(OsFile *id){
   if( id->pAux ) return SQLITE_OK;
   if( id->isOpen ){
     /* printf("CLOSE %s (%d blocks)\n", (*id)->zName, (*id)->nBlk); */
-    writeCache((OsTestFile*)id->pAux);
-    origIo.xClose(id);
+    writeCache(id);
+    origIo.xClose(&id->pBase);
   }
   closeFile(id);
   return SQLITE_OK;
@@ -472,15 +472,18 @@ static int crashParamsObjCmd(
   sqlite3Io.xOpenReadWrite = crashOpenReadWrite;
   sqlite3Io.xOpenExclusive = crashOpenExclusive;
   sqlite3Io.xOpenReadOnly = crashOpenReadOnly;
-  sqlite3Io.xCopyOsFile = crashCopyOsFile;
+  sqlite3Io.xSet
   return TCL_OK;
 }
 
+#endif
 /*
 ** This procedure registers the TCL procedures defined in this file.
 */
 int Sqlitetest6_Init(Tcl_Interp *interp){
+#if 0
   Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
+#endif
   return TCL_OK;
 }
 
index 145664044da2cd67842ff8a06a74be7d5e8a4f97..782e0163c61d789c5aff243305615a73a6100dac 100644 (file)
@@ -202,7 +202,7 @@ static int opcodeNoPush(u8 op){
     NOPUSH_MASK_6 + (NOPUSH_MASK_7<<16),
     NOPUSH_MASK_8 + (NOPUSH_MASK_9<<16)
   };
-  assert( op>=0 && op<32*5 );
+  assert( op<32*5 );
   return (masks[op>>5] & (1<<(op&0x1F)));
 }
 
@@ -967,7 +967,7 @@ static int vdbeCommit(sqlite3 *db){
     int needSync = 0;
     char *zMaster = 0;   /* File-name for the master journal */
     char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
-    OsFile master;
+    OsFile *master = 0;
 
     /* Select a master journal file name */
     do {
@@ -981,7 +981,6 @@ static int vdbeCommit(sqlite3 *db){
     }while( sqlite3Io.xFileExists(zMaster) );
 
     /* Open the master journal. */
-    memset(&master, 0, sizeof(master));
     rc = sqlite3Io.xOpenExclusive(zMaster, &master, 0);
     if( rc!=SQLITE_OK ){
       sqliteFree(zMaster);
@@ -1003,7 +1002,7 @@ static int vdbeCommit(sqlite3 *db){
         if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){
           needSync = 1;
         }
-        rc = sqlite3Io.xWrite(&master, zFile, strlen(zFile)+1);
+        rc = sqlite3Io.xWrite(master, zFile, strlen(zFile)+1);
         if( rc!=SQLITE_OK ){
           sqlite3Io.xClose(&master);
           sqlite3Io.xDelete(zMaster);
@@ -1018,9 +1017,9 @@ static int vdbeCommit(sqlite3 *db){
     ** the master journal file is store in so that it gets synced too.
     */
     zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);
-    rc = sqlite3Io.xOpenDirectory(zMainFile, &master);
+    rc = sqlite3Io.xOpenDirectory(zMainFile, master);
     if( rc!=SQLITE_OK ||
-          (needSync && (rc=sqlite3Io.xSync(&master,0))!=SQLITE_OK) ){
+          (needSync && (rc=sqlite3Io.xSync(master,0))!=SQLITE_OK) ){
       sqlite3Io.xClose(&master);
       sqlite3Io.xDelete(zMaster);
       sqliteFree(zMaster);
index b96d86d12bf0142156a55dca50aad70ff580b028..4799ce1e518abecba4b325d98ada9ccab4fa047d 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this script is testing the ATTACH and DETACH commands
 # and related functionality.
 #
-# $Id: attach.test,v 1.40 2005/03/29 03:11:00 danielk1977 Exp $
+# $Id: attach.test,v 1.41 2005/11/29 03:13:22 drh Exp $
 #
 
 set testdir [file dirname $argv0]
@@ -742,5 +742,4 @@ db close
 file delete -force test2.db
 file delete -force no-such-file
 
-
 finish_test