diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-25 16:59:53 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-25 16:59:53 +0000 |
commit | 2c225270c09e184b4958c149103dbd62ac6deb44 (patch) | |
tree | b61b7e0122264779798100f6b587882de0e3e17e /third_party | |
parent | b77a85cca0c3400bb567108eea6f18f004675d25 (diff) | |
download | chromium_src-2c225270c09e184b4958c149103dbd62ac6deb44.zip chromium_src-2c225270c09e184b4958c149103dbd62ac6deb44.tar.gz chromium_src-2c225270c09e184b4958c149103dbd62ac6deb44.tar.bz2 |
Backport more SQLite changes to enable system-sqlite experiments.
BUG=22208
Review URL: http://codereview.chromium.org/7629003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98252 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
-rw-r--r-- | third_party/sqlite/amalgamation/sqlite3.c | 181 | ||||
-rw-r--r-- | third_party/sqlite/src/src/os_unix.c | 181 | ||||
-rw-r--r-- | third_party/sqlite/src/test/syscall.test | 2 | ||||
-rw-r--r-- | third_party/sqlite/system-sqlite.patch | 924 |
4 files changed, 1057 insertions, 231 deletions
diff --git a/third_party/sqlite/amalgamation/sqlite3.c b/third_party/sqlite/amalgamation/sqlite3.c index 3e794a9..9c66c16 100644 --- a/third_party/sqlite/amalgamation/sqlite3.c +++ b/third_party/sqlite/amalgamation/sqlite3.c @@ -24144,7 +24144,6 @@ struct unixFile { sqlite3_io_methods const *pMethod; /* Always the first entry */ unixInodeInfo *pInode; /* Info about locks on this inode */ int h; /* The file descriptor */ - int dirfd; /* File descriptor for the directory */ unsigned char eFileLock; /* The type of lock held on this fd */ unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ int lastErrno; /* The unix errno from last I/O error */ @@ -24188,6 +24187,7 @@ struct unixFile { */ #define UNIXFILE_EXCL 0x01 /* Connections from one process only */ #define UNIXFILE_RDONLY 0x02 /* Connection is read only */ +#define UNIXFILE_DIRSYNC 0x04 /* Directory sync needed */ /* ** Include code that is common to all os_*.c files @@ -24426,6 +24426,9 @@ SQLITE_API int sqlite3_open_file_count = 0; #define threadid 0 #endif +/* Forward reference */ +static int openDirectory(const char*, int*); + /* ** Many system calls are accessed through pointer-to-functions so that ** they may be overridden at runtime to facilitate fault injection during @@ -24522,6 +24525,12 @@ static struct unix_syscall { #endif #define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent) + { "unlink", (sqlite3_syscall_ptr)unlink, 0 }, +#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent) + + { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 }, +#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent) + }; /* End of the overrideable system calls */ /* @@ -25876,10 +25885,6 @@ static int unixUnlock(sqlite3_file *id, int eFileLock){ */ static int closeUnixFile(sqlite3_file *id){ unixFile *pFile = (unixFile*)id; - if( pFile->dirfd>=0 ){ - robust_close(pFile, pFile->dirfd, __LINE__); - pFile->dirfd=-1; - } if( pFile->h>=0 ){ robust_close(pFile, pFile->h, __LINE__); pFile->h = -1; @@ -25887,7 +25892,7 @@ static int closeUnixFile(sqlite3_file *id){ #if OS_VXWORKS if( pFile->pId ){ if( pFile->isDelete ){ - unlink(pFile->pId->zCanonicalName); + osUnlink(pFile->pId->zCanonicalName); } vxworksReleaseFileId(pFile->pId); pFile->pId = 0; @@ -26134,7 +26139,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) { /* To fully unlock the database, delete the lock file */ assert( eFileLock==NO_LOCK ); - if( unlink(zLockFile) ){ + if( osUnlink(zLockFile) ){ int rc = 0; int tErrno = errno; if( ENOENT != tErrno ){ @@ -27371,6 +27376,50 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ } /* +** 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 ){ +#ifdef FD_CLOEXEC + osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); +#endif + OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); + } + } + *pFd = fd; + return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); +} + +/* ** Make sure all writes to a particular file are committed to disk. ** ** If dataOnly==0 then both the file itself and its metadata (file @@ -27410,28 +27459,23 @@ static int unixSync(sqlite3_file *id, int flags){ pFile->lastErrno = errno; return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); } - if( pFile->dirfd>=0 ){ - OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, + + /* Also fsync the directory containing the file if the DIRSYNC flag + ** is set. This is a one-time occurrance. 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)); -#ifndef SQLITE_DISABLE_DIRSYNC - /* The directory sync is only attempted if full_fsync is - ** turned off or unavailable. If a full_fsync occurred above, - ** then the directory sync is superfluous. - */ - if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){ - /* - ** We have received multiple reports of fsync() returning - ** errors when applied to directories on certain file systems. - ** A failed directory sync is not a big deal. So it seems - ** better to ignore the error. Ticket #1657 - */ - /* pFile->lastErrno = errno; */ - /* return SQLITE_IOERR; */ + 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; } -#endif - /* Only need to sync once, so close the directory when we are done */ - robust_close(pFile, pFile->dirfd, __LINE__); - pFile->dirfd = -1; + pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; } return rc; } @@ -28255,7 +28299,7 @@ static int unixShmUnmap( assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ - if( deleteFlag && pShmNode->h>=0 ) unlink(pShmNode->zFilename); + if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename); unixShmPurge(pDbFd); } unixLeaveMutex(); @@ -28575,7 +28619,7 @@ void initUnixFile(sqlite3_file* file) { int fillInUnixFile( sqlite3_vfs *pVfs, /* Pointer to vfs object */ int h, /* Open file descriptor of file being opened */ - int dirfd, /* Directory file descriptor */ + int syncDir, /* True to sync directory on first sync */ sqlite3_file *pId, /* Write to the unixFile structure here */ const char *zFilename, /* Name of the file being opened */ int noLock, /* Omit locking if true */ @@ -28606,7 +28650,6 @@ int fillInUnixFile( OSTRACE(("OPEN %-3d %s\n", h, zFilename)); pNew->h = h; - pNew->dirfd = dirfd; pNew->zPath = zFilename; if( memcmp(pVfs->zName,"unix-excl",10)==0 ){ pNew->ctrlFlags = UNIXFILE_EXCL; @@ -28616,6 +28659,9 @@ int fillInUnixFile( if( isReadOnly ){ pNew->ctrlFlags |= UNIXFILE_RDONLY; } + if( syncDir ){ + pNew->ctrlFlags |= UNIXFILE_DIRSYNC; + } #if OS_VXWORKS pNew->pId = vxworksFindFileId(zFilename); @@ -28742,13 +28788,12 @@ int fillInUnixFile( if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); h = -1; - unlink(zFilename); + osUnlink(zFilename); isDelete = 0; } pNew->isDelete = isDelete; #endif if( rc!=SQLITE_OK ){ - if( dirfd>=0 ) robust_close(pNew, dirfd, __LINE__); if( h>=0 ) robust_close(pNew, h, __LINE__); }else{ pNew->pMethod = pLockingStyle; @@ -28758,37 +28803,6 @@ int fillInUnixFile( } /* -** 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. -** -** 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 ){ -#ifdef FD_CLOEXEC - osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); -#endif - OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); - } - } - *pFd = fd; - return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); -} - -/* ** Return the name of a directory in which to put temporary files. ** If no suitable temporary file directory can be found, return NULL. */ @@ -29083,7 +29097,6 @@ static int unixOpen( ){ unixFile *p = (unixFile *)pFile; int fd = -1; /* File descriptor returned by open() */ - int dirfd = -1; /* Directory file descriptor */ int openFlags = 0; /* Flags to pass to open() */ int eType = flags&0xFFFFFF00; /* Type of file to open */ int noLock; /* True to omit locking primitives */ @@ -29102,7 +29115,7 @@ static int unixOpen( ** 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 isOpenDirectory = (isCreate && ( + int syncDir = (isCreate && ( eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_WAL @@ -29149,7 +29162,7 @@ static int unixOpen( } }else if( !zName ){ /* If zName is NULL, the upper layer is requesting a temp file. */ - assert(isDelete && !isOpenDirectory); + assert(isDelete && !syncDir); rc = unixGetTempname(MAX_PATHNAME+1, zTmpname); if( rc!=SQLITE_OK ){ return rc; @@ -29202,7 +29215,7 @@ static int unixOpen( #if OS_VXWORKS zPath = zName; #else - unlink(zName); + osUnlink(zName); #endif } #if SQLITE_ENABLE_LOCKING_STYLE @@ -29211,19 +29224,6 @@ static int unixOpen( } #endif - if( isOpenDirectory ){ - rc = openDirectory(zPath, &dirfd); - if( rc!=SQLITE_OK ){ - /* It is safe to close fd at this point, because it is guaranteed not - ** to be open on a database file. If it were open on a database file, - ** it would not be safe to close as this would release any locks held - ** on the file by this process. */ - assert( eType!=SQLITE_OPEN_MAIN_DB ); - robust_close(p, fd, __LINE__); - goto open_finished; - } - } - #ifdef FD_CLOEXEC osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); #endif @@ -29235,7 +29235,6 @@ static int unixOpen( struct statfs fsInfo; if( fstatfs(fd, &fsInfo) == -1 ){ ((unixFile*)pFile)->lastErrno = errno; - if( dirfd>=0 ) robust_close(p, dirfd, __LINE__); robust_close(p, fd, __LINE__); return SQLITE_IOERR_ACCESS; } @@ -29267,9 +29266,6 @@ static int unixOpen( ** not while other file descriptors opened by the same process on ** the same file are working. */ p->lastErrno = errno; - if( dirfd>=0 ){ - robust_close(p, dirfd, __LINE__); - } robust_close(p, fd, __LINE__); rc = SQLITE_IOERR_ACCESS; goto open_finished; @@ -29277,7 +29273,7 @@ static int unixOpen( useProxy = !(fsInfo.f_flags&MNT_LOCAL); } if( useProxy ){ - rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, + rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, isDelete, isReadonly); if( rc==SQLITE_OK ){ rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); @@ -29295,7 +29291,7 @@ static int unixOpen( } #endif - rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, + rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, isDelete, isReadonly); open_finished: if( rc!=SQLITE_OK ){ @@ -29317,13 +29313,13 @@ static int unixDelete( int rc = SQLITE_OK; UNUSED_PARAMETER(NotUsed); SimulateIOError(return SQLITE_IOERR_DELETE); - if( unlink(zPath)==(-1) && errno!=ENOENT ){ + if( osUnlink(zPath)==(-1) && errno!=ENOENT ){ return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); } #ifndef SQLITE_DISABLE_DIRSYNC if( dirSync ){ int fd; - rc = openDirectory(zPath, &fd); + rc = osOpenDirectory(zPath, &fd); if( rc==SQLITE_OK ){ #if OS_VXWORKS if( fsync(fd)==-1 ) @@ -29334,6 +29330,8 @@ static int unixDelete( rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); } robust_close(0, fd, __LINE__); + }else if( rc==SQLITE_CANTOPEN ){ + rc = SQLITE_OK; } } #endif @@ -29895,7 +29893,6 @@ static int proxyCreateUnixFile( int islockfile /* if non zero missing dirs will be created */ ) { int fd = -1; - int dirfd = -1; unixFile *pNew; int rc = SQLITE_OK; int openFlags = O_RDWR | O_CREAT; @@ -29960,7 +29957,7 @@ static int proxyCreateUnixFile( pUnused->flags = openFlags; pNew->pUnused = pUnused; - rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0, 0); + rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0); if( rc==SQLITE_OK ){ *ppFile = pNew; return SQLITE_OK; @@ -30074,7 +30071,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ end_breaklock: if( rc ){ if( fd>=0 ){ - unlink(tPath); + osUnlink(tPath); robust_close(pFile, fd, __LINE__); } fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); @@ -30897,7 +30894,7 @@ SQLITE_API int sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==16 ); + assert( ArraySize(aSyscall)==18 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c index e5b2540..804c588 100644 --- a/third_party/sqlite/src/src/os_unix.c +++ b/third_party/sqlite/src/src/os_unix.c @@ -204,7 +204,6 @@ struct unixFile { sqlite3_io_methods const *pMethod; /* Always the first entry */ unixInodeInfo *pInode; /* Info about locks on this inode */ int h; /* The file descriptor */ - int dirfd; /* File descriptor for the directory */ unsigned char eFileLock; /* The type of lock held on this fd */ unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ int lastErrno; /* The unix errno from last I/O error */ @@ -248,6 +247,7 @@ struct unixFile { */ #define UNIXFILE_EXCL 0x01 /* Connections from one process only */ #define UNIXFILE_RDONLY 0x02 /* Connection is read only */ +#define UNIXFILE_DIRSYNC 0x04 /* Directory sync needed */ /* ** Include code that is common to all os_*.c files @@ -281,6 +281,9 @@ struct unixFile { #define threadid 0 #endif +/* Forward reference */ +static int openDirectory(const char*, int*); + /* ** Many system calls are accessed through pointer-to-functions so that ** they may be overridden at runtime to facilitate fault injection during @@ -377,6 +380,12 @@ static struct unix_syscall { #endif #define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent) + { "unlink", (sqlite3_syscall_ptr)unlink, 0 }, +#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent) + + { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 }, +#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent) + }; /* End of the overrideable system calls */ /* @@ -1731,10 +1740,6 @@ static int unixUnlock(sqlite3_file *id, int eFileLock){ */ static int closeUnixFile(sqlite3_file *id){ unixFile *pFile = (unixFile*)id; - if( pFile->dirfd>=0 ){ - robust_close(pFile, pFile->dirfd, __LINE__); - pFile->dirfd=-1; - } if( pFile->h>=0 ){ robust_close(pFile, pFile->h, __LINE__); pFile->h = -1; @@ -1742,7 +1747,7 @@ static int closeUnixFile(sqlite3_file *id){ #if OS_VXWORKS if( pFile->pId ){ if( pFile->isDelete ){ - unlink(pFile->pId->zCanonicalName); + osUnlink(pFile->pId->zCanonicalName); } vxworksReleaseFileId(pFile->pId); pFile->pId = 0; @@ -1989,7 +1994,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) { /* To fully unlock the database, delete the lock file */ assert( eFileLock==NO_LOCK ); - if( unlink(zLockFile) ){ + if( osUnlink(zLockFile) ){ int rc = 0; int tErrno = errno; if( ENOENT != tErrno ){ @@ -3226,6 +3231,50 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ } /* +** 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 ){ +#ifdef FD_CLOEXEC + osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); +#endif + OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); + } + } + *pFd = fd; + return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); +} + +/* ** Make sure all writes to a particular file are committed to disk. ** ** If dataOnly==0 then both the file itself and its metadata (file @@ -3265,28 +3314,23 @@ static int unixSync(sqlite3_file *id, int flags){ pFile->lastErrno = errno; return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); } - if( pFile->dirfd>=0 ){ - OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, + + /* Also fsync the directory containing the file if the DIRSYNC flag + ** is set. This is a one-time occurrance. 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)); -#ifndef SQLITE_DISABLE_DIRSYNC - /* The directory sync is only attempted if full_fsync is - ** turned off or unavailable. If a full_fsync occurred above, - ** then the directory sync is superfluous. - */ - if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){ - /* - ** We have received multiple reports of fsync() returning - ** errors when applied to directories on certain file systems. - ** A failed directory sync is not a big deal. So it seems - ** better to ignore the error. Ticket #1657 - */ - /* pFile->lastErrno = errno; */ - /* return SQLITE_IOERR; */ + 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; } -#endif - /* Only need to sync once, so close the directory when we are done */ - robust_close(pFile, pFile->dirfd, __LINE__); - pFile->dirfd = -1; + pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; } return rc; } @@ -4110,7 +4154,7 @@ static int unixShmUnmap( assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ - if( deleteFlag && pShmNode->h>=0 ) unlink(pShmNode->zFilename); + if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename); unixShmPurge(pDbFd); } unixLeaveMutex(); @@ -4430,7 +4474,7 @@ void initUnixFile(sqlite3_file* file) { int fillInUnixFile( sqlite3_vfs *pVfs, /* Pointer to vfs object */ int h, /* Open file descriptor of file being opened */ - int dirfd, /* Directory file descriptor */ + int syncDir, /* True to sync directory on first sync */ sqlite3_file *pId, /* Write to the unixFile structure here */ const char *zFilename, /* Name of the file being opened */ int noLock, /* Omit locking if true */ @@ -4461,7 +4505,6 @@ int fillInUnixFile( OSTRACE(("OPEN %-3d %s\n", h, zFilename)); pNew->h = h; - pNew->dirfd = dirfd; pNew->zPath = zFilename; if( memcmp(pVfs->zName,"unix-excl",10)==0 ){ pNew->ctrlFlags = UNIXFILE_EXCL; @@ -4471,6 +4514,9 @@ int fillInUnixFile( if( isReadOnly ){ pNew->ctrlFlags |= UNIXFILE_RDONLY; } + if( syncDir ){ + pNew->ctrlFlags |= UNIXFILE_DIRSYNC; + } #if OS_VXWORKS pNew->pId = vxworksFindFileId(zFilename); @@ -4597,13 +4643,12 @@ int fillInUnixFile( if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); h = -1; - unlink(zFilename); + osUnlink(zFilename); isDelete = 0; } pNew->isDelete = isDelete; #endif if( rc!=SQLITE_OK ){ - if( dirfd>=0 ) robust_close(pNew, dirfd, __LINE__); if( h>=0 ) robust_close(pNew, h, __LINE__); }else{ pNew->pMethod = pLockingStyle; @@ -4613,37 +4658,6 @@ int fillInUnixFile( } /* -** 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. -** -** 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 ){ -#ifdef FD_CLOEXEC - osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); -#endif - OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); - } - } - *pFd = fd; - return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); -} - -/* ** Return the name of a directory in which to put temporary files. ** If no suitable temporary file directory can be found, return NULL. */ @@ -4938,7 +4952,6 @@ static int unixOpen( ){ unixFile *p = (unixFile *)pFile; int fd = -1; /* File descriptor returned by open() */ - int dirfd = -1; /* Directory file descriptor */ int openFlags = 0; /* Flags to pass to open() */ int eType = flags&0xFFFFFF00; /* Type of file to open */ int noLock; /* True to omit locking primitives */ @@ -4957,7 +4970,7 @@ static int unixOpen( ** 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 isOpenDirectory = (isCreate && ( + int syncDir = (isCreate && ( eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_WAL @@ -5004,7 +5017,7 @@ static int unixOpen( } }else if( !zName ){ /* If zName is NULL, the upper layer is requesting a temp file. */ - assert(isDelete && !isOpenDirectory); + assert(isDelete && !syncDir); rc = unixGetTempname(MAX_PATHNAME+1, zTmpname); if( rc!=SQLITE_OK ){ return rc; @@ -5057,7 +5070,7 @@ static int unixOpen( #if OS_VXWORKS zPath = zName; #else - unlink(zName); + osUnlink(zName); #endif } #if SQLITE_ENABLE_LOCKING_STYLE @@ -5066,19 +5079,6 @@ static int unixOpen( } #endif - if( isOpenDirectory ){ - rc = openDirectory(zPath, &dirfd); - if( rc!=SQLITE_OK ){ - /* It is safe to close fd at this point, because it is guaranteed not - ** to be open on a database file. If it were open on a database file, - ** it would not be safe to close as this would release any locks held - ** on the file by this process. */ - assert( eType!=SQLITE_OPEN_MAIN_DB ); - robust_close(p, fd, __LINE__); - goto open_finished; - } - } - #ifdef FD_CLOEXEC osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); #endif @@ -5090,7 +5090,6 @@ static int unixOpen( struct statfs fsInfo; if( fstatfs(fd, &fsInfo) == -1 ){ ((unixFile*)pFile)->lastErrno = errno; - if( dirfd>=0 ) robust_close(p, dirfd, __LINE__); robust_close(p, fd, __LINE__); return SQLITE_IOERR_ACCESS; } @@ -5122,9 +5121,6 @@ static int unixOpen( ** not while other file descriptors opened by the same process on ** the same file are working. */ p->lastErrno = errno; - if( dirfd>=0 ){ - robust_close(p, dirfd, __LINE__); - } robust_close(p, fd, __LINE__); rc = SQLITE_IOERR_ACCESS; goto open_finished; @@ -5132,7 +5128,7 @@ static int unixOpen( useProxy = !(fsInfo.f_flags&MNT_LOCAL); } if( useProxy ){ - rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, + rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, isDelete, isReadonly); if( rc==SQLITE_OK ){ rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); @@ -5150,7 +5146,7 @@ static int unixOpen( } #endif - rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, + rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, isDelete, isReadonly); open_finished: if( rc!=SQLITE_OK ){ @@ -5172,13 +5168,13 @@ static int unixDelete( int rc = SQLITE_OK; UNUSED_PARAMETER(NotUsed); SimulateIOError(return SQLITE_IOERR_DELETE); - if( unlink(zPath)==(-1) && errno!=ENOENT ){ + if( osUnlink(zPath)==(-1) && errno!=ENOENT ){ return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); } #ifndef SQLITE_DISABLE_DIRSYNC if( dirSync ){ int fd; - rc = openDirectory(zPath, &fd); + rc = osOpenDirectory(zPath, &fd); if( rc==SQLITE_OK ){ #if OS_VXWORKS if( fsync(fd)==-1 ) @@ -5189,6 +5185,8 @@ static int unixDelete( rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); } robust_close(0, fd, __LINE__); + }else if( rc==SQLITE_CANTOPEN ){ + rc = SQLITE_OK; } } #endif @@ -5750,7 +5748,6 @@ static int proxyCreateUnixFile( int islockfile /* if non zero missing dirs will be created */ ) { int fd = -1; - int dirfd = -1; unixFile *pNew; int rc = SQLITE_OK; int openFlags = O_RDWR | O_CREAT; @@ -5815,7 +5812,7 @@ static int proxyCreateUnixFile( pUnused->flags = openFlags; pNew->pUnused = pUnused; - rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0, 0); + rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0); if( rc==SQLITE_OK ){ *ppFile = pNew; return SQLITE_OK; @@ -5929,7 +5926,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ end_breaklock: if( rc ){ if( fd>=0 ){ - unlink(tPath); + osUnlink(tPath); robust_close(pFile, fd, __LINE__); } fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); @@ -6752,7 +6749,7 @@ int sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==16 ); + assert( ArraySize(aSyscall)==18 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ diff --git a/third_party/sqlite/src/test/syscall.test b/third_party/sqlite/src/test/syscall.test index 4442612..201bd63 100644 --- a/third_party/sqlite/src/test/syscall.test +++ b/third_party/sqlite/src/test/syscall.test @@ -59,7 +59,7 @@ do_test 2.1.2 { test_syscall exists nosuchcall } 0 foreach s { open close access getcwd stat fstat ftruncate fcntl read pread write pwrite fchmod fallocate - pread64 pwrite64 + pread64 pwrite64 unlink openDirectory } { if {[test_syscall exists $s]} {lappend syscall_list $s} } diff --git a/third_party/sqlite/system-sqlite.patch b/third_party/sqlite/system-sqlite.patch index f61f019..4760cea 100644 --- a/third_party/sqlite/system-sqlite.patch +++ b/third_party/sqlite/system-sqlite.patch @@ -1,48 +1,880 @@ -This is a backport of http://sqlite.org/src/ci/9109128cb5, -which is needed for experiments with using unpatched sqlite. +This is a backport of the following sqlite changes: + +1. http://sqlite.org/src/ci/9109128cb5 +2. http://sqlite.org/src/ci/713b1b7dc1 +3. http://sqlite.org/src/ci/8d1b5c3ac0 +4. http://sqlite.org/src/ci/6b236069e1 +5. http://sqlite.org/src/ci/880b51150a + +which are needed for experiments with using unpatched sqlite. If you hit a merge conflict on this file it is most likely -that you've upgraded to version of sqlite that includes this patch. -Index: src/os_unix.c -=================================================================== ---- src/os_unix.c -+++ src/os_unix.c -@@ -4787,11 +4787,11 @@ - ** ignored and -1 is returned. The caller will try to open a new file - ** descriptor on the same path, fail, and return an error to SQLite. - ** - ** Even if a subsequent open() call does succeed, the consequences of - ** not searching for a resusable file descriptor are not dire. */ -- if( 0==stat(zPath, &sStat) ){ -+ if( 0==osStat(zPath, &sStat) ){ - unixInodeInfo *pInode; - - unixEnterMutex(); - pInode = inodeList; - while( pInode && (pInode->fileId.dev!=sStat.st_dev -@@ -4863,11 +4863,11 @@ - while( nDb>0 && zPath[nDb]!='-' ) nDb--; - if( nDb==0 ) return SQLITE_OK; - memcpy(zDb, zPath, nDb); - zDb[nDb] = '\0'; - -- if( 0==stat(zDb, &sStat) ){ -+ if( 0==osStat(zDb, &sStat) ){ - *pMode = sStat.st_mode & 0777; - }else{ - rc = SQLITE_IOERR_FSTAT; - } - }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ -@@ -5208,11 +5208,11 @@ - assert(!"Invalid flags argument"); - } - *pResOut = (osAccess(zPath, amode)==0); - if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){ - struct stat buf; -- if( 0==stat(zPath, &buf) && buf.st_size==0 ){ -+ if( 0==osStat(zPath, &buf) && buf.st_size==0 ){ - *pResOut = 0; - } - } - return SQLITE_OK; +that you've upgraded to version of sqlite that includes those patches. +diff --git a/third_party/sqlite/amalgamation/sqlite3.c b/third_party/sqlite/amalgamation/sqlite3.c +index 3e794a9..73ff15f 100644 +--- a/third_party/sqlite/amalgamation/sqlite3.c ++++ b/third_party/sqlite/amalgamation/sqlite3.c +@@ -24144,7 +24144,6 @@ struct unixFile { + sqlite3_io_methods const *pMethod; /* Always the first entry */ + unixInodeInfo *pInode; /* Info about locks on this inode */ + int h; /* The file descriptor */ +- int dirfd; /* File descriptor for the directory */ + unsigned char eFileLock; /* The type of lock held on this fd */ + unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ + int lastErrno; /* The unix errno from last I/O error */ +@@ -24188,6 +24187,7 @@ struct unixFile { + */ + #define UNIXFILE_EXCL 0x01 /* Connections from one process only */ + #define UNIXFILE_RDONLY 0x02 /* Connection is read only */ ++#define UNIXFILE_DIRSYNC 0x04 /* Directory sync needed */ + + /* + ** Include code that is common to all os_*.c files +@@ -24426,6 +24426,9 @@ SQLITE_API int sqlite3_open_file_count = 0; + #define threadid 0 + #endif + ++/* Forward reference */ ++static int openDirectory(const char*, int*); ++ + /* + ** Many system calls are accessed through pointer-to-functions so that + ** they may be overridden at runtime to facilitate fault injection during +@@ -24522,6 +24525,12 @@ static struct unix_syscall { + #endif + #define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent) + ++ { "unlink", (sqlite3_syscall_ptr)unlink, 0 }, ++#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent) ++ ++ { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 }, ++#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent) ++ + }; /* End of the overrideable system calls */ + + /* +@@ -25876,10 +25885,6 @@ static int unixUnlock(sqlite3_file *id, int eFileLock){ + */ + static int closeUnixFile(sqlite3_file *id){ + unixFile *pFile = (unixFile*)id; +- if( pFile->dirfd>=0 ){ +- robust_close(pFile, pFile->dirfd, __LINE__); +- pFile->dirfd=-1; +- } + if( pFile->h>=0 ){ + robust_close(pFile, pFile->h, __LINE__); + pFile->h = -1; +@@ -25887,7 +25892,7 @@ static int closeUnixFile(sqlite3_file *id){ + #if OS_VXWORKS + if( pFile->pId ){ + if( pFile->isDelete ){ +- unlink(pFile->pId->zCanonicalName); ++ osUnlink(pFile->pId->zCanonicalName); + } + vxworksReleaseFileId(pFile->pId); + pFile->pId = 0; +@@ -26134,7 +26139,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) { + + /* To fully unlock the database, delete the lock file */ + assert( eFileLock==NO_LOCK ); +- if( unlink(zLockFile) ){ ++ if( osUnlink(zLockFile) ){ + int rc = 0; + int tErrno = errno; + if( ENOENT != tErrno ){ +@@ -27371,6 +27376,50 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ } - + + /* ++** 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 ){ ++#ifdef FD_CLOEXEC ++ osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); ++#endif ++ OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); ++ } ++ } ++ *pFd = fd; ++ return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); ++} ++ ++/* + ** Make sure all writes to a particular file are committed to disk. + ** + ** If dataOnly==0 then both the file itself and its metadata (file +@@ -27410,28 +27459,21 @@ static int unixSync(sqlite3_file *id, int flags){ + pFile->lastErrno = errno; + return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); + } +- if( pFile->dirfd>=0 ){ +- OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, ++ ++ /* Also fsync the directory containing the file if the DIRSYNC flag ++ ** is set. This is a one-time occurrance. 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)); +-#ifndef SQLITE_DISABLE_DIRSYNC +- /* The directory sync is only attempted if full_fsync is +- ** turned off or unavailable. If a full_fsync occurred above, +- ** then the directory sync is superfluous. +- */ +- if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){ +- /* +- ** We have received multiple reports of fsync() returning +- ** errors when applied to directories on certain file systems. +- ** A failed directory sync is not a big deal. So it seems +- ** better to ignore the error. Ticket #1657 +- */ +- /* pFile->lastErrno = errno; */ +- /* return SQLITE_IOERR; */ ++ rc = osOpenDirectory(pFile->zPath, &dirfd); ++ if( rc==SQLITE_OK && dirfd>=0 ){ ++ full_fsync(dirfd, 0, 0); ++ robust_close(pFile, dirfd, __LINE__); + } +-#endif +- /* Only need to sync once, so close the directory when we are done */ +- robust_close(pFile, pFile->dirfd, __LINE__); +- pFile->dirfd = -1; ++ pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; + } + return rc; + } +@@ -28255,7 +28297,7 @@ static int unixShmUnmap( + assert( pShmNode->nRef>0 ); + pShmNode->nRef--; + if( pShmNode->nRef==0 ){ +- if( deleteFlag && pShmNode->h>=0 ) unlink(pShmNode->zFilename); ++ if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename); + unixShmPurge(pDbFd); + } + unixLeaveMutex(); +@@ -28575,7 +28617,7 @@ void initUnixFile(sqlite3_file* file) { + int fillInUnixFile( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + int h, /* Open file descriptor of file being opened */ +- int dirfd, /* Directory file descriptor */ ++ int syncDir, /* True to sync directory on first sync */ + sqlite3_file *pId, /* Write to the unixFile structure here */ + const char *zFilename, /* Name of the file being opened */ + int noLock, /* Omit locking if true */ +@@ -28606,7 +28648,6 @@ int fillInUnixFile( + + OSTRACE(("OPEN %-3d %s\n", h, zFilename)); + pNew->h = h; +- pNew->dirfd = dirfd; + pNew->zPath = zFilename; + if( memcmp(pVfs->zName,"unix-excl",10)==0 ){ + pNew->ctrlFlags = UNIXFILE_EXCL; +@@ -28616,6 +28657,9 @@ int fillInUnixFile( + if( isReadOnly ){ + pNew->ctrlFlags |= UNIXFILE_RDONLY; + } ++ if( syncDir ){ ++ pNew->ctrlFlags |= UNIXFILE_DIRSYNC; ++ } + + #if OS_VXWORKS + pNew->pId = vxworksFindFileId(zFilename); +@@ -28742,13 +28786,12 @@ int fillInUnixFile( + if( rc!=SQLITE_OK ){ + if( h>=0 ) robust_close(pNew, h, __LINE__); + h = -1; +- unlink(zFilename); ++ osUnlink(zFilename); + isDelete = 0; + } + pNew->isDelete = isDelete; + #endif + if( rc!=SQLITE_OK ){ +- if( dirfd>=0 ) robust_close(pNew, dirfd, __LINE__); + if( h>=0 ) robust_close(pNew, h, __LINE__); + }else{ + pNew->pMethod = pLockingStyle; +@@ -28758,37 +28801,6 @@ int fillInUnixFile( + } + + /* +-** 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. +-** +-** 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 ){ +-#ifdef FD_CLOEXEC +- osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); +-#endif +- OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); +- } +- } +- *pFd = fd; +- return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); +-} +- +-/* + ** Return the name of a directory in which to put temporary files. + ** If no suitable temporary file directory can be found, return NULL. + */ +@@ -29083,7 +29095,6 @@ static int unixOpen( + ){ + unixFile *p = (unixFile *)pFile; + int fd = -1; /* File descriptor returned by open() */ +- int dirfd = -1; /* Directory file descriptor */ + int openFlags = 0; /* Flags to pass to open() */ + int eType = flags&0xFFFFFF00; /* Type of file to open */ + int noLock; /* True to omit locking primitives */ +@@ -29102,7 +29113,7 @@ static int unixOpen( + ** 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 isOpenDirectory = (isCreate && ( ++ int syncDir = (isCreate && ( + eType==SQLITE_OPEN_MASTER_JOURNAL + || eType==SQLITE_OPEN_MAIN_JOURNAL + || eType==SQLITE_OPEN_WAL +@@ -29149,7 +29160,7 @@ static int unixOpen( + } + }else if( !zName ){ + /* If zName is NULL, the upper layer is requesting a temp file. */ +- assert(isDelete && !isOpenDirectory); ++ assert(isDelete && !syncDir); + rc = unixGetTempname(MAX_PATHNAME+1, zTmpname); + if( rc!=SQLITE_OK ){ + return rc; +@@ -29202,7 +29213,7 @@ static int unixOpen( + #if OS_VXWORKS + zPath = zName; + #else +- unlink(zName); ++ osUnlink(zName); + #endif + } + #if SQLITE_ENABLE_LOCKING_STYLE +@@ -29211,19 +29222,6 @@ static int unixOpen( + } + #endif + +- if( isOpenDirectory ){ +- rc = openDirectory(zPath, &dirfd); +- if( rc!=SQLITE_OK ){ +- /* It is safe to close fd at this point, because it is guaranteed not +- ** to be open on a database file. If it were open on a database file, +- ** it would not be safe to close as this would release any locks held +- ** on the file by this process. */ +- assert( eType!=SQLITE_OPEN_MAIN_DB ); +- robust_close(p, fd, __LINE__); +- goto open_finished; +- } +- } +- + #ifdef FD_CLOEXEC + osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); + #endif +@@ -29235,7 +29233,6 @@ static int unixOpen( + struct statfs fsInfo; + if( fstatfs(fd, &fsInfo) == -1 ){ + ((unixFile*)pFile)->lastErrno = errno; +- if( dirfd>=0 ) robust_close(p, dirfd, __LINE__); + robust_close(p, fd, __LINE__); + return SQLITE_IOERR_ACCESS; + } +@@ -29267,9 +29264,6 @@ static int unixOpen( + ** not while other file descriptors opened by the same process on + ** the same file are working. */ + p->lastErrno = errno; +- if( dirfd>=0 ){ +- robust_close(p, dirfd, __LINE__); +- } + robust_close(p, fd, __LINE__); + rc = SQLITE_IOERR_ACCESS; + goto open_finished; +@@ -29277,7 +29271,7 @@ static int unixOpen( + useProxy = !(fsInfo.f_flags&MNT_LOCAL); + } + if( useProxy ){ +- rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, ++ rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, + isDelete, isReadonly); + if( rc==SQLITE_OK ){ + rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); +@@ -29295,7 +29289,7 @@ static int unixOpen( + } + #endif + +- rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, ++ rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, + isDelete, isReadonly); + open_finished: + if( rc!=SQLITE_OK ){ +@@ -29317,13 +29311,13 @@ static int unixDelete( + int rc = SQLITE_OK; + UNUSED_PARAMETER(NotUsed); + SimulateIOError(return SQLITE_IOERR_DELETE); +- if( unlink(zPath)==(-1) && errno!=ENOENT ){ ++ if( osUnlink(zPath)==(-1) && errno!=ENOENT ){ + return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); + } + #ifndef SQLITE_DISABLE_DIRSYNC + if( dirSync ){ + int fd; +- rc = openDirectory(zPath, &fd); ++ rc = osOpenDirectory(zPath, &fd); + if( rc==SQLITE_OK ){ + #if OS_VXWORKS + if( fsync(fd)==-1 ) +@@ -29895,7 +29889,6 @@ static int proxyCreateUnixFile( + int islockfile /* if non zero missing dirs will be created */ + ) { + int fd = -1; +- int dirfd = -1; + unixFile *pNew; + int rc = SQLITE_OK; + int openFlags = O_RDWR | O_CREAT; +@@ -29960,7 +29953,7 @@ static int proxyCreateUnixFile( + pUnused->flags = openFlags; + pNew->pUnused = pUnused; + +- rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0, 0); ++ rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0); + if( rc==SQLITE_OK ){ + *ppFile = pNew; + return SQLITE_OK; +@@ -30074,7 +30067,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ + end_breaklock: + if( rc ){ + if( fd>=0 ){ +- unlink(tPath); ++ osUnlink(tPath); + robust_close(pFile, fd, __LINE__); + } + fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); +@@ -30897,7 +30890,7 @@ SQLITE_API int sqlite3_os_init(void){ + + /* Double-check that the aSyscall[] array has been constructed + ** correctly. See ticket [bb3a86e890c8e96ab] */ +- assert( ArraySize(aSyscall)==16 ); ++ assert( ArraySize(aSyscall)==18 ); + + /* Register all VFSes defined in the aVfs[] array */ + for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ +diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c +index e5b2540..804c588 100644 +--- a/third_party/sqlite/src/src/os_unix.c ++++ b/third_party/sqlite/src/src/os_unix.c +@@ -204,7 +204,6 @@ struct unixFile { + sqlite3_io_methods const *pMethod; /* Always the first entry */ + unixInodeInfo *pInode; /* Info about locks on this inode */ + int h; /* The file descriptor */ +- int dirfd; /* File descriptor for the directory */ + unsigned char eFileLock; /* The type of lock held on this fd */ + unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ + int lastErrno; /* The unix errno from last I/O error */ +@@ -248,6 +247,7 @@ struct unixFile { + */ + #define UNIXFILE_EXCL 0x01 /* Connections from one process only */ + #define UNIXFILE_RDONLY 0x02 /* Connection is read only */ ++#define UNIXFILE_DIRSYNC 0x04 /* Directory sync needed */ + + /* + ** Include code that is common to all os_*.c files +@@ -281,6 +281,9 @@ struct unixFile { + #define threadid 0 + #endif + ++/* Forward reference */ ++static int openDirectory(const char*, int*); ++ + /* + ** Many system calls are accessed through pointer-to-functions so that + ** they may be overridden at runtime to facilitate fault injection during +@@ -377,6 +380,12 @@ static struct unix_syscall { + #endif + #define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent) + ++ { "unlink", (sqlite3_syscall_ptr)unlink, 0 }, ++#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent) ++ ++ { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 }, ++#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent) ++ + }; /* End of the overrideable system calls */ + + /* +@@ -1731,10 +1740,6 @@ static int unixUnlock(sqlite3_file *id, int eFileLock){ + */ + static int closeUnixFile(sqlite3_file *id){ + unixFile *pFile = (unixFile*)id; +- if( pFile->dirfd>=0 ){ +- robust_close(pFile, pFile->dirfd, __LINE__); +- pFile->dirfd=-1; +- } + if( pFile->h>=0 ){ + robust_close(pFile, pFile->h, __LINE__); + pFile->h = -1; +@@ -1742,7 +1747,7 @@ static int closeUnixFile(sqlite3_file *id){ + #if OS_VXWORKS + if( pFile->pId ){ + if( pFile->isDelete ){ +- unlink(pFile->pId->zCanonicalName); ++ osUnlink(pFile->pId->zCanonicalName); + } + vxworksReleaseFileId(pFile->pId); + pFile->pId = 0; +@@ -1989,7 +1994,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) { + + /* To fully unlock the database, delete the lock file */ + assert( eFileLock==NO_LOCK ); +- if( unlink(zLockFile) ){ ++ if( osUnlink(zLockFile) ){ + int rc = 0; + int tErrno = errno; + if( ENOENT != tErrno ){ +@@ -3226,6 +3231,50 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ + } + + /* ++** 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 ){ ++#ifdef FD_CLOEXEC ++ osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); ++#endif ++ OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); ++ } ++ } ++ *pFd = fd; ++ return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); ++} ++ ++/* + ** Make sure all writes to a particular file are committed to disk. + ** + ** If dataOnly==0 then both the file itself and its metadata (file +@@ -3265,28 +3314,23 @@ static int unixSync(sqlite3_file *id, int flags){ + pFile->lastErrno = errno; + return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); + } +- if( pFile->dirfd>=0 ){ +- OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, ++ ++ /* Also fsync the directory containing the file if the DIRSYNC flag ++ ** is set. This is a one-time occurrance. 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)); +-#ifndef SQLITE_DISABLE_DIRSYNC +- /* The directory sync is only attempted if full_fsync is +- ** turned off or unavailable. If a full_fsync occurred above, +- ** then the directory sync is superfluous. +- */ +- if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){ +- /* +- ** We have received multiple reports of fsync() returning +- ** errors when applied to directories on certain file systems. +- ** A failed directory sync is not a big deal. So it seems +- ** better to ignore the error. Ticket #1657 +- */ +- /* pFile->lastErrno = errno; */ +- /* return SQLITE_IOERR; */ ++ 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; + } +-#endif +- /* Only need to sync once, so close the directory when we are done */ +- robust_close(pFile, pFile->dirfd, __LINE__); +- pFile->dirfd = -1; ++ pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; + } + return rc; + } +@@ -4110,7 +4154,7 @@ static int unixShmUnmap( + assert( pShmNode->nRef>0 ); + pShmNode->nRef--; + if( pShmNode->nRef==0 ){ +- if( deleteFlag && pShmNode->h>=0 ) unlink(pShmNode->zFilename); ++ if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename); + unixShmPurge(pDbFd); + } + unixLeaveMutex(); +@@ -4430,7 +4474,7 @@ void initUnixFile(sqlite3_file* file) { + int fillInUnixFile( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + int h, /* Open file descriptor of file being opened */ +- int dirfd, /* Directory file descriptor */ ++ int syncDir, /* True to sync directory on first sync */ + sqlite3_file *pId, /* Write to the unixFile structure here */ + const char *zFilename, /* Name of the file being opened */ + int noLock, /* Omit locking if true */ +@@ -4461,7 +4505,6 @@ int fillInUnixFile( + + OSTRACE(("OPEN %-3d %s\n", h, zFilename)); + pNew->h = h; +- pNew->dirfd = dirfd; + pNew->zPath = zFilename; + if( memcmp(pVfs->zName,"unix-excl",10)==0 ){ + pNew->ctrlFlags = UNIXFILE_EXCL; +@@ -4471,6 +4514,9 @@ int fillInUnixFile( + if( isReadOnly ){ + pNew->ctrlFlags |= UNIXFILE_RDONLY; + } ++ if( syncDir ){ ++ pNew->ctrlFlags |= UNIXFILE_DIRSYNC; ++ } + + #if OS_VXWORKS + pNew->pId = vxworksFindFileId(zFilename); +@@ -4597,13 +4643,12 @@ int fillInUnixFile( + if( rc!=SQLITE_OK ){ + if( h>=0 ) robust_close(pNew, h, __LINE__); + h = -1; +- unlink(zFilename); ++ osUnlink(zFilename); + isDelete = 0; + } + pNew->isDelete = isDelete; + #endif + if( rc!=SQLITE_OK ){ +- if( dirfd>=0 ) robust_close(pNew, dirfd, __LINE__); + if( h>=0 ) robust_close(pNew, h, __LINE__); + }else{ + pNew->pMethod = pLockingStyle; +@@ -4613,37 +4658,6 @@ int fillInUnixFile( + } + + /* +-** 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. +-** +-** 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 ){ +-#ifdef FD_CLOEXEC +- osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); +-#endif +- OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); +- } +- } +- *pFd = fd; +- return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); +-} +- +-/* + ** Return the name of a directory in which to put temporary files. + ** If no suitable temporary file directory can be found, return NULL. + */ +@@ -4938,7 +4952,6 @@ static int unixOpen( + ){ + unixFile *p = (unixFile *)pFile; + int fd = -1; /* File descriptor returned by open() */ +- int dirfd = -1; /* Directory file descriptor */ + int openFlags = 0; /* Flags to pass to open() */ + int eType = flags&0xFFFFFF00; /* Type of file to open */ + int noLock; /* True to omit locking primitives */ +@@ -4957,7 +4970,7 @@ static int unixOpen( + ** 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 isOpenDirectory = (isCreate && ( ++ int syncDir = (isCreate && ( + eType==SQLITE_OPEN_MASTER_JOURNAL + || eType==SQLITE_OPEN_MAIN_JOURNAL + || eType==SQLITE_OPEN_WAL +@@ -5004,7 +5017,7 @@ static int unixOpen( + } + }else if( !zName ){ + /* If zName is NULL, the upper layer is requesting a temp file. */ +- assert(isDelete && !isOpenDirectory); ++ assert(isDelete && !syncDir); + rc = unixGetTempname(MAX_PATHNAME+1, zTmpname); + if( rc!=SQLITE_OK ){ + return rc; +@@ -5057,7 +5070,7 @@ static int unixOpen( + #if OS_VXWORKS + zPath = zName; + #else +- unlink(zName); ++ osUnlink(zName); + #endif + } + #if SQLITE_ENABLE_LOCKING_STYLE +@@ -5066,19 +5079,6 @@ static int unixOpen( + } + #endif + +- if( isOpenDirectory ){ +- rc = openDirectory(zPath, &dirfd); +- if( rc!=SQLITE_OK ){ +- /* It is safe to close fd at this point, because it is guaranteed not +- ** to be open on a database file. If it were open on a database file, +- ** it would not be safe to close as this would release any locks held +- ** on the file by this process. */ +- assert( eType!=SQLITE_OPEN_MAIN_DB ); +- robust_close(p, fd, __LINE__); +- goto open_finished; +- } +- } +- + #ifdef FD_CLOEXEC + osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); + #endif +@@ -5090,7 +5090,6 @@ static int unixOpen( + struct statfs fsInfo; + if( fstatfs(fd, &fsInfo) == -1 ){ + ((unixFile*)pFile)->lastErrno = errno; +- if( dirfd>=0 ) robust_close(p, dirfd, __LINE__); + robust_close(p, fd, __LINE__); + return SQLITE_IOERR_ACCESS; + } +@@ -5122,9 +5121,6 @@ static int unixOpen( + ** not while other file descriptors opened by the same process on + ** the same file are working. */ + p->lastErrno = errno; +- if( dirfd>=0 ){ +- robust_close(p, dirfd, __LINE__); +- } + robust_close(p, fd, __LINE__); + rc = SQLITE_IOERR_ACCESS; + goto open_finished; +@@ -5132,7 +5128,7 @@ static int unixOpen( + useProxy = !(fsInfo.f_flags&MNT_LOCAL); + } + if( useProxy ){ +- rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, ++ rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, + isDelete, isReadonly); + if( rc==SQLITE_OK ){ + rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); +@@ -5150,7 +5146,7 @@ static int unixOpen( + } + #endif + +- rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, ++ rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, + isDelete, isReadonly); + open_finished: + if( rc!=SQLITE_OK ){ +@@ -5172,13 +5168,13 @@ static int unixDelete( + int rc = SQLITE_OK; + UNUSED_PARAMETER(NotUsed); + SimulateIOError(return SQLITE_IOERR_DELETE); +- if( unlink(zPath)==(-1) && errno!=ENOENT ){ ++ if( osUnlink(zPath)==(-1) && errno!=ENOENT ){ + return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); + } + #ifndef SQLITE_DISABLE_DIRSYNC + if( dirSync ){ + int fd; +- rc = openDirectory(zPath, &fd); ++ rc = osOpenDirectory(zPath, &fd); + if( rc==SQLITE_OK ){ + #if OS_VXWORKS + if( fsync(fd)==-1 ) +@@ -5189,6 +5185,8 @@ static int unixDelete( + rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); + } + robust_close(0, fd, __LINE__); ++ }else if( rc==SQLITE_CANTOPEN ){ ++ rc = SQLITE_OK; + } + } + #endif +@@ -5750,7 +5748,6 @@ static int proxyCreateUnixFile( + int islockfile /* if non zero missing dirs will be created */ + ) { + int fd = -1; +- int dirfd = -1; + unixFile *pNew; + int rc = SQLITE_OK; + int openFlags = O_RDWR | O_CREAT; +@@ -5815,7 +5812,7 @@ static int proxyCreateUnixFile( + pUnused->flags = openFlags; + pNew->pUnused = pUnused; + +- rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0, 0); ++ rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0); + if( rc==SQLITE_OK ){ + *ppFile = pNew; + return SQLITE_OK; +@@ -5929,7 +5926,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ + end_breaklock: + if( rc ){ + if( fd>=0 ){ +- unlink(tPath); ++ osUnlink(tPath); + robust_close(pFile, fd, __LINE__); + } + fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); +@@ -6752,7 +6749,7 @@ int sqlite3_os_init(void){ + + /* Double-check that the aSyscall[] array has been constructed + ** correctly. See ticket [bb3a86e890c8e96ab] */ +- assert( ArraySize(aSyscall)==16 ); ++ assert( ArraySize(aSyscall)==18 ); + + /* Register all VFSes defined in the aVfs[] array */ + for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ +diff --git a/third_party/sqlite/src/test/syscall.test b/third_party/sqlite/src/test/syscall.test +index 4442612..201bd63 100644 +--- a/third_party/sqlite/src/test/syscall.test ++++ b/third_party/sqlite/src/test/syscall.test +@@ -59,7 +59,7 @@ do_test 2.1.2 { test_syscall exists nosuchcall } 0 + foreach s { + open close access getcwd stat fstat ftruncate + fcntl read pread write pwrite fchmod fallocate +- pread64 pwrite64 ++ pread64 pwrite64 unlink openDirectory + } { + if {[test_syscall exists $s]} {lappend syscall_list $s} + } +diff --git a/third_party/sqlite/system-sqlite.patch b/third_party/sqlite/system-sqlite.patch +index f61f019..31d6b00 100644 +--- a/third_party/sqlite/system-sqlite.patch ++++ b/third_party/sqlite/system-sqlite.patch +@@ -1,48 +0,0 @@ +-This is a backport of http://sqlite.org/src/ci/9109128cb5, +-which is needed for experiments with using unpatched sqlite. +-If you hit a merge conflict on this file it is most likely +-that you've upgraded to version of sqlite that includes this patch. +-Index: src/os_unix.c +-=================================================================== +---- src/os_unix.c +-+++ src/os_unix.c +-@@ -4787,11 +4787,11 @@ +- ** ignored and -1 is returned. The caller will try to open a new file +- ** descriptor on the same path, fail, and return an error to SQLite. +- ** +- ** Even if a subsequent open() call does succeed, the consequences of +- ** not searching for a resusable file descriptor are not dire. */ +-- if( 0==stat(zPath, &sStat) ){ +-+ if( 0==osStat(zPath, &sStat) ){ +- unixInodeInfo *pInode; +- +- unixEnterMutex(); +- pInode = inodeList; +- while( pInode && (pInode->fileId.dev!=sStat.st_dev +-@@ -4863,11 +4863,11 @@ +- while( nDb>0 && zPath[nDb]!='-' ) nDb--; +- if( nDb==0 ) return SQLITE_OK; +- memcpy(zDb, zPath, nDb); +- zDb[nDb] = '\0'; +- +-- if( 0==stat(zDb, &sStat) ){ +-+ if( 0==osStat(zDb, &sStat) ){ +- *pMode = sStat.st_mode & 0777; +- }else{ +- rc = SQLITE_IOERR_FSTAT; +- } +- }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ +-@@ -5208,11 +5208,11 @@ +- assert(!"Invalid flags argument"); +- } +- *pResOut = (osAccess(zPath, amode)==0); +- if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){ +- struct stat buf; +-- if( 0==stat(zPath, &buf) && buf.st_size==0 ){ +-+ if( 0==osStat(zPath, &buf) && buf.st_size==0 ){ +- *pResOut = 0; +- } +- } +- return SQLITE_OK; +- } +- |