12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651 |
- /*
- ** 2004 May 22
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
- **
- ** May you do good and not evil.
- ** May you find forgiveness for yourself and forgive others.
- ** May you share freely, never taking more than you give.
- **
- ******************************************************************************
- **
- ** This file contains code that is specific to Windows.
- */
- #include "sqliteInt.h"
- #if SQLITE_OS_RTT /* This file is used for rt-thread only */
- #include <rtthread.h>
- /*
- ** Include code that is common to all os_*.c files
- */
- #include "os_common.h"
- /*
- ** Compiling and using WAL mode requires several APIs that are not
- ** available in rt-thread.
- */
- #if !defined(SQLITE_OMIT_WAL)
- # error "WAL mode requires not support from the rt-thread, compile\
- with SQLITE_OMIT_WAL."
- #endif
- /*
- ** Are most of the rtt ANSI APIs available (i.e. with certain exceptions
- ** based on the sub-platform)?
- */
- #if !defined(SQLITE_RTT_NO_ANSI)
- # warning "please ensure rtt ANSI APIs is available, otherwise compile with\
- SQLITE_RTT_NO_ANSI"
- # define SQLITE_RTT_HAS_ANSI
- #endif
- /*
- ** Are most of the rtt Unicode APIs available (i.e. with certain exceptions
- ** based on the sub-platform)?
- */
- #if !defined(SQLITE_RTT_NO_WIDE)
- # error "rtt not support Unicode APIs"
- # define SQLITE_RTT_HAS_WIDE
- #endif
- /*
- ** Make sure at least one set of rtt APIs is available.
- */
- #if !defined(SQLITE_RTT_HAS_ANSI) && !defined(SQLITE_RTT_HAS_WIDE)
- # error "At least one of SQLITE_RTT_HAS_ANSI and SQLITE_RTT_HAS_WIDE\
- must be defined."
- #endif
- /*
- ** Maximum pathname length (in chars) for rtt. This should normally be
- ** MAX_PATH.
- */
- #ifndef SQLITE_RTT_MAX_PATH_CHARS
- # warning "default Maximum pathname length be 255, otherwise compile with\
- SQLITE_RTT_MAX_PATH_CHARS=?"
- # define SQLITE_RTT_MAX_PATH_CHARS (255)
- #endif
- /*
- ** Maximum supported path-length.
- */
- #define MAX_PATHNAME 512
- /*
- ** Returns non-zero if the character should be treated as a directory
- ** separator.
- */
- #ifndef rttIsDirSep
- # define rttIsDirSep(a) ((a) == '/')
- #endif
- /*
- ** This macro is used when a local variable is set to a value that is
- ** [sometimes] not used by the code (e.g. via conditional compilation).
- */
- #ifndef UNUSED_VARIABLE_VALUE
- # define UNUSED_VARIABLE_VALUE(x) (void)(x)
- #endif
- /*
- ** Returns the string that should be used as the directory separator.
- */
- #ifndef rttGetDirDep
- # define rttGetDirDep() "/"
- #endif
- /*
- ** The winFile structure is a subclass of sqlite3_file* specific to the win32
- ** portability layer.
- */
- typedef struct rttFile rttFile;
- struct rttFile {
- sqlite3_io_methods const *pMethod; /* Always the first entry */
- sqlite3_vfs *pVfs; /* The VFS that created this rttFile */
- int h; /* The file descriptor */
- unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
- unsigned char eFileLock; /* The type of lock held on this fd */
- int lastErrno; /* The unix errno from last I/O error */
- void *lockingContext; /* Locking style specific state */
- const char *zPath; /* Name of the file */
- int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
- #if SQLITE_ENABLE_LOCKING_STYLE
- int openFlags; /* The flags specified at open() */
- #endif
- #if SQLITE_ENABLE_LOCKING_STYLE
- unsigned fsFlags; /* cached details from statfs() */
- #endif
- #ifdef SQLITE_DEBUG
- /* The next group of variables are used to track whether or not the
- ** transaction counter in bytes 24-27 of database files are updated
- ** whenever any part of the database changes. An assertion fault will
- ** occur if a file is updated without also updating the transaction
- ** counter. This test is made to avoid new problems similar to the
- ** one described by ticket #3584.
- */
- unsigned char transCntrChng; /* True if the transaction counter changed */
- unsigned char dbUpdate; /* True if any part of database file changed */
- unsigned char inNormalWrite; /* True if in a normal write operation */
- #endif
- #ifdef SQLITE_TEST
- /* In test mode, increase the size of this structure a bit so that
- ** it is larger than the struct CrashFile defined in test6.c.
- */
- char aPadding[32];
- #endif
- };
- /*
- ** Allowed values for the rttFile.ctrlFlags bitmask:
- */
- #define UNIXFILE_EXCL 0x01 /* Connections from one process only */
- #define UNIXFILE_RDONLY 0x02 /* Connection is read only */
- #define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
- #ifndef SQLITE_DISABLE_DIRSYNC
- # define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
- #else
- # define UNIXFILE_DIRSYNC 0x00
- #endif
- #define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
- #define UNIXFILE_DELETE 0x20 /* Delete on close */
- #define UNIXFILE_URI 0x40 /* Filename might have query parameters */
- #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
- #define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings have been issued */
- /*
- ** The following variable is (normally) set once and never changes
- ** thereafter. It records whether the operating system is Win9x
- ** or WinNT.
- **
- ** 0: Operating system unknown.
- ** 1: Operating system is rtt.
- **
- ** In order to facilitate testing on a rtt system, the test fixture
- ** can manually set this value to 1 to emulate Win98 behavior.
- */
- #ifdef SQLITE_TEST
- int sqlite3_os_type = 0;
- #elif !SQLITE_OS_RTT && \
- defined(SQLITE_RTT_HAS_ANSI) && defined(SQLITE_RTT_HAS_WIDE)
- static int sqlite3_os_type = 0;
- #endif
- #ifndef SYSCALL
- # define SYSCALL sqlite3_syscall_ptr
- #endif
- #include <dfs_posix.h>
- static int _Access(const char *pathname, int mode)
- {
- int fd;
- fd = open(pathname, O_RDONLY, mode);
- if (fd >= 0)
- {
- close(fd);
- return 0;
- }
- return -1;
- }
- /*
- ** Invoke open(). Do so multiple times, until it either succeeds or
- ** fails for some reason other than EINTR.
- **
- ** If the file creation mode "m" is 0 then set it to the default for
- ** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
- ** 0644) as modified by the system umask. If m is not 0, then
- ** make the file creation mode be exactly m ignoring the umask.
- **
- ** The m parameter will be non-zero only when creating -wal, -journal,
- ** and -shm files. We want those files to have *exactly* the same
- ** permissions as their original database, unadulterated by the umask.
- ** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
- ** transaction crashes and leaves behind hot journals, then any
- ** process that is able to write to the database will also be able to
- ** recover the hot journals.
- */
- static int robust_open(const char *z, int f, mode_t m);
- /*
- ** Open a file descriptor to the directory containing file zFilename.
- ** If successful, *pFd is set to the opened file descriptor and
- ** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
- ** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
- ** value.
- **
- ** The directory file descriptor is used for only one thing - to
- ** fsync() a directory to make sure file creation and deletion events
- ** are flushed to disk. Such fsyncs are not needed on newer
- ** journaling filesystems, but are required on older filesystems.
- **
- ** This routine can be overridden using the xSetSysCall interface.
- ** The ability to override this routine was added in support of the
- ** chromium sandbox. Opening a directory is a security risk (we are
- ** told) so making it overrideable allows the chromium sandbox to
- ** replace this routine with a harmless no-op. To make this routine
- ** a no-op, replace it with a stub that returns SQLITE_OK but leaves
- ** *pFd set to a negative number.
- **
- ** If SQLITE_OK is returned, the caller is responsible for closing
- ** the file descriptor *pFd using close().
- */
- static int openDirectory(const char *zFilename, int *pFd);
- /*
- ** Many system calls are accessed through pointer-to-functions so that
- ** they may be overridden at runtime to facilitate fault injection during
- ** testing and sandboxing. The following array holds the names and pointers
- ** to all overrideable system calls.
- */
- static struct rtt_syscall {
- const char *zName; /* Name of the system call */
- sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
- sqlite3_syscall_ptr pDefault; /* Default value */
- } aSyscall[] = {
- {"sleep", (sqlite3_syscall_ptr)rt_thread_delay, 0},
- #define osSleep ((rt_err_t(*)(rt_tick_t))aSyscall[0].pCurrent)
- { "open", (sqlite3_syscall_ptr)open, 0 },
- #define osOpen ((int(*)(const char*,int,int))aSyscall[1].pCurrent)
- { "close", (sqlite3_syscall_ptr)close, 0 },
- #define osClose ((int(*)(int))aSyscall[2].pCurrent)
- { "getcwd", (sqlite3_syscall_ptr)getcwd, 0 },
- #define osGetcwd ((char*(*)(char*,size_t))aSyscall[3].pCurrent)
- { "stat", (sqlite3_syscall_ptr)stat, 0 },
- #define osStat ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
- { "fstat", (sqlite3_syscall_ptr)fstat, 0 },
- #define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
- { "read", (sqlite3_syscall_ptr)read, 0 },
- #define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[6].pCurrent)
- { "write", (sqlite3_syscall_ptr)write, 0 },
- #define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[7].pCurrent)
- { "unlink", (sqlite3_syscall_ptr)unlink, 0 },
- #define osUnlink ((int(*)(const char*))aSyscall[8].pCurrent)
- { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 },
- #define osOpenDirectory ((int(*)(const char*,int*))aSyscall[9].pCurrent)
- { "mkdir", (sqlite3_syscall_ptr)mkdir, 0 },
- #define osMkdir ((int(*)(const char*,mode_t))aSyscall[10].pCurrent)
- { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
- #define osRmdir ((int(*)(const char*))aSyscall[11].pCurrent)
- {"access", (sqlite3_syscall_ptr)_Access, 0 },
- #define osAccess ((int(*)(const char*, int))aSyscall[12].pCurrent)
- }; /* End of the overrideable system calls */
- /*
- ** Do not accept any file descriptor less than this value, in order to avoid
- ** opening database file using file descriptors that are commonly used for
- ** standard input, output, and error.
- */
- #ifndef SQLITE_MINIMUM_FILE_DESCRIPTOR
- # define SQLITE_MINIMUM_FILE_DESCRIPTOR 3
- #endif
- /*
- ** Invoke open(). Do so multiple times, until it either succeeds or
- ** fails for some reason other than EINTR.
- **
- ** If the file creation mode "m" is 0 then set it to the default for
- ** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
- ** 0644) as modified by the system umask. If m is not 0, then
- ** make the file creation mode be exactly m ignoring the umask.
- **
- ** The m parameter will be non-zero only when creating -wal, -journal,
- ** and -shm files. We want those files to have *exactly* the same
- ** permissions as their original database, unadulterated by the umask.
- ** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
- ** transaction crashes and leaves behind hot journals, then any
- ** process that is able to write to the database will also be able to
- ** recover the hot journals.
- */
- static int robust_open(const char *z, int f, mode_t m){
- int fd;
- mode_t m2 = m ;
- while(1){
- #if defined(O_CLOEXEC)
- fd = osOpen(z,f|O_CLOEXEC,m2);
- #else
- fd = osOpen(z,f,m2);
- #endif
- if( fd<0 ){
- if( errno==EINTR ) continue;
- break;
- }
- if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break;
- osClose(fd);
- sqlite3_log(SQLITE_WARNING,
- "attempt to open \"%s\" as file descriptor %d", z, fd);
- fd = -1;
- if( osOpen("/dev/null", f, m)<0 ) break;
- }
- return fd;
- }
- /*
- ** Open a file descriptor to the directory containing file zFilename.
- ** If successful, *pFd is set to the opened file descriptor and
- ** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
- ** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
- ** value.
- **
- ** The directory file descriptor is used for only one thing - to
- ** fsync() a directory to make sure file creation and deletion events
- ** are flushed to disk. Such fsyncs are not needed on newer
- ** journaling filesystems, but are required on older filesystems.
- **
- ** This routine can be overridden using the xSetSysCall interface.
- ** The ability to override this routine was added in support of the
- ** chromium sandbox. Opening a directory is a security risk (we are
- ** told) so making it overrideable allows the chromium sandbox to
- ** replace this routine with a harmless no-op. To make this routine
- ** a no-op, replace it with a stub that returns SQLITE_OK but leaves
- ** *pFd set to a negative number.
- **
- ** If SQLITE_OK is returned, the caller is responsible for closing
- ** the file descriptor *pFd using close().
- */
- static int openDirectory(const char *zFilename, int *pFd){
- int ii;
- int fd = -1;
- char zDirname[MAX_PATHNAME+1];
- sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
- for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
- if( ii>0 ){
- zDirname[ii] = '\0';
- fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
- if( fd>=0 ){
- OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
- }
- }
- *pFd = fd;
- return (fd>=0?SQLITE_OK:rttLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
- }
- /*
- ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
- ** "win32" VFSes. Return SQLITE_OK opon successfully updating the
- ** system call pointer, or SQLITE_NOTFOUND if there is no configurable
- ** system call named zName.
- */
- static int rttSetSystemCall(
- sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
- const char *zName, /* Name of system call to override */
- sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
- ){
- unsigned int i;
- int rc = SQLITE_NOTFOUND;
- UNUSED_PARAMETER(pNotUsed);
- if( zName==0 ){
- /* If no zName is given, restore all system calls to their default
- ** settings and return NULL
- */
- rc = SQLITE_OK;
- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
- if( aSyscall[i].pDefault ){
- aSyscall[i].pCurrent = aSyscall[i].pDefault;
- }
- }
- }else{
- /* If zName is specified, operate on only the one system call
- ** specified.
- */
- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
- if( strcmp(zName, aSyscall[i].zName)==0 ){
- if( aSyscall[i].pDefault==0 ){
- aSyscall[i].pDefault = aSyscall[i].pCurrent;
- }
- rc = SQLITE_OK;
- if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
- aSyscall[i].pCurrent = pNewFunc;
- break;
- }
- }
- }
- return rc;
- }
- /*
- ** Return the value of a system call. Return NULL if zName is not a
- ** recognized system call name. NULL is also returned if the system call
- ** is currently undefined.
- */
- static sqlite3_syscall_ptr rttGetSystemCall(
- sqlite3_vfs *pNotUsed,
- const char *zName
- ){
- unsigned int i;
- UNUSED_PARAMETER(pNotUsed);
- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
- if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
- }
- return 0;
- }
- /*
- ** Return the name of the first system call after zName. If zName==NULL
- ** then return the name of the first system call. Return NULL if zName
- ** is the last system call or if zName is not the name of a valid
- ** system call.
- */
- static const char *rttNextSystemCall(sqlite3_vfs *p, const char *zName){
- int i = -1;
- UNUSED_PARAMETER(p);
- if( zName ){
- for(i=0; i<ArraySize(aSyscall)-1; i++){
- if( strcmp(zName, aSyscall[i].zName)==0 ) break;
- }
- }
- for(i++; i<ArraySize(aSyscall); i++){
- if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
- }
- return 0;
- }
- /*
- ** The following routine suspends the current thread for at least ms
- ** milliseconds. This is equivalent to the Win32 Sleep() interface.
- */
- void sqlite3_rtt_sleep(int milliseconds){
- rt_tick_t sleep_tick;
- if (milliseconds <= 0)
- return;
- sleep_tick = rt_tick_from_millisecond(milliseconds);
- osSleep(sleep_tick);
- }
- /*
- ** Helper functions to obtain and relinquish the global mutex. The
- ** global mutex is used to protect the unixInodeInfo and
- ** vxworksFileId objects used by this file, all of which may be
- ** shared by multiple threads.
- **
- ** Function unixMutexHeld() is used to assert() that the global mutex
- ** is held when required. This function is only used as part of assert()
- ** statements. e.g.
- **
- ** unixEnterMutex()
- ** assert( unixMutexHeld() );
- ** unixEnterLeave()
- */
- static void rttEnterMutex(void){
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
- }
- static void rttLeaveMutex(void){
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
- }
- #ifdef SQLITE_DEBUG
- static int rttMutexHeld(void) {
- return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
- }
- #endif
- #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
- /*
- ** Helper function for printing out trace information from debugging
- ** binaries. This returns the string represetation of the supplied
- ** integer lock-type.
- */
- static const char *azFileLock(int eFileLock){
- switch( eFileLock ){
- case NO_LOCK: return "NONE";
- case SHARED_LOCK: return "SHARED";
- case RESERVED_LOCK: return "RESERVED";
- case PENDING_LOCK: return "PENDING";
- case EXCLUSIVE_LOCK: return "EXCLUSIVE";
- }
- return "ERROR";
- }
- #endif
- /*
- ** This routine translates a standard POSIX errno code into something
- ** useful to the clients of the sqlite3 functions. Specifically, it is
- ** intended to translate a variety of "try again" errors into SQLITE_BUSY
- ** and a variety of "please close the file descriptor NOW" errors into
- ** SQLITE_IOERR
- **
- ** Errors during initialization of locks, or file system support for locks,
- ** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
- */
- static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
- switch (posixError) {
- #if 0
- /* At one point this code was not commented out. In theory, this branch
- ** should never be hit, as this function should only be called after
- ** a locking-related function (i.e. fcntl()) has returned non-zero with
- ** the value of errno as the first argument. Since a system call has failed,
- ** errno should be non-zero.
- **
- ** Despite this, if errno really is zero, we still don't want to return
- ** SQLITE_OK. The system call failed, and *some* SQLite error should be
- ** propagated back to the caller. Commenting this branch out means errno==0
- ** will be handled by the "default:" case below.
- */
- case 0:
- return SQLITE_OK;
- #endif
- case EAGAIN:
- case ETIMEDOUT:
- case EBUSY:
- case EINTR:
- case ENOLCK:
- /* random NFS retry error, unless during file system support
- * introspection, in which it actually means what it says */
- return SQLITE_BUSY;
- case EACCES:
- /* EACCES is like EAGAIN during locking operations, but not any other time*/
- if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
- (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
- (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
- (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
- return SQLITE_BUSY;
- }
- /* else fall through */
- case EPERM:
- return SQLITE_PERM;
- /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
- ** this module never makes such a call. And the code in SQLite itself
- ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
- ** this case is also commented out. If the system does set errno to EDEADLK,
- ** the default SQLITE_IOERR_XXX code will be returned. */
- #if 0
- case EDEADLK:
- return SQLITE_IOERR_BLOCKED;
- #endif
- #if EOPNOTSUPP!=ENOTSUP
- case EOPNOTSUPP:
- /* something went terribly awry, unless during file system support
- * introspection, in which it actually means what it says */
- #endif
- #ifdef ENOTSUP
- case ENOTSUP:
- /* invalid fd, unless during file system support introspection, in which
- * it actually means what it says */
- #endif
- case EIO:
- case EBADF:
- case EINVAL:
- case ENOTCONN:
- case ENODEV:
- case ENXIO:
- case ENOENT:
- #ifdef ESTALE /* ESTALE is not defined on Interix systems */
- case ESTALE:
- #endif
- case ENOSYS:
- /* these should force the client to close the file and reconnect */
- default:
- return sqliteIOErr;
- }
- }
- /*
- **
- ** This function - unixLogError_x(), is only ever called via the macro
- ** unixLogError().
- **
- ** It is invoked after an error occurs in an OS function and errno has been
- ** set. It logs a message using sqlite3_log() containing the current value of
- ** errno and, if possible, the human-readable equivalent from strerror() or
- ** strerror_r().
- **
- ** The first argument passed to the macro should be the error code that
- ** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
- ** The two subsequent arguments should be the name of the OS function that
- ** failed (e.g. "unlink", "open") and the associated file-system path,
- ** if any.
- */
- #define rttLogError(a,b,c) rttLogErrorAtLine(a,b,c,__LINE__)
- static int rttLogErrorAtLine(
- int errcode, /* SQLite error code */
- const char *zFunc, /* Name of OS function that failed */
- const char *zPath, /* File path associated with error */
- int iLine /* Source line number where error occurred */
- ){
- char *zErr; /* Message from strerror() or equivalent */
- int iErrno = errno; /* Saved syscall error number */
- /* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
- ** the strerror() function to obtain the human-readable error message
- ** equivalent to errno. Otherwise, use strerror_r().
- */
- #if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
- char aErr[80];
- memset(aErr, 0, sizeof(aErr));
- zErr = aErr;
- /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
- ** assume that the system provides the GNU version of strerror_r() that
- ** returns a pointer to a buffer containing the error message. That pointer
- ** may point to aErr[], or it may point to some static storage somewhere.
- ** Otherwise, assume that the system provides the POSIX version of
- ** strerror_r(), which always writes an error message into aErr[].
- **
- ** If the code incorrectly assumes that it is the POSIX version that is
- ** available, the error message will often be an empty string. Not a
- ** huge problem. Incorrectly concluding that the GNU version is available
- ** could lead to a segfault though.
- */
- #if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
- zErr =
- # endif
- strerror_r(iErrno, aErr, sizeof(aErr)-1);
- #elif SQLITE_THREADSAFE
- /* This is a threadsafe build, but strerror_r() is not available. */
- zErr = "";
- #else
- /* Non-threadsafe build, use strerror(). */
- zErr = strerror(iErrno);
- #endif
- if( zPath==0 ) zPath = "";
- sqlite3_log(errcode,
- "os_rtt.c:%d: (%d) %s(%s) - %s",
- iLine, iErrno, zFunc, zPath, zErr
- );
- return errcode;
- }
- static int robust_ftruncate(int h, sqlite3_int64 sz){
- int rc;
- rc = -1;
- return rc;
- }
- /*
- ** Close a file descriptor.
- **
- ** We assume that close() almost always works, since it is only in a
- ** very sick application or on a very sick platform that it might fail.
- ** If it does fail, simply leak the file descriptor, but do log the
- ** error.
- **
- ** Note that it is not safe to retry close() after EINTR since the
- ** file descriptor might have already been reused by another thread.
- ** So we don't even try to recover from an EINTR. Just log the error
- ** and move on.
- */
- static void robust_close(rttFile *pFile, int h, int lineno){
- if( osClose(h) ){
- rttLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
- pFile ? pFile->zPath : 0, lineno);
- }
- }
- /*
- ** Check a rttFile that is a database. Verify the following:
- **
- ** (1) There is exactly one hard link on the file
- ** (2) The file is not a symbolic link
- ** (3) The file has not been renamed or unlinked
- **
- ** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
- */
- static void verifyDbFile(rttFile *pFile){
- struct stat buf;
- int rc;
- if( pFile->ctrlFlags & UNIXFILE_WARNED ){
- /* One or more of the following warnings have already been issued. Do not
- ** repeat them so as not to clutter the error log */
- return;
- }
- rc = osFstat(pFile->h, &buf);
- if( rc!=0 ){
- sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
- pFile->ctrlFlags |= UNIXFILE_WARNED;
- return;
- }
- if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
- sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
- pFile->ctrlFlags |= UNIXFILE_WARNED;
- return;
- }
- }
- /*
- ** This function performs the parts of the "close file" operation
- ** common to all locking schemes. It closes the directory and file
- ** handles, if they are valid, and sets all fields of the rttFile
- ** structure to 0.
- **
- ** It is *not* necessary to hold the mutex when this routine is called,
- ** even on VxWorks. A mutex will be acquired on VxWorks by the
- ** vxworksReleaseFileId() routine.
- */
- static int closeRttFile(sqlite3_file *id){
- rttFile *pFile = (rttFile*)id;
- if( pFile->h>=0 ){
- robust_close(pFile, pFile->h, __LINE__);
- pFile->h = -1;
- }
- OSTRACE(("CLOSE %-3d\n", pFile->h));
- OpenCounter(-1);
- memset(pFile, 0, sizeof(rttFile));
- return SQLITE_OK;
- }
- /************** End of the posix advisory lock implementation *****************
- ******************************************************************************/
- /******************************************************************************
- ****************************** No-op Locking **********************************
- **
- ** Of the various locking implementations available, this is by far the
- ** simplest: locking is ignored. No attempt is made to lock the database
- ** file for reading or writing.
- **
- ** This locking mode is appropriate for use on read-only databases
- ** (ex: databases that are burned into CD-ROM, for example.) It can
- ** also be used if the application employs some external mechanism to
- ** prevent simultaneous access of the same database by two or more
- ** database connections. But there is a serious risk of database
- ** corruption if this locking mode is used in situations where multiple
- ** database connections are accessing the same database file at the same
- ** time and one or more of those connections are writing.
- */
- static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
- UNUSED_PARAMETER(NotUsed);
- *pResOut = 0;
- return SQLITE_OK;
- }
- static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return SQLITE_OK;
- }
- static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return SQLITE_OK;
- }
- /*
- ** Close the file.
- */
- static int nolockClose(sqlite3_file *id) {
- return closeRttFile(id);
- }
- /******************* End of the no-op lock implementation *********************
- ******************************************************************************/
- /******************************************************************************
- ************************* Begin dot-file Locking ******************************
- **
- ** The dotfile locking implementation uses the existence of separate lock
- ** files (really a directory) to control access to the database. This works
- ** on just about every filesystem imaginable. But there are serious downsides:
- **
- ** (1) There is zero concurrency. A single reader blocks all other
- ** connections from reading or writing the database.
- **
- ** (2) An application crash or power loss can leave stale lock files
- ** sitting around that need to be cleared manually.
- **
- ** Nevertheless, a dotlock is an appropriate locking mode for use if no
- ** other locking strategy is available.
- **
- ** Dotfile locking works by creating a subdirectory in the same directory as
- ** the database and with the same name but with a ".lock" extension added.
- ** The existence of a lock directory implies an EXCLUSIVE lock. All other
- ** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
- */
- /*
- ** The file suffix added to the data base filename in order to create the
- ** lock directory.
- */
- #define DOTLOCK_SUFFIX ".lock"
- /*
- ** This routine checks if there is a RESERVED lock held on the specified
- ** file by this or any other process. If such a lock is held, set *pResOut
- ** to a non-zero value otherwise *pResOut is set to zero. The return value
- ** is set to SQLITE_OK unless an I/O error occurs during lock checking.
- **
- ** In dotfile locking, either a lock exists or it does not. So in this
- ** variation of CheckReservedLock(), *pResOut is set to true if any lock
- ** is held on the file and false if the file is unlocked.
- */
- static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
- int rc = SQLITE_OK;
- int reserved = 0;
- rttFile *pFile = (rttFile*)id;
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
- assert( pFile );
- /* Check if a thread in this process holds such a lock */
- if( pFile->eFileLock>SHARED_LOCK ){
- /* Either this connection or some other connection in the same process
- ** holds a lock on the file. No need to check further. */
- reserved = 1;
- }else{
- /* The lock is held if and only if the lockfile exists */
- const char *zLockFile = (const char*)pFile->lockingContext;
- reserved = 0;
- }
- OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
- *pResOut = reserved;
- return rc;
- }
- /*
- ** Lock the file with the lock specified by parameter eFileLock - one
- ** of the following:
- **
- ** (1) SHARED_LOCK
- ** (2) RESERVED_LOCK
- ** (3) PENDING_LOCK
- ** (4) EXCLUSIVE_LOCK
- **
- ** Sometimes when requesting one lock state, additional lock states
- ** are inserted in between. The locking might fail on one of the later
- ** transitions leaving the lock state different from what it started but
- ** still short of its goal. The following chart shows the allowed
- ** transitions and the inserted intermediate states:
- **
- ** UNLOCKED -> SHARED
- ** SHARED -> RESERVED
- ** SHARED -> (PENDING) -> EXCLUSIVE
- ** RESERVED -> (PENDING) -> EXCLUSIVE
- ** PENDING -> EXCLUSIVE
- **
- ** This routine will only increase a lock. Use the sqlite3OsUnlock()
- ** routine to lower a locking level.
- **
- ** With dotfile locking, we really only support state (4): EXCLUSIVE.
- ** But we track the other locking levels internally.
- */
- static int dotlockLock(sqlite3_file *id, int eFileLock) {
- rttFile *pFile = (rttFile*)id;
- char *zLockFile = (char *)pFile->lockingContext;
- int rc = SQLITE_OK;
- /* If we have any lock, then the lock file already exists. All we have
- ** to do is adjust our internal record of the lock level.
- */
- if( pFile->eFileLock > NO_LOCK ){
- pFile->eFileLock = eFileLock;
- return SQLITE_OK;
- }
- /* grab an exclusive lock */
- rc = osMkdir(zLockFile, 0777);
- if( rc<0 ){
- /* failed to open/create the lock directory */
- int tErrno = errno;
- if( EEXIST == tErrno ){
- rc = SQLITE_BUSY;
- } else {
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- }
- return rc;
- }
- /* got it, set the type and return ok */
- pFile->eFileLock = eFileLock;
- return rc;
- }
- /*
- ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
- ** must be either NO_LOCK or SHARED_LOCK.
- **
- ** If the locking level of the file descriptor is already at or below
- ** the requested locking level, this routine is a no-op.
- **
- ** When the locking level reaches NO_LOCK, delete the lock file.
- */
- static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
- rttFile *pFile = (rttFile*)id;
- char *zLockFile = (char *)pFile->lockingContext;
- int rc;
- assert( pFile );
- OSTRACE(("UNLOCK %d %d was %d tnm=%s (dotlock)\n", pFile->h, eFileLock,
- pFile->eFileLock, rt_thread_self()->name ));
- assert( eFileLock<=SHARED_LOCK );
- /* no-op if possible */
- if( pFile->eFileLock==eFileLock ){
- return SQLITE_OK;
- }
- /* To downgrade to shared, simply update our internal notion of the
- ** lock state. No need to mess with the file on disk.
- */
- if( eFileLock==SHARED_LOCK ){
- pFile->eFileLock = SHARED_LOCK;
- return SQLITE_OK;
- }
- /* To fully unlock the database, delete the lock file */
- assert( eFileLock==NO_LOCK );
- rc = osRmdir(zLockFile);
- if( rc<0 && errno==ENOTDIR ) rc = osUnlink(zLockFile);
- if( rc<0 ){
- int tErrno = errno;
- rc = 0;
- if( ENOENT != tErrno ){
- rc = SQLITE_IOERR_UNLOCK;
- }
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- return rc;
- }
- pFile->eFileLock = NO_LOCK;
- return SQLITE_OK;
- }
- /*
- ** Close a file. Make sure the lock has been released before closing.
- */
- static int dotlockClose(sqlite3_file *id) {
- int rc = SQLITE_OK;
- if( id ){
- rttFile *pFile = (rttFile*)id;
- dotlockUnlock(id, NO_LOCK);
- sqlite3_free(pFile->lockingContext);
- rc = closeRttFile(id);
- }
- return rc;
- }
- /****************** End of the dot-file lock implementation *******************
- ******************************************************************************/
- /******************************************************************************
- ************************** Begin flock Locking ********************************
- **
- ** Use the flock() system call to do file locking.
- **
- ** flock() locking is like dot-file locking in that the various
- ** fine-grain locking levels supported by SQLite are collapsed into
- ** a single exclusive lock. In other words, SHARED, RESERVED, and
- ** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite
- ** still works when you do this, but concurrency is reduced since
- ** only a single process can be reading the database at a time.
- **
- ** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
- ** compiling for VXWORKS.
- */
- #if SQLITE_ENABLE_LOCKING_STYLE
- #warning "rtt file lock not available"
- /*
- ** Retry flock() calls that fail with EINTR
- */
- static int robust_flock(int fd, int op){
- int rc = 0;
- return rc;
- }
- /*
- ** This routine checks if there is a RESERVED lock held on the specified
- ** file by this or any other process. If such a lock is held, set *pResOut
- ** to a non-zero value otherwise *pResOut is set to zero. The return value
- ** is set to SQLITE_OK unless an I/O error occurs during lock checking.
- */
- static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
- rttFile *pFile = (rttFile*)id;
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
- assert( pFile );
- /* Check if a thread in this process holds such a lock */
- if( pFile->eFileLock>SHARED_LOCK ){
- reserved = 1;
- }
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- /* attempt to get the lock */
- int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
- if( !lrc ){
- /* got the lock, unlock it */
- lrc = robust_flock(pFile->h, LOCK_UN);
- if ( lrc ) {
- int tErrno = errno;
- /* unlock failed with an error */
- lrc = SQLITE_IOERR_UNLOCK;
- if( IS_LOCK_ERROR(lrc) ){
- pFile->lastErrno = tErrno;
- rc = lrc;
- }
- }
- } else {
- int tErrno = errno;
- reserved = 1;
- /* someone else might have it reserved */
- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(lrc) ){
- pFile->lastErrno = tErrno;
- rc = lrc;
- }
- }
- }
- OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
- #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
- rc = SQLITE_OK;
- reserved=1;
- }
- #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
- *pResOut = reserved;
- return rc;
- }
- /*
- ** Lock the file with the lock specified by parameter eFileLock - one
- ** of the following:
- **
- ** (1) SHARED_LOCK
- ** (2) RESERVED_LOCK
- ** (3) PENDING_LOCK
- ** (4) EXCLUSIVE_LOCK
- **
- ** Sometimes when requesting one lock state, additional lock states
- ** are inserted in between. The locking might fail on one of the later
- ** transitions leaving the lock state different from what it started but
- ** still short of its goal. The following chart shows the allowed
- ** transitions and the inserted intermediate states:
- **
- ** UNLOCKED -> SHARED
- ** SHARED -> RESERVED
- ** SHARED -> (PENDING) -> EXCLUSIVE
- ** RESERVED -> (PENDING) -> EXCLUSIVE
- ** PENDING -> EXCLUSIVE
- **
- ** flock() only really support EXCLUSIVE locks. We track intermediate
- ** lock states in the sqlite3_file structure, but all locks SHARED or
- ** above are really EXCLUSIVE locks and exclude all other processes from
- ** access the file.
- **
- ** This routine will only increase a lock. Use the sqlite3OsUnlock()
- ** routine to lower a locking level.
- */
- static int flockLock(sqlite3_file *id, int eFileLock) {
- int rc = SQLITE_OK;
- rttFile *pFile = (rttFile*)id;
- assert( pFile );
- /* if we already have a lock, it is exclusive.
- ** Just adjust level and punt on outta here. */
- if (pFile->eFileLock > NO_LOCK) {
- pFile->eFileLock = eFileLock;
- return SQLITE_OK;
- }
- /* grab an exclusive lock */
- if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
- int tErrno = errno;
- /* didn't get, must be busy */
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- } else {
- /* got it, set the type and return ok */
- pFile->eFileLock = eFileLock;
- }
- OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
- rc==SQLITE_OK ? "ok" : "failed"));
- #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
- rc = SQLITE_BUSY;
- }
- #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
- return rc;
- }
- /*
- ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
- ** must be either NO_LOCK or SHARED_LOCK.
- **
- ** If the locking level of the file descriptor is already at or below
- ** the requested locking level, this routine is a no-op.
- */
- static int flockUnlock(sqlite3_file *id, int eFileLock) {
- rttFile *pFile = (rttFile*)id;
- assert( pFile );
- OSTRACE(("UNLOCK %d %d was %d tnm=%s (flock)\n", pFile->h, eFileLock,
- pFile->eFileLock, rt_thread_self()->name));
- assert( eFileLock<=SHARED_LOCK );
- /* no-op if possible */
- if( pFile->eFileLock==eFileLock ){
- return SQLITE_OK;
- }
- /* shared can just be set because we always have an exclusive */
- if (eFileLock==SHARED_LOCK) {
- pFile->eFileLock = eFileLock;
- return SQLITE_OK;
- }
- /* no, really, unlock. */
- if( robust_flock(pFile->h, LOCK_UN) ){
- #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- return SQLITE_OK;
- #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
- return SQLITE_IOERR_UNLOCK;
- }else{
- pFile->eFileLock = NO_LOCK;
- return SQLITE_OK;
- }
- }
- /*
- ** Close a file.
- */
- static int flockClose(sqlite3_file *id) {
- int rc = SQLITE_OK;
- if( id ){
- flockUnlock(id, NO_LOCK);
- rc = closeRttFile(id);
- }
- return rc;
- }
- #endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
- /******************* End of the flock lock implementation *********************
- ******************************************************************************/
- /******************************************************************************
- **************** Non-locking sqlite3_file methods *****************************
- **
- ** The next division contains implementations for all methods of the
- ** sqlite3_file object other than the locking methods. The locking
- ** methods were defined in divisions above (one locking method per
- ** division). Those methods that are common to all locking modes
- ** are gather together into this division.
- */
- /*
- ** Seek to the offset passed as the second argument, then read cnt
- ** bytes into pBuf. Return the number of bytes actually read.
- **
- ** NB: If you define USE_PREAD or USE_PREAD64, then it might also
- ** be necessary to define _XOPEN_SOURCE to be 500. This varies from
- ** one system to another. Since SQLite does not define USE_PREAD
- ** any any form by default, we will not attempt to define _XOPEN_SOURCE.
- ** See tickets #2741 and #2681.
- **
- ** To avoid stomping the errno value on a failed read the lastErrno value
- ** is set before returning.
- */
- static int seekAndRead(rttFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
- int got;
- int prior = 0;
- #if (!defined(USE_PREAD) && !defined(USE_PREAD64))
- i64 newOffset;
- #endif
- TIMER_START;
- assert( cnt==(cnt&0x1ffff) );
- assert( id->h>2 );
- cnt &= 0x1ffff;
- do{
- #if defined(USE_PREAD)
- #error "rtt pread not support"
- got = osPread(id->h, pBuf, cnt, offset);
- SimulateIOError( got = -1 );
- #elif defined(USE_PREAD64)
- #error "rtt pread64 not support"
- got = osPread64(id->h, pBuf, cnt, offset);
- SimulateIOError( got = -1 );
- #else
- newOffset = lseek(id->h, offset, SEEK_SET);
- SimulateIOError( newOffset-- );
- if( newOffset!=offset ){
- if( newOffset == -1 ){
- ((rttFile*)id)->lastErrno = errno;
- }else{
- ((rttFile*)id)->lastErrno = 0;
- }
- return -1;
- }
- got = osRead(id->h, pBuf, cnt);
- #endif
- if( got==cnt ) break;
- if( got<0 ){
- if( errno==EINTR ){ got = 1; continue; }
- prior = 0;
- ((rttFile*)id)->lastErrno = errno;
- break;
- }else if( got>0 ){
- cnt -= got;
- offset += got;
- prior += got;
- pBuf = (void*)(got + (char*)pBuf);
- }
- }while( got>0 );
- TIMER_END;
- OSTRACE(("READ %-3d %5d %7lld %llu\n",
- id->h, got+prior, offset-prior, TIMER_ELAPSED));
- return got+prior;
- }
- /*
- ** Read data from a file into a buffer. Return SQLITE_OK if all
- ** bytes were read successfully and SQLITE_IOERR if anything goes
- ** wrong.
- */
- static int rttRead(
- sqlite3_file *id,
- void *pBuf,
- int amt,
- sqlite3_int64 offset
- ){
- rttFile *pFile = (rttFile *)id;
- int got;
- assert( id );
- assert( offset>=0 );
- assert( amt>0 );
- got = seekAndRead(pFile, offset, pBuf, amt);
- if( got==amt ){
- return SQLITE_OK;
- }else if( got<0 ){
- /* lastErrno set by seekAndRead */
- return SQLITE_IOERR_READ;
- }else{
- pFile->lastErrno = 0; /* not a system error */
- /* Unread parts of the buffer must be zero-filled */
- memset(&((char*)pBuf)[got], 0, amt-got);
- return SQLITE_IOERR_SHORT_READ;
- }
- }
- /*
- ** Attempt to seek the file-descriptor passed as the first argument to
- ** absolute offset iOff, then attempt to write nBuf bytes of data from
- ** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise,
- ** return the actual number of bytes written (which may be less than
- ** nBuf).
- */
- static int seekAndWriteFd(
- int fd, /* File descriptor to write to */
- i64 iOff, /* File offset to begin writing at */
- const void *pBuf, /* Copy data from this buffer to the file */
- int nBuf, /* Size of buffer pBuf in bytes */
- int *piErrno /* OUT: Error number if error occurs */
- ){
- int rc = 0; /* Value returned by system call */
- assert( nBuf==(nBuf&0x1ffff) );
- assert( fd>2 );
- nBuf &= 0x1ffff;
- TIMER_START;
- #if defined(USE_PREAD)
- do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
- #elif defined(USE_PREAD64)
- do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
- #else
- do{
- i64 iSeek = lseek(fd, iOff, SEEK_SET);
- SimulateIOError( iSeek-- );
- if( iSeek!=iOff ){
- if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0);
- return -1;
- }
- rc = osWrite(fd, pBuf, nBuf);
- }while( rc<0 && errno==EINTR );
- #endif
- TIMER_END;
- OSTRACE(("WRITE %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED));
- if( rc<0 && piErrno ) *piErrno = errno;
- return rc;
- }
- /*
- ** Seek to the offset in id->offset then read cnt bytes into pBuf.
- ** Return the number of bytes actually read. Update the offset.
- **
- ** To avoid stomping the errno value on a failed write the lastErrno value
- ** is set before returning.
- */
- static int seekAndWrite(rttFile *id, i64 offset, const void *pBuf, int cnt){
- return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno);
- }
- /*
- ** Write data from a buffer into a file. Return SQLITE_OK on success
- ** or some other error code on failure.
- */
- static int rttWrite(
- sqlite3_file *id,
- const void *pBuf,
- int amt,
- sqlite3_int64 offset
- ){
- rttFile *pFile = (rttFile*)id;
- int wrote = 0;
- assert( id );
- assert( amt>0 );
- #ifdef SQLITE_DEBUG
- /* If we are doing a normal write to a database file (as opposed to
- ** doing a hot-journal rollback or a write to some file other than a
- ** normal database file) then record the fact that the database
- ** has changed. If the transaction counter is modified, record that
- ** fact too.
- */
- if( pFile->inNormalWrite ){
- pFile->dbUpdate = 1; /* The database has been modified */
- if( offset<=24 && offset+amt>=27 ){
- int rc;
- char oldCntr[4];
- SimulateIOErrorBenign(1);
- rc = seekAndRead(pFile, 24, oldCntr, 4);
- SimulateIOErrorBenign(0);
- if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
- pFile->transCntrChng = 1; /* The transaction counter has changed */
- }
- }
- }
- #endif
- while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){
- amt -= wrote;
- offset += wrote;
- pBuf = &((char*)pBuf)[wrote];
- }
- SimulateIOError(( wrote=(-1), amt=1 ));
- SimulateDiskfullError(( wrote=0, amt=1 ));
- if( amt>0 ){
- if( wrote<0 && pFile->lastErrno!=ENOSPC ){
- /* lastErrno set by seekAndWrite */
- return SQLITE_IOERR_WRITE;
- }else{
- pFile->lastErrno = 0; /* not a system error */
- return SQLITE_FULL;
- }
- }
- return SQLITE_OK;
- }
- #ifdef SQLITE_TEST
- /*
- ** Count the number of fullsyncs and normal syncs. This is used to test
- ** that syncs and fullsyncs are occurring at the right times.
- */
- int sqlite3_sync_count = 0;
- int sqlite3_fullsync_count = 0;
- #endif
- /*
- ** We do not trust systems to provide a working fdatasync(). Some do.
- ** Others do no. To be safe, we will stick with the (slightly slower)
- ** fsync(). If you know that your system does support fdatasync() correctly,
- ** then simply compile with -Dfdatasync=fdatasync
- */
- #if !defined(fdatasync)
- #include "dfs.h"
- #include "dfs_file.h"
- int fdatasync(fd)
- {
- struct dfs_fd *dfs_fd;
- dfs_fd = fd_get(fd);
- return dfs_file_flush(dfs_fd);
- }
- #endif
- /*
- ** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
- ** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently
- ** only available on Mac OS X. But that could change.
- */
- #ifdef F_FULLFSYNC
- # define HAVE_FULLFSYNC 0
- #endif
- /*
- ** The fsync() system call does not work as advertised on many
- ** unix systems. The following procedure is an attempt to make
- ** it work better.
- **
- ** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful
- ** for testing when we want to run through the test suite quickly.
- ** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
- ** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
- ** or power failure will likely corrupt the database file.
- **
- ** SQLite sets the dataOnly flag if the size of the file is unchanged.
- ** The idea behind dataOnly is that it should only write the file content
- ** to disk, not the inode. We only set dataOnly if the file size is
- ** unchanged since the file size is part of the inode. However,
- ** Ted Ts'o tells us that fdatasync() will also write the inode if the
- ** file size has changed. The only real difference between fdatasync()
- ** and fsync(), Ted tells us, is that fdatasync() will not flush the
- ** inode if the mtime or owner or other inode attributes have changed.
- ** We only care about the file size, not the other file attributes, so
- ** as far as SQLite is concerned, an fdatasync() is always adequate.
- ** So, we always use fdatasync() if it is available, regardless of
- ** the value of the dataOnly flag.
- */
- static int full_fsync(int fd, int fullSync, int dataOnly){
- int rc;
- /* The following "ifdef/elif/else/" block has the same structure as
- ** the one below. It is replicated here solely to avoid cluttering
- ** up the real code with the UNUSED_PARAMETER() macros.
- */
- #ifdef SQLITE_NO_SYNC
- UNUSED_PARAMETER(fd);
- UNUSED_PARAMETER(fullSync);
- UNUSED_PARAMETER(dataOnly);
- #elif HAVE_FULLFSYNC
- UNUSED_PARAMETER(dataOnly);
- #else
- UNUSED_PARAMETER(fullSync);
- UNUSED_PARAMETER(dataOnly);
- #endif
- /* Record the number of times that we do a normal fsync() and
- ** FULLSYNC. This is used during testing to verify that this procedure
- ** gets called with the correct arguments.
- */
- #ifdef SQLITE_TEST
- if( fullSync ) sqlite3_fullsync_count++;
- sqlite3_sync_count++;
- #endif
- /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
- ** no-op
- */
- #ifdef SQLITE_NO_SYNC
- rc = SQLITE_OK;
- #elif HAVE_FULLFSYNC
- #error "rtt not support FULLFSYNC"
- #else
- rc = fdatasync(fd);
- #endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
- return rc;
- }
- /*
- ** Make sure all writes to a particular file are committed to disk.
- **
- ** If dataOnly==0 then both the file itself and its metadata (file
- ** size, access time, etc) are synced. If dataOnly!=0 then only the
- ** file data is synced.
- **
- ** Under Rtt, also make sure that the directory entry for the file
- ** has been created by fsync-ing the directory that contains the file.
- ** If we do not do this and we encounter a power failure, the directory
- ** entry for the journal might not exist after we reboot. The next
- ** SQLite to access the file will not know that the journal exists (because
- ** the directory entry for the journal was never created) and the transaction
- ** will not roll back - possibly leading to database corruption.
- */
- static int rttSync(sqlite3_file *id, int flags){
- int rc;
- rttFile *pFile = (rttFile*)id;
- int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);
- int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;
- /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
- assert((flags&0x0F)==SQLITE_SYNC_NORMAL
- || (flags&0x0F)==SQLITE_SYNC_FULL
- );
- /* Rtt cannot, but some systems may return SQLITE_FULL from here. This
- ** line is to test that doing so does not cause any problems.
- */
- SimulateDiskfullError( return SQLITE_FULL );
- assert( pFile );
- OSTRACE(("SYNC %-3d\n", pFile->h));
- rc = full_fsync(pFile->h, isFullsync, isDataOnly);
- SimulateIOError( rc=1 );
- if( rc ){
- pFile->lastErrno = errno;
- return rttLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
- }
- /* Also fsync the directory containing the file if the DIRSYNC flag
- ** is set. This is a one-time occurrence. Many systems (examples: AIX)
- ** are unable to fsync a directory, so ignore errors on the fsync.
- */
- if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
- int dirfd;
- OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
- HAVE_FULLFSYNC, isFullsync));
- rc = osOpenDirectory(pFile->zPath, &dirfd);
- if( rc==SQLITE_OK && dirfd>=0 ){
- full_fsync(dirfd, 0, 0);
- robust_close(pFile, dirfd, __LINE__);
- }else if( rc==SQLITE_CANTOPEN ){
- rc = SQLITE_OK;
- }
- pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
- }
- return rc;
- }
- /*
- ** Truncate an open file to a specified size
- */
- static int rttTruncate(sqlite3_file *id, i64 nByte){
- rttFile *pFile = (rttFile *)id;
- int rc;
- assert( pFile );
- SimulateIOError( return SQLITE_IOERR_TRUNCATE );
- /* If the user has configured a chunk-size for this file, truncate the
- ** file so that it consists of an integer number of chunks (i.e. the
- ** actual file size after the operation may be larger than the requested
- ** size).
- */
- if( pFile->szChunk>0 ){
- nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
- }
- rc = robust_ftruncate(pFile->h, (off_t)nByte);
- if( rc ){
- pFile->lastErrno = errno;
- return rttLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
- }else{
- #ifdef SQLITE_DEBUG
- /* If we are doing a normal write to a database file (as opposed to
- ** doing a hot-journal rollback or a write to some file other than a
- ** normal database file) and we truncate the file to zero length,
- ** that effectively updates the change counter. This might happen
- ** when restoring a database using the backup API from a zero-length
- ** source.
- */
- if( pFile->inNormalWrite && nByte==0 ){
- pFile->transCntrChng = 1;
- }
- #endif
- return SQLITE_OK;
- }
- }
- /*
- ** Determine the current size of a file in bytes
- */
- static int rttFileSize(sqlite3_file *id, i64 *pSize){
- int rc;
- struct stat buf;
- assert( id );
- rc = osFstat(((rttFile*)id)->h, &buf);
- SimulateIOError( rc=1 );
- if( rc!=0 ){
- ((rttFile*)id)->lastErrno = errno;
- return SQLITE_IOERR_FSTAT;
- }
- *pSize = buf.st_size;
- /* When opening a zero-size database, the findInodeInfo() procedure
- ** writes a single byte into that file in order to work around a bug
- ** in the OS-X msdos filesystem. In order to avoid problems with upper
- ** layers, we need to report this file size as zero even though it is
- ** really 1. Ticket #3260.
- */
- if( *pSize==1 ) *pSize = 0;
- return SQLITE_OK;
- }
- /*
- ** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
- ** file-control operation. Enlarge the database to nBytes in size
- ** (rounded up to the next chunk-size). If the database is already
- ** nBytes or larger, this routine is a no-op.
- */
- static int fcntlSizeHint(rttFile *pFile, i64 nByte){
- if( pFile->szChunk>0 ){
- i64 nSize; /* Required file size */
- struct stat buf; /* Used to hold return values of fstat() */
- if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
- nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
- if( nSize>(i64)buf.st_size ){
- /* If the OS does not have posix_fallocate(), fake it. First use
- ** ftruncate() to set the file size, then write a single byte to
- ** the last byte in each block within the extended region. This
- ** is the same technique used by glibc to implement posix_fallocate()
- ** on systems that do not have a real fallocate() system call.
- */
- int nBlk = buf.st_blksize; /* File-system block size */
- i64 iWrite; /* Next offset to write to */
- if( robust_ftruncate(pFile->h, nSize) ){
- pFile->lastErrno = errno;
- return rttLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
- }
- iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
- while( iWrite<nSize ){
- int nWrite = seekAndWrite(pFile, iWrite, "", 1);
- if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
- iWrite += nBlk;
- }
- }
- }
- return SQLITE_OK;
- }
- /*
- ** If *pArg is inititially negative then this is a query. Set *pArg to
- ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
- **
- ** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
- */
- static void rttModeBit(rttFile *pFile, unsigned char mask, int *pArg){
- if( *pArg<0 ){
- *pArg = (pFile->ctrlFlags & mask)!=0;
- }else if( (*pArg)==0 ){
- pFile->ctrlFlags &= ~mask;
- }else{
- pFile->ctrlFlags |= mask;
- }
- }
- /* Forward declaration */
- static int rttGetTempname(int nBuf, char *zBuf);
- /*
- ** Information and control of an open file handle.
- */
- static int rttFileControl(sqlite3_file *id, int op, void *pArg){
- rttFile *pFile = (rttFile*)id;
- switch( op ){
- case SQLITE_FCNTL_LOCKSTATE: {
- *(int*)pArg = pFile->eFileLock;
- return SQLITE_OK;
- }
- case SQLITE_LAST_ERRNO: {
- *(int*)pArg = pFile->lastErrno;
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_CHUNK_SIZE: {
- pFile->szChunk = *(int *)pArg;
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_SIZE_HINT: {
- int rc;
- SimulateIOErrorBenign(1);
- rc = fcntlSizeHint(pFile, *(i64 *)pArg);
- SimulateIOErrorBenign(0);
- return rc;
- }
- case SQLITE_FCNTL_PERSIST_WAL: {
- rttModeBit(pFile, UNIXFILE_PERSIST_WAL, (int*)pArg);
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
- rttModeBit(pFile, UNIXFILE_PSOW, (int*)pArg);
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_VFSNAME: {
- *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_TEMPFILENAME: {
- char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
- if( zTFile ){
- rttGetTempname(pFile->pVfs->mxPathname, zTFile);
- *(char**)pArg = zTFile;
- }
- return SQLITE_OK;
- }
- #ifdef SQLITE_DEBUG
- /* The pager calls this method to signal that it has done
- ** a rollback and that the database is therefore unchanged and
- ** it hence it is OK for the transaction change counter to be
- ** unchanged.
- */
- case SQLITE_FCNTL_DB_UNCHANGED: {
- ((rttFile*)id)->dbUpdate = 0;
- return SQLITE_OK;
- }
- #endif
- }
- return SQLITE_NOTFOUND;
- }
- /*
- ** Return the sector size in bytes of the underlying block device for
- ** the specified file. This is almost always 512 bytes, but may be
- ** larger for some devices.
- **
- ** SQLite code assumes this function cannot fail. It also assumes that
- ** if two files are created in the same file-system directory (i.e.
- ** a database and its journal file) that the sector size will be the
- ** same for both.
- */
- static int rttSectorSize(sqlite3_file *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- return SQLITE_DEFAULT_SECTOR_SIZE;
- }
- /*
- ** Return the device characteristics for the file.
- **
- ** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
- ** However, that choice is contraversial since technically the underlying
- ** file system does not always provide powersafe overwrites. (In other
- ** words, after a power-loss event, parts of the file that were never
- ** written might end up being altered.) However, non-PSOW behavior is very,
- ** very rare. And asserting PSOW makes a large reduction in the amount
- ** of required I/O for journaling, since a lot of padding is eliminated.
- ** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control
- ** available to turn it off and URI query parameter available to turn it off.
- */
- static int rttDeviceCharacteristics(sqlite3_file *id){
- rttFile *p = (rttFile*)id;
- int rc = 0;
- if( p->ctrlFlags & UNIXFILE_PSOW ){
- rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
- }
- return rc;
- }
- #ifndef SQLITE_OMIT_WAL
- # error "WAL mode requires not support from the rt-thread, compile\
- with SQLITE_OMIT_WAL."
- #else
- # define rttShmMap 0
- # define rttShmLock 0
- # define rttShmBarrier 0
- # define rttShmUnmap 0
- #endif /* #ifndef SQLITE_OMIT_WAL */
- #if SQLITE_MAX_MMAP_SIZE>0
- #error "rtt not spportt mmap"
- #endif /* SQLITE_MAX_MMAP_SIZE>0 */
- /*
- ** If possible, return a pointer to a mapping of file fd starting at offset
- ** iOff. The mapping must be valid for at least nAmt bytes.
- **
- ** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
- ** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
- ** Finally, if an error does occur, return an SQLite error code. The final
- ** value of *pp is undefined in this case.
- **
- ** If this function does return a pointer, the caller must eventually
- ** release the reference by calling unixUnfetch().
- */
- static int rttFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
- *pp = 0;
- return SQLITE_OK;
- }
- /*
- ** If the third argument is non-NULL, then this function releases a
- ** reference obtained by an earlier call to unixFetch(). The second
- ** argument passed to this function must be the same as the corresponding
- ** argument that was passed to the unixFetch() invocation.
- **
- ** Or, if the third argument is NULL, then this function is being called
- ** to inform the VFS layer that, according to POSIX, any existing mapping
- ** may now be invalid and should be unmapped.
- */
- static int rttUnfetch(sqlite3_file *fd, i64 iOff, void *p){
- rttFile *pFd = (rttFile *)fd; /* The underlying database file */
- UNUSED_PARAMETER(iOff);
- return SQLITE_OK;
- }
- /*
- ** Here ends the implementation of all sqlite3_file methods.
- **
- ********************** End sqlite3_file Methods *******************************
- ******************************************************************************/
- /*
- ** This division contains definitions of sqlite3_io_methods objects that
- ** implement various file locking strategies. It also contains definitions
- ** of "finder" functions. A finder-function is used to locate the appropriate
- ** sqlite3_io_methods object for a particular database file. The pAppData
- ** field of the sqlite3_vfs VFS objects are initialized to be pointers to
- ** the correct finder-function for that VFS.
- **
- ** Most finder functions return a pointer to a fixed sqlite3_io_methods
- ** object. The only interesting finder-function is autolockIoFinder, which
- ** looks at the filesystem type and tries to guess the best locking
- ** strategy from that.
- **
- ** For finder-funtion F, two objects are created:
- **
- ** (1) The real finder-function named "FImpt()".
- **
- ** (2) A constant pointer to this function named just "F".
- **
- **
- ** A pointer to the F pointer is used as the pAppData value for VFS
- ** objects. We have to do this instead of letting pAppData point
- ** directly at the finder-function since C90 rules prevent a void*
- ** from be cast into a function pointer.
- **
- **
- ** Each instance of this macro generates two objects:
- **
- ** * A constant sqlite3_io_methods object call METHOD that has locking
- ** methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
- **
- ** * An I/O method finder function called FINDER that returns a pointer
- ** to the METHOD object in the previous bullet.
- */
- #define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK) \
- static const sqlite3_io_methods METHOD = { \
- VERSION, /* iVersion */ \
- CLOSE, /* xClose */ \
- rttRead, /* xRead */ \
- rttWrite, /* xWrite */ \
- rttTruncate, /* xTruncate */ \
- rttSync, /* xSync */ \
- rttFileSize, /* xFileSize */ \
- LOCK, /* xLock */ \
- UNLOCK, /* xUnlock */ \
- CKLOCK, /* xCheckReservedLock */ \
- rttFileControl, /* xFileControl */ \
- rttSectorSize, /* xSectorSize */ \
- rttDeviceCharacteristics, /* xDeviceCapabilities */ \
- rttShmMap, /* xShmMap */ \
- rttShmLock, /* xShmLock */ \
- rttShmBarrier, /* xShmBarrier */ \
- rttShmUnmap, /* xShmUnmap */ \
- rttFetch, /* xFetch */ \
- rttUnfetch, /* xUnfetch */ \
- }; \
- static const sqlite3_io_methods *FINDER##Impl(const char *z, rttFile *p){ \
- UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \
- return &METHOD; \
- } \
- static const sqlite3_io_methods *(*const FINDER)(const char*,rttFile *p) \
- = FINDER##Impl;
- /*
- ** Here are all of the sqlite3_io_methods objects for each of the
- ** locking strategies. Functions that return pointers to these methods
- ** are also created.
- */
- IOMETHODS(
- nolockIoFinder, /* Finder function name */
- nolockIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
- nolockClose, /* xClose method */
- nolockLock, /* xLock method */
- nolockUnlock, /* xUnlock method */
- nolockCheckReservedLock /* xCheckReservedLock method */
- )
- IOMETHODS(
- dotlockIoFinder, /* Finder function name */
- dotlockIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
- dotlockClose, /* xClose method */
- dotlockLock, /* xLock method */
- dotlockUnlock, /* xUnlock method */
- dotlockCheckReservedLock /* xCheckReservedLock method */
- )
- #if SQLITE_ENABLE_LOCKING_STYLE
- IOMETHODS(
- flockIoFinder, /* Finder function name */
- flockIoMethods, /* sqlite3_io_methods object name */
- 1, /* shared memory is disabled */
- flockClose, /* xClose method */
- flockLock, /* xLock method */
- flockUnlock, /* xUnlock method */
- flockCheckReservedLock /* xCheckReservedLock method */
- )
- #endif
- /*
- ** An abstract type for a pointer to a IO method finder function:
- */
- typedef const sqlite3_io_methods *(*finder_type)(const char*,rttFile*);
- /****************************************************************************
- **************************** sqlite3_vfs methods ****************************
- **
- ** This division contains the implementation of methods on the
- ** sqlite3_vfs object.
- */
- /*
- ** Initialize the contents of the rttFile structure pointed to by pId.
- */
- static int fillInRttFile(
- sqlite3_vfs *pVfs, /* Pointer to vfs object */
- int h, /* Open file descriptor of file being opened */
- sqlite3_file *pId, /* Write to the rttFile structure here */
- const char *zFilename, /* Name of the file being opened */
- int ctrlFlags /* Zero or more UNIXFILE_* values */
- ){
- const sqlite3_io_methods *pLockingStyle;
- rttFile *pNew = (rttFile *)pId;
- int rc = SQLITE_OK;
- assert( pNew->pInode==NULL );
- /* Usually the path zFilename should not be a relative pathname. The
- ** exception is when opening the proxy "conch" file in builds that
- ** include the special Apple locking styles.
- */
- assert( zFilename==0 || zFilename[0]=='/' );
- /* No locking occurs in temporary files */
- assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
- OSTRACE(("OPEN %-3d %s\n", h, zFilename));
- pNew->h = h;
- pNew->pVfs = pVfs;
- pNew->zPath = zFilename;
- pNew->ctrlFlags = (u8)ctrlFlags;
- if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
- "psow", SQLITE_POWERSAFE_OVERWRITE) ){
- pNew->ctrlFlags |= UNIXFILE_PSOW;
- }
- if( strcmp(pVfs->zName,"unix-excl")==0 ){
- pNew->ctrlFlags |= UNIXFILE_EXCL;
- }
- if( ctrlFlags & UNIXFILE_NOLOCK ){
- pLockingStyle = &nolockIoMethods;
- }else{
- pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew);
- #if SQLITE_ENABLE_LOCKING_STYLE
- /* Cache zFilename in the locking context (AFP and dotlock override) for
- ** proxyLock activation is possible (remote proxy is based on db name)
- ** zFilename remains valid until file is closed, to support */
- pNew->lockingContext = (void*)zFilename;
- #endif
- }
- if( pLockingStyle == &dotlockIoMethods ){
- /* Dotfile locking uses the file path so it needs to be included in
- ** the dotlockLockingContext
- */
- char *zLockFile;
- int nFilename;
- assert( zFilename!=0 );
- nFilename = (int)strlen(zFilename) + 6;
- zLockFile = (char *)sqlite3_malloc(nFilename);
- if( zLockFile==0 ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
- }
- pNew->lockingContext = zLockFile;
- }
- pNew->lastErrno = 0;
- if( rc!=SQLITE_OK ){
- if( h>=0 ) robust_close(pNew, h, __LINE__);
- }else{
- pNew->pMethod = pLockingStyle;
- OpenCounter(+1);
- verifyDbFile(pNew);
- }
- return rc;
- }
- /*
- ** Return the name of a directory in which to put temporary files.
- ** If no suitable temporary file directory can be found, return NULL.
- */
- static const char *rttTempFileDir(void){
- static const char *azDirs[] = {
- 0,
- "/sql",
- "/sql/tmp"
- "/tmp",
- 0 /* List terminator */
- };
- unsigned int i;
- struct stat buf;
- const char *zDir = 0;
- azDirs[0] = sqlite3_temp_directory;
- for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
- if( zDir==0 ) continue;
- if( osStat(zDir, &buf) ) continue;
- if( !S_ISDIR(buf.st_mode) ) continue;
- break;
- }
- return zDir;
- }
- /*
- ** Create a temporary file name in zBuf. zBuf must be allocated
- ** by the calling process and must be big enough to hold at least
- ** pVfs->mxPathname bytes.
- */
- static int rttGetTempname(int nBuf, char *zBuf){
- static const unsigned char zChars[] =
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789";
- unsigned int i, j;
- const char *zDir;
- /* It's odd to simulate an io-error here, but really this is just
- ** using the io-error infrastructure to test that SQLite handles this
- ** function failing.
- */
- SimulateIOError( return SQLITE_IOERR );
- zDir = rttTempFileDir();
- if( zDir==0 ) zDir = ".";
- /* Check that the output buffer is large enough for the temporary file
- ** name. If it is not, return SQLITE_ERROR.
- */
- if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){
- return SQLITE_ERROR;
- }
- do{
- sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
- j = (int)strlen(zBuf);
- sqlite3_randomness(15, &zBuf[j]);
- for(i=0; i<15; i++, j++){
- zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
- }
- zBuf[j] = 0;
- zBuf[j+1] = 0;
- }while( osAccess(zBuf,0)==0 );
- return SQLITE_OK;
- }
- /*
- ** Open the file zPath.
- **
- ** Previously, the SQLite OS layer used three functions in place of this
- ** one:
- **
- ** sqlite3OsOpenReadWrite();
- ** sqlite3OsOpenReadOnly();
- ** sqlite3OsOpenExclusive();
- **
- ** These calls correspond to the following combinations of flags:
- **
- ** ReadWrite() -> (READWRITE | CREATE)
- ** ReadOnly() -> (READONLY)
- ** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
- **
- ** The old OpenExclusive() accepted a boolean argument - "delFlag". If
- ** true, the file was configured to be automatically deleted when the
- ** file handle closed. To achieve the same effect using this new
- ** interface, add the DELETEONCLOSE flag to those specified above for
- ** OpenExclusive().
- */
- static int rttOpen(
- sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */
- const char *zPath, /* Pathname of file to be opened */
- sqlite3_file *pFile, /* The file descriptor to be filled in */
- int flags, /* Input flags to control the opening */
- int *pOutFlags /* Output flags returned to SQLite core */
- ){
- rttFile *p = (rttFile *)pFile;
- int fd = -1; /* File descriptor returned by open() */
- int openFlags = 0; /* Flags to pass to open() */
- int eType = flags&0xFFFFFF00; /* Type of file to open */
- int noLock; /* True to omit locking primitives */
- int rc = SQLITE_OK; /* Function Return Code */
- int ctrlFlags = 0; /* UNIXFILE_* flags */
- int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
- int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
- int isCreate = (flags & SQLITE_OPEN_CREATE);
- int isReadonly = (flags & SQLITE_OPEN_READONLY);
- int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
- #if SQLITE_ENABLE_LOCKING_STYLE
- int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
- #endif
- /* If creating a master or main-file journal, this function will open
- ** a file-descriptor on the directory too. The first time unixSync()
- ** is called the directory file descriptor will be fsync()ed and close()d.
- */
- int syncDir = (isCreate && (
- eType==SQLITE_OPEN_MASTER_JOURNAL
- || eType==SQLITE_OPEN_MAIN_JOURNAL
- || eType==SQLITE_OPEN_WAL
- ));
- /* If argument zPath is a NULL pointer, this function is required to open
- ** a temporary file. Use this buffer to store the file name in.
- */
- char zTmpname[MAX_PATHNAME+2];
- const char *zName = zPath;
- /* Check the following statements are true:
- **
- ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
- ** (b) if CREATE is set, then READWRITE must also be set, and
- ** (c) if EXCLUSIVE is set, then CREATE must also be set.
- ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
- */
- assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
- assert(isCreate==0 || isReadWrite);
- assert(isExclusive==0 || isCreate);
- assert(isDelete==0 || isCreate);
- /* The main DB, main journal, WAL file and master journal are never
- ** automatically deleted. Nor are they ever temporary files. */
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
- /* Assert that the upper layer has set one of the "file-type" flags. */
- assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
- || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
- || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
- || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
- );
- memset(p, 0, sizeof(rttFile));
- if( !zName ){
- /* If zName is NULL, the upper layer is requesting a temp file. */
- assert(isDelete && !syncDir);
- rc = rttGetTempname(MAX_PATHNAME+2, zTmpname);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- zName = zTmpname;
- /* Generated temporary filenames are always double-zero terminated
- ** for use by sqlite3_uri_parameter(). */
- assert( zName[strlen(zName)+1]==0 );
- }
- /* Determine the value of the flags parameter passed to POSIX function
- ** open(). These must be calculated even if open() is not called, as
- ** they may be stored as part of the file handle and used by the
- ** 'conch file' locking functions later on. */
- if( isReadonly ) openFlags |= O_RDONLY;
- if( isReadWrite ) openFlags |= O_RDWR;
- if( isCreate ) openFlags |= O_CREAT;
- if( isExclusive ) openFlags |= (O_EXCL|0/*O_NOFOLLOW8*/);
- openFlags |= (0/*O_LARGEFILE*/|O_BINARY);
- if( fd<0 ){
- mode_t openMode = 0; /* Permissions to create file with */
- fd = robust_open(zName, openFlags, openMode);
- OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
- if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
- /* Failed to open the file for read/write access. Try read-only. */
- flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
- openFlags &= ~(O_RDWR|O_CREAT);
- flags |= SQLITE_OPEN_READONLY;
- openFlags |= O_RDONLY;
- isReadonly = 1;
- fd = robust_open(zName, openFlags, openMode);
- }
- if( fd<0 ){
- rc = rttLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
- goto open_finished;
- }
- }
- assert( fd>=0 );
- if( pOutFlags ){
- *pOutFlags = flags;
- }
- if( isDelete ){
- osUnlink(zName);
- }
- #if SQLITE_ENABLE_LOCKING_STYLE
- else{
- p->openFlags = openFlags;
- }
- #endif
- noLock = eType!=SQLITE_OPEN_MAIN_DB;
- /* Set up appropriate ctrlFlags */
- if( isDelete ) ctrlFlags |= UNIXFILE_DELETE;
- if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY;
- if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK;
- if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC;
- if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
- rc = fillInRttFile(pVfs, fd, pFile, zPath, ctrlFlags);
- open_finished:
- return rc;
- }
- /*
- ** Delete the file at zPath. If the dirSync argument is true, fsync()
- ** the directory after deleting the file.
- */
- static int rttDelete(
- sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */
- const char *zPath, /* Name of file to be deleted */
- int dirSync /* If true, fsync() directory after deleting file */
- ){
- int rc = SQLITE_OK;
- UNUSED_PARAMETER(NotUsed);
- SimulateIOError(return SQLITE_IOERR_DELETE);
- if( osUnlink(zPath)==(-1) ){
- if( errno==ENOENT ){
- rc = SQLITE_IOERR_DELETE_NOENT;
- }else{
- rc = rttLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
- }
- return rc;
- }
- #ifndef SQLITE_DISABLE_DIRSYNC
- if( (dirSync & 1)!=0 ){
- int fd;
- rc = osOpenDirectory(zPath, &fd);
- if( rc==SQLITE_OK ){
- robust_close(0, fd, __LINE__);
- }else if( rc==SQLITE_CANTOPEN ){
- rc = SQLITE_OK;
- }
- }
- #endif
- return rc;
- }
- /*
- ** Test the existence of or access permissions of file zPath. The
- ** test performed depends on the value of flags:
- **
- ** SQLITE_ACCESS_EXISTS: Return 1 if the file exists
- ** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
- ** SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
- **
- ** Otherwise return 0.
- */
- static int rttAccess(
- sqlite3_vfs *NotUsed, /* The VFS containing this xAccess method */
- const char *zPath, /* Path of the file to examine */
- int flags, /* What do we want to learn about the zPath file? */
- int *pResOut /* Write result boolean here */
- ){
- int amode = 0;
- UNUSED_PARAMETER(NotUsed);
- SimulateIOError( return SQLITE_IOERR_ACCESS; );
- switch( flags ){
- case SQLITE_ACCESS_EXISTS:
- amode = F_OK;
- break;
- case SQLITE_ACCESS_READWRITE:
- amode = W_OK|R_OK;
- break;
- case SQLITE_ACCESS_READ:
- amode = R_OK;
- break;
- default:
- assert(!"Invalid flags argument");
- }
- *pResOut = (osAccess(zPath, amode)==0);
- if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
- struct stat buf;
- if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
- *pResOut = 0;
- }
- }
- return SQLITE_OK;
- }
- /*
- ** Turn a relative pathname into a full pathname. The relative path
- ** is stored as a nul-terminated string in the buffer pointed to by
- ** zPath.
- **
- ** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
- ** (in this case, MAX_PATHNAME bytes). The full-path is written to
- ** this buffer before returning.
- */
- static int rttFullPathname(
- sqlite3_vfs *pVfs, /* Pointer to vfs object */
- const char *zPath, /* Possibly relative input path */
- int nOut, /* Size of output buffer in bytes */
- char *zOut /* Output buffer */
- ){
- /* It's odd to simulate an io-error here, but really this is just
- ** using the io-error infrastructure to test that SQLite handles this
- ** function failing. This function could fail if, for example, the
- ** current working directory has been unlinked.
- */
- SimulateIOError( return SQLITE_ERROR );
- assert( pVfs->mxPathname==MAX_PATHNAME );
- UNUSED_PARAMETER(pVfs);
- zOut[nOut-1] = '\0';
- if( zPath[0]=='/' ){
- sqlite3_snprintf(nOut, zOut, "%s", zPath);
- }else{
- int nCwd;
- if( osGetcwd(zOut, nOut-1)==0 ){
- return rttLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
- }
- nCwd = (int)strlen(zOut);
- sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
- }
- return SQLITE_OK;
- }
- #ifndef SQLITE_OMIT_LOAD_EXTENSION
- # error "rtt not support load extension, compile with SQLITE_OMIT_WAL."
- #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
- #define rttDlOpen 0
- #define rttDlError 0
- #define rttDlSym 0
- #define rttDlClose 0
- #endif
- /*
- ** Write nBuf bytes of random data to the supplied buffer zBuf.
- */
- static int rttRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
- UNUSED_PARAMETER(NotUsed);
- assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int)));
- /* We have to initialize zBuf to prevent valgrind from reporting
- ** errors. The reports issued by valgrind are incorrect - we would
- ** prefer that the randomness be increased by making use of the
- ** uninitialized space in zBuf - but valgrind errors tend to worry
- ** some users. Rather than argue, it seems easier just to initialize
- ** the whole array and silence valgrind, even if that means less randomness
- ** in the random seed.
- **
- ** When testing, initializing zBuf[] to zero is all we do. That means
- ** that we always use the same random number sequence. This makes the
- ** tests repeatable.
- */
- memset(zBuf, 0, nBuf);
- {
- int i;
- char tick8, tick16;
- tick8 = (char)rt_tick_get();
- tick16 = (char)(rt_tick_get() >> 8);
- for (i=0; i<nBuf; i++)
- {
- zBuf[i] = (char)(i ^ tick8 ^ tick16);
- tick8 = zBuf[i];
- tick16 = ~(tick8 ^ tick16);
- }
- }
- return nBuf;
- }
- /*
- ** Sleep for a little while. Return the amount of time slept.
- ** The argument is the number of microseconds we want to sleep.
- ** The return value is the number of microseconds of sleep actually
- ** requested from the underlying operating system, a number which
- ** might be greater than or equal to the argument, but not less
- ** than the argument.
- */
- static int rttSleep(sqlite3_vfs *NotUsed, int microseconds){
- int seconds = (microseconds+999999)/1000000;
- osSleep(seconds * 1000);
- UNUSED_PARAMETER(NotUsed);
- return seconds*1000000;
- }
- /*
- ** The following variable, if set to a non-zero value, is interpreted as
- ** the number of seconds since 1970 and is used to set the result of
- ** sqlite3OsCurrentTime() during testing.
- */
- #ifdef SQLITE_TEST
- int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
- #endif
- #ifndef NO_GETTOD
- #define NO_GETTOD 1
- #endif
- /*
- ** Find the current time (in Universal Coordinated Time). Write into *piNow
- ** the current time and date as a Julian Day number times 86_400_000. In
- ** other words, write into *piNow the number of milliseconds since the Julian
- ** epoch of noon in Greenwich on November 24, 4714 B.C according to the
- ** proleptic Gregorian calendar.
- **
- ** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
- ** cannot be found.
- */
- static int rttCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
- static const sqlite3_int64 rttEpoch = 24405875*(sqlite3_int64)8640000;
- int rc = SQLITE_OK;
- #if defined(NO_GETTOD)
- time_t t;
- time(&t);
- *piNow = ((sqlite3_int64)t)*1000 + rttEpoch;
- #else
- struct timeval sNow;
- if( gettimeofday(&sNow, 0)==0 ){
- *piNow = rttEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
- }else{
- rc = SQLITE_ERROR;
- }
- #endif
- #ifdef SQLITE_TEST
- if( sqlite3_current_time ){
- *piNow = 1000*(sqlite3_int64)sqlite3_current_time + rttEpoch;
- }
- #endif
- UNUSED_PARAMETER(NotUsed);
- return rc;
- }
- /*
- ** Find the current time (in Universal Coordinated Time). Write the
- ** current time and date as a Julian Day number into *prNow and
- ** return 0. Return 1 if the time and date cannot be found.
- */
- static int rttCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
- sqlite3_int64 i = 0;
- int rc;
- UNUSED_PARAMETER(NotUsed);
- rc = rttCurrentTimeInt64(0, &i);
- *prNow = i/86400000.0;
- return rc;
- }
- /*
- ** We added the xGetLastError() method with the intention of providing
- ** better low-level error messages when operating-system problems come up
- ** during SQLite operation. But so far, none of that has been implemented
- ** in the core. So this routine is never called. For now, it is merely
- ** a place-holder.
- */
- static int rttGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
- UNUSED_PARAMETER(NotUsed);
- UNUSED_PARAMETER(NotUsed2);
- UNUSED_PARAMETER(NotUsed3);
- return 0;
- }
- /*
- ************************ End of sqlite3_vfs methods ***************************
- ******************************************************************************/
- /*
- ** Initialize the operating system interface.
- **
- ** This routine registers all VFS implementations for unix-like operating
- ** systems. This routine, and the sqlite3_os_end() routine that follows,
- ** should be the only routines in this file that are visible from other
- ** files.
- **
- ** This routine is called once during SQLite initialization and by a
- ** single thread. The memory allocation and mutex subsystems have not
- ** necessarily been initialized when this routine is called, and so they
- ** should not be used.
- */
- /*
- ** The following macro defines an initializer for an sqlite3_vfs object.
- ** The name of the VFS is NAME. The pAppData is a pointer to a pointer
- ** to the "finder" function. (pAppData is a pointer to a pointer because
- ** silly C90 rules prohibit a void* from being cast to a function pointer
- ** and so we have to go through the intermediate pointer to avoid problems
- ** when compiling with -pedantic-errors on GCC.)
- **
- ** The FINDER parameter to this macro is the name of the pointer to the
- ** finder-function. The finder-function returns a pointer to the
- ** sqlite_io_methods object that implements the desired locking
- ** behaviors. See the division above that contains the IOMETHODS
- ** macro for addition information on finder-functions.
- **
- ** Most finders simply return a pointer to a fixed sqlite3_io_methods
- ** object. But the "autolockIoFinder" available on MacOSX does a little
- ** more than that; it looks at the filesystem type that hosts the
- ** database file and tries to choose an locking method appropriate for
- ** that filesystem time.
- */
- #define UNIXVFS(VFSNAME, FINDER) { \
- 3, /* iVersion */ \
- sizeof(rttFile), /* szOsFile */ \
- MAX_PATHNAME, /* mxPathname */ \
- 0, /* pNext */ \
- VFSNAME, /* zName */ \
- (void*)&FINDER, /* pAppData */ \
- rttOpen, /* xOpen */ \
- rttDelete, /* xDelete */ \
- rttAccess, /* xAccess */ \
- rttFullPathname, /* xFullPathname */ \
- rttDlOpen, /* xDlOpen */ \
- rttDlError, /* xDlError */ \
- rttDlSym, /* xDlSym */ \
- rttDlClose, /* xDlClose */ \
- rttRandomness, /* xRandomness */ \
- rttSleep, /* xSleep */ \
- rttCurrentTime, /* xCurrentTime */ \
- rttGetLastError, /* xGetLastError */ \
- rttCurrentTimeInt64, /* xCurrentTimeInt64 */ \
- rttSetSystemCall, /* xSetSystemCall */ \
- rttGetSystemCall, /* xGetSystemCall */ \
- rttNextSystemCall, /* xNextSystemCall */ \
- }
- int sqlite3_os_init(void){
- /*
- ** All default VFSes for unix are contained in the following array.
- **
- ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
- ** by the SQLite core when the VFS is registered. So the following
- ** array cannot be const.
- */
- static sqlite3_vfs aVfs[] = {
- UNIXVFS("unix-none", nolockIoFinder ),
- UNIXVFS("unix-dotfile", dotlockIoFinder ),
- #if SQLITE_ENABLE_LOCKING_STYLE
- UNIXVFS("unix-flock", flockIoFinder ),
- #endif
- };
- unsigned int i; /* Loop counter */
- /* Double-check that the aSyscall[] array has been constructed
- ** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==24 );
- /* Register all VFSes defined in the aVfs[] array */
- for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
- sqlite3_vfs_register(&aVfs[i], i==0);
- }
- return SQLITE_OK;
- }
- /*
- ** Shutdown the operating system interface.
- **
- ** Some operating systems might need to do some cleanup in this routine,
- ** to release dynamically allocated objects. But not on unix.
- ** This routine is a no-op for unix.
- */
- int sqlite3_os_end(void){
- return SQLITE_OK;
- }
- #endif /* SQLITE_OS_RTT */
|