Changeset 68310 in webkit


Ignore:
Timestamp:
Sep 24, 2010 4:17:42 PM (14 years ago)
Author:
commit-queue@webkit.org
Message:

2010-09-24 Pawel Hajdan <phajdan.jr@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):
Location:
trunk/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r68307 r68310  
     12010-09-24  Pawel Hajdan  <phajdan.jr@chromium.org>
     2
     3        Reviewed by Dumitru Daniliuc.
     4
     5        Move the implementation of chromium_vfs to webkit for POSIX.
     6        This allows us to link Chrome with system-provided SQLite on Linux.
     7        See also http://code.google.com/p/chromium/issues/detail?id=22208.
     8        https://bugs.webkit.org/show_bug.cgi?id=45416
     9
     10        No new tests.
     11
     12        * platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp:
     13        (sqliteErrorFromPosixError):
     14        (releaseLockInfo):
     15        (releaseOpenInfo):
     16        (findLockInfo):
     17        (chromiumCheckReservedLock):
     18        (rangeLock):
     19        (chromiumLock):
     20        (closePendingFds):
     21        (chromiumUnlock):
     22        (chromiumCloseNoLock):
     23        (chromiumClose):
     24        (chromiumCheckReservedLockNoop):
     25        (chromiumLockNoop):
     26        (chromiumUnlockNoop):
     27        (seekAndRead):
     28        (chromiumRead):
     29        (seekAndWrite):
     30        (chromiumWrite):
     31        (syncWrapper):
     32        (chromiumSync):
     33        (chromiumTruncate):
     34        (chromiumFileSize):
     35        (chromiumFileControl):
     36        (chromiumSectorSize):
     37        (chromiumDeviceCharacteristics):
     38        (fillInChromiumFile):
     39        (findReusableFd):
     40        (chromiumOpen):
     41        (chromiumDelete):
     42        (chromiumAccess):
     43        (chromiumFullPathname):
     44        (chromiumDlOpen):
     45        (chromiumDlError):
     46        (chromiumDlSym):
     47        (chromiumDlClose):
     48        (chromiumRandomness):
     49        (chromiumSleep):
     50        (chromiumCurrentTime):
     51        (chromiumGetLastError):
     52        (WebCore::SQLiteFileSystem::registerSQLiteVFS):
     53
    1542010-09-24  Andreas Kling  <andreas.kling@nokia.com>
    255
  • trunk/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp

    r59273 r68310  
    3535#include <sqlite3.h>
    3636
     37#include <errno.h>
    3738#include <fcntl.h>
    3839#include <string.h>
     40#include <sys/stat.h>
     41#include <sys/time.h>
     42#include <sys/types.h>
    3943#include <unistd.h>
    4044
    4145using namespace WebCore;
    4246
    43 // Defined in Chromium's codebase in third_party/sqlite/src/os_unix.c
    44 extern "C" {
    45 void chromium_sqlite3_initialize_unix_sqlite3_file(sqlite3_file* file);
    46 int chromium_sqlite3_fill_in_unix_sqlite3_file(sqlite3_vfs* vfs, int fd, int dirfd, sqlite3_file* file, const char* fileName, int noLock);
    47 int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file, const char* fileName, int flags, int* fd);
    48 void chromium_sqlite3_update_reusable_file_handle(sqlite3_file* file, int fd, int flags);
    49 void chromium_sqlite3_destroy_reusable_file_handle(sqlite3_file* file);
    50 }
    51 
    52 // Chromium's Posix implementation of SQLite VFS
    53 namespace {
     47// Chromium's Posix implementation of SQLite VFS.
     48// This is heavily based on SQLite's os_unix.c,
     49// without parts we don't need.
     50
     51// Identifies a file by its device number and inode.
     52struct ChromiumFileId {
     53    dev_t dev; // Device number.
     54    ino_t ino; // Inode number.
     55};
     56
     57// Information about file locks (one per open inode). Note that many open
     58// file descriptors may refer to the same inode.
     59struct ChromiumLockInfo {
     60    ChromiumFileId lockKey; // File identifier.
     61    int cnt; // Number of shared locks held.
     62    int locktype; // Type of the lock.
     63    int nRef; // Reference count.
     64
     65    // Double-linked list pointers.
     66    ChromiumLockInfo* pNext;
     67    ChromiumLockInfo* pPrev;
     68};
     69
     70// Information about a file descriptor that cannot be closed immediately.
     71struct ChromiumUnusedFd {
     72    int fd; // File descriptor.
     73    int flags; // Flags this file descriptor was opened with.
     74    ChromiumUnusedFd* pNext; // Next unused file descriptor on the same file.
     75};
     76
     77// Information about an open inode. When we want to close an inode
     78// that still has locks, we defer the close until all locks are cleared.
     79struct ChromiumOpenInfo {
     80    ChromiumFileId fileId; // The lookup key.
     81    int nRef; // Reference count.
     82    int nLock; // Number of outstanding locks.
     83    ChromiumUnusedFd* pUnused; // List of file descriptors to close.
     84
     85    // Double-linked list pointers.
     86    ChromiumOpenInfo* pNext;
     87    ChromiumOpenInfo* pPrev;
     88};
     89
     90// Keep track of locks and inodes in double-linked lists.
     91static struct ChromiumLockInfo* lockList = 0;
     92static struct ChromiumOpenInfo* openList = 0;
     93
     94// Extension of sqlite3_file specific to the chromium VFS.
     95struct ChromiumFile {
     96    sqlite3_io_methods const* pMethod; // Implementation of sqlite3_file.
     97    ChromiumOpenInfo* pOpen; // Information about all open file descriptors for this file.
     98    ChromiumLockInfo* pLock; // Information about all locks for this file.
     99    int h; // File descriptor.
     100    int dirfd; // File descriptor for the file directory.
     101    unsigned char locktype; // Type of the lock used for this file.
     102    int lastErrno; // Value of errno for last operation on this file.
     103    ChromiumUnusedFd* pUnused; // Information about unused file descriptors for this file.
     104};
     105
     106// The following constants specify the range of bytes used for locking.
     107// SQLiteSharedSize is the number of bytes available in the pool from which
     108// a random byte is selected for a shared lock.  The pool of bytes for
     109// shared locks begins at SQLiteSharedFirstByte.
     110// The values are the same as used by SQLite for compatibility.
     111static const off_t SQLitePendingByte = 0x40000000;
     112static const off_t SQLiteReservedByte = SQLitePendingByte + 1;
     113static const off_t SQLiteSharedFirstByte = SQLitePendingByte + 2;
     114static const off_t SQLiteSharedSize = 510;
     115
     116// Maps a POSIX error code to an SQLite error code.
     117static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr)
     118{
     119    switch (posixError) {
     120    case 0:
     121        return SQLITE_OK;
     122    case EAGAIN:
     123    case ETIMEDOUT:
     124    case EBUSY:
     125    case EINTR:
     126    case ENOLCK: 
     127        return SQLITE_BUSY;
     128    case EACCES:
     129        // EACCES is like EAGAIN during locking operations.
     130        if ((sqliteIOErr == SQLITE_IOERR_LOCK) ||
     131            (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
     132            (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
     133            (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK))
     134            return SQLITE_BUSY;
     135        return SQLITE_PERM;
     136    case EPERM:
     137        return SQLITE_PERM;
     138    case EDEADLK:
     139        return SQLITE_IOERR_BLOCKED;
     140    default:
     141        return sqliteIOErr;
     142    }
     143}
     144
     145// Releases a ChromiumLockInfo structure previously allocated by findLockInfo().
     146static void releaseLockInfo(ChromiumLockInfo* pLock)
     147{
     148    if (!pLock)
     149        return;
     150
     151    pLock->nRef--;
     152    if (pLock->nRef > 0)
     153        return;
     154
     155    if (pLock->pPrev) {
     156        ASSERT(pLock->pPrev->pNext == pLock);
     157        pLock->pPrev->pNext = pLock->pNext;
     158    } else {
     159        ASSERT(lockList == pLock);
     160        lockList = pLock->pNext;
     161    }
     162    if (pLock->pNext) {
     163        ASSERT(pLock->pNext->pPrev == pLock);
     164        pLock->pNext->pPrev = pLock->pPrev;
     165    }
     166
     167    sqlite3_free(pLock);
     168}
     169
     170// Releases a ChromiumOpenInfo structure previously allocated by findLockInfo().
     171static void releaseOpenInfo(ChromiumOpenInfo* pOpen)
     172{
     173    if (!pOpen)
     174        return;
     175
     176    pOpen->nRef--;
     177    if (pOpen->nRef > 0)
     178        return;
     179
     180    if (pOpen->pPrev) {
     181        ASSERT(pOpen->pPrev->pNext == pOpen);
     182        pOpen->pPrev->pNext = pOpen->pNext;
     183    } else {
     184        ASSERT(openList == pOpen);
     185        openList = pOpen->pNext;
     186    }
     187    if (pOpen->pNext) {
     188        ASSERT(pOpen->pNext->pPrev == pOpen);
     189        pOpen->pNext->pPrev = pOpen->pPrev;
     190    }
     191
     192    ASSERT(!pOpen->pUnused); // Make sure we're not leaking memory and file descriptors.
     193
     194    sqlite3_free(pOpen);
     195}
     196
     197// Locates ChromiumLockInfo and ChromiumOpenInfo for given file descriptor (creating new ones if needed).
     198// Returns a SQLite error code.
     199static int findLockInfo(ChromiumFile* pFile, ChromiumLockInfo** ppLock, ChromiumOpenInfo** ppOpen)
     200{
     201    int fd = pFile->h;
     202    struct stat statbuf;
     203    int rc = fstat(fd, &statbuf);
     204    if (rc) {
     205        pFile->lastErrno = errno;
     206#ifdef EOVERFLOW
     207        if (pFile->lastErrno == EOVERFLOW)
     208            return SQLITE_NOLFS;
     209#endif
     210        return SQLITE_IOERR;
     211    }
     212
     213#if OS(DARWIN)
     214    // On OS X on an msdos/fat filesystems, the inode number is reported
     215    // incorrectly for zero-size files. See http://www.sqlite.org/cvstrac/tktview?tn=3260.
     216    // To work around this problem we always increase the file size to 1 by writing a single byte
     217    // prior to accessing the inode number. The one byte written is an ASCII 'S' character which
     218    // also happens to be the first byte in the header of every SQLite database.  In this way,
     219    // if there is a race condition such that another thread has already populated the first page
     220    // of the database, no damage is done.
     221    if (!statbuf.st_size) {
     222        rc = write(fd, "S", 1);
     223        if (rc != 1)
     224            return SQLITE_IOERR;
     225        rc = fstat(fd, &statbuf);
     226        if (rc) {
     227            pFile->lastErrno = errno;
     228            return SQLITE_IOERR;
     229        }
     230    }
     231#endif
     232
     233    ChromiumFileId fileId;
     234    memset(&fileId, 0, sizeof(fileId));
     235    fileId.dev = statbuf.st_dev;
     236    fileId.ino = statbuf.st_ino;
     237
     238    ChromiumLockInfo* pLock = 0;
     239
     240    if (ppLock) {
     241        pLock = lockList;
     242        while (pLock && memcmp(&fileId, &pLock->lockKey, sizeof(fileId)))
     243            pLock = pLock->pNext;
     244        if (pLock)
     245            pLock->nRef++;
     246        else {
     247            pLock = static_cast<ChromiumLockInfo*>(sqlite3_malloc(sizeof(*pLock)));
     248            if (!pLock)
     249                return SQLITE_NOMEM;
     250            pLock->lockKey = fileId;
     251            pLock->nRef = 1;
     252            pLock->cnt = 0;
     253            pLock->locktype = 0;
     254            pLock->pNext = lockList;
     255            pLock->pPrev = 0;
     256            if (lockList)
     257                lockList->pPrev = pLock;
     258            lockList = pLock;
     259        }
     260        *ppLock = pLock;
     261    }
     262
     263    if (ppOpen) {
     264        ChromiumOpenInfo* pOpen = openList;
     265        while (pOpen && memcmp(&fileId, &pOpen->fileId, sizeof(fileId)))
     266            pOpen = pOpen->pNext;
     267        if (pOpen)
     268            pOpen->nRef++;
     269        else {
     270            pOpen = static_cast<ChromiumOpenInfo*>(sqlite3_malloc(sizeof(*pOpen)));
     271            if (!pOpen) {
     272                releaseLockInfo(pLock);
     273                return SQLITE_NOMEM;
     274            }
     275            memset(pOpen, 0, sizeof(*pOpen));
     276            pOpen->fileId = fileId;
     277            pOpen->nRef = 1;
     278            pOpen->pNext = openList;
     279            if (openList)
     280                openList->pPrev = pOpen;
     281            openList = pOpen;
     282        }
     283        *ppOpen = pOpen;
     284    }
     285
     286    return rc;
     287}
     288
     289// Checks if there is a RESERVED lock held on the specified file by this or any other process.
     290// If the lock is held, sets pResOut to a non-zero value. Returns a SQLite error code.
     291static int chromiumCheckReservedLock(sqlite3_file* id, int* pResOut)
     292{
     293    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
     294    ASSERT(pFile);
     295
     296    // Look for locks held by this process.
     297    int reserved = 0;
     298    if (pFile->pLock->locktype > SQLITE_LOCK_SHARED)
     299        reserved = 1;
     300
     301    // Look for locks held by other processes.
     302    int rc = SQLITE_OK;
     303    if (!reserved) {
     304        struct flock lock;
     305        lock.l_whence = SEEK_SET;
     306        lock.l_start = SQLiteReservedByte;
     307        lock.l_len = 1;
     308        lock.l_type = F_WRLCK;
     309        if (-1 == fcntl(pFile->h, F_GETLK, &lock)) {
     310            int tErrno = errno;
     311            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
     312            pFile->lastErrno = tErrno;
     313        } else if (lock.l_type != F_UNLCK)
     314            reserved = 1;
     315    }
     316
     317    *pResOut = reserved;
     318    return rc;
     319}
     320
     321// Performs a file locking operation on a range of bytes in a file.
     322// The |op| parameter should be one of F_RFLCK, F_WRLCK or F_UNLCK.
     323// Returns a Unix error code, and also writes it to pErrcode.
     324static int rangeLock(ChromiumFile* pFile, int op, int* pErrcode)
     325{
     326    struct flock lock;
     327    lock.l_type = op;
     328    lock.l_start = SQLiteSharedFirstByte;
     329    lock.l_whence = SEEK_SET;
     330    lock.l_len = SQLiteSharedSize;
     331    int rc = fcntl(pFile->h, F_SETLK, &lock);
     332    *pErrcode = errno;
     333    return rc;
     334}
     335
     336// Locks the file with the lock specified by parameter locktype - one
     337// of the following:
     338//
     339//     (1) SQLITE_LOCK_SHARED
     340//     (2) SQLITE_LOCK_RESERVED
     341//     (3) SQLITE_LOCK_PENDING
     342//     (4) SQLITE_LOCK_EXCLUSIVE
     343//
     344// Sometimes when requesting one lock state, additional lock states
     345// are inserted in between.  The locking might fail on one of the later
     346// transitions leaving the lock state different from what it started but
     347// still short of its goal.  The following chart shows the allowed
     348// transitions and the inserted intermediate states:
     349//
     350//    UNLOCKED -> SHARED
     351//    SHARED -> RESERVED
     352//    SHARED -> (PENDING) -> EXCLUSIVE
     353//    RESERVED -> (PENDING) -> EXCLUSIVE
     354//    PENDING -> EXCLUSIVE
     355static int chromiumLock(sqlite3_file* id, int locktype)
     356{
     357    // To obtain a SHARED lock, a read-lock is obtained on the 'pending
     358    // byte'.  If this is successful, a random byte from the 'shared byte
     359    // range' is read-locked and the lock on the 'pending byte' released.
     360    //
     361    // A process may only obtain a RESERVED lock after it has a SHARED lock.
     362    // A RESERVED lock is implemented by grabbing a write-lock on the
     363    // 'reserved byte'.
     364    //
     365    // A process may only obtain a PENDING lock after it has obtained a
     366    // SHARED lock. A PENDING lock is implemented by obtaining a write-lock
     367    // on the 'pending byte'. This ensures that no new SHARED locks can be
     368    // obtained, but existing SHARED locks are allowed to persist. A process
     369    // does not have to obtain a RESERVED lock on the way to a PENDING lock.
     370    // This property is used by the algorithm for rolling back a journal file
     371    // after a crash.
     372    //
     373    // An EXCLUSIVE lock, obtained after a PENDING lock is held, is
     374    // implemented by obtaining a write-lock on the entire 'shared byte
     375    // range'. Since all other locks require a read-lock on one of the bytes
     376    // within this range, this ensures that no other locks are held on the
     377    // database.
     378
     379    int rc = SQLITE_OK;
     380    struct flock lock;
     381    int s = 0;
     382    int tErrno;
     383
     384    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
     385    ASSERT(pFile);
     386
     387    ChromiumLockInfo* pLock = pFile->pLock;
     388
     389    // If there is already a lock of this type or more restrictive, do nothing.
     390    if (pFile->locktype >= locktype)
     391        return SQLITE_OK;
     392
     393    // Make sure we never move from unlocked to anything higher than shared lock.
     394    ASSERT(pFile->locktype != SQLITE_LOCK_NONE || locktype == SQLITE_LOCK_SHARED);
     395
     396    // Make sure we never request a pending lock.
     397    ASSERT(locktype != SQLITE_LOCK_PENDING);
     398
     399    // Make sure a shared lock is always held when a RESERVED lock is requested.
     400    ASSERT(locktype != SQLITE_LOCK_RESERVED || pFile->locktype == SQLITE_LOCK_SHARED);
     401
     402    // If some thread using this PID has a lock via a different ChromiumFile
     403    // handle that precludes the requested lock, return BUSY.
     404    if (pFile->locktype != pLock->locktype &&
     405        (pLock->locktype >= SQLITE_LOCK_PENDING || locktype > SQLITE_LOCK_SHARED))
     406        return SQLITE_BUSY;
     407
     408    // If a SHARED lock is requested, and some thread using this PID already
     409    // has a SHARED or RESERVED lock, then just increment reference counts.
     410    if (locktype == SQLITE_LOCK_SHARED &&
     411        (pLock->locktype == SQLITE_LOCK_SHARED || pLock->locktype == SQLITE_LOCK_RESERVED)) {
     412        ASSERT(!pFile->locktype);
     413        ASSERT(pLock->cnt > 0);
     414        pFile->locktype = SQLITE_LOCK_SHARED;
     415        pLock->cnt++;
     416        pFile->pOpen->nLock++;
     417        return SQLITE_OK;
     418    }
     419
     420    // A PENDING lock is needed before acquiring a SHARED lock and before
     421    // acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
     422    // be released.
     423    lock.l_len = 1;
     424    lock.l_whence = SEEK_SET;
     425    if (locktype == SQLITE_LOCK_SHARED ||
     426        (locktype == SQLITE_LOCK_EXCLUSIVE && pFile->locktype < SQLITE_LOCK_PENDING)) {
     427        lock.l_type = (locktype == SQLITE_LOCK_SHARED ? F_RDLCK : F_WRLCK);
     428        lock.l_start = SQLitePendingByte;
     429        s = fcntl(pFile->h, F_SETLK, &lock);
     430        if (s == -1) {
     431            tErrno = errno;
     432            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
     433            if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
     434                pFile->lastErrno = tErrno;
     435            return rc;
     436        }
     437    }
     438
     439    if (locktype == SQLITE_LOCK_SHARED) {
     440        ASSERT(!pLock->cnt);
     441        ASSERT(!pLock->locktype);
     442
     443        s = rangeLock(pFile, F_RDLCK, &tErrno);
     444
     445        // Drop the temporary PENDING lock.
     446        lock.l_start = SQLitePendingByte;
     447        lock.l_len = 1;
     448        lock.l_type = F_UNLCK;
     449        if (fcntl(pFile->h, F_SETLK, &lock)) {
     450            if (s != -1) {
     451                tErrno = errno;
     452                rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
     453                if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
     454                    pFile->lastErrno = tErrno;
     455                return rc;
     456            }
     457        }
     458        if (s == -1) {
     459            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
     460            if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
     461                pFile->lastErrno = tErrno;
     462        } else {
     463            pFile->locktype = SQLITE_LOCK_SHARED;
     464            pFile->pOpen->nLock++;
     465            pLock->cnt = 1;
     466        }
     467    } else if (locktype == SQLITE_LOCK_EXCLUSIVE && pLock->cnt > 1) {
     468        // We are trying for an exclusive lock but another thread in the
     469        // same process is still holding a shared lock.
     470        rc = SQLITE_BUSY;
     471    }  else {
     472        // The request was for a RESERVED or EXCLUSIVE lock.  It is
     473        // assumed that there is a SHARED or greater lock on the file
     474        // already.
     475        ASSERT(pFile->locktype);
     476        lock.l_type = F_WRLCK;
     477        switch (locktype) {
     478        case SQLITE_LOCK_RESERVED:
     479            lock.l_start = SQLiteReservedByte;
     480            s = fcntl(pFile->h, F_SETLK, &lock);
     481            tErrno = errno;
     482            break;
     483        case SQLITE_LOCK_EXCLUSIVE:
     484            s = rangeLock(pFile, F_WRLCK, &tErrno);
     485            break;
     486        default:
     487            ASSERT_NOT_REACHED();
     488        }
     489        if (s == -1) {
     490            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
     491            if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
     492                pFile->lastErrno = tErrno;
     493        }
     494    }
     495 
     496    if (rc == SQLITE_OK) {
     497        pFile->locktype = locktype;
     498        pLock->locktype = locktype;
     499    } else if (locktype == SQLITE_LOCK_EXCLUSIVE) {
     500        pFile->locktype = SQLITE_LOCK_PENDING;
     501        pLock->locktype = SQLITE_LOCK_PENDING;
     502    }
     503
     504    return rc;
     505}
     506
     507// Closes all file descriptors for given ChromiumFile for which the close has been deferred.
     508// Returns a SQLite error code.
     509static int closePendingFds(ChromiumFile* pFile)
     510{
     511    int rc = SQLITE_OK;
     512    ChromiumOpenInfo* pOpen = pFile->pOpen;
     513    ChromiumUnusedFd* pError = 0;
     514    ChromiumUnusedFd* pNext;
     515    for (ChromiumUnusedFd* p = pOpen->pUnused; p; p = pNext) {
     516        pNext = p->pNext;
     517        if (close(p->fd)) {
     518            pFile->lastErrno = errno;
     519            rc = SQLITE_IOERR_CLOSE;
     520            p->pNext = pError;
     521            pError = p;
     522        } else
     523            sqlite3_free(p);
     524    }
     525    pOpen->pUnused = pError;
     526    return rc;
     527}
     528
     529// Lowers the locking level on file descriptor.
     530// locktype must be either SQLITE_LOCK_NONE or SQLITE_LOCK_SHARED.
     531static int chromiumUnlock(sqlite3_file* id, int locktype)
     532{
     533    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
     534    ASSERT(pFile);
     535    ASSERT(locktype <= SQLITE_LOCK_SHARED);
     536
     537    if (pFile->locktype <= locktype)
     538        return SQLITE_OK;
     539
     540    ChromiumLockInfo* pLock = pFile->pLock;
     541    ASSERT(pLock->cnt);
     542
     543    struct flock lock;
     544    int rc = SQLITE_OK;
     545    int h = pFile->h;
     546    int tErrno;
     547
     548    if (pFile->locktype > SQLITE_LOCK_SHARED) {
     549        ASSERT(pLock->locktype == pFile->locktype);
     550
     551        if (locktype == SQLITE_LOCK_SHARED && rangeLock(pFile, F_RDLCK, &tErrno) == -1) {
     552            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
     553            if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
     554                pFile->lastErrno = tErrno;
     555            if (rc == SQLITE_OK)
     556                pFile->locktype = locktype;
     557            return rc;
     558        }
     559        lock.l_type = F_UNLCK;
     560        lock.l_whence = SEEK_SET;
     561        lock.l_start = SQLitePendingByte;
     562        lock.l_len = 2;
     563        if (fcntl(h, F_SETLK, &lock) != -1)
     564            pLock->locktype = SQLITE_LOCK_SHARED;
     565        else {
     566            tErrno = errno;
     567            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
     568            if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
     569                pFile->lastErrno = tErrno;
     570            if (rc == SQLITE_OK)
     571                pFile->locktype = locktype;
     572            return rc;
     573        }
     574    }
     575    if (locktype == SQLITE_LOCK_NONE) {
     576        struct ChromiumOpenInfo *pOpen;
     577
     578        pLock->cnt--;
     579
     580        // Release the lock using an OS call only when all threads in this same process have released the lock.
     581        if (!pLock->cnt) {
     582            lock.l_type = F_UNLCK;
     583            lock.l_whence = SEEK_SET;
     584            lock.l_start = lock.l_len = 0L;
     585            if (fcntl(h, F_SETLK, &lock) != -1)
     586                pLock->locktype = SQLITE_LOCK_NONE;
     587            else {
     588                tErrno = errno;
     589                rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
     590                if ((rc != SQLITE_OK) && (rc != SQLITE_BUSY))
     591                    pFile->lastErrno = tErrno;
     592                pLock->locktype = SQLITE_LOCK_NONE;
     593                pFile->locktype = SQLITE_LOCK_NONE;
     594            }
     595        }
     596
     597        pOpen = pFile->pOpen;
     598        pOpen->nLock--;
     599        ASSERT(pOpen->nLock >= 0);
     600        if (!pOpen->nLock) {
     601            int rc2 = closePendingFds(pFile);
     602            if (rc == SQLITE_OK)
     603                rc = rc2;
     604        }
     605    }
     606
     607    if (rc == SQLITE_OK)
     608        pFile->locktype = locktype;
     609    return rc;
     610}
     611
     612// Closes all file handles for given ChromiumFile and sets all its fields to 0.
     613// Returns a SQLite error code.
     614static int chromiumCloseNoLock(sqlite3_file* id)
     615{
     616    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
     617    if (!pFile)
     618        return SQLITE_OK;
     619    if (pFile->dirfd >= 0) {
     620        if (close(pFile->dirfd)) {
     621            pFile->lastErrno = errno;
     622            return SQLITE_IOERR_DIR_CLOSE;
     623        }
     624        pFile->dirfd = -1;
     625    }
     626    if (pFile->h >= 0 && close(pFile->h)) {
     627        pFile->lastErrno = errno;
     628        return SQLITE_IOERR_CLOSE;
     629    }
     630    sqlite3_free(pFile->pUnused);
     631    memset(pFile, 0, sizeof(ChromiumFile));
     632    return SQLITE_OK;
     633}
     634
     635// Closes a ChromiumFile, including locking operations. Returns a SQLite error code.
     636static int chromiumClose(sqlite3_file* id)
     637{
     638    if (!id)
     639        return SQLITE_OK;
     640
     641    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
     642    chromiumUnlock(id, SQLITE_LOCK_NONE);
     643    if (pFile->pOpen && pFile->pOpen->nLock) {
     644        // If there are outstanding locks, do not actually close the file just
     645        // yet because that would clear those locks.
     646        ChromiumOpenInfo* pOpen = pFile->pOpen;
     647        ChromiumUnusedFd* p = pFile->pUnused;
     648        p->pNext = pOpen->pUnused;
     649        pOpen->pUnused = p;
     650        pFile->h = -1;
     651        pFile->pUnused = 0;
     652    }
     653    releaseLockInfo(pFile->pLock);
     654    releaseOpenInfo(pFile->pOpen);
     655    return chromiumCloseNoLock(id);
     656}
     657
     658static int chromiumCheckReservedLockNoop(sqlite3_file*, int* pResOut)
     659{
     660    *pResOut = 0;
     661    return SQLITE_OK;
     662}
     663
     664static int chromiumLockNoop(sqlite3_file*, int)
     665{
     666    return SQLITE_OK;
     667}
     668
     669static int chromiumUnlockNoop(sqlite3_file*, int)
     670{
     671    return SQLITE_OK;
     672}
     673
     674// Seeks to the requested offset and reads up to |cnt| bytes into |pBuf|. Returns number of bytes actually read.
     675static int seekAndRead(ChromiumFile* id, sqlite3_int64 offset, void* pBuf, int cnt)
     676{
     677    sqlite_int64 newOffset = lseek(id->h, offset, SEEK_SET);
     678    if (newOffset != offset) {
     679        id->lastErrno = (newOffset == -1) ? errno : 0;
     680        return -1;
     681    }
     682    int got = read(id->h, pBuf, cnt);
     683    if (got < 0)
     684        id->lastErrno = errno;
     685    return got;
     686}
     687
     688// Reads data from file into a buffer. Returns a SQLite error code.
     689static int chromiumRead(sqlite3_file* id, void* pBuf, int amt, sqlite3_int64 offset)
     690{
     691    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
     692    ASSERT(pFile);
     693
     694    // The bytes in the locking range should never be read.
     695    ASSERT(!pFile->pUnused || offset >= SQLitePendingByte + 512 || offset + amt <= SQLitePendingByte);
     696
     697    int got = seekAndRead(pFile, offset, pBuf, amt);
     698    if (got == amt)
     699        return SQLITE_OK;
     700
     701    if (got < 0)
     702        return SQLITE_IOERR_READ;
     703
     704    // Unread parts of the buffer must be zero-filled.
     705    memset(&(reinterpret_cast<char*>(pBuf))[got], 0, amt - got);
     706    pFile->lastErrno = 0;
     707    return SQLITE_IOERR_SHORT_READ;
     708}
     709
     710// Seeks to the requested offset and writes up to |cnt| bytes. Returns number of bytes actually written.
     711static int seekAndWrite(ChromiumFile* id, sqlite_int64 offset, const void* pBuf, int cnt)
     712{
     713    sqlite_int64 newOffset = lseek(id->h, offset, SEEK_SET);
     714    if (newOffset != offset) {
     715        id->lastErrno = (newOffset == -1) ? errno : 0;
     716        return -1;
     717    }
     718    int got = write(id->h, pBuf, cnt);
     719    if (got < 0)
     720        id->lastErrno = errno;
     721    return got;
     722}
     723
     724// Writes data from buffer into a file. Returns a SQLite error code.
     725static int chromiumWrite(sqlite3_file* id, const void* pBuf, int amt, sqlite3_int64 offset)
     726{
     727    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
     728    ASSERT(pFile);
     729    ASSERT(amt > 0);
     730
     731    // The bytes in the locking range should never be written.
     732    ASSERT(!pFile->pUnused || offset >= SQLitePendingByte + 512 || offset + amt <= SQLitePendingByte);
     733
     734    int wrote = 0;
     735    while (amt > 0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt)) > 0) {
     736        amt -= wrote;
     737        offset += wrote;
     738        pBuf = &(reinterpret_cast<const char*>(pBuf))[wrote];
     739    }
     740    if (amt > 0) {
     741        if (wrote < 0)
     742            return SQLITE_IOERR_WRITE;
     743        pFile->lastErrno = 0;
     744        return SQLITE_FULL;
     745    }
     746    return SQLITE_OK;
     747}
     748
     749static bool syncWrapper(int fd, bool fullSync)
     750{
     751#if OS(DARWIN)
     752    bool success = false;
     753    if (fullSync)
     754        success = !fcntl(fd, F_FULLFSYNC, 0);
     755    if (!success)
     756        success = !fsync(fd);
     757    return success;
     758#else
     759    return !fdatasync(fd);
     760#endif
     761}
     762
     763// Makes sure all writes to a particular file are committed to disk. Returns a SQLite error code.
     764static int chromiumSync(sqlite3_file* id, int flags)
     765{
     766    ASSERT((flags & 0x0F) == SQLITE_SYNC_NORMAL || (flags & 0x0F) == SQLITE_SYNC_FULL);
     767
     768    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
     769    ASSERT(pFile);
     770
     771    bool isFullSync = ((flags & 0x0F) == SQLITE_SYNC_FULL);
     772
     773    if (!syncWrapper(pFile->h, isFullSync)) {
     774        pFile->lastErrno = errno;
     775        return SQLITE_IOERR_FSYNC;
     776    }
     777
     778    if (pFile->dirfd >= 0) {
     779#if !OS(DARWIN)
     780        if (!isFullSync) {
     781            // Ignore directory sync failures, see http://www.sqlite.org/cvstrac/tktview?tn=1657.
     782            syncWrapper(pFile->dirfd, false);
     783        }
     784#endif
     785        if (!close(pFile->dirfd))
     786            pFile->dirfd = -1;
     787        else {
     788            pFile->lastErrno = errno;
     789            return SQLITE_IOERR_DIR_CLOSE;
     790        }
     791    }
     792
     793    return SQLITE_OK;
     794}
     795
     796// Truncates an open file to the specified size. Returns a SQLite error code.
     797static int chromiumTruncate(sqlite3_file* id, sqlite_int64 nByte)
     798{
     799    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
     800    ASSERT(pFile);
     801
     802    if (ftruncate(pFile->h, nByte)) {
     803        pFile->lastErrno = errno;
     804        return SQLITE_IOERR_TRUNCATE;
     805    }
     806
     807    return SQLITE_OK;
     808}
     809
     810// Determines the size of a file in bytes. Returns a SQLite error code.
     811static int chromiumFileSize(sqlite3_file* id, sqlite_int64* pSize)
     812{
     813    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
     814    ASSERT(pFile);
     815
     816    struct stat buf;
     817    if (fstat(pFile->h, &buf)) {
     818        pFile->lastErrno = errno;
     819        return SQLITE_IOERR_FSTAT;
     820    }
     821    *pSize = buf.st_size;
     822
     823    // When opening a zero-size database, findLockInfo writes a single byte into that file
     824    // in order to work around a bug in the OS X msdos filesystem. In order to avoid problems
     825    // with upper layers, we need to report this file size as zero even though it is really 1.
     826    // See http://www.sqlite.org/cvstrac/tktview?tn=3260.
     827    if (*pSize == 1)
     828        *pSize = 0;
     829
     830    return SQLITE_OK;
     831}
     832
     833static int chromiumFileControl(sqlite3_file* id, int op, void* pArg)
     834{
     835    ChromiumFile* pFile = reinterpret_cast<ChromiumFile*>(id);
     836    ASSERT(pFile);
     837
     838    switch (op) {
     839    case SQLITE_FCNTL_LOCKSTATE:
     840        *reinterpret_cast<int*>(pArg) = pFile->locktype;
     841        return SQLITE_OK;
     842    case SQLITE_LAST_ERRNO:
     843        *reinterpret_cast<int*>(pArg) = pFile->lastErrno;
     844        return SQLITE_OK;
     845    }
     846    return SQLITE_ERROR;
     847}
     848
     849// Same as SQLITE_DEFAULT_SECTOR_SIZE from sqlite's os.h.
     850static const int SQLiteDefaultSectorSize = 512;
     851
     852static int chromiumSectorSize(sqlite3_file*)
     853{
     854    return SQLiteDefaultSectorSize;
     855}
     856
     857static int chromiumDeviceCharacteristics(sqlite3_file*)
     858{
     859    return 0;
     860}
     861
     862static const sqlite3_io_methods posixIoMethods = {
     863    1,
     864    chromiumClose,
     865    chromiumRead,
     866    chromiumWrite,
     867    chromiumTruncate,
     868    chromiumSync,
     869    chromiumFileSize,
     870    chromiumLock,
     871    chromiumUnlock,
     872    chromiumCheckReservedLock,
     873    chromiumFileControl,
     874    chromiumSectorSize,
     875    chromiumDeviceCharacteristics
     876};
     877
     878static const sqlite3_io_methods nolockIoMethods = {
     879    1,
     880    chromiumCloseNoLock,
     881    chromiumRead,
     882    chromiumWrite,
     883    chromiumTruncate,
     884    chromiumSync,
     885    chromiumFileSize,
     886    chromiumLockNoop,
     887    chromiumUnlockNoop,
     888    chromiumCheckReservedLockNoop,
     889    chromiumFileControl,
     890    chromiumSectorSize,
     891    chromiumDeviceCharacteristics
     892};
     893
     894// Initializes a ChromiumFile. Returns a SQLite error code.
     895static int fillInChromiumFile(sqlite3_vfs* pVfs, int h, int dirfd, sqlite3_file* pId, const char* zFilename, int noLock)
     896{
     897    ChromiumFile* pNew = reinterpret_cast<ChromiumFile*>(pId);
     898
     899    ASSERT(!pNew->pLock);
     900    ASSERT(!pNew->pOpen);
     901
     902    pNew->h = h;
     903    pNew->dirfd = dirfd;
     904
     905    int rc = SQLITE_OK;
     906    const sqlite3_io_methods* pLockingStyle;
     907    if (noLock)
     908        pLockingStyle = &nolockIoMethods;
     909    else {
     910        pLockingStyle = &posixIoMethods;
     911        rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
     912        if (rc != SQLITE_OK) {
     913            // If an error occured in findLockInfo(), close the file descriptor
     914            // immediately. This can happen in two scenarios:
     915            //
     916            //   (a) A call to fstat() failed.
     917            //   (b) A malloc failed.
     918            //
     919            // Scenario (b) may only occur if the process is holding no other
     920            // file descriptors open on the same file. If there were other file
     921            // descriptors on this file, then no malloc would be required by
     922            // findLockInfo(). If this is the case, it is quite safe to close
     923            // handle h - as it is guaranteed that no posix locks will be released
     924            // by doing so.
     925            //
     926            // If scenario (a) caused the error then things are not so safe. The
     927            // implicit assumption here is that if fstat() fails, things are in
     928            // such bad shape that dropping a lock or two doesn't matter much.
     929            close(h);
     930            h = -1;
     931        }
     932    }
     933
     934    pNew->lastErrno = 0;
     935    if (rc != SQLITE_OK) {
     936        if (dirfd >= 0)
     937            close(dirfd);
     938        if (h >= 0)
     939            close(h);
     940    } else
     941        pNew->pMethod = pLockingStyle;
     942    return rc;
     943}
     944
     945// Searches for an unused file descriptor that was opened on the database
     946// file identified by zPath with matching flags. Returns 0 if not found.
     947static ChromiumUnusedFd* findReusableFd(const char* zPath, int flags)
     948{
     949    ChromiumUnusedFd* pUnused = 0;
     950
     951    struct stat sStat;
     952    if (!stat(zPath, &sStat)) {
     953        ChromiumFileId id;
     954        id.dev = sStat.st_dev;
     955        id.ino = sStat.st_ino;
     956
     957        ChromiumOpenInfo* pO = 0;
     958        for (pO = openList; pO && memcmp(&id, &pO->fileId, sizeof(id)); pO = pO->pNext) { }
     959        if (pO) {
     960            ChromiumUnusedFd** pp;
     961            for (pp = &pO->pUnused; *pp && (*pp)->flags != flags; pp = &((*pp)->pNext)) { }
     962            pUnused = *pp;
     963            if (pUnused)
     964                *pp = pUnused->pNext;
     965        }
     966    }
     967    return pUnused;
     968}
    54969
    55970// Opens a file.
     
    60975// desiredFlags - the desired open mode flags.
    61976// usedFlags - the actual open mode flags that were used.
    62 int chromiumOpen(sqlite3_vfs* vfs, const char* fileName,
    63                  sqlite3_file* id, int desiredFlags, int* usedFlags)
    64 {
    65     chromium_sqlite3_initialize_unix_sqlite3_file(id);
     977static int chromiumOpen(sqlite3_vfs* vfs, const char* fileName,
     978                        sqlite3_file* id, int desiredFlags, int* usedFlags)
     979{
     980    // The mask 0x00007F00 gives us the 7 bits that determine the type of the file SQLite is trying to open.
     981    int fileType = desiredFlags & 0x00007F00;
     982
     983    memset(id, 0, sizeof(ChromiumFile));
     984    ChromiumFile* chromiumFile = reinterpret_cast<ChromiumFile*>(id);
    66985    int fd = -1;
    67     int result = chromium_sqlite3_get_reusable_file_handle(id, fileName, desiredFlags, &fd);
    68     if (result != SQLITE_OK)
    69         return result;
     986    if (fileType == SQLITE_OPEN_MAIN_DB) {
     987        ChromiumUnusedFd* unusedFd = findReusableFd(fileName, desiredFlags);
     988        if (unusedFd)
     989            fd = unusedFd->fd;
     990        else {
     991            unusedFd = static_cast<ChromiumUnusedFd*>(sqlite3_malloc(sizeof(*unusedFd)));
     992            if (!unusedFd)
     993                return SQLITE_NOMEM;
     994        }
     995        chromiumFile->pUnused = unusedFd;
     996    }
    70997
    71998    if (fd < 0) {
     
    771004    }
    781005    if (fd < 0) {
    79         chromium_sqlite3_destroy_reusable_file_handle(id);
     1006        sqlite3_free(chromiumFile->pUnused);
    801007        return SQLITE_CANTOPEN;
    811008    }
     
    831010    if (usedFlags)
    841011        *usedFlags = desiredFlags;
    85     chromium_sqlite3_update_reusable_file_handle(id, fd, desiredFlags);
     1012    if (chromiumFile->pUnused) {
     1013        chromiumFile->pUnused->fd = fd;
     1014        chromiumFile->pUnused->flags = desiredFlags;
     1015    }
    861016
    871017    fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
    881018
    89     // The mask 0x00007F00 gives us the 7 bits that determine the type of the file SQLite is trying to open.
    90     int fileType = desiredFlags & 0x00007F00;
    911019    int noLock = (fileType != SQLITE_OPEN_MAIN_DB);
    92     result = chromium_sqlite3_fill_in_unix_sqlite3_file(vfs, fd, -1, id, fileName, noLock);
    93     if (result != SQLITE_OK)
    94         chromium_sqlite3_destroy_reusable_file_handle(id);
    95     return result;
     1020    int rc = fillInChromiumFile(vfs, fd, -1, id, fileName, noLock);
     1021    if (rc != SQLITE_OK)
     1022        sqlite3_free(chromiumFile->pUnused);
     1023    return rc;
    961024}
    971025
     
    1021030// syncDir - determines if the directory to which this file belongs
    1031031//           should be synched after the file is deleted.
    104 int chromiumDelete(sqlite3_vfs*, const char* fileName, int syncDir)
     1032static int chromiumDelete(sqlite3_vfs*, const char* fileName, int syncDir)
    1051033{
    1061034    return ChromiumBridge::databaseDeleteFile(fileName, syncDir);
     
    1131041// flag - the type of test to make on this file.
    1141042// res - the result.
    115 int chromiumAccess(sqlite3_vfs*, const char* fileName, int flag, int* res)
     1043static int chromiumAccess(sqlite3_vfs*, const char* fileName, int flag, int* res)
    1161044{
    1171045    int attr = static_cast<int>(ChromiumBridge::databaseGetFileAttributes(fileName));
     
    1231051    switch (flag) {
    1241052    case SQLITE_ACCESS_EXISTS:
    125         *res = 1;   // if the file doesn't exist, attr < 0
     1053        *res = 1; // if the file doesn't exist, attr < 0
    1261054        break;
    1271055    case SQLITE_ACCESS_READWRITE:
     
    1441072// bufSize - the size of the output buffer in bytes.
    1451073// absolutePath - the output buffer where the absolute path will be stored.
    146 int chromiumFullPathname(sqlite3_vfs* vfs, const char* relativePath,
    147                          int, char* absolutePath)
     1074static int chromiumFullPathname(sqlite3_vfs* vfs, const char* relativePath,
     1075                                int, char* absolutePath)
    1481076{
    1491077    // The renderer process doesn't need to know the absolute path of the file
     
    1531081
    1541082#ifndef SQLITE_OMIT_LOAD_EXTENSION
    155 // Returns NULL, thus disallowing loading libraries in the renderer process.
    156 //
    157 // vfs - pointer to the sqlite3_vfs object.
    158 // fileName - the name of the shared library file.
    159 void* chromiumDlOpen(sqlite3_vfs*, const char*)
     1083// We disallow loading DSOs inside the renderer process, so the following procedures are no-op.
     1084static void* chromiumDlOpen(sqlite3_vfs*, const char*)
    1601085{
    1611086    return 0;
     1087}
     1088
     1089static void chromiumDlError(sqlite3_vfs*, int, char*)
     1090{
     1091}
     1092
     1093static void (*chromiumDlSym(sqlite3_vfs*, void*, const char*))()
     1094{
     1095    return 0;
     1096}
     1097
     1098static void chromiumDlClose(sqlite3_vfs*, void*)
     1099{
    1621100}
    1631101#else
    1641102#define chromiumDlOpen 0
     1103#define chromiumDlError 0
     1104#define chromiumDlSym 0
     1105#define chromiumDlClose 0
    1651106#endif // SQLITE_OMIT_LOAD_EXTENSION
    1661107
    167 } // namespace
     1108// Generates a seed for SQLite's PRNG.
     1109static int chromiumRandomness(sqlite3_vfs*, int nBuf, char *zBuf)
     1110{
     1111    ASSERT(static_cast<size_t>(nBuf) >= (sizeof(time_t) + sizeof(int)));
     1112
     1113    memset(zBuf, 0, nBuf);
     1114    int fd = open("/dev/urandom", O_RDONLY);
     1115    if (fd < 0) {
     1116        time_t t;
     1117        time(&t);
     1118        memcpy(zBuf, &t, sizeof(t));
     1119        int pid = getpid();
     1120        memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
     1121        return sizeof(t) + sizeof(pid);
     1122    }
     1123    nBuf = read(fd, zBuf, nBuf);
     1124    close(fd);
     1125    return nBuf;
     1126}
     1127
     1128// Sleeps for at least |microseconds|, and returns the actual
     1129// amount of time spent sleeping (in microseconds).
     1130static int chromiumSleep(sqlite3_vfs*, int microseconds)
     1131{
     1132#if OS(DARWIN)
     1133    usleep(microseconds);
     1134    return microseconds;
     1135#else
     1136    // Round to the nearest second.
     1137    int seconds = (microseconds + 999999) / 1000000;
     1138    sleep(seconds);
     1139    return seconds * 1000000;
     1140#endif
     1141}
     1142
     1143// Retrieves the current system time (UTC).
     1144static int chromiumCurrentTime(sqlite3_vfs*, double* now)
     1145{
     1146    struct timeval timeval;
     1147    gettimeofday(&timeval, 0);
     1148    *now = 2440587.5 + timeval.tv_sec / 86400.0 + timeval.tv_usec / 86400000000.0;
     1149    return 0;
     1150}
     1151
     1152// This is not yet implemented in SQLite core.
     1153static int chromiumGetLastError(sqlite3_vfs*, int, char*)
     1154{
     1155    return 0;
     1156}
     1157
     1158// Same as MAX_PATHNAME from sqlite's os_unix.c.
     1159static const int chromiumMaxPathname = 512;
    1681160
    1691161namespace WebCore {
     
    1711163void SQLiteFileSystem::registerSQLiteVFS()
    1721164{
    173     sqlite3_vfs* unix_vfs = sqlite3_vfs_find("unix");
    1741165    static sqlite3_vfs chromium_vfs = {
    1751166        1,
    176         unix_vfs->szOsFile,
    177         unix_vfs->mxPathname,
     1167        sizeof(ChromiumFile),
     1168        chromiumMaxPathname,
    1781169        0,
    1791170        "chromium_vfs",
    180         unix_vfs->pAppData,
     1171        0,
    1811172        chromiumOpen,
    1821173        chromiumDelete,
     
    1841175        chromiumFullPathname,
    1851176        chromiumDlOpen,
    186         unix_vfs->xDlError,
    187         unix_vfs->xDlSym,
    188         unix_vfs->xDlClose,
    189         unix_vfs->xRandomness,
    190         unix_vfs->xSleep,
    191         unix_vfs->xCurrentTime,
    192         unix_vfs->xGetLastError
     1177        chromiumDlError,
     1178        chromiumDlSym,
     1179        chromiumDlClose,
     1180        chromiumRandomness,
     1181        chromiumSleep,
     1182        chromiumCurrentTime,
     1183        chromiumGetLastError
    1931184    };
    1941185    sqlite3_vfs_register(&chromium_vfs, 0);
Note: See TracChangeset for help on using the changeset viewer.