[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

commit-queue at webkit.org commit-queue at webkit.org
Wed Dec 22 13:45:23 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit a1f0f7ad48446b46c6c17121a7edd9f4c76318b1
Author: commit-queue at webkit.org <commit-queue at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Sep 24 23:17:42 2010 +0000

    2010-09-24  Pawel Hajdan  <phajdan.jr at chromium.org>
    
            Reviewed by Dumitru Daniliuc.
    
            Move the implementation of chromium_vfs to webkit for POSIX.
            This allows us to link Chrome with system-provided SQLite on Linux.
            See also http://code.google.com/p/chromium/issues/detail?id=22208.
            https://bugs.webkit.org/show_bug.cgi?id=45416
    
            No new tests.
    
            * platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp:
            (sqliteErrorFromPosixError):
            (releaseLockInfo):
            (releaseOpenInfo):
            (findLockInfo):
            (chromiumCheckReservedLock):
            (rangeLock):
            (chromiumLock):
            (closePendingFds):
            (chromiumUnlock):
            (chromiumCloseNoLock):
            (chromiumClose):
            (chromiumCheckReservedLockNoop):
            (chromiumLockNoop):
            (chromiumUnlockNoop):
            (seekAndRead):
            (chromiumRead):
            (seekAndWrite):
            (chromiumWrite):
            (syncWrapper):
            (chromiumSync):
            (chromiumTruncate):
            (chromiumFileSize):
            (chromiumFileControl):
            (chromiumSectorSize):
            (chromiumDeviceCharacteristics):
            (fillInChromiumFile):
            (findReusableFd):
            (chromiumOpen):
            (chromiumDelete):
            (chromiumAccess):
            (chromiumFullPathname):
            (chromiumDlOpen):
            (chromiumDlError):
            (chromiumDlSym):
            (chromiumDlClose):
            (chromiumRandomness):
            (chromiumSleep):
            (chromiumCurrentTime):
            (chromiumGetLastError):
            (WebCore::SQLiteFileSystem::registerSQLiteVFS):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@68310 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 3c3d7e4..ac5e3cf 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,56 @@
+2010-09-24  Pawel Hajdan  <phajdan.jr at chromium.org>
+
+        Reviewed by Dumitru Daniliuc.
+
+        Move the implementation of chromium_vfs to webkit for POSIX.
+        This allows us to link Chrome with system-provided SQLite on Linux.
+        See also http://code.google.com/p/chromium/issues/detail?id=22208.
+        https://bugs.webkit.org/show_bug.cgi?id=45416
+
+        No new tests.
+
+        * platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp:
+        (sqliteErrorFromPosixError):
+        (releaseLockInfo):
+        (releaseOpenInfo):
+        (findLockInfo):
+        (chromiumCheckReservedLock):
+        (rangeLock):
+        (chromiumLock):
+        (closePendingFds):
+        (chromiumUnlock):
+        (chromiumCloseNoLock):
+        (chromiumClose):
+        (chromiumCheckReservedLockNoop):
+        (chromiumLockNoop):
+        (chromiumUnlockNoop):
+        (seekAndRead):
+        (chromiumRead):
+        (seekAndWrite):
+        (chromiumWrite):
+        (syncWrapper):
+        (chromiumSync):
+        (chromiumTruncate):
+        (chromiumFileSize):
+        (chromiumFileControl):
+        (chromiumSectorSize):
+        (chromiumDeviceCharacteristics):
+        (fillInChromiumFile):
+        (findReusableFd):
+        (chromiumOpen):
+        (chromiumDelete):
+        (chromiumAccess):
+        (chromiumFullPathname):
+        (chromiumDlOpen):
+        (chromiumDlError):
+        (chromiumDlSym):
+        (chromiumDlClose):
+        (chromiumRandomness):
+        (chromiumSleep):
+        (chromiumCurrentTime):
+        (chromiumGetLastError):
+        (WebCore::SQLiteFileSystem::registerSQLiteVFS):
+
 2010-09-24  Andreas Kling  <andreas.kling at nokia.com>
 
         Reviewed by Dirk Schulze.
diff --git a/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp b/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp
index 6549936..1102df5 100644
--- a/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp
+++ b/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp
@@ -34,23 +34,938 @@
 #include "ChromiumBridge.h"
 #include <sqlite3.h>
 
+#include <errno.h>
 #include <fcntl.h>
 #include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 using namespace WebCore;
 
-// Defined in Chromium's codebase in third_party/sqlite/src/os_unix.c
-extern "C" {
-void chromium_sqlite3_initialize_unix_sqlite3_file(sqlite3_file* file);
-int chromium_sqlite3_fill_in_unix_sqlite3_file(sqlite3_vfs* vfs, int fd, int dirfd, sqlite3_file* file, const char* fileName, int noLock);
-int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file, const char* fileName, int flags, int* fd);
-void chromium_sqlite3_update_reusable_file_handle(sqlite3_file* file, int fd, int flags);
-void chromium_sqlite3_destroy_reusable_file_handle(sqlite3_file* file);
+// Chromium's Posix implementation of SQLite VFS.
+// This is heavily based on SQLite's os_unix.c,
+// without parts we don't need.
+
+// Identifies a file by its device number and inode.
+struct ChromiumFileId {
+    dev_t dev; // Device number.
+    ino_t ino; // Inode number.
+};
+
+// Information about file locks (one per open inode). Note that many open
+// file descriptors may refer to the same inode.
+struct ChromiumLockInfo {
+    ChromiumFileId lockKey; // File identifier.
+    int cnt; // Number of shared locks held.
+    int locktype; // Type of the lock.
+    int nRef; // Reference count.
+
+    // Double-linked list pointers.
+    ChromiumLockInfo* pNext; 
+    ChromiumLockInfo* pPrev;
+};
+
+// Information about a file descriptor that cannot be closed immediately.
+struct ChromiumUnusedFd {
+    int fd; // File descriptor.
+    int flags; // Flags this file descriptor was opened with.
+    ChromiumUnusedFd* pNext; // Next unused file descriptor on the same file.
+};
+
+// Information about an open inode. When we want to close an inode
+// that still has locks, we defer the close until all locks are cleared.
+struct ChromiumOpenInfo {
+    ChromiumFileId fileId; // The lookup key.
+    int nRef; // Reference count.
+    int nLock; // Number of outstanding locks.
+    ChromiumUnusedFd* pUnused; // List of file descriptors to close.
+
+    // Double-linked list pointers.
+    ChromiumOpenInfo* pNext;
+    ChromiumOpenInfo* pPrev;
+};
+
+// Keep track of locks and inodes in double-linked lists.
+static struct ChromiumLockInfo* lockList = 0;
+static struct ChromiumOpenInfo* openList = 0;
+
+// Extension of sqlite3_file specific to the chromium VFS.
+struct ChromiumFile {
+    sqlite3_io_methods const* pMethod; // Implementation of sqlite3_file.
+    ChromiumOpenInfo* pOpen; // Information about all open file descriptors for this file.
+    ChromiumLockInfo* pLock; // Information about all locks for this file.
+    int h; // File descriptor.
+    int dirfd; // File descriptor for the file directory.
+    unsigned char locktype; // Type of the lock used for this file.
+    int lastErrno; // Value of errno for last operation on this file.
+    ChromiumUnusedFd* pUnused; // Information about unused file descriptors for this file.
+};
+
+// The following constants specify the range of bytes used for locking.
+// SQLiteSharedSize is the number of bytes available in the pool from which
+// a random byte is selected for a shared lock.  The pool of bytes for
+// shared locks begins at SQLiteSharedFirstByte. 
+// The values are the same as used by SQLite for compatibility.
+static const off_t SQLitePendingByte = 0x40000000;
+static const off_t SQLiteReservedByte = SQLitePendingByte + 1;
+static const off_t SQLiteSharedFirstByte = SQLitePendingByte + 2;
+static const off_t SQLiteSharedSize = 510;
+
+// Maps a POSIX error code to an SQLite error code.
+static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr)
+{
+    switch (posixError) {
+    case 0: 
+        return SQLITE_OK;
+    case EAGAIN:
+    case ETIMEDOUT:
+    case EBUSY:
+    case EINTR:
+    case ENOLCK:  
+        return SQLITE_BUSY;
+    case EACCES: 
+        // EACCES is like EAGAIN during locking operations.
+        if ((sqliteIOErr == SQLITE_IOERR_LOCK) ||
+            (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
+            (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
+            (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK))
+            return SQLITE_BUSY;
+        return SQLITE_PERM;
+    case EPERM: 
+        return SQLITE_PERM;
+    case EDEADLK:
+        return SQLITE_IOERR_BLOCKED;
+    default: 
+        return sqliteIOErr;
+    }
+}
+
+// Releases a ChromiumLockInfo structure previously allocated by findLockInfo().
+static void releaseLockInfo(ChromiumLockInfo* pLock)
+{
+    if (!pLock)
+        return;
+
+    pLock->nRef--;
+    if (pLock->nRef > 0)
+        return;
+
+    if (pLock->pPrev) {
+        ASSERT(pLock->pPrev->pNext == pLock);
+        pLock->pPrev->pNext = pLock->pNext;
+    } else {
+        ASSERT(lockList == pLock);
+        lockList = pLock->pNext;
+    }
+    if (pLock->pNext) {
+        ASSERT(pLock->pNext->pPrev == pLock);
+        pLock->pNext->pPrev = pLock->pPrev;
+    }
+
+    sqlite3_free(pLock);
+}
+
+// Releases a ChromiumOpenInfo structure previously allocated by findLockInfo().
+static void releaseOpenInfo(ChromiumOpenInfo* pOpen)
+{
+    if (!pOpen)
+        return;
+
+    pOpen->nRef--;
+    if (pOpen->nRef > 0)
+        return;
+
+    if (pOpen->pPrev) {
+        ASSERT(pOpen->pPrev->pNext == pOpen);
+        pOpen->pPrev->pNext = pOpen->pNext;
+    } else {
+        ASSERT(openList == pOpen);
+        openList = pOpen->pNext;
+    }
+    if (pOpen->pNext) {
+        ASSERT(pOpen->pNext->pPrev == pOpen);
+        pOpen->pNext->pPrev = pOpen->pPrev;
+    }
+
+    ASSERT(!pOpen->pUnused); // Make sure we're not leaking memory and file descriptors.
+
+    sqlite3_free(pOpen);
+}
+
+// Locates ChromiumLockInfo and ChromiumOpenInfo for given file descriptor (creating new ones if needed).
+// Returns a SQLite error code.
+static int findLockInfo(ChromiumFile* pFile, ChromiumLockInfo** ppLock, ChromiumOpenInfo** ppOpen)
+{
+    int fd = pFile->h;
+    struct stat statbuf;
+    int rc = fstat(fd, &statbuf);
+    if (rc) {
+        pFile->lastErrno = errno;
+#ifdef EOVERFLOW
+        if (pFile->lastErrno == EOVERFLOW)
+            return SQLITE_NOLFS;
+#endif
+        return SQLITE_IOERR;
+    }
+
+#if OS(DARWIN)
+    // On OS X on an msdos/fat filesystems, the inode number is reported
+    // incorrectly for zero-size files. See http://www.sqlite.org/cvstrac/tktview?tn=3260.
+    // To work around this problem we always increase the file size to 1 by writing a single byte
+    // prior to accessing the inode number. The one byte written is an ASCII 'S' character which
+    // also happens to be the first byte in the header of every SQLite database.  In this way,
+    // if there is a race condition such that another thread has already populated the first page
+    // of the database, no damage is done.
+    if (!statbuf.st_size) {
+        rc = write(fd, "S", 1);
+        if (rc != 1)
+            return SQLITE_IOERR;
+        rc = fstat(fd, &statbuf);
+        if (rc) {
+            pFile->lastErrno = errno;
+            return SQLITE_IOERR;
+        }
+    }
+#endif
+
+    ChromiumFileId fileId;
+    memset(&fileId, 0, sizeof(fileId));
+    fileId.dev = statbuf.st_dev;
+    fileId.ino = statbuf.st_ino;
+
+    ChromiumLockInfo* pLock = 0;
+
+    if (ppLock) {
+        pLock = lockList;
+        while (pLock && memcmp(&fileId, &pLock->lockKey, sizeof(fileId)))
+            pLock = pLock->pNext;
+        if (pLock)
+            pLock->nRef++;
+        else {
+            pLock = static_cast<ChromiumLockInfo*>(sqlite3_malloc(sizeof(*pLock)));
+            if (!pLock)
+                return SQLITE_NOMEM;
+            pLock->lockKey = fileId;
+            pLock->nRef = 1;
+            pLock->cnt = 0;
+            pLock->locktype = 0;
+            pLock->pNext = lockList;
+            pLock->pPrev = 0;
+            if (lockList)
+                lockList->pPrev = pLock;
+            lockList = pLock;
+        }
+        *ppLock = pLock;
+    }
+
+    if (ppOpen) {
+        ChromiumOpenInfo* pOpen = openList;
+        while (pOpen && memcmp(&fileId, &pOpen->fileId, sizeof(fileId)))
+            pOpen = pOpen->pNext;
+        if (pOpen)
+            pOpen->nRef++;
+        else {
+            pOpen = static_cast<ChromiumOpenInfo*>(sqlite3_malloc(sizeof(*pOpen)));
+            if (!pOpen) {
+                releaseLockInfo(pLock);
+                return SQLITE_NOMEM;
+            }
+            memset(pOpen, 0, sizeof(*pOpen));
+            pOpen->fileId = fileId;
+            pOpen->nRef = 1;
+            pOpen->pNext = openList;
+            if (openList)
+                openList->pPrev = pOpen;
+            openList = pOpen;
+        }
+        *ppOpen = pOpen;
+    }
+
+    return rc;
+}
+
+// Checks if there is a RESERVED lock held on the specified file by this or any other process.
+// If the lock is held, sets pResOut to a non-zero value. Returns a SQLite error code.
+static int chromiumCheckReservedLock(sqlite3_file* id, int* pResOut)
+{
+    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
+    ASSERT(pFile);
+
+    // Look for locks held by this process.
+    int reserved = 0;
+    if (pFile->pLock->locktype > SQLITE_LOCK_SHARED)
+        reserved = 1;
+
+    // Look for locks held by other processes.
+    int rc = SQLITE_OK;
+    if (!reserved) {
+        struct flock lock;
+        lock.l_whence = SEEK_SET;
+        lock.l_start = SQLiteReservedByte;
+        lock.l_len = 1;
+        lock.l_type = F_WRLCK;
+        if (-1 == fcntl(pFile->h, F_GETLK, &lock)) {
+            int tErrno = errno;
+            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
+            pFile->lastErrno = tErrno;
+        } else if (lock.l_type != F_UNLCK)
+            reserved = 1;
+    }
+
+    *pResOut = reserved;
+    return rc;
+}
+
+// Performs a file locking operation on a range of bytes in a file.
+// The |op| parameter should be one of F_RFLCK, F_WRLCK or F_UNLCK.
+// Returns a Unix error code, and also writes it to pErrcode.
+static int rangeLock(ChromiumFile* pFile, int op, int* pErrcode)
+{
+    struct flock lock;
+    lock.l_type = op;
+    lock.l_start = SQLiteSharedFirstByte;
+    lock.l_whence = SEEK_SET;
+    lock.l_len = SQLiteSharedSize;
+    int rc = fcntl(pFile->h, F_SETLK, &lock);
+    *pErrcode = errno;
+    return rc;
+}
+
+// Locks the file with the lock specified by parameter locktype - one
+// of the following:
+//
+//     (1) SQLITE_LOCK_SHARED
+//     (2) SQLITE_LOCK_RESERVED
+//     (3) SQLITE_LOCK_PENDING
+//     (4) SQLITE_LOCK_EXCLUSIVE
+//
+// 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
+static int chromiumLock(sqlite3_file* id, int locktype)
+{
+    // To obtain a SHARED lock, a read-lock is obtained on the 'pending
+    // byte'.  If this is successful, a random byte from the 'shared byte
+    // range' is read-locked and the lock on the 'pending byte' released.
+    //
+    // A process may only obtain a RESERVED lock after it has a SHARED lock.
+    // A RESERVED lock is implemented by grabbing a write-lock on the
+    // 'reserved byte'. 
+    //
+    // A process may only obtain a PENDING lock after it has obtained a
+    // SHARED lock. A PENDING lock is implemented by obtaining a write-lock
+    // on the 'pending byte'. This ensures that no new SHARED locks can be
+    // obtained, but existing SHARED locks are allowed to persist. A process
+    // does not have to obtain a RESERVED lock on the way to a PENDING lock.
+    // This property is used by the algorithm for rolling back a journal file
+    // after a crash.
+    //
+    // An EXCLUSIVE lock, obtained after a PENDING lock is held, is
+    // implemented by obtaining a write-lock on the entire 'shared byte
+    // range'. Since all other locks require a read-lock on one of the bytes
+    // within this range, this ensures that no other locks are held on the
+    // database. 
+
+    int rc = SQLITE_OK;
+    struct flock lock;
+    int s = 0;
+    int tErrno;
+
+    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
+    ASSERT(pFile);
+
+    ChromiumLockInfo* pLock = pFile->pLock;
+
+    // If there is already a lock of this type or more restrictive, do nothing.
+    if (pFile->locktype >= locktype)
+        return SQLITE_OK;
+
+    // Make sure we never move from unlocked to anything higher than shared lock.
+    ASSERT(pFile->locktype != SQLITE_LOCK_NONE || locktype == SQLITE_LOCK_SHARED);
+
+    // Make sure we never request a pending lock.
+    ASSERT(locktype != SQLITE_LOCK_PENDING);
+
+    // Make sure a shared lock is always held when a RESERVED lock is requested.
+    ASSERT(locktype != SQLITE_LOCK_RESERVED || pFile->locktype == SQLITE_LOCK_SHARED);
+
+    // If some thread using this PID has a lock via a different ChromiumFile
+    // handle that precludes the requested lock, return BUSY.
+    if (pFile->locktype != pLock->locktype &&
+        (pLock->locktype >= SQLITE_LOCK_PENDING || locktype > SQLITE_LOCK_SHARED))
+        return SQLITE_BUSY;
+
+    // If a SHARED lock is requested, and some thread using this PID already
+    // has a SHARED or RESERVED lock, then just increment reference counts.
+    if (locktype == SQLITE_LOCK_SHARED &&
+        (pLock->locktype == SQLITE_LOCK_SHARED || pLock->locktype == SQLITE_LOCK_RESERVED)) {
+        ASSERT(!pFile->locktype);
+        ASSERT(pLock->cnt > 0);
+        pFile->locktype = SQLITE_LOCK_SHARED;
+        pLock->cnt++;
+        pFile->pOpen->nLock++;
+        return SQLITE_OK;
+    }
+
+    // A PENDING lock is needed before acquiring a SHARED lock and before
+    // acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
+    // be released.
+    lock.l_len = 1;
+    lock.l_whence = SEEK_SET;
+    if (locktype == SQLITE_LOCK_SHARED ||
+        (locktype == SQLITE_LOCK_EXCLUSIVE && pFile->locktype < SQLITE_LOCK_PENDING)) {
+        lock.l_type = (locktype == SQLITE_LOCK_SHARED ? F_RDLCK : F_WRLCK);
+        lock.l_start = SQLitePendingByte;
+        s = fcntl(pFile->h, F_SETLK, &lock);
+        if (s == -1) {
+            tErrno = errno;
+            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+            if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
+                pFile->lastErrno = tErrno;
+            return rc;
+        }
+    }
+
+    if (locktype == SQLITE_LOCK_SHARED) {
+        ASSERT(!pLock->cnt);
+        ASSERT(!pLock->locktype);
+
+        s = rangeLock(pFile, F_RDLCK, &tErrno);
+
+        // Drop the temporary PENDING lock.
+        lock.l_start = SQLitePendingByte;
+        lock.l_len = 1;
+        lock.l_type = F_UNLCK;
+        if (fcntl(pFile->h, F_SETLK, &lock)) {
+            if (s != -1) {
+                tErrno = errno; 
+                rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); 
+                if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
+                    pFile->lastErrno = tErrno;
+                return rc;
+            }
+        }
+        if (s == -1) {
+            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+            if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
+                pFile->lastErrno = tErrno;
+        } else {
+            pFile->locktype = SQLITE_LOCK_SHARED;
+            pFile->pOpen->nLock++;
+            pLock->cnt = 1;
+        }
+    } else if (locktype == SQLITE_LOCK_EXCLUSIVE && pLock->cnt > 1) {
+        // We are trying for an exclusive lock but another thread in the
+        // same process is still holding a shared lock.
+        rc = SQLITE_BUSY;
+    }  else {
+        // The request was for a RESERVED or EXCLUSIVE lock.  It is
+        // assumed that there is a SHARED or greater lock on the file
+        // already.
+        ASSERT(pFile->locktype);
+        lock.l_type = F_WRLCK;
+        switch (locktype) {
+        case SQLITE_LOCK_RESERVED:
+            lock.l_start = SQLiteReservedByte;
+            s = fcntl(pFile->h, F_SETLK, &lock);
+            tErrno = errno;
+            break;
+        case SQLITE_LOCK_EXCLUSIVE:
+            s = rangeLock(pFile, F_WRLCK, &tErrno);
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+        if (s == -1) {
+            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+            if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
+                pFile->lastErrno = tErrno;
+        }
+    }
+  
+    if (rc == SQLITE_OK) {
+        pFile->locktype = locktype;
+        pLock->locktype = locktype;
+    } else if (locktype == SQLITE_LOCK_EXCLUSIVE) {
+        pFile->locktype = SQLITE_LOCK_PENDING;
+        pLock->locktype = SQLITE_LOCK_PENDING;
+    }
+
+    return rc;
+}
+
+// Closes all file descriptors for given ChromiumFile for which the close has been deferred.
+// Returns a SQLite error code.
+static int closePendingFds(ChromiumFile* pFile)
+{
+    int rc = SQLITE_OK;
+    ChromiumOpenInfo* pOpen = pFile->pOpen;
+    ChromiumUnusedFd* pError = 0;
+    ChromiumUnusedFd* pNext;
+    for (ChromiumUnusedFd* p = pOpen->pUnused; p; p = pNext) {
+        pNext = p->pNext;
+        if (close(p->fd)) {
+            pFile->lastErrno = errno;
+            rc = SQLITE_IOERR_CLOSE;
+            p->pNext = pError;
+            pError = p;
+        } else
+            sqlite3_free(p);
+    }
+    pOpen->pUnused = pError;
+    return rc;
+}
+
+// Lowers the locking level on file descriptor.
+// locktype must be either SQLITE_LOCK_NONE or SQLITE_LOCK_SHARED.
+static int chromiumUnlock(sqlite3_file* id, int locktype)
+{
+    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
+    ASSERT(pFile);
+    ASSERT(locktype <= SQLITE_LOCK_SHARED);
+
+    if (pFile->locktype <= locktype)
+        return SQLITE_OK;
+
+    ChromiumLockInfo* pLock = pFile->pLock;
+    ASSERT(pLock->cnt);
+
+    struct flock lock;
+    int rc = SQLITE_OK;
+    int h = pFile->h;
+    int tErrno;
+
+    if (pFile->locktype > SQLITE_LOCK_SHARED) {
+        ASSERT(pLock->locktype == pFile->locktype);
+
+        if (locktype == SQLITE_LOCK_SHARED && rangeLock(pFile, F_RDLCK, &tErrno) == -1) {
+            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
+            if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
+                pFile->lastErrno = tErrno;
+            if (rc == SQLITE_OK)
+                pFile->locktype = locktype;
+            return rc;
+        }
+        lock.l_type = F_UNLCK;
+        lock.l_whence = SEEK_SET;
+        lock.l_start = SQLitePendingByte;
+        lock.l_len = 2;
+        if (fcntl(h, F_SETLK, &lock) != -1)
+            pLock->locktype = SQLITE_LOCK_SHARED;
+        else {
+            tErrno = errno;
+            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+            if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
+                pFile->lastErrno = tErrno;
+            if (rc == SQLITE_OK)
+                pFile->locktype = locktype;
+            return rc;
+        }
+    }
+    if (locktype == SQLITE_LOCK_NONE) {
+        struct ChromiumOpenInfo *pOpen;
+
+        pLock->cnt--;
+
+        // Release the lock using an OS call only when all threads in this same process have released the lock.
+        if (!pLock->cnt) {
+            lock.l_type = F_UNLCK;
+            lock.l_whence = SEEK_SET;
+            lock.l_start = lock.l_len = 0L;
+            if (fcntl(h, F_SETLK, &lock) != -1)
+                pLock->locktype = SQLITE_LOCK_NONE;
+            else {
+                tErrno = errno;
+                rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+                if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
+                    pFile->lastErrno = tErrno;
+                pLock->locktype = SQLITE_LOCK_NONE;
+                pFile->locktype = SQLITE_LOCK_NONE;
+            }
+        }
+
+        pOpen = pFile->pOpen;
+        pOpen->nLock--;
+        ASSERT(pOpen->nLock >= 0);
+        if (!pOpen->nLock) {
+            int rc2 = closePendingFds(pFile);
+            if (rc == SQLITE_OK)
+                rc = rc2;
+        }
+    }
+
+    if (rc == SQLITE_OK)
+        pFile->locktype = locktype;
+    return rc;
 }
 
-// Chromium's Posix implementation of SQLite VFS
-namespace {
+// Closes all file handles for given ChromiumFile and sets all its fields to 0.
+// Returns a SQLite error code.
+static int chromiumCloseNoLock(sqlite3_file* id)
+{
+    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
+    if (!pFile)
+        return SQLITE_OK;
+    if (pFile->dirfd >= 0) {
+        if (close(pFile->dirfd)) {
+            pFile->lastErrno = errno;
+            return SQLITE_IOERR_DIR_CLOSE;
+        }
+        pFile->dirfd = -1;
+    }
+    if (pFile->h >= 0 && close(pFile->h)) {
+        pFile->lastErrno = errno;
+        return SQLITE_IOERR_CLOSE;
+    }
+    sqlite3_free(pFile->pUnused);
+    memset(pFile, 0, sizeof(ChromiumFile));
+    return SQLITE_OK;
+}
+
+// Closes a ChromiumFile, including locking operations. Returns a SQLite error code.
+static int chromiumClose(sqlite3_file* id)
+{
+    if (!id)
+        return SQLITE_OK;
+
+    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
+    chromiumUnlock(id, SQLITE_LOCK_NONE);
+    if (pFile->pOpen && pFile->pOpen->nLock) {
+        // If there are outstanding locks, do not actually close the file just
+        // yet because that would clear those locks.
+        ChromiumOpenInfo* pOpen = pFile->pOpen;
+        ChromiumUnusedFd* p = pFile->pUnused;
+        p->pNext = pOpen->pUnused;
+        pOpen->pUnused = p;
+        pFile->h = -1;
+        pFile->pUnused = 0;
+    }
+    releaseLockInfo(pFile->pLock);
+    releaseOpenInfo(pFile->pOpen);
+    return chromiumCloseNoLock(id);
+}
+
+static int chromiumCheckReservedLockNoop(sqlite3_file*, int* pResOut)
+{
+    *pResOut = 0;
+    return SQLITE_OK;
+}
+
+static int chromiumLockNoop(sqlite3_file*, int)
+{
+    return SQLITE_OK;
+}
+
+static int chromiumUnlockNoop(sqlite3_file*, int)
+{
+    return SQLITE_OK;
+}
+
+// Seeks to the requested offset and reads up to |cnt| bytes into |pBuf|. Returns number of bytes actually read.
+static int seekAndRead(ChromiumFile* id, sqlite3_int64 offset, void* pBuf, int cnt)
+{
+    sqlite_int64 newOffset = lseek(id->h, offset, SEEK_SET);
+    if (newOffset != offset) {
+        id->lastErrno = (newOffset == -1) ? errno : 0;
+        return -1;
+    }
+    int got = read(id->h, pBuf, cnt);
+    if (got < 0)
+        id->lastErrno = errno;
+    return got;
+}
+
+// Reads data from file into a buffer. Returns a SQLite error code.
+static int chromiumRead(sqlite3_file* id, void* pBuf, int amt, sqlite3_int64 offset)
+{
+    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
+    ASSERT(pFile);
+
+    // The bytes in the locking range should never be read.
+    ASSERT(!pFile->pUnused || offset >= SQLitePendingByte + 512 || offset + amt <= SQLitePendingByte);
+
+    int got = seekAndRead(pFile, offset, pBuf, amt);
+    if (got == amt)
+        return SQLITE_OK;
+
+    if (got < 0)
+        return SQLITE_IOERR_READ;
+
+    // Unread parts of the buffer must be zero-filled.
+    memset(&(reinterpret_cast<char*>(pBuf))[got], 0, amt - got);
+    pFile->lastErrno = 0;
+    return SQLITE_IOERR_SHORT_READ;
+}
+
+// Seeks to the requested offset and writes up to |cnt| bytes. Returns number of bytes actually written.
+static int seekAndWrite(ChromiumFile* id, sqlite_int64 offset, const void* pBuf, int cnt)
+{
+    sqlite_int64 newOffset = lseek(id->h, offset, SEEK_SET);
+    if (newOffset != offset) {
+        id->lastErrno = (newOffset == -1) ? errno : 0;
+        return -1;
+    }
+    int got = write(id->h, pBuf, cnt);
+    if (got < 0)
+        id->lastErrno = errno;
+    return got;
+}
+
+// Writes data from buffer into a file. Returns a SQLite error code.
+static int chromiumWrite(sqlite3_file* id, const void* pBuf, int amt, sqlite3_int64 offset)
+{
+    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
+    ASSERT(pFile);
+    ASSERT(amt > 0);
+
+    // The bytes in the locking range should never be written.
+    ASSERT(!pFile->pUnused || offset >= SQLitePendingByte + 512 || offset + amt <= SQLitePendingByte);
+
+    int wrote = 0;
+    while (amt > 0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt)) > 0) {
+        amt -= wrote;
+        offset += wrote;
+        pBuf = &(reinterpret_cast<const char*>(pBuf))[wrote];
+    }
+    if (amt > 0) {
+        if (wrote < 0)
+            return SQLITE_IOERR_WRITE;
+        pFile->lastErrno = 0;
+        return SQLITE_FULL;
+    }
+    return SQLITE_OK;
+}
+
+static bool syncWrapper(int fd, bool fullSync)
+{
+#if OS(DARWIN)
+    bool success = false;
+    if (fullSync)
+        success = !fcntl(fd, F_FULLFSYNC, 0);
+    if (!success)
+        success = !fsync(fd);
+    return success;
+#else
+    return !fdatasync(fd);
+#endif
+}
+
+// Makes sure all writes to a particular file are committed to disk. Returns a SQLite error code.
+static int chromiumSync(sqlite3_file* id, int flags)
+{
+    ASSERT((flags & 0x0F) == SQLITE_SYNC_NORMAL || (flags & 0x0F) == SQLITE_SYNC_FULL);
+
+    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
+    ASSERT(pFile);
+
+    bool isFullSync = ((flags & 0x0F) == SQLITE_SYNC_FULL);
+
+    if (!syncWrapper(pFile->h, isFullSync)) {
+        pFile->lastErrno = errno;
+        return SQLITE_IOERR_FSYNC;
+    }
+
+    if (pFile->dirfd >= 0) {
+#if !OS(DARWIN)
+        if (!isFullSync) {
+            // Ignore directory sync failures, see http://www.sqlite.org/cvstrac/tktview?tn=1657.
+            syncWrapper(pFile->dirfd, false);
+        }
+#endif
+        if (!close(pFile->dirfd))
+            pFile->dirfd = -1;
+        else {
+            pFile->lastErrno = errno;
+            return SQLITE_IOERR_DIR_CLOSE;
+        }
+    }
+
+    return SQLITE_OK;
+}
+
+// Truncates an open file to the specified size. Returns a SQLite error code.
+static int chromiumTruncate(sqlite3_file* id, sqlite_int64 nByte)
+{
+    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
+    ASSERT(pFile);
+
+    if (ftruncate(pFile->h, nByte)) {
+        pFile->lastErrno = errno;
+        return SQLITE_IOERR_TRUNCATE;
+    }
+
+    return SQLITE_OK;
+}
+
+// Determines the size of a file in bytes. Returns a SQLite error code.
+static int chromiumFileSize(sqlite3_file* id, sqlite_int64* pSize)
+{
+    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
+    ASSERT(pFile);
+
+    struct stat buf;
+    if (fstat(pFile->h, &buf)) {
+        pFile->lastErrno = errno;
+        return SQLITE_IOERR_FSTAT;
+    }
+    *pSize = buf.st_size;
+
+    // When opening a zero-size database, findLockInfo 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.
+    // See http://www.sqlite.org/cvstrac/tktview?tn=3260.
+    if (*pSize == 1)
+        *pSize = 0;
+
+    return SQLITE_OK;
+}
+
+static int chromiumFileControl(sqlite3_file* id, int op, void* pArg)
+{
+    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
+    ASSERT(pFile);
+
+    switch (op) {
+    case SQLITE_FCNTL_LOCKSTATE:
+        *reinterpret_cast<int*>(pArg) = pFile->locktype;
+        return SQLITE_OK;
+    case SQLITE_LAST_ERRNO:
+        *reinterpret_cast<int*>(pArg) = pFile->lastErrno;
+        return SQLITE_OK;
+    }
+    return SQLITE_ERROR;
+}
+
+// Same as SQLITE_DEFAULT_SECTOR_SIZE from sqlite's os.h.
+static const int SQLiteDefaultSectorSize = 512;
+
+static int chromiumSectorSize(sqlite3_file*)
+{
+    return SQLiteDefaultSectorSize;
+}
+
+static int chromiumDeviceCharacteristics(sqlite3_file*)
+{
+    return 0;
+}
+
+static const sqlite3_io_methods posixIoMethods = {
+    1,
+    chromiumClose,
+    chromiumRead,
+    chromiumWrite,
+    chromiumTruncate,
+    chromiumSync,
+    chromiumFileSize,
+    chromiumLock,
+    chromiumUnlock,
+    chromiumCheckReservedLock,
+    chromiumFileControl,
+    chromiumSectorSize,
+    chromiumDeviceCharacteristics
+};
+
+static const sqlite3_io_methods nolockIoMethods = {
+    1,
+    chromiumCloseNoLock,
+    chromiumRead,
+    chromiumWrite,
+    chromiumTruncate,
+    chromiumSync,
+    chromiumFileSize,
+    chromiumLockNoop,
+    chromiumUnlockNoop,
+    chromiumCheckReservedLockNoop,
+    chromiumFileControl,
+    chromiumSectorSize,
+    chromiumDeviceCharacteristics
+};
+
+// Initializes a ChromiumFile. Returns a SQLite error code.
+static int fillInChromiumFile(sqlite3_vfs* pVfs, int h, int dirfd, sqlite3_file* pId, const char* zFilename, int noLock)
+{
+    ChromiumFile* pNew = reinterpret_cast<ChromiumFile*>(pId);
+
+    ASSERT(!pNew->pLock);
+    ASSERT(!pNew->pOpen);
+
+    pNew->h = h;
+    pNew->dirfd = dirfd;
+
+    int rc = SQLITE_OK;
+    const sqlite3_io_methods* pLockingStyle;
+    if (noLock)
+        pLockingStyle = &nolockIoMethods;
+    else {
+        pLockingStyle = &posixIoMethods;
+        rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
+        if (rc != SQLITE_OK) {
+            // If an error occured in findLockInfo(), close the file descriptor
+            // immediately. This can happen in two scenarios:
+            //
+            //   (a) A call to fstat() failed.
+            //   (b) A malloc failed.
+            //
+            // Scenario (b) may only occur if the process is holding no other
+            // file descriptors open on the same file. If there were other file
+            // descriptors on this file, then no malloc would be required by
+            // findLockInfo(). If this is the case, it is quite safe to close
+            // handle h - as it is guaranteed that no posix locks will be released
+            // by doing so.
+            //
+            // If scenario (a) caused the error then things are not so safe. The
+            // implicit assumption here is that if fstat() fails, things are in
+            // such bad shape that dropping a lock or two doesn't matter much.
+            close(h);
+            h = -1;
+        }
+    }
+
+    pNew->lastErrno = 0;
+    if (rc != SQLITE_OK) {
+        if (dirfd >= 0)
+            close(dirfd);
+        if (h >= 0)
+            close(h);
+    } else
+        pNew->pMethod = pLockingStyle;
+    return rc;
+}
+
+// Searches for an unused file descriptor that was opened on the database 
+// file identified by zPath with matching flags. Returns 0 if not found.
+static ChromiumUnusedFd* findReusableFd(const char* zPath, int flags)
+{
+    ChromiumUnusedFd* pUnused = 0;
+
+    struct stat sStat;
+    if (!stat(zPath, &sStat)) {
+        ChromiumFileId id;
+        id.dev = sStat.st_dev;
+        id.ino = sStat.st_ino;
+
+        ChromiumOpenInfo* pO = 0;
+        for (pO = openList; pO && memcmp(&id, &pO->fileId, sizeof(id)); pO = pO->pNext) { }
+        if (pO) {
+            ChromiumUnusedFd** pp;
+            for (pp = &pO->pUnused; *pp && (*pp)->flags != flags; pp = &((*pp)->pNext)) { }
+            pUnused = *pp;
+            if (pUnused)
+                *pp = pUnused->pNext;
+        }
+    }
+    return pUnused;
+}
 
 // Opens a file.
 //
@@ -59,14 +974,26 @@ namespace {
 // id - the structure that will manipulate the newly opened file.
 // desiredFlags - the desired open mode flags.
 // usedFlags - the actual open mode flags that were used.
-int chromiumOpen(sqlite3_vfs* vfs, const char* fileName,
-                 sqlite3_file* id, int desiredFlags, int* usedFlags)
+static int chromiumOpen(sqlite3_vfs* vfs, const char* fileName,
+                        sqlite3_file* id, int desiredFlags, int* usedFlags)
 {
-    chromium_sqlite3_initialize_unix_sqlite3_file(id);
+    // The mask 0x00007F00 gives us the 7 bits that determine the type of the file SQLite is trying to open.
+    int fileType = desiredFlags & 0x00007F00;
+
+    memset(id, 0, sizeof(ChromiumFile));
+    ChromiumFile* chromiumFile = reinterpret_cast<ChromiumFile*>(id);
     int fd = -1;
-    int result = chromium_sqlite3_get_reusable_file_handle(id, fileName, desiredFlags, &fd);
-    if (result != SQLITE_OK)
-        return result;
+    if (fileType == SQLITE_OPEN_MAIN_DB) {
+        ChromiumUnusedFd* unusedFd = findReusableFd(fileName, desiredFlags);
+        if (unusedFd)
+            fd = unusedFd->fd;
+        else {
+            unusedFd = static_cast<ChromiumUnusedFd*>(sqlite3_malloc(sizeof(*unusedFd)));
+            if (!unusedFd)
+                return SQLITE_NOMEM;
+        }
+        chromiumFile->pUnused = unusedFd;
+    }
 
     if (fd < 0) {
         fd = ChromiumBridge::databaseOpenFile(fileName, desiredFlags);
@@ -76,23 +1003,24 @@ int chromiumOpen(sqlite3_vfs* vfs, const char* fileName,
         }
     }
     if (fd < 0) {
-        chromium_sqlite3_destroy_reusable_file_handle(id);
+        sqlite3_free(chromiumFile->pUnused);
         return SQLITE_CANTOPEN;
     }
 
     if (usedFlags)
         *usedFlags = desiredFlags;
-    chromium_sqlite3_update_reusable_file_handle(id, fd, desiredFlags);
+    if (chromiumFile->pUnused) {
+        chromiumFile->pUnused->fd = fd;
+        chromiumFile->pUnused->flags = desiredFlags;
+    }
 
     fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
 
-    // The mask 0x00007F00 gives us the 7 bits that determine the type of the file SQLite is trying to open.
-    int fileType = desiredFlags & 0x00007F00;
     int noLock = (fileType != SQLITE_OPEN_MAIN_DB);
-    result = chromium_sqlite3_fill_in_unix_sqlite3_file(vfs, fd, -1, id, fileName, noLock);
-    if (result != SQLITE_OK)
-        chromium_sqlite3_destroy_reusable_file_handle(id);
-    return result;
+    int rc = fillInChromiumFile(vfs, fd, -1, id, fileName, noLock);
+    if (rc != SQLITE_OK)
+        sqlite3_free(chromiumFile->pUnused);
+    return rc;
 }
 
 // Deletes the given file.
@@ -101,7 +1029,7 @@ int chromiumOpen(sqlite3_vfs* vfs, const char* fileName,
 // fileName - the name of the file.
 // syncDir - determines if the directory to which this file belongs
 //           should be synched after the file is deleted.
-int chromiumDelete(sqlite3_vfs*, const char* fileName, int syncDir)
+static int chromiumDelete(sqlite3_vfs*, const char* fileName, int syncDir)
 {
     return ChromiumBridge::databaseDeleteFile(fileName, syncDir);
 }
@@ -112,7 +1040,7 @@ int chromiumDelete(sqlite3_vfs*, const char* fileName, int syncDir)
 // fileName - the name of the file.
 // flag - the type of test to make on this file.
 // res - the result.
-int chromiumAccess(sqlite3_vfs*, const char* fileName, int flag, int* res)
+static int chromiumAccess(sqlite3_vfs*, const char* fileName, int flag, int* res)
 {
     int attr = static_cast<int>(ChromiumBridge::databaseGetFileAttributes(fileName));
     if (attr < 0) {
@@ -122,7 +1050,7 @@ int chromiumAccess(sqlite3_vfs*, const char* fileName, int flag, int* res)
 
     switch (flag) {
     case SQLITE_ACCESS_EXISTS:
-        *res = 1;   // if the file doesn't exist, attr < 0
+        *res = 1; // if the file doesn't exist, attr < 0
         break;
     case SQLITE_ACCESS_READWRITE:
         *res = (attr & W_OK) && (attr & R_OK);
@@ -143,8 +1071,8 @@ int chromiumAccess(sqlite3_vfs*, const char* fileName, int flag, int* res)
 // relativePath - the relative path.
 // bufSize - the size of the output buffer in bytes.
 // absolutePath - the output buffer where the absolute path will be stored.
-int chromiumFullPathname(sqlite3_vfs* vfs, const char* relativePath,
-                         int, char* absolutePath)
+static int chromiumFullPathname(sqlite3_vfs* vfs, const char* relativePath,
+                                int, char* absolutePath)
 {
     // The renderer process doesn't need to know the absolute path of the file
     sqlite3_snprintf(vfs->mxPathname, absolutePath, "%s", relativePath);
@@ -152,44 +1080,107 @@ int chromiumFullPathname(sqlite3_vfs* vfs, const char* relativePath,
 }
 
 #ifndef SQLITE_OMIT_LOAD_EXTENSION
-// Returns NULL, thus disallowing loading libraries in the renderer process.
-//
-// vfs - pointer to the sqlite3_vfs object.
-// fileName - the name of the shared library file.
-void* chromiumDlOpen(sqlite3_vfs*, const char*)
+// We disallow loading DSOs inside the renderer process, so the following procedures are no-op.
+static void* chromiumDlOpen(sqlite3_vfs*, const char*)
+{
+    return 0;
+}
+
+static void chromiumDlError(sqlite3_vfs*, int, char*)
+{
+}
+
+static void (*chromiumDlSym(sqlite3_vfs*, void*, const char*))()
 {
     return 0;
 }
+
+static void chromiumDlClose(sqlite3_vfs*, void*)
+{
+}
 #else
 #define chromiumDlOpen 0
+#define chromiumDlError 0
+#define chromiumDlSym 0
+#define chromiumDlClose 0
 #endif // SQLITE_OMIT_LOAD_EXTENSION
 
-} // namespace
+// Generates a seed for SQLite's PRNG.
+static int chromiumRandomness(sqlite3_vfs*, int nBuf, char *zBuf)
+{
+    ASSERT(static_cast<size_t>(nBuf) >= (sizeof(time_t) + sizeof(int)));
+
+    memset(zBuf, 0, nBuf);
+    int fd = open("/dev/urandom", O_RDONLY);
+    if (fd < 0) {
+        time_t t;
+        time(&t);
+        memcpy(zBuf, &t, sizeof(t));
+        int pid = getpid();
+        memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
+        return sizeof(t) + sizeof(pid);
+    }
+    nBuf = read(fd, zBuf, nBuf);
+    close(fd);
+    return nBuf;
+}
+
+// Sleeps for at least |microseconds|, and returns the actual
+// amount of time spent sleeping (in microseconds).
+static int chromiumSleep(sqlite3_vfs*, int microseconds)
+{
+#if OS(DARWIN)
+    usleep(microseconds);
+    return microseconds;
+#else
+    // Round to the nearest second.
+    int seconds = (microseconds + 999999) / 1000000;
+    sleep(seconds);
+    return seconds * 1000000;
+#endif
+}
+
+// Retrieves the current system time (UTC).
+static int chromiumCurrentTime(sqlite3_vfs*, double* now)
+{
+    struct timeval timeval;
+    gettimeofday(&timeval, 0);
+    *now = 2440587.5 + timeval.tv_sec / 86400.0 + timeval.tv_usec / 86400000000.0;
+    return 0;
+}
+
+// This is not yet implemented in SQLite core.
+static int chromiumGetLastError(sqlite3_vfs*, int, char*)
+{
+    return 0;
+}
+
+// Same as MAX_PATHNAME from sqlite's os_unix.c.
+static const int chromiumMaxPathname = 512;
 
 namespace WebCore {
 
 void SQLiteFileSystem::registerSQLiteVFS()
 {
-    sqlite3_vfs* unix_vfs = sqlite3_vfs_find("unix");
     static sqlite3_vfs chromium_vfs = {
         1,
-        unix_vfs->szOsFile,
-        unix_vfs->mxPathname,
+        sizeof(ChromiumFile),
+        chromiumMaxPathname,
         0,
         "chromium_vfs",
-        unix_vfs->pAppData,
+        0,
         chromiumOpen,
         chromiumDelete,
         chromiumAccess,
         chromiumFullPathname,
         chromiumDlOpen,
-        unix_vfs->xDlError,
-        unix_vfs->xDlSym,
-        unix_vfs->xDlClose,
-        unix_vfs->xRandomness,
-        unix_vfs->xSleep,
-        unix_vfs->xCurrentTime,
-        unix_vfs->xGetLastError
+        chromiumDlError,
+        chromiumDlSym,
+        chromiumDlClose,
+        chromiumRandomness,
+        chromiumSleep,
+        chromiumCurrentTime,
+        chromiumGetLastError
     };
     sqlite3_vfs_register(&chromium_vfs, 0);
 }

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list