]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Port ot MacOS Classic. Ticket #218. (CVS 820)
authordrh <drh@noemail.net>
Wed, 8 Jan 2003 13:02:52 +0000 (13:02 +0000)
committerdrh <drh@noemail.net>
Wed, 8 Jan 2003 13:02:52 +0000 (13:02 +0000)
FossilOrigin-Name: 13f82d67f60ae869d5bf2e31d9357a860aa62bad

manifest
manifest.uuid
src/os.c
src/os.h
src/shell.c

index 739cf123ea16c8eb13c2930cbf213d01ebb7c539..9ca81c610b117321ee2acd1e6400c2f23870e846 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Avoid\scalling\struncate()\sand\sstat()\son\sthe\scheckpoint\sjournal\sto\simprove\sthe\nspeed\sof\sa\slarge\snumber\sof\sUPDATEs\swithin\sa\stransaction.\s(CVS\s819)
-D 2003-01-07T14:46:08
+C Port\sot\sMacOS\sClassic.\s\sTicket\s#218.\s(CVS\s820)
+D 2003-01-08T13:02:52
 F Makefile.in 868c17a1ae1c07603d491274cc8f86c04acf2a1e
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -30,15 +30,15 @@ F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
 F src/insert.c 764300a0bd8074a2174946c0bf8a550bd833397a
 F src/main.c cee05c2ba23b5e78f9671f319dbd68e2130e0f68
 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
-F src/os.c 740022806209e44cab0abddfb1fee65c77702e21
-F src/os.h 09fd96b4d733aae2f3b98b2ae9ceea40b8fd780d
+F src/os.c 28447687e7914306650f72058f62f7162faeef1f
+F src/os.h afa3e096213bad86845f8bdca81a9e917505e401
 F src/pager.c 20ea93000c5580f1ee4fa56dcc3d3589da35c70f
 F src/pager.h 540833e8cb826b80ce2e39aa917deee5e12db626
 F src/parse.y 427a17888c117cc9cc35311eda0603d55437f02b
 F src/printf.c 5c50fc1da75c8f5bf432b1ad17d91d6653acd167
 F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
 F src/select.c cc8640e5d4e3ec1a8de58fde6b2fdd6f846b7263
-F src/shell.c 53185af128613a2bac79d50128f4c17794f0f992
+F src/shell.c c9946847b81b8b7f32ad195498dafbc623c6874f
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
 F src/sqlite.h.in 98b1574b2362abe02c4a4c73b9dbf99bcd713ab3
 F src/sqliteInt.h 65dfa06bc49ebff83361bfb259ee4c675534808a
@@ -152,7 +152,7 @@ F www/speed.tcl a20a792738475b68756ea7a19321600f23d1d803
 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 46d8f5e377bf790c18a7acdd1f3bc20b538d69eb
-R 137ba05a6f797353869b0a39dc185e2c
+P 2f89e9e6963cb715f3671f1fdbf4c966aadff6c8
+R 4381eebdc5a5f587e474f3576a177725
 U drh
-Z e1ac466b5c8e5a1eafdd3945463b4e3b
+Z e0436c44fc862536b296cf3de00d786b
index 83e96ee63d05770c26e8df5855ad4a952d40a18a..9dfcef19ab1e6943a270b64c7fbe011acbbd0077 100644 (file)
@@ -1 +1 @@
-2f89e9e6963cb715f3671f1fdbf4c966aadff6c8
\ No newline at end of file
+13f82d67f60ae869d5bf2e31d9357a860aa62bad
\ No newline at end of file
index ab0b75038bbf132b63f7e39cc7af468e48aab550..a44e6c3a68c05d690902146f67a3273a9c971cbe 100644 (file)
--- a/src/os.c
+++ b/src/os.c
 # include <winbase.h>
 #endif
 
