2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present 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
27 #include <sys/types.h>
33 #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
35 #include <sqlite3ext.h>
37 #include <folly/portability/Fcntl.h>
38 #include <folly/portability/Unistd.h>
43 ** For a build without mutexes, no-op the mutex calls.
45 #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
46 #define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
47 #define sqlite3_mutex_free(X)
48 #define sqlite3_mutex_enter(X)
49 #define sqlite3_mutex_try(X) SQLITE_OK
50 #define sqlite3_mutex_leave(X)
51 #define sqlite3_mutex_held(X) ((void)(X),1)
52 #define sqlite3_mutex_notheld(X) ((void)(X),1)
53 #endif /* SQLITE_THREADSAFE==0 */
63 sqlite3_vfs
* pOrigVfs
;
65 sqlite3_io_methods sIoMethodsV1
;
66 sqlite3_mutex
* pMutex
;
70 static void embeddedEnter() { sqlite3_mutex_enter(gEmbedded
.pMutex
); }
71 static void embeddedLeave() { sqlite3_mutex_leave(gEmbedded
.pMutex
); }
73 static int embeddedOpen(sqlite3_vfs
*pVfs
, const char *zName
,
74 sqlite3_file
*pConn
, int flags
,
76 memset(pConn
, 0, pVfs
->szOsFile
);
77 assert(zName
|| (flags
& SQLITE_OPEN_DELETEONCLOSE
));
80 const char *p
= strchr(zName
, ':');
81 unsigned long off
, len
;
83 if (p
&& sscanf(p
+ 1, "%lu:%lu%c", &off
, &len
, &c
) == 2) {
84 embeddedConn
*eConn
= (embeddedConn
*)pConn
;
85 eConn
->base
.pMethods
= &gEmbedded
.sIoMethodsV1
;
86 char *tmp
= strdup(zName
);
88 eConn
->fd
= open(tmp
, O_RDONLY
, 0);
90 if (eConn
->fd
< 0) return SQLITE_CANTOPEN
;
93 *pOutFlags
= SQLITE_OPEN_READONLY
;
98 sqlite3_vfs
*pOrigVfs
= gEmbedded
.pOrigVfs
; /* Real VFS */
99 return pOrigVfs
->xOpen(pOrigVfs
, zName
, pConn
, flags
, pOutFlags
);
103 embeddedDelete(sqlite3_vfs
* /*pVfs*/, const char* zName
, int syncDir
) {
104 return gEmbedded
.pOrigVfs
->xDelete(gEmbedded
.pOrigVfs
, zName
, syncDir
);
107 static int embeddedAccess(sqlite3_vfs
* /*a*/, const char* b
, int c
, int* d
) {
108 return gEmbedded
.pOrigVfs
->xAccess(gEmbedded
.pOrigVfs
, b
, c
, d
);
112 embeddedFullPathname(sqlite3_vfs
* /*a*/, const char* b
, int c
, char* d
) {
113 return gEmbedded
.pOrigVfs
->xFullPathname(gEmbedded
.pOrigVfs
, b
, c
, d
);
116 static void* embeddedDlOpen(sqlite3_vfs
* /*a*/, const char* b
) {
117 return gEmbedded
.pOrigVfs
->xDlOpen(gEmbedded
.pOrigVfs
, b
);
120 static void embeddedDlError(sqlite3_vfs
* /*a*/, int b
, char* c
) {
121 gEmbedded
.pOrigVfs
->xDlError(gEmbedded
.pOrigVfs
, b
, c
);
124 static void (*embeddedDlSym(sqlite3_vfs
* /*a*/, void* b
, const char* c
))() {
125 return gEmbedded
.pOrigVfs
->xDlSym(gEmbedded
.pOrigVfs
, b
, c
);
128 static void embeddedDlClose(sqlite3_vfs
* /*a*/, void* b
) {
129 gEmbedded
.pOrigVfs
->xDlClose(gEmbedded
.pOrigVfs
, b
);
132 static int embeddedRandomness(sqlite3_vfs
* /*a*/, int b
, char* c
) {
133 return gEmbedded
.pOrigVfs
->xRandomness(gEmbedded
.pOrigVfs
, b
, c
);
136 static int embeddedSleep(sqlite3_vfs
* /*a*/, int b
) {
137 return gEmbedded
.pOrigVfs
->xSleep(gEmbedded
.pOrigVfs
, b
);
140 static int embeddedCurrentTime(sqlite3_vfs
* /*a*/, double* b
) {
141 return gEmbedded
.pOrigVfs
->xCurrentTime(gEmbedded
.pOrigVfs
, b
);
144 static int embeddedGetLastError(sqlite3_vfs
* /*a*/, int b
, char* c
) {
145 return gEmbedded
.pOrigVfs
->xGetLastError(gEmbedded
.pOrigVfs
, b
, c
);
148 static int embeddedCurrentTimeInt64(sqlite3_vfs
* /*a*/, sqlite3_int64
* b
) {
149 return gEmbedded
.pOrigVfs
->xCurrentTimeInt64(gEmbedded
.pOrigVfs
, b
);
152 static int embeddedClose(sqlite3_file
* pConn
) {
153 embeddedConn
* p
= (embeddedConn
*)pConn
;
154 return close(p
->fd
) ? SQLITE_OK
: SQLITE_ERROR
;
157 static int embeddedRead(sqlite3_file
* pConn
, void* pBuf
,
158 int iAmt
, sqlite3_int64 iOfst
) {
159 embeddedConn
* p
= (embeddedConn
*)pConn
;
160 if (iOfst
> p
->len
) return SQLITE_IOERR_READ
;
162 if (iAmt
+ iOfst
> p
->len
) {
163 rc
= SQLITE_IOERR_SHORT_READ
;
164 iAmt
= p
->len
- iOfst
;
168 if (lseek(p
->fd
, iOfst
, SEEK_SET
) != iOfst
) {
169 rc
= SQLITE_IOERR_READ
;
170 } else if (read(p
->fd
, pBuf
, iAmt
) != iAmt
) {
171 rc
= SQLITE_IOERR_READ
;
177 static int embeddedWrite(sqlite3_file
* /*pConn*/, const void* /*pBuf*/,
178 int /*iAmt*/, sqlite3_int64
/*iOfst*/) {
179 return SQLITE_IOERR_WRITE
;
182 static int embeddedTruncate(sqlite3_file
* /*pConn*/, sqlite3_int64
/*size*/) {
183 return SQLITE_IOERR_TRUNCATE
;
186 static int embeddedSync(sqlite3_file
* /*pConn*/, int /*flags*/) {
190 static int embeddedFileSize(sqlite3_file
* pConn
, sqlite3_int64
* pSize
) {
191 embeddedConn
* p
= (embeddedConn
*)pConn
;
196 static int embeddedLock(sqlite3_file
* /*pConn*/, int /*lock*/) {
200 static int embeddedUnlock(sqlite3_file
* /*pConn*/, int /*lock*/) {
205 embeddedCheckReservedLock(sqlite3_file
* /*pConn*/, int* /*pResOut*/) {
206 return SQLITE_IOERR_CHECKRESERVEDLOCK
;
210 embeddedFileControl(sqlite3_file
* /*pConn*/, int /*op*/, void* /*pArg*/) {
214 static int embeddedSectorSize(sqlite3_file
* /*pConn*/) {
218 static int embeddedDeviceCharacteristics(sqlite3_file
* /*pConn*/) {
222 int sqlite3_embedded_initialize(const char* zOrigVfsName
, int makeDefault
) {
223 sqlite3_vfs
* pOrigVfs
;
224 if (gEmbedded
.isInitialized
) return SQLITE_MISUSE
;
225 pOrigVfs
= sqlite3_vfs_find(zOrigVfsName
);
226 if (pOrigVfs
==0) return SQLITE_ERROR
;
227 assert(pOrigVfs
!=&gEmbedded
.sThisVfs
);
228 gEmbedded
.pMutex
= sqlite3_mutex_alloc(SQLITE_MUTEX_FAST
);
229 if (!gEmbedded
.pMutex
) {
233 gEmbedded
.isInitialized
= 1;
234 gEmbedded
.pOrigVfs
= pOrigVfs
;
235 gEmbedded
.sThisVfs
= *pOrigVfs
;
236 gEmbedded
.sThisVfs
.szOsFile
+= sizeof(embeddedConn
);
237 gEmbedded
.sThisVfs
.zName
= "embedded";
238 gEmbedded
.sThisVfs
.xOpen
= embeddedOpen
;
239 gEmbedded
.sThisVfs
.xDelete
= embeddedDelete
;
240 gEmbedded
.sThisVfs
.xAccess
= embeddedAccess
;
241 gEmbedded
.sThisVfs
.xFullPathname
= embeddedFullPathname
;
242 gEmbedded
.sThisVfs
.xDlOpen
= embeddedDlOpen
;
243 gEmbedded
.sThisVfs
.xDlError
= embeddedDlError
;
244 gEmbedded
.sThisVfs
.xDlSym
= embeddedDlSym
;
245 gEmbedded
.sThisVfs
.xDlClose
= embeddedDlClose
;
246 gEmbedded
.sThisVfs
.xRandomness
= embeddedRandomness
;
247 gEmbedded
.sThisVfs
.xSleep
= embeddedSleep
;
248 gEmbedded
.sThisVfs
.xCurrentTime
= embeddedCurrentTime
;
249 gEmbedded
.sThisVfs
.xGetLastError
= embeddedGetLastError
;
250 gEmbedded
.sThisVfs
.xCurrentTimeInt64
= embeddedCurrentTimeInt64
;
252 gEmbedded
.sIoMethodsV1
.iVersion
= 1;
253 gEmbedded
.sIoMethodsV1
.xClose
= embeddedClose
;
254 gEmbedded
.sIoMethodsV1
.xRead
= embeddedRead
;
255 gEmbedded
.sIoMethodsV1
.xWrite
= embeddedWrite
;
256 gEmbedded
.sIoMethodsV1
.xTruncate
= embeddedTruncate
;
257 gEmbedded
.sIoMethodsV1
.xSync
= embeddedSync
;
258 gEmbedded
.sIoMethodsV1
.xFileSize
= embeddedFileSize
;
259 gEmbedded
.sIoMethodsV1
.xLock
= embeddedLock
;
260 gEmbedded
.sIoMethodsV1
.xUnlock
= embeddedUnlock
;
261 gEmbedded
.sIoMethodsV1
.xCheckReservedLock
= embeddedCheckReservedLock
;
262 gEmbedded
.sIoMethodsV1
.xFileControl
= embeddedFileControl
;
263 gEmbedded
.sIoMethodsV1
.xSectorSize
= embeddedSectorSize
;
264 gEmbedded
.sIoMethodsV1
.xDeviceCharacteristics
=
265 embeddedDeviceCharacteristics
;
267 sqlite3_vfs_register(&gEmbedded
.sThisVfs
, makeDefault
);
272 int sqlite3_embedded_shutdown() {
273 if ( gEmbedded
.isInitialized
==0 ) return SQLITE_MISUSE
;
274 gEmbedded
.isInitialized
= 0;
275 sqlite3_mutex_free(gEmbedded
.pMutex
);
276 sqlite3_vfs_unregister(&gEmbedded
.sThisVfs
);
277 memset(&gEmbedded
, 0, sizeof(gEmbedded
));