| /* |
| * Copyright (C) 2009 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| // Expose chromium_sqlite3_* functions from Chromium's patched SQLite. |
| #define CHROMIUM_SQLITE_INTERNALS |
| |
| #include "modules/webdatabase/sqlite/SQLiteFileSystem.h" |
| |
| #include "public/platform/Platform.h" |
| #include "third_party/sqlite/sqlite3.h" |
| |
| #include <fcntl.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| namespace blink { |
| |
| // Chromium's Posix implementation of SQLite VFS |
| namespace { |
| |
| struct chromiumVfsFile { |
| sqlite3_io_methods* pMethods; |
| sqlite3_file* wrappedFile; |
| char* wrappedFileName; |
| }; |
| |
| int chromiumClose(sqlite3_file* sqliteFile) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| int r = chromiumFile->wrappedFile->pMethods->xClose(chromiumFile->wrappedFile); |
| sqlite3_free(chromiumFile->wrappedFileName); |
| sqlite3_free(chromiumFile->wrappedFile); |
| memset(chromiumFile, 0, sizeof(*chromiumFile)); |
| return r; |
| } |
| |
| int chromiumRead(sqlite3_file* sqliteFile, void* pBuf, int iAmt, sqlite3_int64 iOfst) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| return chromiumFile->wrappedFile->pMethods->xRead(chromiumFile->wrappedFile, pBuf, iAmt, iOfst); |
| } |
| |
| int chromiumWrite(sqlite3_file* sqliteFile, const void* pBuf, int iAmt, sqlite3_int64 iOfst) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| return chromiumFile->wrappedFile->pMethods->xWrite(chromiumFile->wrappedFile, pBuf, iAmt, iOfst); |
| } |
| |
| int chromiumTruncate(sqlite3_file* sqliteFile, sqlite3_int64 size) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| |
| // The OSX and Linux sandboxes block ftruncate(), proxy to the browser |
| // process. |
| if (Platform::current()->databaseSetFileSize(String(chromiumFile->wrappedFileName), size)) |
| return SQLITE_OK; |
| return SQLITE_IOERR_TRUNCATE; |
| } |
| |
| int chromiumSync(sqlite3_file* sqliteFile, int flags) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| return chromiumFile->wrappedFile->pMethods->xSync(chromiumFile->wrappedFile, flags); |
| } |
| |
| int chromiumFileSize(sqlite3_file* sqliteFile, sqlite3_int64* pSize) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| return chromiumFile->wrappedFile->pMethods->xFileSize(chromiumFile->wrappedFile, pSize); |
| } |
| |
| int chromiumLock(sqlite3_file* sqliteFile, int eFileLock) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| return chromiumFile->wrappedFile->pMethods->xLock(chromiumFile->wrappedFile, eFileLock); |
| } |
| |
| int chromiumUnlock(sqlite3_file* sqliteFile, int eFileLock) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| return chromiumFile->wrappedFile->pMethods->xUnlock(chromiumFile->wrappedFile, eFileLock); |
| } |
| |
| int chromiumCheckReservedLock(sqlite3_file* sqliteFile, int* pResOut) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| return chromiumFile->wrappedFile->pMethods->xCheckReservedLock(chromiumFile->wrappedFile, pResOut); |
| } |
| |
| int chromiumFileControl(sqlite3_file* sqliteFile, int op, void* pArg) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| return chromiumFile->wrappedFile->pMethods->xFileControl(chromiumFile->wrappedFile, op, pArg); |
| } |
| |
| int chromiumSectorSize(sqlite3_file* sqliteFile) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| return chromiumFile->wrappedFile->pMethods->xSectorSize(chromiumFile->wrappedFile); |
| } |
| |
| int chromiumDeviceCharacteristics(sqlite3_file* sqliteFile) |
| { |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(sqliteFile); |
| return chromiumFile->wrappedFile->pMethods->xDeviceCharacteristics(chromiumFile->wrappedFile); |
| } |
| |
| // Opens a file. |
| // |
| // vfs - pointer to the sqlite3_vfs object. |
| // fileName - the name of the file. |
| // 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 chromiumOpenInternal(sqlite3_vfs* vfs, const char* fileName, sqlite3_file* id, int desiredFlags, int* usedFlags) |
| { |
| int fd = Platform::current()->databaseOpenFile(String(fileName), desiredFlags); |
| if ((fd < 0) && (desiredFlags & SQLITE_OPEN_READWRITE)) { |
| desiredFlags = (desiredFlags & ~(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)) | SQLITE_OPEN_READONLY; |
| fd = Platform::current()->databaseOpenFile(String(fileName), desiredFlags); |
| } |
| if (fd < 0) |
| return SQLITE_CANTOPEN; |
| |
| if (usedFlags) |
| *usedFlags = 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); |
| sqlite3_vfs* wrappedVfs = static_cast<sqlite3_vfs*>(vfs->pAppData); |
| return chromium_sqlite3_fill_in_unix_sqlite3_file(wrappedVfs, fd, id, fileName, noLock, desiredFlags); |
| } |
| |
| int chromiumOpen(sqlite3_vfs* vfs, const char* fileName, sqlite3_file* id, int desiredFlags, int* usedFlags) |
| { |
| sqlite3_vfs* wrappedVfs = static_cast<sqlite3_vfs*>(vfs->pAppData); |
| sqlite3_file* wrappedFile = static_cast<sqlite3_file*>(sqlite3_malloc(wrappedVfs->szOsFile)); |
| if (!wrappedFile) |
| return SQLITE_NOMEM; |
| |
| // Make a local copy of the file name. SQLite's os_unix.c appears to be written to allow caching the pointer passed |
| // in to this function, but that seems brittle. |
| char* wrappedFileName = sqlite3_mprintf("%s", fileName); |
| if (!wrappedFileName) { |
| sqlite3_free(wrappedFile); |
| return SQLITE_NOMEM; |
| } |
| |
| // SQLite's unixOpen() makes assumptions about the structure of |fileName|. Our local copy may not answer those |
| // assumptions correctly. |
| int rc = chromiumOpenInternal(vfs, fileName, wrappedFile, desiredFlags, usedFlags); |
| if (rc != SQLITE_OK) { |
| sqlite3_free(wrappedFileName); |
| sqlite3_free(wrappedFile); |
| return rc; |
| } |
| |
| static sqlite3_io_methods chromiumIoMethods = { |
| 1, |
| chromiumClose, |
| chromiumRead, |
| chromiumWrite, |
| chromiumTruncate, |
| chromiumSync, |
| chromiumFileSize, |
| chromiumLock, |
| chromiumUnlock, |
| chromiumCheckReservedLock, |
| chromiumFileControl, |
| chromiumSectorSize, |
| chromiumDeviceCharacteristics, |
| // Methods above are valid for version 1. |
| }; |
| chromiumVfsFile* chromiumFile = reinterpret_cast<chromiumVfsFile*>(id); |
| chromiumFile->pMethods = &chromiumIoMethods; |
| chromiumFile->wrappedFile = wrappedFile; |
| chromiumFile->wrappedFileName = wrappedFileName; |
| return SQLITE_OK; |
| } |
| |
| // Deletes the given file. |
| // |
| // vfs - pointer to the sqlite3_vfs object. |
| // 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) |
| { |
| return Platform::current()->databaseDeleteFile(String(fileName), syncDir); |
| } |
| |
| // Check the existance and status of the given file. |
| // |
| // vfs - pointer to the sqlite3_vfs object. |
| // 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) |
| { |
| int attr = static_cast<int>(Platform::current()->databaseGetFileAttributes(String(fileName))); |
| if (attr < 0) { |
| *res = 0; |
| return SQLITE_OK; |
| } |
| |
| switch (flag) { |
| case SQLITE_ACCESS_EXISTS: |
| *res = 1; // if the file doesn't exist, attr < 0 |
| break; |
| case SQLITE_ACCESS_READWRITE: |
| *res = (attr & W_OK) && (attr & R_OK); |
| break; |
| case SQLITE_ACCESS_READ: |
| *res = (attr & R_OK); |
| break; |
| default: |
| return SQLITE_ERROR; |
| } |
| |
| return SQLITE_OK; |
| } |
| |
| // Turns a relative pathname into a full pathname. |
| // |
| // vfs - pointer to the sqlite3_vfs object. |
| // 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 bufSize, char* absolutePath) |
| { |
| // The renderer process doesn't need to know the absolute path of the file |
| sqlite3_snprintf(bufSize, absolutePath, "%s", relativePath); |
| return SQLITE_OK; |
| } |
| |
| // Do not allow loading libraries in the renderer. |
| void* chromiumDlOpen(sqlite3_vfs*, const char*) |
| { |
| return 0; |
| } |
| |
| void chromiumDlError(sqlite3_vfs*, int bufSize, char* errorBuffer) |
| { |
| sqlite3_snprintf(bufSize, errorBuffer, "Dynamic loading not supported"); |
| } |
| |
| void(*chromiumDlSym(sqlite3_vfs*, void*, const char*))(void) |
| { |
| return 0; |
| } |
| |
| void chromiumDlClose(sqlite3_vfs*, void*) |
| { |
| } |
| |
| int chromiumRandomness(sqlite3_vfs* vfs, int bufSize, char* buffer) |
| { |
| sqlite3_vfs* wrappedVfs = static_cast<sqlite3_vfs*>(vfs->pAppData); |
| return wrappedVfs->xRandomness(wrappedVfs, bufSize, buffer); |
| } |
| |
| int chromiumSleep(sqlite3_vfs* vfs, int microseconds) |
| { |
| sqlite3_vfs* wrappedVfs = static_cast<sqlite3_vfs*>(vfs->pAppData); |
| return wrappedVfs->xSleep(wrappedVfs, microseconds); |
| } |
| |
| int chromiumCurrentTime(sqlite3_vfs* vfs, double* prNow) |
| { |
| sqlite3_vfs* wrappedVfs = static_cast<sqlite3_vfs*>(vfs->pAppData); |
| return wrappedVfs->xCurrentTime(wrappedVfs, prNow); |
| } |
| |
| int chromiumGetLastError(sqlite3_vfs* vfs, int e, char* s) |
| { |
| // xGetLastError() has never been used by SQLite. The implementation in os_win.c indicates this is a reasonable implementation. |
| *s = '\0'; |
| return 0; |
| } |
| |
| } // namespace |
| |
| void SQLiteFileSystem::registerSQLiteVFS() |
| { |
| sqlite3_vfs* wrappedVfs = sqlite3_vfs_find("unix"); |
| |
| // These are implemented by delegating to |wrappedVfs|. |
| // TODO(shess): Implement local versions. |
| ASSERT(wrappedVfs->xRandomness); |
| ASSERT(wrappedVfs->xSleep); |
| ASSERT(wrappedVfs->xCurrentTime); |
| |
| static sqlite3_vfs chromium_vfs = { |
| 1, |
| sizeof(chromiumVfsFile), |
| wrappedVfs->mxPathname, |
| 0, |
| "chromium_vfs", |
| wrappedVfs, |
| chromiumOpen, |
| chromiumDelete, |
| chromiumAccess, |
| chromiumFullPathname, |
| chromiumDlOpen, |
| chromiumDlError, |
| chromiumDlSym, |
| chromiumDlClose, |
| chromiumRandomness, |
| chromiumSleep, |
| chromiumCurrentTime, |
| chromiumGetLastError |
| }; |
| sqlite3_vfs_register(&chromium_vfs, 0); |
| } |
| |
| } // namespace blink |