00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "os.h"
00018 #include "sqliteInt.h"
00019
00020 #if OS_UNIX
00021 # include <time.h>
00022 # include <errno.h>
00023 # include <unistd.h>
00024 # ifndef O_LARGEFILE
00025 # define O_LARGEFILE 0
00026 # endif
00027 # ifdef SQLITE_DISABLE_LFS
00028 # undef O_LARGEFILE
00029 # define O_LARGEFILE 0
00030 # endif
00031 # ifndef O_NOFOLLOW
00032 # define O_NOFOLLOW 0
00033 # endif
00034 # ifndef O_BINARY
00035 # define O_BINARY 0
00036 # endif
00037 #endif
00038
00039
00040 #if OS_WIN
00041 # include <winbase.h>
00042 #endif
00043
00044 #if OS_MAC
00045 # include <extras.h>
00046 # include <path2fss.h>
00047 # include <TextUtils.h>
00048 # include <FinderRegistry.h>
00049 # include <Folders.h>
00050 # include <Timer.h>
00051 # include <OSUtils.h>
00052 #endif
00053
00054
00055
00056
00057
00058
00059
00060 #ifdef __DJGPP__
00061 # define fcntl(A,B,C) 0
00062 #endif
00063
00064
00065
00066
00067
00068
00069
00070 #if OS_UNIX && defined(THREADSAFE) && THREADSAFE
00071 # include <pthread.h>
00072 # define SQLITE_UNIX_THREADS 1
00073 #endif
00074 #if OS_WIN && defined(THREADSAFE) && THREADSAFE
00075 # define SQLITE_W32_THREADS 1
00076 #endif
00077 #if OS_MAC && defined(THREADSAFE) && THREADSAFE
00078 # include <Multiprocessing.h>
00079 # define SQLITE_MACOS_MULTITASKING 1
00080 #endif
00081
00082
00083
00084
00085 #if 0
00086 static int last_page = 0;
00087 __inline__ unsigned long long int hwtime(void){
00088 unsigned long long int x;
00089 __asm__("rdtsc\n\t"
00090 "mov %%edx, %%ecx\n\t"
00091 :"=A" (x));
00092 return x;
00093 }
00094 static unsigned long long int g_start;
00095 static unsigned int elapse;
00096 #define TIMER_START g_start=hwtime()
00097 #define TIMER_END elapse=hwtime()-g_start
00098 #define SEEK(X) last_page=(X)
00099 #define TRACE1(X) fprintf(stderr,X)
00100 #define TRACE2(X,Y) fprintf(stderr,X,Y)
00101 #define TRACE3(X,Y,Z) fprintf(stderr,X,Y,Z)
00102 #define TRACE4(X,Y,Z,A) fprintf(stderr,X,Y,Z,A)
00103 #define TRACE5(X,Y,Z,A,B) fprintf(stderr,X,Y,Z,A,B)
00104 #else
00105 #define TIMER_START
00106 #define TIMER_END
00107 #define SEEK(X)
00108 #define TRACE1(X)
00109 #define TRACE2(X,Y)
00110 #define TRACE3(X,Y,Z)
00111 #define TRACE4(X,Y,Z,A)
00112 #define TRACE5(X,Y,Z,A,B)
00113 #endif
00114
00115
00116 #if OS_UNIX
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 struct lockKey {
00210 dev_t dev;
00211 ino_t ino;
00212 pid_t pid;
00213 };
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 struct lockInfo {
00225 struct lockKey key;
00226 int cnt;
00227 int nRef;
00228 };
00229
00230
00231
00232
00233
00234
00235 struct openKey {
00236 dev_t dev;
00237 ino_t ino;
00238 };
00239
00240
00241
00242
00243
00244
00245
00246
00247 struct openCnt {
00248 struct openKey key;
00249 int nRef;
00250 int nLock;
00251 int nPending;
00252 int *aPending;
00253 };
00254
00255
00256
00257
00258
00259 static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };
00260 static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };
00261
00262
00263
00264
00265 static void releaseLockInfo(struct lockInfo *pLock){
00266 pLock->nRef--;
00267 if( pLock->nRef==0 ){
00268 sqliteHashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0);
00269 sqliteFree(pLock);
00270 }
00271 }
00272
00273
00274
00275
00276 static void releaseOpenCnt(struct openCnt *pOpen){
00277 pOpen->nRef--;
00278 if( pOpen->nRef==0 ){
00279 sqliteHashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);
00280 sqliteFree(pOpen->aPending);
00281 sqliteFree(pOpen);
00282 }
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292 int findLockInfo(
00293 int fd,
00294 struct lockInfo **ppLock,
00295 struct openCnt **ppOpen
00296 ){
00297 int rc;
00298 struct lockKey key1;
00299 struct openKey key2;
00300 struct stat statbuf;
00301 struct lockInfo *pLock;
00302 struct openCnt *pOpen;
00303 rc = fstat(fd, &statbuf);
00304 if( rc!=0 ) return 1;
00305 memset(&key1, 0, sizeof(key1));
00306 key1.dev = statbuf.st_dev;
00307 key1.ino = statbuf.st_ino;
00308 key1.pid = getpid();
00309 memset(&key2, 0, sizeof(key2));
00310 key2.dev = statbuf.st_dev;
00311 key2.ino = statbuf.st_ino;
00312 pLock = (struct lockInfo*)sqliteHashFind(&lockHash, &key1, sizeof(key1));
00313 if( pLock==0 ){
00314 struct lockInfo *pOld;
00315 pLock = sqliteMallocRaw( sizeof(*pLock) );
00316 if( pLock==0 ) return 1;
00317 pLock->key = key1;
00318 pLock->nRef = 1;
00319 pLock->cnt = 0;
00320 pOld = sqliteHashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);
00321 if( pOld!=0 ){
00322 assert( pOld==pLock );
00323 sqliteFree(pLock);
00324 return 1;
00325 }
00326 }else{
00327 pLock->nRef++;
00328 }
00329 *ppLock = pLock;
00330 pOpen = (struct openCnt*)sqliteHashFind(&openHash, &key2, sizeof(key2));
00331 if( pOpen==0 ){
00332 struct openCnt *pOld;
00333 pOpen = sqliteMallocRaw( sizeof(*pOpen) );
00334 if( pOpen==0 ){
00335 releaseLockInfo(pLock);
00336 return 1;
00337 }
00338 pOpen->key = key2;
00339 pOpen->nRef = 1;
00340 pOpen->nLock = 0;
00341 pOpen->nPending = 0;
00342 pOpen->aPending = 0;
00343 pOld = sqliteHashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen);
00344 if( pOld!=0 ){
00345 assert( pOld==pOpen );
00346 sqliteFree(pOpen);
00347 releaseLockInfo(pLock);
00348 return 1;
00349 }
00350 }else{
00351 pOpen->nRef++;
00352 }
00353 *ppOpen = pOpen;
00354 return 0;
00355 }
00356
00357 #endif
00359
00360
00361
00362
00363
00364 #ifdef SQLITE_TEST
00365 int sqlite_io_error_pending = 0;
00366 #define SimulateIOError(A) \
00367 if( sqlite_io_error_pending ) \
00368 if( sqlite_io_error_pending-- == 1 ){ local_ioerr(); return A; }
00369 static void local_ioerr(){
00370 sqlite_io_error_pending = 0;
00371 }
00372 #else
00373 #define SimulateIOError(A)
00374 #endif
00375
00376
00377
00378
00379 #ifdef SQLITE_TEST
00380 int sqlite_open_file_count = 0;
00381 #define OpenCounter(X) sqlite_open_file_count+=(X)
00382 #else
00383 #define OpenCounter(X)
00384 #endif
00385
00386
00387
00388
00389
00390 int sqliteOsDelete(const char *zFilename){
00391 #if OS_UNIX
00392 unlink(zFilename);
00393 #endif
00394 #if OS_WIN
00395 DeleteFile(zFilename);
00396 #endif
00397 #if OS_MAC
00398 unlink(zFilename);
00399 #endif
00400 return SQLITE_OK;
00401 }
00402
00403
00404
00405
00406 int sqliteOsFileExists(const char *zFilename){
00407 #if OS_UNIX
00408 return access(zFilename, 0)==0;
00409 #endif
00410 #if OS_WIN
00411 return GetFileAttributes(zFilename) != 0xffffffff;
00412 #endif
00413 #if OS_MAC
00414 return access(zFilename, 0)==0;
00415 #endif
00416 }
00417
00418
00419 #if 0
00420
00421
00422
00423 int sqliteOsFileRename(const char *zOldName, const char *zNewName){
00424 #if OS_UNIX
00425 if( link(zOldName, zNewName) ){
00426 return SQLITE_ERROR;
00427 }
00428 unlink(zOldName);
00429 return SQLITE_OK;
00430 #endif
00431 #if OS_WIN
00432 if( !MoveFile(zOldName, zNewName) ){
00433 return SQLITE_ERROR;
00434 }
00435 return SQLITE_OK;
00436 #endif
00437 #if OS_MAC
00438
00439 return SQLITE_ERROR;
00440 #endif
00441 }
00442 #endif
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 int sqliteOsOpenReadWrite(
00458 const char *zFilename,
00459 OsFile *id,
00460 int *pReadonly
00461 ){
00462 #if OS_UNIX
00463 int rc;
00464 id->dirfd = -1;
00465 id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644);
00466 if( id->fd<0 ){
00467 #ifdef EISDIR
00468 if( errno==EISDIR ){
00469 return SQLITE_CANTOPEN;
00470 }
00471 #endif
00472 id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
00473 if( id->fd<0 ){
00474 return SQLITE_CANTOPEN;
00475 }
00476 *pReadonly = 1;
00477 }else{
00478 *pReadonly = 0;
00479 }
00480 sqliteOsEnterMutex();
00481 rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
00482 sqliteOsLeaveMutex();
00483 if( rc ){
00484 close(id->fd);
00485 return SQLITE_NOMEM;
00486 }
00487 id->locked = 0;
00488 TRACE3("OPEN %-3d %s\n", id->fd, zFilename);
00489 OpenCounter(+1);
00490 return SQLITE_OK;
00491 #endif
00492 #if OS_WIN
00493 HANDLE h = CreateFile(zFilename,
00494 GENERIC_READ | GENERIC_WRITE,
00495 FILE_SHARE_READ | FILE_SHARE_WRITE,
00496 NULL,
00497 OPEN_ALWAYS,
00498 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
00499 NULL
00500 );
00501 if( h==INVALID_HANDLE_VALUE ){
00502 h = CreateFile(zFilename,
00503 GENERIC_READ,
00504 FILE_SHARE_READ,
00505 NULL,
00506 OPEN_ALWAYS,
00507 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
00508 NULL
00509 );
00510 if( h==INVALID_HANDLE_VALUE ){
00511 return SQLITE_CANTOPEN;
00512 }
00513 *pReadonly = 1;
00514 }else{
00515 *pReadonly = 0;
00516 }
00517 id->h = h;
00518 id->locked = 0;
00519 OpenCounter(+1);
00520 return SQLITE_OK;
00521 #endif
00522 #if OS_MAC
00523 FSSpec fsSpec;
00524 # ifdef _LARGE_FILE
00525 HFSUniStr255 dfName;
00526 FSRef fsRef;
00527 if( __path2fss(zFilename, &fsSpec) != noErr ){
00528 if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
00529 return SQLITE_CANTOPEN;
00530 }
00531 if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
00532 return SQLITE_CANTOPEN;
00533 FSGetDataForkName(&dfName);
00534 if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
00535 fsRdWrShPerm, &(id->refNum)) != noErr ){
00536 if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
00537 fsRdWrPerm, &(id->refNum)) != noErr ){
00538 if (FSOpenFork(&fsRef, dfName.length, dfName.unicode,
00539 fsRdPerm, &(id->refNum)) != noErr )
00540 return SQLITE_CANTOPEN;
00541 else
00542 *pReadonly = 1;
00543 } else
00544 *pReadonly = 0;
00545 } else
00546 *pReadonly = 0;
00547 # else
00548 __path2fss(zFilename, &fsSpec);
00549 if( !sqliteOsFileExists(zFilename) ){
00550 if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
00551 return SQLITE_CANTOPEN;
00552 }
00553 if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNum)) != noErr ){
00554 if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ){
00555 if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr )
00556 return SQLITE_CANTOPEN;
00557 else
00558 *pReadonly = 1;
00559 } else
00560 *pReadonly = 0;
00561 } else
00562 *pReadonly = 0;
00563 # endif
00564 if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){
00565 id->refNumRF = -1;
00566 }
00567 id->locked = 0;
00568 id->delOnClose = 0;
00569 OpenCounter(+1);
00570 return SQLITE_OK;
00571 #endif
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 int sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
00590 #if OS_UNIX
00591 int rc;
00592 if( access(zFilename, 0)==0 ){
00593 return SQLITE_CANTOPEN;
00594 }
00595 id->dirfd = -1;
00596 id->fd = open(zFilename,
00597 O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600);
00598 if( id->fd<0 ){
00599 return SQLITE_CANTOPEN;
00600 }
00601 sqliteOsEnterMutex();
00602 rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
00603 sqliteOsLeaveMutex();
00604 if( rc ){
00605 close(id->fd);
00606 unlink(zFilename);
00607 return SQLITE_NOMEM;
00608 }
00609 id->locked = 0;
00610 if( delFlag ){
00611 unlink(zFilename);
00612 }
00613 TRACE3("OPEN-EX %-3d %s\n", id->fd, zFilename);
00614 OpenCounter(+1);
00615 return SQLITE_OK;
00616 #endif
00617 #if OS_WIN
00618 HANDLE h;
00619 int fileflags;
00620 if( delFlag ){
00621 fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
00622 | FILE_FLAG_DELETE_ON_CLOSE;
00623 }else{
00624 fileflags = FILE_FLAG_RANDOM_ACCESS;
00625 }
00626 h = CreateFile(zFilename,
00627 GENERIC_READ | GENERIC_WRITE,
00628 0,
00629 NULL,
00630 CREATE_ALWAYS,
00631 fileflags,
00632 NULL
00633 );
00634 if( h==INVALID_HANDLE_VALUE ){
00635 return SQLITE_CANTOPEN;
00636 }
00637 id->h = h;
00638 id->locked = 0;
00639 OpenCounter(+1);
00640 return SQLITE_OK;
00641 #endif
00642 #if OS_MAC
00643 FSSpec fsSpec;
00644 # ifdef _LARGE_FILE
00645 HFSUniStr255 dfName;
00646 FSRef fsRef;
00647 __path2fss(zFilename, &fsSpec);
00648 if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
00649 return SQLITE_CANTOPEN;
00650 if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
00651 return SQLITE_CANTOPEN;
00652 FSGetDataForkName(&dfName);
00653 if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
00654 fsRdWrPerm, &(id->refNum)) != noErr )
00655 return SQLITE_CANTOPEN;
00656 # else
00657 __path2fss(zFilename, &fsSpec);
00658 if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
00659 return SQLITE_CANTOPEN;
00660 if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr )
00661 return SQLITE_CANTOPEN;
00662 # endif
00663 id->refNumRF = -1;
00664 id->locked = 0;
00665 id->delOnClose = delFlag;
00666 if (delFlag)
00667 id->pathToDel = sqliteOsFullPathname(zFilename);
00668 OpenCounter(+1);
00669 return SQLITE_OK;
00670 #endif
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680 int sqliteOsOpenReadOnly(const char *zFilename, OsFile *id){
00681 #if OS_UNIX
00682 int rc;
00683 id->dirfd = -1;
00684 id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
00685 if( id->fd<0 ){
00686 return SQLITE_CANTOPEN;
00687 }
00688 sqliteOsEnterMutex();
00689 rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
00690 sqliteOsLeaveMutex();
00691 if( rc ){
00692 close(id->fd);
00693 return SQLITE_NOMEM;
00694 }
00695 id->locked = 0;
00696 TRACE3("OPEN-RO %-3d %s\n", id->fd, zFilename);
00697 OpenCounter(+1);
00698 return SQLITE_OK;
00699 #endif
00700 #if OS_WIN
00701 HANDLE h = CreateFile(zFilename,
00702 GENERIC_READ,
00703 0,
00704 NULL,
00705 OPEN_EXISTING,
00706 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
00707 NULL
00708 );
00709 if( h==INVALID_HANDLE_VALUE ){
00710 return SQLITE_CANTOPEN;
00711 }
00712 id->h = h;
00713 id->locked = 0;
00714 OpenCounter(+1);
00715 return SQLITE_OK;
00716 #endif
00717 #if OS_MAC
00718 FSSpec fsSpec;
00719 # ifdef _LARGE_FILE
00720 HFSUniStr255 dfName;
00721 FSRef fsRef;
00722 if( __path2fss(zFilename, &fsSpec) != noErr )
00723 return SQLITE_CANTOPEN;
00724 if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
00725 return SQLITE_CANTOPEN;
00726 FSGetDataForkName(&dfName);
00727 if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
00728 fsRdPerm, &(id->refNum)) != noErr )
00729 return SQLITE_CANTOPEN;
00730 # else
00731 __path2fss(zFilename, &fsSpec);
00732 if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr )
00733 return SQLITE_CANTOPEN;
00734 # endif
00735 if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){
00736 id->refNumRF = -1;
00737 }
00738 id->locked = 0;
00739 id->delOnClose = 0;
00740 OpenCounter(+1);
00741 return SQLITE_OK;
00742 #endif
00743 }
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 int sqliteOsOpenDirectory(
00762 const char *zDirname,
00763 OsFile *id
00764 ){
00765 #if OS_UNIX
00766 if( id->fd<0 ){
00767
00768
00769 return SQLITE_CANTOPEN;
00770 }
00771 assert( id->dirfd<0 );
00772 id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0644);
00773 if( id->dirfd<0 ){
00774 return SQLITE_CANTOPEN;
00775 }
00776 TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname);
00777 #endif
00778 return SQLITE_OK;
00779 }
00780
00781
00782
00783
00784
00785
00786 const char *sqlite_temp_directory = 0;
00787
00788
00789
00790
00791
00792 int sqliteOsTempFileName(char *zBuf){
00793 #if OS_UNIX
00794 static const char *azDirs[] = {
00795 0,
00796 "/var/tmp",
00797 "/usr/tmp",
00798 "/tmp",
00799 ".",
00800 };
00801 static unsigned char zChars[] =
00802 "abcdefghijklmnopqrstuvwxyz"
00803 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00804 "0123456789";
00805 int i, j;
00806 struct stat buf;
00807 const char *zDir = ".";
00808 azDirs[0] = sqlite_temp_directory;
00809 for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
00810 if( azDirs[i]==0 ) continue;
00811 if( stat(azDirs[i], &buf) ) continue;
00812 if( !S_ISDIR(buf.st_mode) ) continue;
00813 if( access(azDirs[i], 07) ) continue;
00814 zDir = azDirs[i];
00815 break;
00816 }
00817 do{
00818 sprintf(zBuf, "%s/"TEMP_FILE_PREFIX, zDir);
00819 j = strlen(zBuf);
00820 sqliteRandomness(15, &zBuf[j]);
00821 for(i=0; i<15; i++, j++){
00822 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
00823 }
00824 zBuf[j] = 0;
00825 }while( access(zBuf,0)==0 );
00826 #endif
00827 #if OS_WIN
00828 static char zChars[] =
00829 "abcdefghijklmnopqrstuvwxyz"
00830 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00831 "0123456789";
00832 int i, j;
00833 const char *zDir;
00834 char zTempPath[SQLITE_TEMPNAME_SIZE];
00835 if( sqlite_temp_directory==0 ){
00836 GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath);
00837 for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
00838 zTempPath[i] = 0;
00839 zDir = zTempPath;
00840 }else{
00841 zDir = sqlite_temp_directory;
00842 }
00843 for(;;){
00844 sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zDir);
00845 j = strlen(zBuf);
00846 sqliteRandomness(15, &zBuf[j]);
00847 for(i=0; i<15; i++, j++){
00848 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
00849 }
00850 zBuf[j] = 0;
00851 if( !sqliteOsFileExists(zBuf) ) break;
00852 }
00853 #endif
00854 #if OS_MAC
00855 static char zChars[] =
00856 "abcdefghijklmnopqrstuvwxyz"
00857 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00858 "0123456789";
00859 int i, j;
00860 char *zDir;
00861 char zTempPath[SQLITE_TEMPNAME_SIZE];
00862 char zdirName[32];
00863 CInfoPBRec infoRec;
00864 Str31 dirName;
00865 memset(&infoRec, 0, sizeof(infoRec));
00866 memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE);
00867 if( sqlite_temp_directory!=0 ){
00868 zDir = sqlite_temp_directory;
00869 }else if( FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder,
00870 &(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){
00871 infoRec.dirInfo.ioNamePtr = dirName;
00872 do{
00873 infoRec.dirInfo.ioFDirIndex = -1;
00874 infoRec.dirInfo.ioDrDirID = infoRec.dirInfo.ioDrParID;
00875 if( PBGetCatInfoSync(&infoRec) == noErr ){
00876 CopyPascalStringToC(dirName, zdirName);
00877 i = strlen(zdirName);
00878 memmove(&(zTempPath[i+1]), zTempPath, strlen(zTempPath));
00879 strcpy(zTempPath, zdirName);
00880 zTempPath[i] = ':';
00881 }else{
00882 *zTempPath = 0;
00883 break;
00884 }
00885 } while( infoRec.dirInfo.ioDrDirID != fsRtDirID );
00886 zDir = zTempPath;
00887 }
00888 if( zDir[0]==0 ){
00889 getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24);
00890 zDir = zTempPath;
00891 }
00892 for(;;){
00893 sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zDir);
00894 j = strlen(zBuf);
00895 sqliteRandomness(15, &zBuf[j]);
00896 for(i=0; i<15; i++, j++){
00897 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
00898 }
00899 zBuf[j] = 0;
00900 if( !sqliteOsFileExists(zBuf) ) break;
00901 }
00902 #endif
00903 return SQLITE_OK;
00904 }
00905
00906
00907
00908
00909 int sqliteOsClose(OsFile *id){
00910 #if OS_UNIX
00911 sqliteOsUnlock(id);
00912 if( id->dirfd>=0 ) close(id->dirfd);
00913 id->dirfd = -1;
00914 sqliteOsEnterMutex();
00915 if( id->pOpen->nLock ){
00916
00917
00918
00919
00920
00921 int *aNew;
00922 struct openCnt *pOpen = id->pOpen;
00923 pOpen->nPending++;
00924 aNew = sqliteRealloc( pOpen->aPending, pOpen->nPending*sizeof(int) );
00925 if( aNew==0 ){
00926
00927 }else{
00928 pOpen->aPending = aNew;
00929 pOpen->aPending[pOpen->nPending-1] = id->fd;
00930 }
00931 }else{
00932
00933 close(id->fd);
00934 }
00935 releaseLockInfo(id->pLock);
00936 releaseOpenCnt(id->pOpen);
00937 sqliteOsLeaveMutex();
00938 TRACE2("CLOSE %-3d\n", id->fd);
00939 OpenCounter(-1);
00940 return SQLITE_OK;
00941 #endif
00942 #if OS_WIN
00943 CloseHandle(id->h);
00944 OpenCounter(-1);
00945 return SQLITE_OK;
00946 #endif
00947 #if OS_MAC
00948 if( id->refNumRF!=-1 )
00949 FSClose(id->refNumRF);
00950 # ifdef _LARGE_FILE
00951 FSCloseFork(id->refNum);
00952 # else
00953 FSClose(id->refNum);
00954 # endif
00955 if( id->delOnClose ){
00956 unlink(id->pathToDel);
00957 sqliteFree(id->pathToDel);
00958 }
00959 OpenCounter(-1);
00960 return SQLITE_OK;
00961 #endif
00962 }
00963
00964
00965
00966
00967
00968
00969 int sqliteOsRead(OsFile *id, void *pBuf, int amt){
00970 #if OS_UNIX
00971 int got;
00972 SimulateIOError(SQLITE_IOERR);
00973 TIMER_START;
00974 got = read(id->fd, pBuf, amt);
00975 TIMER_END;
00976 TRACE4("READ %-3d %7d %d\n", id->fd, last_page, elapse);
00977 SEEK(0);
00978
00979 if( got==amt ){
00980 return SQLITE_OK;
00981 }else{
00982 return SQLITE_IOERR;
00983 }
00984 #endif
00985 #if OS_WIN
00986 DWORD got;
00987 SimulateIOError(SQLITE_IOERR);
00988 TRACE2("READ %d\n", last_page);
00989 if( !ReadFile(id->h, pBuf, amt, &got, 0) ){
00990 got = 0;
00991 }
00992 if( got==(DWORD)amt ){
00993 return SQLITE_OK;
00994 }else{
00995 return SQLITE_IOERR;
00996 }
00997 #endif
00998 #if OS_MAC
00999 int got;
01000 SimulateIOError(SQLITE_IOERR);
01001 TRACE2("READ %d\n", last_page);
01002 # ifdef _LARGE_FILE
01003 FSReadFork(id->refNum, fsAtMark, 0, (ByteCount)amt, pBuf, (ByteCount*)&got);
01004 # else
01005 got = amt;
01006 FSRead(id->refNum, &got, pBuf);
01007 # endif
01008 if( got==amt ){
01009 return SQLITE_OK;
01010 }else{
01011 return SQLITE_IOERR;
01012 }
01013 #endif
01014 }
01015
01016
01017
01018
01019
01020 int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){
01021 #if OS_UNIX
01022 int wrote = 0;
01023 SimulateIOError(SQLITE_IOERR);
01024 TIMER_START;
01025 while( amt>0 && (wrote = write(id->fd, pBuf, amt))>0 ){
01026 amt -= wrote;
01027 pBuf = &((char*)pBuf)[wrote];
01028 }
01029 TIMER_END;
01030 TRACE4("WRITE %-3d %7d %d\n", id->fd, last_page, elapse);
01031 SEEK(0);
01032 if( amt>0 ){
01033 return SQLITE_FULL;
01034 }
01035 return SQLITE_OK;
01036 #endif
01037 #if OS_WIN
01038 int rc;
01039 DWORD wrote;
01040 SimulateIOError(SQLITE_IOERR);
01041 TRACE2("WRITE %d\n", last_page);
01042 while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){
01043 amt -= wrote;
01044 pBuf = &((char*)pBuf)[wrote];
01045 }
01046 if( !rc || amt>(int)wrote ){
01047 return SQLITE_FULL;
01048 }
01049 return SQLITE_OK;
01050 #endif
01051 #if OS_MAC
01052 OSErr oserr;
01053 int wrote = 0;
01054 SimulateIOError(SQLITE_IOERR);
01055 TRACE2("WRITE %d\n", last_page);
01056 while( amt>0 ){
01057 # ifdef _LARGE_FILE
01058 oserr = FSWriteFork(id->refNum, fsAtMark, 0,
01059 (ByteCount)amt, pBuf, (ByteCount*)&wrote);
01060 # else
01061 wrote = amt;
01062 oserr = FSWrite(id->refNum, &wrote, pBuf);
01063 # endif
01064 if( wrote == 0 || oserr != noErr)
01065 break;
01066 amt -= wrote;
01067 pBuf = &((char*)pBuf)[wrote];
01068 }
01069 if( oserr != noErr || amt>wrote ){
01070 return SQLITE_FULL;
01071 }
01072 return SQLITE_OK;
01073 #endif
01074 }
01075
01076
01077
01078
01079 int sqliteOsSeek(OsFile *id, off_t offset){
01080 SEEK(offset/1024 + 1);
01081 #if OS_UNIX
01082 lseek(id->fd, offset, SEEK_SET);
01083 return SQLITE_OK;
01084 #endif
01085 #if OS_WIN
01086 {
01087 LONG upperBits = offset>>32;
01088 LONG lowerBits = offset & 0xffffffff;
01089 DWORD rc;
01090 rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN);
01091
01092 }
01093 return SQLITE_OK;
01094 #endif
01095 #if OS_MAC
01096 {
01097 off_t curSize;
01098 if( sqliteOsFileSize(id, &curSize) != SQLITE_OK ){
01099 return SQLITE_IOERR;
01100 }
01101 if( offset >= curSize ){
01102 if( sqliteOsTruncate(id, offset+1) != SQLITE_OK ){
01103 return SQLITE_IOERR;
01104 }
01105 }
01106 # ifdef _LARGE_FILE
01107 if( FSSetForkPosition(id->refNum, fsFromStart, offset) != noErr ){
01108 # else
01109 if( SetFPos(id->refNum, fsFromStart, offset) != noErr ){
01110 # endif
01111 return SQLITE_IOERR;
01112 }else{
01113 return SQLITE_OK;
01114 }
01115 }
01116 #endif
01117 }
01118
01119 #ifdef SQLITE_NOSYNC
01120 # define fsync(X) 0
01121 #endif
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134 int sqliteOsSync(OsFile *id){
01135 #if OS_UNIX
01136 SimulateIOError(SQLITE_IOERR);
01137 TRACE2("SYNC %-3d\n", id->fd);
01138 if( fsync(id->fd) ){
01139 return SQLITE_IOERR;
01140 }else{
01141 if( id->dirfd>=0 ){
01142 TRACE2("DIRSYNC %-3d\n", id->dirfd);
01143 fsync(id->dirfd);
01144 close(id->dirfd);
01145 id->dirfd = -1;
01146 }
01147 return SQLITE_OK;
01148 }
01149 #endif
01150 #if OS_WIN
01151 if( FlushFileBuffers(id->h) ){
01152 return SQLITE_OK;
01153 }else{
01154 return SQLITE_IOERR;
01155 }
01156 #endif
01157 #if OS_MAC
01158 # ifdef _LARGE_FILE
01159 if( FSFlushFork(id->refNum) != noErr ){
01160 # else
01161 ParamBlockRec params;
01162 memset(¶ms, 0, sizeof(ParamBlockRec));
01163 params.ioParam.ioRefNum = id->refNum;
01164 if( PBFlushFileSync(¶ms) != noErr ){
01165 # endif
01166 return SQLITE_IOERR;
01167 }else{
01168 return SQLITE_OK;
01169 }
01170 #endif
01171 }
01172
01173
01174
01175
01176 int sqliteOsTruncate(OsFile *id, off_t nByte){
01177 SimulateIOError(SQLITE_IOERR);
01178 #if OS_UNIX
01179 return ftruncate(id->fd, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
01180 #endif
01181 #if OS_WIN
01182 {
01183 LONG upperBits = nByte>>32;
01184 SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN);
01185 SetEndOfFile(id->h);
01186 }
01187 return SQLITE_OK;
01188 #endif
01189 #if OS_MAC
01190 # ifdef _LARGE_FILE
01191 if( FSSetForkSize(id->refNum, fsFromStart, nByte) != noErr){
01192 # else
01193 if( SetEOF(id->refNum, nByte) != noErr ){
01194 # endif
01195 return SQLITE_IOERR;
01196 }else{
01197 return SQLITE_OK;
01198 }
01199 #endif
01200 }
01201
01202
01203
01204
01205 int sqliteOsFileSize(OsFile *id, off_t *pSize){
01206 #if OS_UNIX
01207 struct stat buf;
01208 SimulateIOError(SQLITE_IOERR);
01209 if( fstat(id->fd, &buf)!=0 ){
01210 return SQLITE_IOERR;
01211 }
01212 *pSize = buf.st_size;
01213 return SQLITE_OK;
01214 #endif
01215 #if OS_WIN
01216 DWORD upperBits, lowerBits;
01217 SimulateIOError(SQLITE_IOERR);
01218 lowerBits = GetFileSize(id->h, &upperBits);
01219 *pSize = (((off_t)upperBits)<<32) + lowerBits;
01220 return SQLITE_OK;
01221 #endif
01222 #if OS_MAC
01223 # ifdef _LARGE_FILE
01224 if( FSGetForkSize(id->refNum, pSize) != noErr){
01225 # else
01226 if( GetEOF(id->refNum, pSize) != noErr ){
01227 # endif
01228 return SQLITE_IOERR;
01229 }else{
01230 return SQLITE_OK;
01231 }
01232 #endif
01233 }
01234
01235 #if OS_WIN
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247 int isNT(void){
01248 static int osType = 0;
01249 if( osType==0 ){
01250 OSVERSIONINFO sInfo;
01251 sInfo.dwOSVersionInfoSize = sizeof(sInfo);
01252 GetVersionEx(&sInfo);
01253 osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
01254 }
01255 return osType==2;
01256 }
01257 #endif
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 #define N_LOCKBYTE 10239
01305 #if OS_MAC
01306 # define FIRST_LOCKBYTE (0x000fffff - N_LOCKBYTE)
01307 #else
01308 # define FIRST_LOCKBYTE (0xffffffff - N_LOCKBYTE)
01309 #endif
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320 int sqliteOsReadLock(OsFile *id){
01321 #if OS_UNIX
01322 int rc;
01323 sqliteOsEnterMutex();
01324 if( id->pLock->cnt>0 ){
01325 if( !id->locked ){
01326 id->pLock->cnt++;
01327 id->locked = 1;
01328 id->pOpen->nLock++;
01329 }
01330 rc = SQLITE_OK;
01331 }else if( id->locked || id->pLock->cnt==0 ){
01332 struct flock lock;
01333 int s;
01334 lock.l_type = F_RDLCK;
01335 lock.l_whence = SEEK_SET;
01336 lock.l_start = lock.l_len = 0L;
01337 s = fcntl(id->fd, F_SETLK, &lock);
01338 if( s!=0 ){
01339 rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
01340 }else{
01341 rc = SQLITE_OK;
01342 if( !id->locked ){
01343 id->pOpen->nLock++;
01344 id->locked = 1;
01345 }
01346 id->pLock->cnt = 1;
01347 }
01348 }else{
01349 rc = SQLITE_BUSY;
01350 }
01351 sqliteOsLeaveMutex();
01352 return rc;
01353 #endif
01354 #if OS_WIN
01355 int rc;
01356 if( id->locked>0 ){
01357 rc = SQLITE_OK;
01358 }else{
01359 int lk;
01360 int res;
01361 int cnt = 100;
01362 sqliteRandomness(sizeof(lk), &lk);
01363 lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;
01364 while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
01365 Sleep(1);
01366 }
01367 if( res ){
01368 UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
01369 if( isNT() ){
01370 OVERLAPPED ovlp;
01371 ovlp.Offset = FIRST_LOCKBYTE+1;
01372 ovlp.OffsetHigh = 0;
01373 ovlp.hEvent = 0;
01374 res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY,
01375 0, N_LOCKBYTE, 0, &ovlp);
01376 }else{
01377 res = LockFile(id->h, FIRST_LOCKBYTE+lk, 0, 1, 0);
01378 }
01379 UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
01380 }
01381 if( res ){
01382 id->locked = lk;
01383 rc = SQLITE_OK;
01384 }else{
01385 rc = SQLITE_BUSY;
01386 }
01387 }
01388 return rc;
01389 #endif
01390 #if OS_MAC
01391 int rc;
01392 if( id->locked>0 || id->refNumRF == -1 ){
01393 rc = SQLITE_OK;
01394 }else{
01395 int lk;
01396 OSErr res;
01397 int cnt = 5;
01398 ParamBlockRec params;
01399 sqliteRandomness(sizeof(lk), &lk);
01400 lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;
01401 memset(¶ms, 0, sizeof(params));
01402 params.ioParam.ioRefNum = id->refNumRF;
01403 params.ioParam.ioPosMode = fsFromStart;
01404 params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
01405 params.ioParam.ioReqCount = 1;
01406 while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){
01407 UInt32 finalTicks;
01408 Delay(1, &finalTicks);
01409 }
01410 if( res == noErr ){
01411 params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
01412 params.ioParam.ioReqCount = N_LOCKBYTE;
01413 PBUnlockRangeSync(¶ms);
01414 params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk;
01415 params.ioParam.ioReqCount = 1;
01416 res = PBLockRangeSync(¶ms);
01417 params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
01418 params.ioParam.ioReqCount = 1;
01419 PBUnlockRangeSync(¶ms);
01420 }
01421 if( res == noErr ){
01422 id->locked = lk;
01423 rc = SQLITE_OK;
01424 }else{
01425 rc = SQLITE_BUSY;
01426 }
01427 }
01428 return rc;
01429 #endif
01430 }
01431
01432
01433
01434
01435
01436
01437
01438 int sqliteOsWriteLock(OsFile *id){
01439 #if OS_UNIX
01440 int rc;
01441 sqliteOsEnterMutex();
01442 if( id->pLock->cnt==0 || (id->pLock->cnt==1 && id->locked==1) ){
01443 struct flock lock;
01444 int s;
01445 lock.l_type = F_WRLCK;
01446 lock.l_whence = SEEK_SET;
01447 lock.l_start = lock.l_len = 0L;
01448 s = fcntl(id->fd, F_SETLK, &lock);
01449 if( s!=0 ){
01450 rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
01451 }else{
01452 rc = SQLITE_OK;
01453 if( !id->locked ){
01454 id->pOpen->nLock++;
01455 id->locked = 1;
01456 }
01457 id->pLock->cnt = -1;
01458 }
01459 }else{
01460 rc = SQLITE_BUSY;
01461 }
01462 sqliteOsLeaveMutex();
01463 return rc;
01464 #endif
01465 #if OS_WIN
01466 int rc;
01467 if( id->locked<0 ){
01468 rc = SQLITE_OK;
01469 }else{
01470 int res;
01471 int cnt = 100;
01472 while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
01473 Sleep(1);
01474 }
01475 if( res ){
01476 if( id->locked>0 ){
01477 if( isNT() ){
01478 UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
01479 }else{
01480 res = UnlockFile(id->h, FIRST_LOCKBYTE + id->locked, 0, 1, 0);
01481 }
01482 }
01483 if( res ){
01484 res = LockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
01485 }else{
01486 res = 0;
01487 }
01488 UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
01489 }
01490 if( res ){
01491 id->locked = -1;
01492 rc = SQLITE_OK;
01493 }else{
01494 rc = SQLITE_BUSY;
01495 }
01496 }
01497 return rc;
01498 #endif
01499 #if OS_MAC
01500 int rc;
01501 if( id->locked<0 || id->refNumRF == -1 ){
01502 rc = SQLITE_OK;
01503 }else{
01504 OSErr res;
01505 int cnt = 5;
01506 ParamBlockRec params;
01507 memset(¶ms, 0, sizeof(params));
01508 params.ioParam.ioRefNum = id->refNumRF;
01509 params.ioParam.ioPosMode = fsFromStart;
01510 params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
01511 params.ioParam.ioReqCount = 1;
01512 while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){
01513 UInt32 finalTicks;
01514 Delay(1, &finalTicks);
01515 }
01516 if( res == noErr ){
01517 params.ioParam.ioPosOffset = FIRST_LOCKBYTE + id->locked;
01518 params.ioParam.ioReqCount = 1;
01519 if( id->locked==0
01520 || PBUnlockRangeSync(¶ms)==noErr ){
01521 params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
01522 params.ioParam.ioReqCount = N_LOCKBYTE;
01523 res = PBLockRangeSync(¶ms);
01524 }else{
01525 res = afpRangeNotLocked;
01526 }
01527 params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
01528 params.ioParam.ioReqCount = 1;
01529 PBUnlockRangeSync(¶ms);
01530 }
01531 if( res == noErr ){
01532 id->locked = -1;
01533 rc = SQLITE_OK;
01534 }else{
01535 rc = SQLITE_BUSY;
01536 }
01537 }
01538 return rc;
01539 #endif
01540 }
01541
01542
01543
01544
01545
01546
01547
01548 int sqliteOsUnlock(OsFile *id){
01549 #if OS_UNIX
01550 int rc;
01551 if( !id->locked ) return SQLITE_OK;
01552 sqliteOsEnterMutex();
01553 assert( id->pLock->cnt!=0 );
01554 if( id->pLock->cnt>1 ){
01555 id->pLock->cnt--;
01556 rc = SQLITE_OK;
01557 }else{
01558 struct flock lock;
01559 int s;
01560 lock.l_type = F_UNLCK;
01561 lock.l_whence = SEEK_SET;
01562 lock.l_start = lock.l_len = 0L;
01563 s = fcntl(id->fd, F_SETLK, &lock);
01564 if( s!=0 ){
01565 rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
01566 }else{
01567 rc = SQLITE_OK;
01568 id->pLock->cnt = 0;
01569 }
01570 }
01571 if( rc==SQLITE_OK ){
01572
01573
01574
01575
01576 struct openCnt *pOpen = id->pOpen;
01577 pOpen->nLock--;
01578 assert( pOpen->nLock>=0 );
01579 if( pOpen->nLock==0 && pOpen->nPending>0 ){
01580 int i;
01581 for(i=0; i<pOpen->nPending; i++){
01582 close(pOpen->aPending[i]);
01583 }
01584 sqliteFree(pOpen->aPending);
01585 pOpen->nPending = 0;
01586 pOpen->aPending = 0;
01587 }
01588 }
01589 sqliteOsLeaveMutex();
01590 id->locked = 0;
01591 return rc;
01592 #endif
01593 #if OS_WIN
01594 int rc;
01595 if( id->locked==0 ){
01596 rc = SQLITE_OK;
01597 }else if( isNT() || id->locked<0 ){
01598 UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
01599 rc = SQLITE_OK;
01600 id->locked = 0;
01601 }else{
01602 UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, 0, 1, 0);
01603 rc = SQLITE_OK;
01604 id->locked = 0;
01605 }
01606 return rc;
01607 #endif
01608 #if OS_MAC
01609 int rc;
01610 ParamBlockRec params;
01611 memset(¶ms, 0, sizeof(params));
01612 params.ioParam.ioRefNum = id->refNumRF;
01613 params.ioParam.ioPosMode = fsFromStart;
01614 if( id->locked==0 || id->refNumRF == -1 ){
01615 rc = SQLITE_OK;
01616 }else if( id->locked<0 ){
01617 params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
01618 params.ioParam.ioReqCount = N_LOCKBYTE;
01619 PBUnlockRangeSync(¶ms);
01620 rc = SQLITE_OK;
01621 id->locked = 0;
01622 }else{
01623 params.ioParam.ioPosOffset = FIRST_LOCKBYTE+id->locked;
01624 params.ioParam.ioReqCount = 1;
01625 PBUnlockRangeSync(¶ms);
01626 rc = SQLITE_OK;
01627 id->locked = 0;
01628 }
01629 return rc;
01630 #endif
01631 }
01632
01633
01634
01635
01636
01637
01638 int sqliteOsRandomSeed(char *zBuf){
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651 memset(zBuf, 0, 256);
01652 #if OS_UNIX && !defined(SQLITE_TEST)
01653 {
01654 int pid;
01655 time((time_t*)zBuf);
01656 pid = getpid();
01657 memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid));
01658 }
01659 #endif
01660 #if OS_WIN && !defined(SQLITE_TEST)
01661 GetSystemTime((LPSYSTEMTIME)zBuf);
01662 #endif
01663 #if OS_MAC
01664 {
01665 int pid;
01666 Microseconds((UnsignedWide*)zBuf);
01667 pid = getpid();
01668 memcpy(&zBuf[sizeof(UnsignedWide)], &pid, sizeof(pid));
01669 }
01670 #endif
01671 return SQLITE_OK;
01672 }
01673
01674
01675
01676
01677 int sqliteOsSleep(int ms){
01678 #if OS_UNIX
01679 #if defined(HAVE_USLEEP) && HAVE_USLEEP
01680 usleep(ms*1000);
01681 return ms;
01682 #else
01683 sleep((ms+999)/1000);
01684 return 1000*((ms+999)/1000);
01685 #endif
01686 #endif
01687 #if OS_WIN
01688 Sleep(ms);
01689 return ms;
01690 #endif
01691 #if OS_MAC
01692 UInt32 finalTicks;
01693 UInt32 ticks = (((UInt32)ms+16)*3)/50;
01694 Delay(ticks, &finalTicks);
01695 return (int)((ticks*50)/3);
01696 #endif
01697 }
01698
01699
01700
01701
01702 static int inMutex = 0;
01703 #ifdef SQLITE_UNIX_THREADS
01704 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
01705 #endif
01706 #ifdef SQLITE_W32_THREADS
01707 static CRITICAL_SECTION cs;
01708 #endif
01709 #ifdef SQLITE_MACOS_MULTITASKING
01710 static MPCriticalRegionID criticalRegion;
01711 #endif
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721 void sqliteOsEnterMutex(){
01722 #ifdef SQLITE_UNIX_THREADS
01723 pthread_mutex_lock(&mutex);
01724 #endif
01725 #ifdef SQLITE_W32_THREADS
01726 static int isInit = 0;
01727 while( !isInit ){
01728 static long lock = 0;
01729 if( InterlockedIncrement(&lock)==1 ){
01730 InitializeCriticalSection(&cs);
01731 isInit = 1;
01732 }else{
01733 Sleep(1);
01734 }
01735 }
01736 EnterCriticalSection(&cs);
01737 #endif
01738 #ifdef SQLITE_MACOS_MULTITASKING
01739 static volatile int notInit = 1;
01740 if( notInit ){
01741 if( notInit == 2 )
01742 MPYield();
01743 else{
01744 notInit = 2;
01745 MPCreateCriticalRegion(&criticalRegion);
01746 notInit = 0;
01747 }
01748 }
01749 MPEnterCriticalRegion(criticalRegion, kDurationForever);
01750 #endif
01751 assert( !inMutex );
01752 inMutex = 1;
01753 }
01754 void sqliteOsLeaveMutex(){
01755 assert( inMutex );
01756 inMutex = 0;
01757 #ifdef SQLITE_UNIX_THREADS
01758 pthread_mutex_unlock(&mutex);
01759 #endif
01760 #ifdef SQLITE_W32_THREADS
01761 LeaveCriticalSection(&cs);
01762 #endif
01763 #ifdef SQLITE_MACOS_MULTITASKING
01764 MPExitCriticalRegion(criticalRegion);
01765 #endif
01766 }
01767
01768
01769
01770
01771
01772
01773
01774 char *sqliteOsFullPathname(const char *zRelative){
01775 #if OS_UNIX
01776 char *zFull = 0;
01777 if( zRelative[0]=='/' ){
01778 sqliteSetString(&zFull, zRelative, (char*)0);
01779 }else{
01780 char zBuf[5000];
01781 zBuf[0] = 0;
01782 sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative,
01783 (char*)0);
01784 }
01785 return zFull;
01786 #endif
01787 #if OS_WIN
01788 char *zNotUsed;
01789 char *zFull;
01790 int nByte;
01791 nByte = GetFullPathName(zRelative, 0, 0, &zNotUsed) + 1;
01792 zFull = sqliteMalloc( nByte );
01793 if( zFull==0 ) return 0;
01794 GetFullPathName(zRelative, nByte, zFull, &zNotUsed);
01795 return zFull;
01796 #endif
01797 #if OS_MAC
01798 char *zFull = 0;
01799 if( zRelative[0]==':' ){
01800 char zBuf[_MAX_PATH+1];
01801 sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), &(zRelative[1]),
01802 (char*)0);
01803 }else{
01804 if( strchr(zRelative, ':') ){
01805 sqliteSetString(&zFull, zRelative, (char*)0);
01806 }else{
01807 char zBuf[_MAX_PATH+1];
01808 sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), zRelative, (char*)0);
01809 }
01810 }
01811 return zFull;
01812 #endif
01813 }
01814
01815
01816
01817
01818
01819 #ifdef SQLITE_TEST
01820 int sqlite_current_time = 0;
01821 #endif
01822
01823
01824
01825
01826
01827
01828 int sqliteOsCurrentTime(double *prNow){
01829 #if OS_UNIX
01830 time_t t;
01831 time(&t);
01832 *prNow = t/86400.0 + 2440587.5;
01833 #endif
01834 #if OS_WIN
01835 FILETIME ft;
01836
01837
01838
01839 double now;
01840 GetSystemTimeAsFileTime( &ft );
01841 now = ((double)ft.dwHighDateTime) * 4294967296.0;
01842 *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
01843 #endif
01844 #ifdef SQLITE_TEST
01845 if( sqlite_current_time ){
01846 *prNow = sqlite_current_time/86400.0 + 2440587.5;
01847 }
01848 #endif
01849 return 0;
01850 }