+#if OS_MAC
+# include <extras.h>
+# include <path2fss.h>
+# include <TextUtils.h>
+# include <FinderRegistry.h>
+# include <Folders.h>
+# include <Timer.h>
+# include <OSUtils.h>
+#endif
+
 /*
 ** Macros for performance tracing.  Normally turned off
 */
@@ -208,6 +218,9 @@ int sqliteOsDelete(const char *zFilename){
 #endif
 #if OS_WIN
   DeleteFile(zFilename);
+#endif
+#if OS_MAC
+  unlink(zFilename);
 #endif
   return SQLITE_OK;
 }
@@ -222,6 +235,9 @@ int sqliteOsFileExists(const char *zFilename){
 #if OS_WIN
   return GetFileAttributes(zFilename) != 0xffffffff;
 #endif
+#if OS_MAC
+  return access(zFilename, 0)==0;
+#endif
 }
 
 
@@ -294,6 +310,55 @@ int sqliteOsOpenReadWrite(
   id->locked = 0;
   return SQLITE_OK;
 #endif
+#if OS_MAC
+  FSSpec fsSpec;
+# ifdef _LARGE_FILE
+  HFSUniStr255 dfName;
+  FSRef fsRef;
+  if( __path2fss(zFilename, &fsSpec) != noErr ){
+    if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
+      return SQLITE_CANTOPEN;
+  }
+  if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
+    return SQLITE_CANTOPEN;
+  FSGetDataForkName(&dfName);
+  if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
+                 fsRdWrShPerm, &(id->refNum)) != noErr ){
+    if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
+                   fsRdWrPerm, &(id->refNum)) != noErr ){
+      if (FSOpenFork(&fsRef, dfName.length, dfName.unicode,
+                   fsRdPerm, &(id->refNum)) != noErr )
+        return SQLITE_CANTOPEN;
+      else
+        *pReadonly = 1;
+    } else
+      *pReadonly = 0;
+  } else
+    *pReadonly = 0;
+# else
+  __path2fss(zFilename, &fsSpec);
+  if( !sqliteOsFileExists(zFilename) ){
+    if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
+      return SQLITE_CANTOPEN;
+  }
+  if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNum)) != noErr ){
+    if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ){
+      if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr )
+        return SQLITE_CANTOPEN;
+      else
+        *pReadonly = 1;
+    } else
+      *pReadonly = 0;
+  } else
+    *pReadonly = 0;
+# endif
+  if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){
+    id->refNumRF = -1;
+  }
+  id->locked = 0;
+  id->delOnClose = 0;
+  return SQLITE_OK;
+#endif
 }
 
 
@@ -359,6 +424,34 @@ int sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
   id->locked = 0;
   return SQLITE_OK;
 #endif
