From b2057f506a09e2adef81fc77efd697d16ae14bec Mon Sep 17 00:00:00 2001 From: bernard Date: Thu, 2 Nov 2017 13:50:42 +0800 Subject: [External] Remove external from RT-Thread --- components/external/SQLite-3.8.1/src/os_rtthread.c | 2718 -------------------- 1 file changed, 2718 deletions(-) delete mode 100644 components/external/SQLite-3.8.1/src/os_rtthread.c (limited to 'components/external/SQLite-3.8.1/src/os_rtthread.c') diff --git a/components/external/SQLite-3.8.1/src/os_rtthread.c b/components/external/SQLite-3.8.1/src/os_rtthread.c deleted file mode 100644 index 6d57ed7098..0000000000 --- a/components/external/SQLite-3.8.1/src/os_rtthread.c +++ /dev/null @@ -1,2718 +0,0 @@ -/* -** 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 -#include - -/* -** 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 - -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; izPath : 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( iWritectrlFlags 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; imxPathname 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