Fix crash when trying to change staticness of a property
[hiphop-php.git] / hphp / util / embedded-vfs.cpp
blob5cc076e00dd380c0c7348a0c19382ec621ca1d02
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #include "hphp/util/embedded-vfs.h"
19 * based on test_demovfs.c and test_multiplex.c in sqlite3
21 #include <sqlite3.h>
22 #include <string.h>
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <stdio.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
33 #ifndef SQLITE_CORE
34 #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
35 #endif
36 #include <sqlite3ext.h>
38 namespace HPHP {
41 ** For a build without mutexes, no-op the mutex calls.
43 #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
44 #define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
45 #define sqlite3_mutex_free(X)
46 #define sqlite3_mutex_enter(X)
47 #define sqlite3_mutex_try(X) SQLITE_OK
48 #define sqlite3_mutex_leave(X)
49 #define sqlite3_mutex_held(X) ((void)(X),1)
50 #define sqlite3_mutex_notheld(X) ((void)(X),1)
51 #endif /* SQLITE_THREADSAFE==0 */
53 struct embeddedConn {
54 sqlite3_file base;
55 int fd;
56 size_t offset;
57 size_t len;
60 static struct {
61 sqlite3_vfs* pOrigVfs;
62 sqlite3_vfs sThisVfs;
63 sqlite3_io_methods sIoMethodsV1;
64 sqlite3_mutex* pMutex;
65 int isInitialized;
66 } gEmbedded;
68 static void embeddedEnter() { sqlite3_mutex_enter(gEmbedded.pMutex); }
69 static void embeddedLeave() { sqlite3_mutex_leave(gEmbedded.pMutex); }
71 static int embeddedOpen(sqlite3_vfs *pVfs, const char *zName,
72 sqlite3_file *pConn, int flags,
73 int *pOutFlags) {
74 memset(pConn, 0, pVfs->szOsFile);
75 assert(zName || (flags & SQLITE_OPEN_DELETEONCLOSE));
77 if (zName) {
78 const char *p = strchr(zName, ':');
79 unsigned long off, len;
80 char c;
81 if (p && sscanf(p + 1, "%lu:%lu%c", &off, &len, &c) == 2) {
82 embeddedConn *eConn = (embeddedConn*)pConn;
83 eConn->base.pMethods = &gEmbedded.sIoMethodsV1;
84 char *tmp = strdup(zName);
85 tmp[p - zName] = 0;
86 eConn->fd = open(tmp, O_RDONLY, 0);
87 free(tmp);
88 if (eConn->fd < 0) return SQLITE_CANTOPEN;
89 eConn->offset = off;
90 eConn->len = len;
91 *pOutFlags = SQLITE_OPEN_READONLY;
92 return SQLITE_OK;
96 sqlite3_vfs *pOrigVfs = gEmbedded.pOrigVfs; /* Real VFS */
97 return pOrigVfs->xOpen(pOrigVfs, zName, pConn, flags, pOutFlags);
100 static int embeddedDelete(sqlite3_vfs* pVfs, const char* zName, int syncDir) {
101 return gEmbedded.pOrigVfs->xDelete(gEmbedded.pOrigVfs, zName, syncDir);
104 static int embeddedAccess(sqlite3_vfs* a, const char* b, int c, int* d) {
105 return gEmbedded.pOrigVfs->xAccess(gEmbedded.pOrigVfs, b, c, d);
108 static int embeddedFullPathname(sqlite3_vfs* a, const char* b, int c, char* d) {
109 return gEmbedded.pOrigVfs->xFullPathname(gEmbedded.pOrigVfs, b, c, d);
112 static void* embeddedDlOpen(sqlite3_vfs* a, const char* b) {
113 return gEmbedded.pOrigVfs->xDlOpen(gEmbedded.pOrigVfs, b);
116 static void embeddedDlError(sqlite3_vfs* a, int b, char* c) {
117 gEmbedded.pOrigVfs->xDlError(gEmbedded.pOrigVfs, b, c);
120 static void (*embeddedDlSym(sqlite3_vfs* a, void* b, const char* c))() {
121 return gEmbedded.pOrigVfs->xDlSym(gEmbedded.pOrigVfs, b, c);
124 static void embeddedDlClose(sqlite3_vfs* a, void* b) {
125 gEmbedded.pOrigVfs->xDlClose(gEmbedded.pOrigVfs, b);
128 static int embeddedRandomness(sqlite3_vfs* a, int b, char* c) {
129 return gEmbedded.pOrigVfs->xRandomness(gEmbedded.pOrigVfs, b, c);
132 static int embeddedSleep(sqlite3_vfs* a, int b) {
133 return gEmbedded.pOrigVfs->xSleep(gEmbedded.pOrigVfs, b);
136 static int embeddedCurrentTime(sqlite3_vfs* a, double* b) {
137 return gEmbedded.pOrigVfs->xCurrentTime(gEmbedded.pOrigVfs, b);
140 static int embeddedGetLastError(sqlite3_vfs* a, int b, char* c) {
141 return gEmbedded.pOrigVfs->xGetLastError(gEmbedded.pOrigVfs, b, c);
144 static int embeddedCurrentTimeInt64(sqlite3_vfs* a, sqlite3_int64* b) {
145 return gEmbedded.pOrigVfs->xCurrentTimeInt64(gEmbedded.pOrigVfs, b);
148 static int embeddedClose(sqlite3_file* pConn) {
149 embeddedConn* p = (embeddedConn*)pConn;
150 return close(p->fd) ? SQLITE_OK : SQLITE_ERROR;
153 static int embeddedRead(sqlite3_file* pConn, void* pBuf,
154 int iAmt, sqlite3_int64 iOfst) {
155 embeddedConn* p = (embeddedConn*)pConn;
156 if (iOfst > p->len) return SQLITE_IOERR_READ;
157 int rc = SQLITE_OK;
158 if (iAmt + iOfst > p->len) {
159 rc = SQLITE_IOERR_SHORT_READ;
160 iAmt = p->len - iOfst;
162 iOfst += p->offset;
163 embeddedEnter();
164 if (lseek(p->fd, iOfst, SEEK_SET) != iOfst) {
165 rc = SQLITE_IOERR_READ;
166 } else if (read(p->fd, pBuf, iAmt) != iAmt) {
167 rc = SQLITE_IOERR_READ;
169 embeddedLeave();
170 return rc;
173 static int embeddedWrite(sqlite3_file* pConn, const void* pBuf,
174 int iAmt, sqlite3_int64 iOfst) {
175 return SQLITE_IOERR_WRITE;
178 static int embeddedTruncate(sqlite3_file* pConn, sqlite3_int64 size) {
179 return SQLITE_IOERR_TRUNCATE;
182 static int embeddedSync(sqlite3_file* pConn, int flags) {
183 return SQLITE_OK;
186 static int embeddedFileSize(sqlite3_file* pConn, sqlite3_int64* pSize) {
187 embeddedConn* p = (embeddedConn*)pConn;
188 *pSize = p->len;
189 return SQLITE_OK;
192 static int embeddedLock(sqlite3_file* pConn, int lock) {
193 return SQLITE_OK;
196 static int embeddedUnlock(sqlite3_file* pConn, int lock) {
197 return SQLITE_OK;
200 static int embeddedCheckReservedLock(sqlite3_file* pConn, int* pResOut) {
201 return SQLITE_IOERR_CHECKRESERVEDLOCK;
204 static int embeddedFileControl(sqlite3_file* pConn, int op, void* pArg) {
205 return SQLITE_OK;
208 static int embeddedSectorSize(sqlite3_file* pConn) {
209 return 0;
212 static int embeddedDeviceCharacteristics(sqlite3_file* pConn) {
213 return 0;
216 int sqlite3_embedded_initialize(const char* zOrigVfsName, int makeDefault) {
217 sqlite3_vfs* pOrigVfs;
218 if (gEmbedded.isInitialized) return SQLITE_MISUSE;
219 pOrigVfs = sqlite3_vfs_find(zOrigVfsName);
220 if (pOrigVfs==0) return SQLITE_ERROR;
221 assert(pOrigVfs!=&gEmbedded.sThisVfs);
222 gEmbedded.pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
223 if (!gEmbedded.pMutex) {
224 return SQLITE_NOMEM;
227 gEmbedded.isInitialized = 1;
228 gEmbedded.pOrigVfs = pOrigVfs;
229 gEmbedded.sThisVfs = *pOrigVfs;
230 gEmbedded.sThisVfs.szOsFile += sizeof(embeddedConn);
231 gEmbedded.sThisVfs.zName = "embedded";
232 gEmbedded.sThisVfs.xOpen = embeddedOpen;
233 gEmbedded.sThisVfs.xDelete = embeddedDelete;
234 gEmbedded.sThisVfs.xAccess = embeddedAccess;
235 gEmbedded.sThisVfs.xFullPathname = embeddedFullPathname;
236 gEmbedded.sThisVfs.xDlOpen = embeddedDlOpen;
237 gEmbedded.sThisVfs.xDlError = embeddedDlError;
238 gEmbedded.sThisVfs.xDlSym = embeddedDlSym;
239 gEmbedded.sThisVfs.xDlClose = embeddedDlClose;
240 gEmbedded.sThisVfs.xRandomness = embeddedRandomness;
241 gEmbedded.sThisVfs.xSleep = embeddedSleep;
242 gEmbedded.sThisVfs.xCurrentTime = embeddedCurrentTime;
243 gEmbedded.sThisVfs.xGetLastError = embeddedGetLastError;
244 gEmbedded.sThisVfs.xCurrentTimeInt64 = embeddedCurrentTimeInt64;
246 gEmbedded.sIoMethodsV1.iVersion = 1;
247 gEmbedded.sIoMethodsV1.xClose = embeddedClose;
248 gEmbedded.sIoMethodsV1.xRead = embeddedRead;
249 gEmbedded.sIoMethodsV1.xWrite = embeddedWrite;
250 gEmbedded.sIoMethodsV1.xTruncate = embeddedTruncate;
251 gEmbedded.sIoMethodsV1.xSync = embeddedSync;
252 gEmbedded.sIoMethodsV1.xFileSize = embeddedFileSize;
253 gEmbedded.sIoMethodsV1.xLock = embeddedLock;
254 gEmbedded.sIoMethodsV1.xUnlock = embeddedUnlock;
255 gEmbedded.sIoMethodsV1.xCheckReservedLock = embeddedCheckReservedLock;
256 gEmbedded.sIoMethodsV1.xFileControl = embeddedFileControl;
257 gEmbedded.sIoMethodsV1.xSectorSize = embeddedSectorSize;
258 gEmbedded.sIoMethodsV1.xDeviceCharacteristics =
259 embeddedDeviceCharacteristics;
261 sqlite3_vfs_register(&gEmbedded.sThisVfs, makeDefault);
263 return SQLITE_OK;
266 int sqlite3_embedded_shutdown() {
267 if ( gEmbedded.isInitialized==0 ) return SQLITE_MISUSE;
268 gEmbedded.isInitialized = 0;
269 sqlite3_mutex_free(gEmbedded.pMutex);
270 sqlite3_vfs_unregister(&gEmbedded.sThisVfs);
271 memset(&gEmbedded, 0, sizeof(gEmbedded));
272 return SQLITE_OK;