+#if OS_MAC
+  FSSpec fsSpec;
+# ifdef _LARGE_FILE
+  HFSUniStr255 dfName;
+  FSRef fsRef;
+  __path2fss(zFilename, &fsSpec);
+  if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
+    return SQLITE_CANTOPEN;
+  if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
+    return SQLITE_CANTOPEN;
+  FSGetDataForkName(&dfName);
+  if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
+                 fsRdWrPerm, &(id->refNum)) != noErr )
+    return SQLITE_CANTOPEN;
+# else
+  __path2fss(zFilename, &fsSpec);
+  if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
+    return SQLITE_CANTOPEN;
+  if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr )
+    return SQLITE_CANTOPEN;
+# endif
+  id->refNumRF = -1;
+  id->locked = 0;
+  id->delOnClose = delFlag;
+  if (delFlag)
+    id->pathToDel = sqliteOsFullPathname(zFilename);
+  return SQLITE_OK;
+#endif
 }
 
 /*
@@ -401,6 +494,31 @@ int sqliteOsOpenReadOnly(const char *zFilename, OsFile *id){
   id->locked = 0;
   return SQLITE_OK;
 #endif
+#if OS_MAC
+  FSSpec fsSpec;
+# ifdef _LARGE_FILE
+  HFSUniStr255 dfName;
+  FSRef fsRef;
+  if( __path2fss(zFilename, &fsSpec) != noErr )
+    return SQLITE_CANTOPEN;
+  if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
+    return SQLITE_CANTOPEN;
+  FSGetDataForkName(&dfName);
+  if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
+                 fsRdPerm, &(id->refNum)) != noErr )
+    return SQLITE_CANTOPEN;
+# else
+  __path2fss(zFilename, &fsSpec);
+  if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr )
+    return SQLITE_CANTOPEN;
+# endif
+  if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){
+    id->refNumRF = -1;
+  }
+  id->locked = 0;
+  id->delOnClose = 0;
+  return SQLITE_OK;
+#endif
 }
 
 /*
@@ -430,7 +548,7 @@ int sqliteOsTempFileName(char *zBuf){
     break;
   }
   do{
-    sprintf(zBuf, "%s/sqlite_", zDir);
+    sprintf(zBuf, "%s/"TEMP_FILE_PREFIX, zDir);
     j = strlen(zBuf);
     for(i=0; i<15; i++){
       int n = sqliteRandomByte() % (sizeof(zChars)-1);
@@ -450,7 +568,50 @@ int sqliteOsTempFileName(char *zBuf){
   for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
   zTempPath[i] = 0;
   for(;;){
-    sprintf(zBuf, "%s\\sqlite_", zTempPath);
+    sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath);
+    j = strlen(zBuf);
+    for(i=0; i<15; i++){
+      int n = sqliteRandomByte() % sizeof(zChars);
+      zBuf[j++] = zChars[n];
+    }
+    zBuf[j] = 0;
+    if( !sqliteOsFileExists(zBuf) ) break;
+  }
+#endif
+#if OS_MAC
+  static char zChars[] =
+    "abcdefghijklmnopqrstuvwxyz"
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "0123456789";
+  int i, j;
+  char zTempPath[SQLITE_TEMPNAME_SIZE];
+  char zdirName[32];
+  CInfoPBRec infoRec;
+  Str31 dirName;
+  memset(&infoRec, 0, sizeof(infoRec));
+  memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE);
+  if( FindFolder(kOnSystemDisk, kTemporaryFolderType,  kCreateFolder,
+       &(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){
+    infoRec.dirInfo.ioNamePtr = dirName;
+    do{
+      infoRec.dirInfo.ioFDirIndex = -1;
+      infoRec.dirInfo.ioDrDirID = infoRec.dirInfo.ioDrParID;
+      if( PBGetCatInfoSync(&infoRec) == noErr ){
+        CopyPascalStringToC(dirName, zdirName);
+        i = strlen(zdirName);
+        memmove(&(zTempPath[i+1]), zTempPath, strlen(zTempPath));
+        strcpy(zTempPath, zdirName);
+        zTempPath[i] = ':';
+      }else{
+        *zTempPath = 0;
+        break;
+      }
+    } while( infoRec.dirInfo.ioDrDirID != fsRtDirID );
+  }
+  if( *zTempPath == 0 )
+    getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24);
+  for(;;){
+    sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zTempPath);
     j = strlen(zBuf);
     for(i=0; i<15; i++){
       int n = sqliteRandomByte() % sizeof(zChars);
@@ -479,6 +640,19 @@ int sqliteOsClose(OsFile *id){
   CloseHandle(id->h);
   return SQLITE_OK;
 #endif
+#if OS_MAC
+  if( id->refNumRF!=-1 )
+    FSClose(id->refNumRF);
+# ifdef _LARGE_FILE
+  FSCloseFork(id->refNum);
+# else
+  FSClose(id->refNum);
+# endif
+  if( id->delOnClose ){
+    unlink(id->pathToDel);
+    sqliteFree(id->pathToDel);
+  }
+#endif
 }
 
 /*
@@ -512,6 +686,22 @@ int sqliteOsRead(OsFile *id, void *pBuf, int amt){
     return SQLITE_IOERR;
   }
 #endif
+#if OS_MAC
+  int got;
+  SimulateIOError(SQLITE_IOERR);
+  TRACE2("READ %d\n", last_page);
+# ifdef _LARGE_FILE
+  FSReadFork(id->refNum, fsAtMark, 0, (ByteCount)amt, pBuf, (ByteCount*)&got);
+# else
+  got = amt;
+  FSRead(id->refNum, &got, pBuf);
+# endif
+  if( got==amt ){
+    return SQLITE_OK;
+  }else{
+    return SQLITE_IOERR;
+  }
+#endif
 }
 
 /*
@@ -546,6 +736,29 @@ int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){
   }
   return SQLITE_OK;
 #endif
+#if OS_MAC
+  OSErr oserr;
+  int wrote = 0;
+  SimulateIOError(SQLITE_IOERR);
+  TRACE2("WRITE %d\n", last_page);
+  while( amt>0 ){
+# ifdef _LARGE_FILE
+    oserr = FSWriteFork(id->refNum, fsAtMark, 0,
+                        (ByteCount)amt, pBuf, (ByteCount*)&wrote);
+# else
+    wrote = amt;
+    oserr = FSWrite(id->refNum, &wrote, pBuf);
+# endif
+    if( wrote == 0 || oserr != noErr)
+      break;
+    amt -= wrote;
+    pBuf = &((char*)pBuf)[wrote];
+  }
+  if( oserr != noErr || amt>wrote ){
+    return SQLITE_FULL;
+  }
+  return SQLITE_OK;
+#endif
 }
 
 /*
@@ -567,15 +780,37 @@ int sqliteOsSeek(OsFile *id, off_t offset){
   }
   return SQLITE_OK;
 #endif
+#if OS_MAC
+  {
+    off_t curSize;
+    if( sqliteOsFileSize(id, &curSize) != SQLITE_OK ){
+      return SQLITE_IOERR;
+    }
+    if( offset >= curSize ){
+      if( sqliteOsTruncate(id, offset+1) != SQLITE_OK ){
+        return SQLITE_IOERR;
+      }
+    }
+# ifdef _LARGE_FILE
+    if( FSSetForkPosition(id->refNum, fsFromStart, offset) != noErr ){
+# else
+    if( SetFPos(id->refNum, fsFromStart, offset) != noErr ){
+# endif
+      return SQLITE_IOERR;
+    }else{
+      return SQLITE_OK;
+    }
+  }
+#endif
 }
 
 /*
 ** Make sure all writes to a particular file are committed to disk.
 */
 int sqliteOsSync(OsFile *id){
+#if OS_UNIX
   SimulateIOError(SQLITE_IOERR);
   TRACE2("SYNC    %-3d\n", id->fd);
-#if OS_UNIX
   if( fsync(id->fd) ){
     return SQLITE_IOERR;
   }else{
@@ -589,6 +824,20 @@ int sqliteOsSync(OsFile *id){
     return SQLITE_IOERR;
   }
 #endif
+#if OS_MAC
+# ifdef _LARGE_FILE
+  if( FSFlushFork(id->refNum) != noErr ){
+# else
+  ParamBlockRec params;
+  memset(&params, 0, sizeof(ParamBlockRec));
+  params.ioParam.ioRefNum = id->refNum;
+  if( PBFlushFileSync(&params) != noErr ){
+# endif
+    return SQLITE_IOERR;
+  }else{
+    return SQLITE_OK;
+  }
+#endif
 }
 
 /*
@@ -607,6 +856,17 @@ int sqliteOsTruncate(OsFile *id, off_t nByte){
   }
   return SQLITE_OK;
 #endif
+#if OS_MAC
+# ifdef _LARGE_FILE
+  if( FSSetForkSize(id->refNum, fsFromStart, nByte) != noErr){
+# else
+  if( SetEOF(id->refNum, nByte) != noErr ){
+# endif
+    return SQLITE_IOERR;
+  }else{
+    return SQLITE_OK;
+  }
+#endif
 }
 
 /*
@@ -629,6 +889,17 @@ int sqliteOsFileSize(OsFile *id, off_t *pSize){
   *pSize = (((off_t)upperBits)<<32) + lowerBits;
   return SQLITE_OK;
 #endif
+#if OS_MAC
+# ifdef _LARGE_FILE
+  if( FSGetForkSize(id->refNum, pSize) != noErr){
+# else
+  if( GetEOF(id->refNum, pSize) != noErr ){
+# endif
+    return SQLITE_IOERR;
+  }else{
+    return SQLITE_OK;
+  }
+#endif
 }
 
 #if OS_WIN
@@ -649,7 +920,7 @@ int isNT(void){
 #endif
 
 /*
-** Windows file locking notes:
+** Windows file locking notes:  [the same/equivalent applies to MacOS]
 **
 ** We cannot use LockFileEx() or UnlockFileEx() because those functions
 ** are not available under Win95/98/ME.  So we use only LockFile() and
@@ -677,6 +948,8 @@ int isNT(void){
 ** another process jumping into the middle and messing us up.  The same
 ** argument applies to sqliteOsWriteLock().
 **
+** Note: On MacOS we use the resource fork for locking.
+**
 ** The following #defines specify the range of bytes used for locking.
 ** N_LOCKBYTE is the number of bytes available for doing the locking.
 ** The first byte used to hold the lock while the lock is changing does
@@ -684,7 +957,11 @@ int isNT(void){
 ** the first byte in the range of bytes used for locking.
 */
 #define N_LOCKBYTE       10239
-#define FIRST_LOCKBYTE   (0xffffffff - N_LOCKBYTE)
+#if OS_MAC
+# define FIRST_LOCKBYTE   (0x000fffff - N_LOCKBYTE)
+#else
+# define FIRST_LOCKBYTE   (0xffffffff - N_LOCKBYTE)
+#endif
 
 /*
 ** Change the status of the lock on the file "id" to be a readlock.
@@ -751,6 +1028,44 @@ int sqliteOsReadLock(OsFile *id){
   }
   return rc;
 #endif
+#if OS_MAC
+  int rc;
+  if( id->locked>0 || id->refNumRF == -1 ){
+    rc = SQLITE_OK;
+  }else{
+    int lk = (sqliteRandomInteger() & 0x7ffffff)%N_LOCKBYTE+1;
+    OSErr res;
+    int cnt = 5;
+    ParamBlockRec params;
+    memset(&params, 0, sizeof(params));
+    params.ioParam.ioRefNum = id->refNumRF;
+    params.ioParam.ioPosMode = fsFromStart;
+    params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
+    params.ioParam.ioReqCount = 1;
+    while( cnt-->0 && (res = PBLockRangeSync(&params))!=noErr ){
+      UInt32 finalTicks;
+      Delay(1, &finalTicks); /* 1/60 sec */
+    }
+    if( res == noErr ){
+      params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
+      params.ioParam.ioReqCount = N_LOCKBYTE;
+      PBUnlockRangeSync(&params);
+      params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk;
+      params.ioParam.ioReqCount = 1;
+      res = PBLockRangeSync(&params);
+      params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
+      params.ioParam.ioReqCount = 1;
+      PBUnlockRangeSync(&params);
+    }
+    if( res == noErr ){
+      id->locked = lk;
+      rc = SQLITE_OK;
+    }else{
+      rc = SQLITE_BUSY;
+    }
+  }
+  return rc;
+#endif
 }
 
 /*
@@ -812,6 +1127,47 @@ int sqliteOsWriteLock(OsFile *id){
   }
   return rc;
 #endif
+#if OS_MAC
+  int rc;
+  if( id->locked<0 || id->refNumRF == -1 ){
+    rc = SQLITE_OK;
+  }else{
+    OSErr res;
+    int cnt = 5;
+    ParamBlockRec params;
+    memset(&params, 0, sizeof(params));
+    params.ioParam.ioRefNum = id->refNumRF;
+    params.ioParam.ioPosMode = fsFromStart;
+    params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
+    params.ioParam.ioReqCount = 1;
+    while( cnt-->0 && (res = PBLockRangeSync(&params))!=noErr ){
+      UInt32 finalTicks;
+      Delay(1, &finalTicks); /* 1/60 sec */
+    }
+    if( res == noErr ){
+      params.ioParam.ioPosOffset = FIRST_LOCKBYTE + id->locked;
+      params.ioParam.ioReqCount = 1;
+      if( id->locked==0 
+            || PBUnlockRangeSync(&params)==noErr ){
+        params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
+        params.ioParam.ioReqCount = N_LOCKBYTE;
+        res = PBLockRangeSync(&params);
+      }else{
+        res = afpRangeNotLocked;
+      }
+      params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
+      params.ioParam.ioReqCount = 1;
+      PBUnlockRangeSync(&params);
+    }
+    if( res == noErr ){
+      id->locked = -1;
+      rc = SQLITE_OK;
+    }else{
+      rc = SQLITE_BUSY;
+    }
+  }
+  return rc;
+#endif
 }
 
 /*
@@ -863,6 +1219,29 @@ int sqliteOsUnlock(OsFile *id){
   }
   return rc;
 #endif
+#if OS_MAC
+  int rc;
+  ParamBlockRec params;
+  memset(&params, 0, sizeof(params));
+  params.ioParam.ioRefNum = id->refNumRF;
+  params.ioParam.ioPosMode = fsFromStart;
+  if( id->locked==0 || id->refNumRF == -1 ){
+    rc = SQLITE_OK;
+  }else if( id->locked<0 ){
+    params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
+    params.ioParam.ioReqCount = N_LOCKBYTE;
+    PBUnlockRangeSync(&params);
+    rc = SQLITE_OK;
+    id->locked = 0;
+  }else{
+    params.ioParam.ioPosOffset = FIRST_LOCKBYTE+id->locked;
+    params.ioParam.ioReqCount = 1;
+    PBUnlockRangeSync(&params);
+    rc = SQLITE_OK;
+    id->locked = 0;
+  }
+  return rc;
+#endif
 }
 
 /*
@@ -885,6 +1264,12 @@ int sqliteOsRandomSeed(char *zBuf){
 #endif
 #if OS_WIN && !defined(SQLITE_TEST)
   GetSystemTime((LPSYSTEMTIME)zBuf);
+#endif
+#if OS_MAC
+  int pid;
+  Microseconds((UnsignedWide*)zBuf);
+  pid = getpid();
+  memcpy(&zBuf[sizeof(UnsignedWide)], &pid, sizeof(pid));
 #endif
   return SQLITE_OK;
 }
@@ -906,6 +1291,12 @@ int sqliteOsSleep(int ms){
   Sleep(ms);
   return ms;
 #endif
+#if OS_MAC
+  UInt32 finalTicks;
+  UInt32 ticks = (((UInt32)ms+16)*3)/50;  /* 1/60 sec per tick */
+  Delay(ticks, &finalTicks);
+  return (int)((ticks*50)/3);
+#endif
 }
 
 /*
@@ -921,6 +1312,10 @@ int sqliteOsSleep(int ms){
 #if OS_WIN && defined(THREADSAFE) && THREADSAFE
 # define SQLITE_W32_THREADS 1
 #endif
+#if OS_MAC && defined(THREADSAFE) && THREADSAFE
+# include <Multiprocessing.h>
+# define SQLITE_MACOS_MULTITASKING 1
+#endif
 
 /*
 ** Static variables used for thread synchronization
@@ -932,6 +1327,9 @@ static int inMutex = 0;
 #ifdef SQLITE_W32_THREADS
   static CRITICAL_SECTION cs;
 #endif
+#ifdef SQLITE_MACOS_MULTITASKING
+  static MPCriticalRegionID criticalRegion;
+#endif
 
 /*
 ** The following pair of routine implement mutual exclusion for
@@ -957,6 +1355,19 @@ void sqliteOsEnterMutex(){
     }
   }
   EnterCriticalSection(&cs);
+#endif
+#ifdef SQLITE_MACOS_MULTITASKING
+  static volatile int notInit = 1;
+  if( notInit ){
+    if( notInit == 2 ) /* as close as you can get to thread safe init */
+      MPYield();
+    else{
+      notInit = 2;
+      MPCreateCriticalRegion(&criticalRegion);
+      notInit = 0;
+    }
+  }
+  MPEnterCriticalRegion(criticalRegion, kDurationForever);
 #endif
   assert( !inMutex );
   inMutex = 1;
