| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718 |
- /*
- ** 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_RTTHREAD /* This file is used for rt-thread only */
- #include <rtthread.h>
- #include <dfs_posix.h>
- /*
- ** Include code that is common to all os_*.c files
- */
- #include "os_common.h"
- #ifndef RT_USING_NEWLIB
- #ifndef EINTR
- #define EINTR 4 /* Interrupted system call */
- #endif
- #ifndef ENOLCK
- #define ENOLCK 46 /* No record locks available */
- #endif
- #ifndef EACCES
- #define EACCES 13 /* Permission denied */
- #endif
- #ifndef EPERM
- #define EPERM 1 /* Operation not permitted */
- #endif
- #ifndef ETIMEDOUT
- #define ETIMEDOUT 145 /* Connection timed out */
- #endif
- #ifndef ENOTCONN
- #define ENOTCONN 134 /* Transport endpoint is not connected */
- #endif
- #if defined(__GNUC__) || defined(__ADSPBLACKFIN__)
- int _gettimeofday(struct timeval *tp, void *ignore) __attribute__((weak));
- int _gettimeofday(struct timeval *tp, void *ignore)
- #elif defined(__CC_ARM)
- __weak int _gettimeofday(struct timeval *tp, void *ignore)
- #elif defined(__IAR_SYSTEMS_ICC__)
- #if __VER__ > 540
- __weak
- #endif
- int _gettimeofday(struct timeval *tp, void *ignore)
- #else
- int _gettimeofday(struct timeval *tp, void *ignore)
- #endif
- {
- return 0;
- }
- #endif /* RT_USING_NEWLIB */
- /*
- ** 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 rtthread ANSI APIs available (i.e. with certain exceptions
- ** based on the sub-platform)?
- */
- #if !defined(SQLITE_RTTHREAD_NO_ANSI)
- # warning "please ensure rtthread ANSI APIs is available, otherwise compile with\
- SQLITE_RTTHREAD_NO_ANSI"
- # define SQLITE_RTTHREAD_HAS_ANSI
- #endif
- /*
- ** Are most of the rtthread Unicode APIs available (i.e. with certain exceptions
- ** based on the sub-platform)?
- */
- #if !defined(SQLITE_RTTHREAD_NO_WIDE)
- # error "rtthread not support Unicode APIs"
- # define SQLITE_RTTHREAD_HAS_WIDE
- #endif
- /*
- ** Make sure at least one set of rtthread APIs is available.
- */
- #if !defined(SQLITE_RTTHREAD_HAS_ANSI) && !defined(SQLITE_RTTHREAD_HAS_WIDE)
- # error "At least one of SQLITE_RTTHREAD_HAS_ANSI and SQLITE_RTTHREAD_HAS_WIDE\
- must be defined."
- #endif
- /*
- ** Maximum pathname length (in chars) for rtthread. This should normally be
- ** MAX_PATH.
- */
- #ifndef SQLITE_RTTHREAD_MAX_PATH_CHARS
- # warning "default Maximum pathname length be 255, otherwise compile with\
- SQLITE_RTTHREAD_MAX_PATH_CHARS=?"
- # define SQLITE_RTTHREAD_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 rtthreadIsDirSep
- # define rtthreadIsDirSep(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 rtthreadGetDirDep
- # define rtthreadGetDirDep() "/"
- #endif
- /*
- ** The winFile structure is a subclass of sqlite3_file* specific to the win32
- ** portability layer.
- */
- typedef struct rtthreadFile rtthreadFile;
- struct rtthreadFile {
- sqlite3_io_methods const *pMethod; /* Always the first entry */
- sqlite3_vfs *pVfs; /* The VFS that created this rtthreadFile */
- 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 rtthreadFile.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 rtthread.
- **
- ** In order to facilitate testing on a rtthread 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_RTTHREAD && \
- defined(SQLITE_RTTHREAD_HAS_ANSI) && defined(SQLITE_RTTHREAD_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 rtthread_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 ((int(*)(int,void*,size_t))aSyscall[6].pCurrent)
- { "write", (sqlite3_syscall_ptr)write, 0 },
- #define osWrite ((int(*)(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 */
- /*
- **
- ** 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 rtthreadLogError(a,b,c) rtthreadLogErrorAtLine(a,b,c,__LINE__)
- static int rtthreadLogErrorAtLine(
- 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_rtthread.c:%d: (%d) %s(%s) - %s",
- iLine, iErrno, zFunc, zPath, zErr
- );
- return errcode;
- }
- /*
- ** 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("/000111sql.test111000", 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:rtthreadLogError(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 rtthreadSetSystemCall(
- 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 rtthreadGetSystemCall(
- 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* rtthreadNextSystemCall(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_rtthread_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 rtthreadEnterMutex(void){
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
- }
- static void rtthreadLeaveMutex(void){
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
- }
- #ifdef SQLITE_DEBUG
- static int rtthreadMutexHeld(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 DFS_STATUS_EAGAIN:
- case ETIMEDOUT:
- case DFS_STATUS_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 DFS_STATUS_EIO:
- case DFS_STATUS_EBADF:
- case DFS_STATUS_EINVAL:
- case ENOTCONN:
- case DFS_STATUS_ENODEV:
- case DFS_STATUS_ENXIO:
- case DFS_STATUS_ENOENT:
- #ifdef ESTALE /* ESTALE is not defined on Interix systems */
- case ESTALE:
- #endif
- case DFS_STATUS_ENOSYS:
- /* these should force the client to close the file and reconnect */
- default:
- return sqliteIOErr;
- }
- }
- 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(rtthreadFile *pFile, int h, int lineno){
- if( osClose(h) ){
- rtthreadLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
- pFile ? pFile->zPath : 0, lineno);
- }
- }
- /*
- ** Check a rtthreadFile 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(rtthreadFile *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;
- }
- #warning " struct \"stat\" has no field \"st_nlink\""
- #ifndef RT_USING_SQLITE
- 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;
- }
- #endif
- }
- /*
- ** 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 rtthreadFile
- ** 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 closeRtthreadFile(sqlite3_file *id){
- rtthreadFile *pFile = (rtthreadFile*)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(rtthreadFile));
- 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 closeRtthreadFile(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"
- /*
- ** Only set the lastErrno if the error code is a real error and not
- ** a normal expected return code of SQLITE_BUSY or SQLITE_OK
- */
- #define IS_LOCK_ERROR(x) (((x) != SQLITE_OK) && ((x) != SQLITE_BUSY))
- /*
- ** 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;
- rtthreadFile *pFile = (rtthreadFile*)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) {
- rtthreadFile *pFile = (rtthreadFile*)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( DFS_STATUS_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) {
- rtthreadFile *pFile = (rtthreadFile*)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==DFS_STATUS_ENOTDIR ) rc = osUnlink(zLockFile);
- if( rc<0 ){
- int tErrno = errno;
- rc = 0;
- if( DFS_STATUS_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 ){
- rtthreadFile *pFile = (rtthreadFile*)id;
- dotlockUnlock(id, NO_LOCK);
- sqlite3_free(pFile->lockingContext);
- rc = closeRtthreadFile(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 "rtthread 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;
- rtthreadFile *pFile = (rtthreadFile*)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;
- rtthreadFile *pFile = (rtthreadFile*)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) {
- rtthreadFile *pFile = (rtthreadFile*)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 = closeRtthreadFile(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(rtthreadFile *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 "rtthread pread not support"
- got = osPread(id->h, pBuf, cnt, offset);
- SimulateIOError( got = -1 );
- #elif defined(USE_PREAD64)
- #error "rtthread 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 ){
- ((rtthreadFile*)id)->lastErrno = errno;
- }else{
- ((rtthreadFile*)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;
- ((rtthreadFile*)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 rtthreadRead(
- sqlite3_file *id,
- void *pBuf,
- int amt,
- sqlite3_int64 offset
- ){
- rtthreadFile *pFile = (rtthreadFile *)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(rtthreadFile *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 rtthreadWrite(
- sqlite3_file *id,
- const void *pBuf,
- int amt,
- sqlite3_int64 offset
- ){
- rtthreadFile *pFile = (rtthreadFile*)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!=DFS_STATUS_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 "rtthread 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 Rtthread, 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 rtthreadSync(sqlite3_file *id, int flags){
- int rc;
- rtthreadFile *pFile = (rtthreadFile*)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
- );
- /* Rtthread 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 rtthreadLogError(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 rtthreadTruncate(sqlite3_file *id, i64 nByte){
- rtthreadFile *pFile = (rtthreadFile *)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 rtthreadLogError(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 rtthreadFileSize(sqlite3_file *id, i64 *pSize){
- int rc;
- struct stat buf;
- assert( id );
- rc = osFstat(((rtthreadFile*)id)->h, &buf);
- SimulateIOError( rc=1 );
- if( rc!=0 ){
- ((rtthreadFile*)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(rtthreadFile *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 = 4096; // no blksize in RT-Thread, use 4096. /* File-system block size */
- i64 iWrite; /* Next offset to write to */
- if( robust_ftruncate(pFile->h, nSize) ){
- pFile->lastErrno = errno;
- return rtthreadLogError(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 rtthreadModeBit(rtthreadFile *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 rtthreadGetTempname(int nBuf, char *zBuf);
- /*
- ** Information and control of an open file handle.
- */
- static int rtthreadFileControl(sqlite3_file *id, int op, void *pArg){
- rtthreadFile *pFile = (rtthreadFile*)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: {
- rtthreadModeBit(pFile, UNIXFILE_PERSIST_WAL, (int*)pArg);
- return SQLITE_OK;
- }
- case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
- rtthreadModeBit(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 ){
- rtthreadGetTempname(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: {
- ((rtthreadFile*)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 rtthreadSectorSize(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 rtthreadDeviceCharacteristics(sqlite3_file *id){
- rtthreadFile *p = (rtthreadFile*)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 rtthreadShmMap 0
- # define rtthreadShmLock 0
- # define rtthreadShmBarrier 0
- # define rtthreadShmUnmap 0
- #endif /* #ifndef SQLITE_OMIT_WAL */
- #if SQLITE_MAX_MMAP_SIZE>0
- #error "rtthread 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 rtthreadFetch(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 rtthreadUnfetch(sqlite3_file *fd, i64 iOff, void *p){
- rtthreadFile *pFd = (rtthreadFile *)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 */ \
- rtthreadRead, /* xRead */ \
- rtthreadWrite, /* xWrite */ \
- rtthreadTruncate, /* xTruncate */ \
- rtthreadSync, /* xSync */ \
- rtthreadFileSize, /* xFileSize */ \
- LOCK, /* xLock */ \
- UNLOCK, /* xUnlock */ \
- CKLOCK, /* xCheckReservedLock */ \
- rtthreadFileControl, /* xFileControl */ \
- rtthreadSectorSize, /* xSectorSize */ \
- rtthreadDeviceCharacteristics, /* xDeviceCapabilities */ \
- rtthreadShmMap, /* xShmMap */ \
- rtthreadShmLock, /* xShmLock */ \
- rtthreadShmBarrier, /* xShmBarrier */ \
- rtthreadShmUnmap, /* xShmUnmap */ \
- rtthreadFetch, /* xFetch */ \
- rtthreadUnfetch, /* xUnfetch */ \
- }; \
- static const sqlite3_io_methods *FINDER##Impl(const char *z, rtthreadFile *p){ \
- UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \
- return &METHOD; \
- } \
- static const sqlite3_io_methods *(*const FINDER)(const char*,rtthreadFile *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*,rtthreadFile*);
- /****************************************************************************
- **************************** sqlite3_vfs methods ****************************
- **
- ** This division contains the implementation of methods on the
- ** sqlite3_vfs object.
- */
- /*
- ** Initialize the contents of the rtthreadFile structure pointed to by pId.
- */
- static int fillInRtthreadFile(
- sqlite3_vfs *pVfs, /* Pointer to vfs object */
- int h, /* Open file descriptor of file being opened */
- sqlite3_file *pId, /* Write to the rtthreadFile structure here */
- const char *zFilename, /* Name of the file being opened */
- int ctrlFlags /* Zero or more UNIXFILE_* values */
- ){
- const sqlite3_io_methods *pLockingStyle;
- rtthreadFile *pNew = (rtthreadFile *)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* rtthreadTempFileDir(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 rtthreadGetTempname(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 = rtthreadTempFileDir();
- 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 rtthreadOpen(
- 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 */
- ){
- rtthreadFile *p = (rtthreadFile *)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(rtthreadFile));
- if( !zName ){
- /* If zName is NULL, the upper layer is requesting a temp file. */
- assert(isDelete && !syncDir);
- rc = rtthreadGetTempname(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!=DFS_STATUS_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 = rtthreadLogError(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 = fillInRtthreadFile(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 rtthreadDelete(
- 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==DFS_STATUS_ENOENT ){
- rc = SQLITE_IOERR_DELETE_NOENT;
- }else{
- rc = rtthreadLogError(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.
- */
- #ifndef F_OK
- # define F_OK 0
- #endif
- #ifndef R_OK
- # define R_OK 4
- #endif
- #ifndef W_OK
- # define W_OK 2
- #endif
- static int rtthreadAccess(
- 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 rtthreadFullPathname(
- 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 rtthreadLogError(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 "rtthread not support load extension, compile with SQLITE_OMIT_WAL."
- #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
- #define rtthreadDlOpen 0
- #define rtthreadDlError 0
- #define rtthreadDlSym 0
- #define rtthreadDlClose 0
- #endif
- /*
- ** Write nBuf bytes of random data to the supplied buffer zBuf.
- */
- static int rtthreadRandomness(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 rtthreadSleep(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 rtthreadCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
- static const sqlite3_int64 rtthreadEpoch = 24405875*(sqlite3_int64)8640000;
- int rc = SQLITE_OK;
- #if defined(NO_GETTOD)
- time_t t;
- time(&t);
- *piNow = ((sqlite3_int64)t)*1000 + rtthreadEpoch;
- #else
- struct timeval sNow;
- if( gettimeofday(&sNow, 0)==0 ){
- *piNow = rtthreadEpoch + 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 + rtthreadEpoch;
- }
- #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 rtthreadCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
- sqlite3_int64 i = 0;
- int rc;
- UNUSED_PARAMETER(NotUsed);
- rc = rtthreadCurrentTimeInt64(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 rtthreadGetLastError(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(rtthreadFile), /* szOsFile */ \
- MAX_PATHNAME, /* mxPathname */ \
- 0, /* pNext */ \
- VFSNAME, /* zName */ \
- (void*)&FINDER, /* pAppData */ \
- rtthreadOpen, /* xOpen */ \
- rtthreadDelete, /* xDelete */ \
- rtthreadAccess, /* xAccess */ \
- rtthreadFullPathname, /* xFullPathname */ \
- rtthreadDlOpen, /* xDlOpen */ \
- rtthreadDlError, /* xDlError */ \
- rtthreadDlSym, /* xDlSym */ \
- rtthreadDlClose, /* xDlClose */ \
- rtthreadRandomness, /* xRandomness */ \
- rtthreadSleep, /* xSleep */ \
- rtthreadCurrentTime, /* xCurrentTime */ \
- rtthreadGetLastError, /* xGetLastError */ \
- rtthreadCurrentTimeInt64, /* xCurrentTimeInt64 */ \
- rtthreadSetSystemCall, /* xSetSystemCall */ \
- rtthreadGetSystemCall, /* xGetSystemCall */ \
- rtthreadNextSystemCall, /* 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_RTTHREAD */
|