From: drh Date: Wed, 8 Jan 2003 13:02:52 +0000 (+0000) Subject: Port ot MacOS Classic. Ticket #218. (CVS 820) X-Git-Tag: version-3.6.10~5253 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=820f3812d88d964358267bbac52fde1806363326;p=thirdparty%2Fsqlite.git Port ot MacOS Classic. Ticket #218. (CVS 820) FossilOrigin-Name: 13f82d67f60ae869d5bf2e31d9357a860aa62bad --- diff --git a/manifest b/manifest index 739cf123ea..9ca81c610b 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 83e96ee63d..9dfcef19ab 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2f89e9e6963cb715f3671f1fdbf4c966aadff6c8 \ No newline at end of file +13f82d67f60ae869d5bf2e31d9357a860aa62bad \ No newline at end of file diff --git a/src/os.c b/src/os.c index ab0b75038b..a44e6c3a68 100644 --- a/src/os.c +++ b/src/os.c @@ -37,6 +37,16 @@ # include #endif +#if OS_MAC +# include +# include +# include +# include +# include +# include +# include +#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(¶ms, 0, sizeof(ParamBlockRec)); + params.ioParam.ioRefNum = id->refNum; + if( PBFlushFileSync(¶ms) != 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(¶ms, 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(¶ms))!=noErr ){ + UInt32 finalTicks; + Delay(1, &finalTicks); /* 1/60 sec */ + } + if( res == noErr ){ + params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; + params.ioParam.ioReqCount = N_LOCKBYTE; + PBUnlockRangeSync(¶ms); + params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk; + params.ioParam.ioReqCount = 1; + res = PBLockRangeSync(¶ms); + params.ioParam.ioPosOffset = FIRST_LOCKBYTE; + params.ioParam.ioReqCount = 1; + PBUnlockRangeSync(¶ms); + } + 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(¶ms, 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(¶ms))!=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(¶ms)==noErr ){ + params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; + params.ioParam.ioReqCount = N_LOCKBYTE; + res = PBLockRangeSync(¶ms); + }else{ + res = afpRangeNotLocked; + } + params.ioParam.ioPosOffset = FIRST_LOCKBYTE; + params.ioParam.ioReqCount = 1; + PBUnlockRangeSync(¶ms); + } + 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(¶ms, 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(¶ms); + rc = SQLITE_OK; + id->locked = 0; + }else{ + params.ioParam.ioPosOffset = FIRST_LOCKBYTE+id->locked; + params.ioParam.ioReqCount = 1; + PBUnlockRangeSync(¶ms); + 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 +# 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 } + diff --git a/src/os.h b/src/os.h index a42e42758b..8491d90dfe 100644 --- 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 @@ -37,22 +39,50 @@ #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 @@ -95,6 +125,26 @@ # define SQLITE_MIN_SLEEP_MS 1 #endif +#if OS_MAC +# include +# include + 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*); diff --git a/src/shell.c b/src/shell.c index f99b56551d..91021bea19 100644 --- a/src/shell.c +++ b/src/shell.c @@ -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 #include @@ -20,13 +20,22 @@ #include "sqlite.h" #include -#if !defined(_WIN32) && !defined(WIN32) +#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) # include # include # include # include #endif +#ifdef __MACOS__ +# include +# include +# include +# include +# include +# include +#endif + #if defined(HAVE_READLINE) && HAVE_READLINE==1 # include # include @@ -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);