@@ -970,6 +1381,9 @@ void sqliteOsLeaveMutex(){
 #ifdef SQLITE_W32_THREADS
   LeaveCriticalSection(&cs);
 #endif
+#ifdef SQLITE_MACOS_MULTITASKING
+  MPExitCriticalRegion(criticalRegion);
+#endif
 }
 
 /*
@@ -993,10 +1407,26 @@ char *sqliteOsFullPathname(const char *zRelative){
   char *zNotUsed;
   char *zFull;
   int nByte;
-  nByte = GetFullPathName(zRelative, 0, 0, &zNotUsed);
+  nByte = GetFullPathName(zRelative, 0, 0, &zNotUsed) + 1;
   zFull = sqliteMalloc( nByte );
   if( zFull==0 ) return 0;
   GetFullPathName(zRelative, nByte, zFull, &zNotUsed);
   return zFull;
 #endif
+#if OS_MAC
+  char *zFull = 0;
+  if( zRelative[0]==':' ){
+    char zBuf[_MAX_PATH+1];
+    sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), &(zRelative[1]), 0);
+  }else{
+    if( strchr(zRelative, ':') ){
+      sqliteSetString(&zFull, zRelative, 0);
+    }else{
+    char zBuf[_MAX_PATH+1];
+      sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), zRelative, 0);
+    }
+  }
+  return zFull;
+#endif
 }
+
index a42e42758b37db1c495f7e2a5a787755baaa2688..8491d90dfe524602d111dcd7f0d014e133fe6b75 100644 (file)
--- a/src/os.h
+++ b/src/os.h
@@ -29,6 +29,8 @@
 ** 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
 #endif
 
 /*
-** Figure out if we are dealing with Unix or Windows.
+** Temporary files are named starting with this prefix followed by 16 random
+** alphanumeric characters, and no file extension. They are stored in the
+** OS's standard temporary file directory, and are deleted prior to exit.
+** If sqlite is being embedded in another program, you may wish to change the
+** prefix to reflect your program's name, so that if your program exits
+** prematurely, old temporary files can be easily identified. This can be done
+** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line.
+*/
+#ifndef TEMP_FILE_PREFIX
+# define TEMP_FILE_PREFIX "sqlite_"
+#endif
+
+/*
+** Figure out if we are dealing with Unix, Windows or MacOS.
+**
+** N.B. MacOS means Mac Classic (or Carbon). Treat Darwin (OS X) as Unix.
+**      The MacOS build is designed to use CodeWarrior (tested with v8)
 */
 #ifndef OS_UNIX
 # ifndef OS_WIN
-#  if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
-#    define OS_WIN 1
-#    define OS_UNIX 0
+#  ifndef OS_MAC
+#    if defined(__MACOS__)
+#      define OS_MAC 1
+#      define OS_WIN 0
+#      define OS_UNIX 0
+#    elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
+#      define OS_MAC 0
+#      define OS_WIN 1
+#      define OS_UNIX 0
+#    else
+#      define OS_MAC 0
+#      define OS_WIN 0
+#      define OS_UNIX 1
+#    endif
 #  else
 #    define OS_WIN 0
-#    define OS_UNIX 1
+#    define OS_UNIX 0
 #  endif
 # else
+#  define OS_MAC 0
 #  define OS_UNIX 0
 # endif
-#endif
-#ifndef OS_WIN
+#else
+# define OS_MAC 0
 # define OS_WIN 0
 #endif
 
 # define SQLITE_MIN_SLEEP_MS 1
 #endif
 
+#if OS_MAC
+# include <unistd.h>
+# include <Files.h>
+  typedef struct OsFile OsFile;
+  struct OsFile {
+    SInt16 refNum;           /* Data fork/file reference number */
+    SInt16 refNumRF;         /* Resource fork reference number (for locking) */
+    int locked;              /* 0: unlocked, <0: write lock, >0: read lock */
+    int delOnClose;          /* True if file is to be deleted on close */
+    char *pathToDel;         /* Name of file to delete on close */
+  };
+# ifdef _LARGE_FILE
+    typedef SInt64 off_t;
+# else
+    typedef SInt32 off_t;
+# endif
+# define SQLITE_TEMPNAME_SIZE _MAX_PATH
+# define SQLITE_MIN_SLEEP_MS 17
+#endif
+
 int sqliteOsDelete(const char*);
 int sqliteOsFileExists(const char*);
 int sqliteOsOpenReadWrite(const char*, OsFile*, int*);
index f99b56551dc9080570edc696cb0ea36d51bc6258..91021bea199cd43dbff5120ea17996358539adeb 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains code to implement the "sqlite" command line
 ** utility for accessing SQLite databases.
 **
-** $Id: shell.c,v 1.63 2002/11/11 13:56:47 drh Exp $
+** $Id: shell.c,v 1.64 2003/01/08 13:02:53 drh Exp $
 */
 #include <stdlib.h>
 #include <string.h>
 #include "sqlite.h"
 #include <ctype.h>
 
-#if !defined(_WIN32) && !defined(WIN32)
+#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
 # include <signal.h>
 # include <pwd.h>
 # include <unistd.h>
 # include <sys/types.h>
 #endif
 
+#ifdef __MACOS__
+# include <console.h>
+# include <signal.h>
+# include <unistd.h>
+# include <extras.h>
+# include <Files.h>
+# include <Folders.h>
+#endif
+
 #if defined(HAVE_READLINE) && HAVE_READLINE==1
 # include <readline/readline.h>
 # include <readline/history.h>
@@ -981,7 +990,7 @@ static void process_input(struct callback_data *p, FILE *in){
 static char *find_home_dir(void){
   char *home_dir = NULL;
 
-#if !defined(_WIN32) && !defined(WIN32)
+#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
   struct passwd *pwent;
   uid_t uid = getuid();
   if( (pwent=getpwuid(uid)) != NULL) {
@@ -989,6 +998,11 @@ static char *find_home_dir(void){
   }
 #endif
 
+#ifdef __MACOS__
+  char home_path[_MAX_PATH+1];
+  home_dir = getcwd(home_path, _MAX_PATH);
+#endif
+
   if (!home_dir) {
     home_dir = getenv("HOME");
     if (!home_dir) {
@@ -1061,6 +1075,12 @@ int main(int argc, char **argv){
   int origArgc = argc;
   char **origArgv = argv;
 
+#ifdef __MACOS__
+  argc = ccommand(&argv);
+  origArgc = argc;
+  origArgv = argv;
+#endif
+
   Argv0 = argv[0];
   main_init(&data);
   process_sqliterc(&data,NULL);