blob: e3346e5df872f57fdfe26716e5b52069611cd311 [file] [log] [blame]
danielk1977a7a8e142008-02-13 18:25:27 +00001/*
drh054889e2005-11-30 03:20:31 +00002** 2005 November 29
3**
4** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
6**
7** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
10**
11******************************************************************************
12**
13** This file contains OS interface code that is common to all
14** architectures.
15*/
drh3f459022006-01-07 16:06:07 +000016#define _SQLITE_OS_C_ 1
drh054889e2005-11-30 03:20:31 +000017#include "sqliteInt.h"
drhbd08af42007-04-05 21:58:33 +000018#undef _SQLITE_OS_C_
drh054889e2005-11-30 03:20:31 +000019
20/*
danielk1977ae72d982007-10-03 08:46:44 +000021** The default SQLite sqlite3_vfs implementations do not allocate
22** memory (actually, os_unix.c allocates a small amount of memory
23** from within OsOpen()), but some third-party implementations may.
24** So we test the effects of a malloc() failing and the sqlite3OsXXX()
25** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
26**
27** The following functions are instrumented for malloc() failure
28** testing:
29**
danielk1977ae72d982007-10-03 08:46:44 +000030** sqlite3OsRead()
31** sqlite3OsWrite()
32** sqlite3OsSync()
mistachkin6c3c1a02011-11-12 03:17:40 +000033** sqlite3OsFileSize()
danielk1977ae72d982007-10-03 08:46:44 +000034** sqlite3OsLock()
mistachkin6c3c1a02011-11-12 03:17:40 +000035** sqlite3OsCheckReservedLock()
36** sqlite3OsFileControl()
37** sqlite3OsShmMap()
38** sqlite3OsOpen()
39** sqlite3OsDelete()
40** sqlite3OsAccess()
41** sqlite3OsFullPathname()
danielk1977ae72d982007-10-03 08:46:44 +000042**
43*/
shanehfd286392010-07-02 19:49:38 +000044#if defined(SQLITE_TEST)
danc396d4a2010-07-02 11:27:43 +000045int sqlite3_memdebug_vfs_oom_test = 1;
46 #define DO_OS_MALLOC_TEST(x) \
47 if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) { \
danielk1977b5a19202009-07-27 11:41:20 +000048 void *pTstAlloc = sqlite3Malloc(10); \
49 if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \
50 sqlite3_free(pTstAlloc); \
danielk1977ae72d982007-10-03 08:46:44 +000051 }
52#else
danielk1977b5a19202009-07-27 11:41:20 +000053 #define DO_OS_MALLOC_TEST(x)
danielk1977ae72d982007-10-03 08:46:44 +000054#endif
55
56/*
drh054889e2005-11-30 03:20:31 +000057** The following routines are convenience wrappers around methods
danielk197762079062007-08-15 17:08:46 +000058** of the sqlite3_file object. This is mostly just syntactic sugar. All
drh054889e2005-11-30 03:20:31 +000059** of this would be completely automatic if SQLite were coded using
60** C++ instead of plain old C.
61*/
danielk1977b4b47412007-08-17 15:53:36 +000062int sqlite3OsClose(sqlite3_file *pId){
danielk1977c7b60172007-08-22 11:22:03 +000063 int rc = SQLITE_OK;
64 if( pId->pMethods ){
65 rc = pId->pMethods->xClose(pId);
66 pId->pMethods = 0;
67 }
68 return rc;
drh054889e2005-11-30 03:20:31 +000069}
danielk197762079062007-08-15 17:08:46 +000070int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
danielk1977b5a19202009-07-27 11:41:20 +000071 DO_OS_MALLOC_TEST(id);
danielk197762079062007-08-15 17:08:46 +000072 return id->pMethods->xRead(id, pBuf, amt, offset);
drh054889e2005-11-30 03:20:31 +000073}
danielk197762079062007-08-15 17:08:46 +000074int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
danielk1977b5a19202009-07-27 11:41:20 +000075 DO_OS_MALLOC_TEST(id);
danielk197762079062007-08-15 17:08:46 +000076 return id->pMethods->xWrite(id, pBuf, amt, offset);
drh054889e2005-11-30 03:20:31 +000077}
danielk197762079062007-08-15 17:08:46 +000078int sqlite3OsTruncate(sqlite3_file *id, i64 size){
79 return id->pMethods->xTruncate(id, size);
drh054889e2005-11-30 03:20:31 +000080}
danielk197790949c22007-08-17 16:50:38 +000081int sqlite3OsSync(sqlite3_file *id, int flags){
danielk1977b5a19202009-07-27 11:41:20 +000082 DO_OS_MALLOC_TEST(id);
danielk197790949c22007-08-17 16:50:38 +000083 return id->pMethods->xSync(id, flags);
drh054889e2005-11-30 03:20:31 +000084}
danielk197762079062007-08-15 17:08:46 +000085int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
danielk1977b5a19202009-07-27 11:41:20 +000086 DO_OS_MALLOC_TEST(id);
danielk197762079062007-08-15 17:08:46 +000087 return id->pMethods->xFileSize(id, pSize);
drh054889e2005-11-30 03:20:31 +000088}
danielk197762079062007-08-15 17:08:46 +000089int sqlite3OsLock(sqlite3_file *id, int lockType){
danielk1977b5a19202009-07-27 11:41:20 +000090 DO_OS_MALLOC_TEST(id);
danielk197762079062007-08-15 17:08:46 +000091 return id->pMethods->xLock(id, lockType);
drh054889e2005-11-30 03:20:31 +000092}
danielk197762079062007-08-15 17:08:46 +000093int sqlite3OsUnlock(sqlite3_file *id, int lockType){
94 return id->pMethods->xUnlock(id, lockType);
drh054889e2005-11-30 03:20:31 +000095}
danielk1977861f7452008-06-05 11:39:11 +000096int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
danielk1977b5a19202009-07-27 11:41:20 +000097 DO_OS_MALLOC_TEST(id);
danielk1977861f7452008-06-05 11:39:11 +000098 return id->pMethods->xCheckReservedLock(id, pResOut);
drh054889e2005-11-30 03:20:31 +000099}
drhcc6bb3e2007-08-31 16:11:35 +0000100int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
mistachkin6c3c1a02011-11-12 03:17:40 +0000101 DO_OS_MALLOC_TEST(id);
danielk1977861f7452008-06-05 11:39:11 +0000102 return id->pMethods->xFileControl(id, op, pArg);
drhcc6bb3e2007-08-31 16:11:35 +0000103}
danielk1977bf260972008-01-22 11:50:13 +0000104int sqlite3OsSectorSize(sqlite3_file *id){
105 int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
106 return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
107}
108int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
109 return id->pMethods->xDeviceCharacteristics(id);
110}
drh73b64e42010-05-30 19:55:15 +0000111int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
112 return id->pMethods->xShmLock(id, offset, n, flags);
drhd9e5c4f2010-05-12 18:01:39 +0000113}
drh286a2882010-05-20 23:51:06 +0000114void sqlite3OsShmBarrier(sqlite3_file *id){
115 id->pMethods->xShmBarrier(id);
116}
drhe11fedc2010-07-14 00:14:30 +0000117int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){
danda9fe0c2010-07-13 18:44:03 +0000118 return id->pMethods->xShmUnmap(id, deleteFlag);
drhd9e5c4f2010-05-12 18:01:39 +0000119}
dan18801912010-06-14 14:07:50 +0000120int sqlite3OsShmMap(
danda9fe0c2010-07-13 18:44:03 +0000121 sqlite3_file *id, /* Database file handle */
122 int iPage,
123 int pgsz,
124 int bExtend, /* True to extend file if necessary */
125 void volatile **pp /* OUT: Pointer to mapping */
dan13a3cb82010-06-11 19:04:21 +0000126){
mistachkin6c3c1a02011-11-12 03:17:40 +0000127 DO_OS_MALLOC_TEST(id);
danda9fe0c2010-07-13 18:44:03 +0000128 return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
dan13a3cb82010-06-11 19:04:21 +0000129}
drh3f459022006-01-07 16:06:07 +0000130
drhd677b3d2007-08-20 22:48:41 +0000131/*
132** The next group of routines are convenience wrappers around the
133** VFS methods.
134*/
danielk1977b4b47412007-08-17 15:53:36 +0000135int sqlite3OsOpen(
136 sqlite3_vfs *pVfs,
137 const char *zPath,
138 sqlite3_file *pFile,
139 int flags,
140 int *pFlagsOut
141){
drh072db2f2009-03-25 14:24:41 +0000142 int rc;
danielk1977b5a19202009-07-27 11:41:20 +0000143 DO_OS_MALLOC_TEST(0);
danddb0ac42010-07-14 14:48:58 +0000144 /* 0x87f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed
drhf1f12682009-09-09 14:17:52 +0000145 ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
146 ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
147 ** reaching the VFS. */
drh877eeb32011-07-20 17:13:30 +0000148 rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
drh072db2f2009-03-25 14:24:41 +0000149 assert( rc==SQLITE_OK || pFile->pMethods==0 );
150 return rc;
drh3f459022006-01-07 16:06:07 +0000151}
danielk1977fee2d252007-08-18 10:59:19 +0000152int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
mistachkin6c3c1a02011-11-12 03:17:40 +0000153 DO_OS_MALLOC_TEST(0);
drh153c62c2007-08-24 03:51:33 +0000154 return pVfs->xDelete(pVfs, zPath, dirSync);
danielk1977b4b47412007-08-17 15:53:36 +0000155}
danielk1977861f7452008-06-05 11:39:11 +0000156int sqlite3OsAccess(
157 sqlite3_vfs *pVfs,
158 const char *zPath,
159 int flags,
160 int *pResOut
161){
danielk1977b5a19202009-07-27 11:41:20 +0000162 DO_OS_MALLOC_TEST(0);
danielk1977861f7452008-06-05 11:39:11 +0000163 return pVfs->xAccess(pVfs, zPath, flags, pResOut);
danielk1977b4b47412007-08-17 15:53:36 +0000164}
danielk1977adfb9b02007-09-17 07:02:56 +0000165int sqlite3OsFullPathname(
166 sqlite3_vfs *pVfs,
167 const char *zPath,
168 int nPathOut,
169 char *zPathOut
170){
mistachkin6c3c1a02011-11-12 03:17:40 +0000171 DO_OS_MALLOC_TEST(0);
drh68ff78b2009-11-16 23:36:33 +0000172 zPathOut[0] = 0;
danielk1977adfb9b02007-09-17 07:02:56 +0000173 return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
danielk1977b4b47412007-08-17 15:53:36 +0000174}
shane75998ab2008-05-29 02:52:59 +0000175#ifndef SQLITE_OMIT_LOAD_EXTENSION
danielk1977b4b47412007-08-17 15:53:36 +0000176void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
drh153c62c2007-08-24 03:51:33 +0000177 return pVfs->xDlOpen(pVfs, zPath);
danielk1977b4b47412007-08-17 15:53:36 +0000178}
179void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
drh153c62c2007-08-24 03:51:33 +0000180 pVfs->xDlError(pVfs, nByte, zBufOut);
danielk1977b4b47412007-08-17 15:53:36 +0000181}
drh1875f7a2008-12-08 18:19:17 +0000182void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
183 return pVfs->xDlSym(pVfs, pHdle, zSym);
danielk1977b4b47412007-08-17 15:53:36 +0000184}
185void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
drh153c62c2007-08-24 03:51:33 +0000186 pVfs->xDlClose(pVfs, pHandle);
danielk1977b4b47412007-08-17 15:53:36 +0000187}
shane75998ab2008-05-29 02:52:59 +0000188#endif /* SQLITE_OMIT_LOAD_EXTENSION */
danielk1977b4b47412007-08-17 15:53:36 +0000189int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
drh153c62c2007-08-24 03:51:33 +0000190 return pVfs->xRandomness(pVfs, nByte, zBufOut);
danielk1977b4b47412007-08-17 15:53:36 +0000191}
192int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
drh153c62c2007-08-24 03:51:33 +0000193 return pVfs->xSleep(pVfs, nMicro);
danielk1977b4b47412007-08-17 15:53:36 +0000194}
drhb7e8ea22010-05-03 14:32:30 +0000195int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
196 int rc;
drhbfccdaf2010-09-01 19:29:57 +0000197 /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()
198 ** method to get the current date and time if that method is available
199 ** (if iVersion is 2 or greater and the function pointer is not NULL) and
200 ** will fall back to xCurrentTime() if xCurrentTimeInt64() is
201 ** unavailable.
202 */
drhb7e8ea22010-05-03 14:32:30 +0000203 if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
204 rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
205 }else{
206 double r;
207 rc = pVfs->xCurrentTime(pVfs, &r);
208 *pTimeOut = (sqlite3_int64)(r*86400000.0);
209 }
210 return rc;
danielk1977b4b47412007-08-17 15:53:36 +0000211}
212
213int sqlite3OsOpenMalloc(
214 sqlite3_vfs *pVfs,
215 const char *zFile,
216 sqlite3_file **ppFile,
danielk1977967a4a12007-08-20 14:23:44 +0000217 int flags,
218 int *pOutFlags
danielk1977b4b47412007-08-17 15:53:36 +0000219){
220 int rc = SQLITE_NOMEM;
221 sqlite3_file *pFile;
mistachkinf1c40f42011-09-17 15:34:50 +0000222 pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
danielk1977b4b47412007-08-17 15:53:36 +0000223 if( pFile ){
danielk1977967a4a12007-08-20 14:23:44 +0000224 rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
danielk1977b4b47412007-08-17 15:53:36 +0000225 if( rc!=SQLITE_OK ){
226 sqlite3_free(pFile);
227 }else{
228 *ppFile = pFile;
229 }
230 }
231 return rc;
232}
233int sqlite3OsCloseFree(sqlite3_file *pFile){
234 int rc = SQLITE_OK;
mlcreech40032982008-04-08 03:09:22 +0000235 assert( pFile );
236 rc = sqlite3OsClose(pFile);
237 sqlite3_free(pFile);
danielk1977b4b47412007-08-17 15:53:36 +0000238 return rc;
239}
240
drhd677b3d2007-08-20 22:48:41 +0000241/*
dan3d6e0602009-08-17 15:52:25 +0000242** This function is a wrapper around the OS specific implementation of
243** sqlite3_os_init(). The purpose of the wrapper is to provide the
244** ability to simulate a malloc failure, so that the handling of an
245** error in sqlite3_os_init() by the upper layers can be tested.
246*/
247int sqlite3OsInit(void){
drhadad77a2009-08-17 16:01:11 +0000248 void *p = sqlite3_malloc(10);
249 if( p==0 ) return SQLITE_NOMEM;
250 sqlite3_free(p);
dan3d6e0602009-08-17 15:52:25 +0000251 return sqlite3_os_init();
252}
253
254/*
danielk1977c0fa4c52008-06-25 17:19:00 +0000255** The list of all registered VFS implementations.
drhd677b3d2007-08-20 22:48:41 +0000256*/
danielk197795e80d62008-09-02 17:18:51 +0000257static sqlite3_vfs * SQLITE_WSD vfsList = 0;
danielk19775c8f8582008-09-02 10:22:00 +0000258#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
drhd677b3d2007-08-20 22:48:41 +0000259
260/*
261** Locate a VFS by name. If no name is given, simply return the
262** first VFS on the list.
263*/
264sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
drha4189802008-06-19 16:07:07 +0000265 sqlite3_vfs *pVfs = 0;
drh18472fa2008-10-07 15:25:48 +0000266#if SQLITE_THREADSAFE
drh40257ff2008-06-13 18:24:27 +0000267 sqlite3_mutex *mutex;
268#endif
269#ifndef SQLITE_OMIT_AUTOINIT
270 int rc = sqlite3_initialize();
271 if( rc ) return 0;
272#endif
drh18472fa2008-10-07 15:25:48 +0000273#if SQLITE_THREADSAFE
danielk197759f8c082008-06-18 17:09:10 +0000274 mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
drh7e8b8482008-01-23 03:03:05 +0000275#endif
drhd677b3d2007-08-20 22:48:41 +0000276 sqlite3_mutex_enter(mutex);
277 for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
278 if( zVfs==0 ) break;
279 if( strcmp(zVfs, pVfs->zName)==0 ) break;
280 }
drhd677b3d2007-08-20 22:48:41 +0000281 sqlite3_mutex_leave(mutex);
282 return pVfs;
danielk1977b4b47412007-08-17 15:53:36 +0000283}
284
drhd677b3d2007-08-20 22:48:41 +0000285/*
drhd677b3d2007-08-20 22:48:41 +0000286** Unlink a VFS from the linked list
287*/
288static void vfsUnlink(sqlite3_vfs *pVfs){
danielk197759f8c082008-06-18 17:09:10 +0000289 assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
drh9bc54492007-10-23 14:49:59 +0000290 if( pVfs==0 ){
291 /* No-op */
292 }else if( vfsList==pVfs ){
drhd677b3d2007-08-20 22:48:41 +0000293 vfsList = pVfs->pNext;
drh9bc54492007-10-23 14:49:59 +0000294 }else if( vfsList ){
drhd677b3d2007-08-20 22:48:41 +0000295 sqlite3_vfs *p = vfsList;
296 while( p->pNext && p->pNext!=pVfs ){
297 p = p->pNext;
298 }
299 if( p->pNext==pVfs ){
300 p->pNext = pVfs->pNext;
301 }
302 }
303}
304
305/*
306** Register a VFS with the system. It is harmless to register the same
307** VFS multiple times. The new VFS becomes the default if makeDflt is
308** true.
309*/
310int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
drh30ddce62011-10-15 00:16:30 +0000311 MUTEX_LOGIC(sqlite3_mutex *mutex;)
drh40257ff2008-06-13 18:24:27 +0000312#ifndef SQLITE_OMIT_AUTOINIT
313 int rc = sqlite3_initialize();
314 if( rc ) return rc;
315#endif
drh30ddce62011-10-15 00:16:30 +0000316 MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
drhd677b3d2007-08-20 22:48:41 +0000317 sqlite3_mutex_enter(mutex);
318 vfsUnlink(pVfs);
319 if( makeDflt || vfsList==0 ){
320 pVfs->pNext = vfsList;
321 vfsList = pVfs;
322 }else{
323 pVfs->pNext = vfsList->pNext;
danielk197795c8a542007-09-01 06:51:27 +0000324 vfsList->pNext = pVfs;
drhd677b3d2007-08-20 22:48:41 +0000325 }
danielk1977f1da17a2007-08-21 13:07:46 +0000326 assert(vfsList);
drhd677b3d2007-08-20 22:48:41 +0000327 sqlite3_mutex_leave(mutex);
328 return SQLITE_OK;
329}
330
331/*
332** Unregister a VFS so that it is no longer accessible.
333*/
334int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
drh18472fa2008-10-07 15:25:48 +0000335#if SQLITE_THREADSAFE
danielk197759f8c082008-06-18 17:09:10 +0000336 sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
drh7e8b8482008-01-23 03:03:05 +0000337#endif
drhd677b3d2007-08-20 22:48:41 +0000338 sqlite3_mutex_enter(mutex);
339 vfsUnlink(pVfs);
340 sqlite3_mutex_leave(mutex);
341 return SQLITE_OK;
342}
drh24076fd2011-12-01 02:32:12 +0000343
344#ifndef SQLITE_OMIT_VFS_STDIO
345/*****************************************************************************
346** The remainder of this file contains a simplified stdio-like interface
347** to the VFS layer.
348*/
349
350/*
351** An instance of the following object records the state of an
352** open file. This object is opaque to all users - the internal
353** structure is only visible to the functions below.
354*/
355struct sqlite3_FILE {
356 char *zFilename; /* Full pathname of the open file */
357 sqlite3_int64 iOfst; /* Current offset into the file */
358 sqlite3_vfs *pVfs; /* The VFS used for this file */
359 u8 alwaysAppend; /* Always append if true */
360 sqlite3_file sFile; /* Open file. MUST BE LAST */
361};
362
363/*
364** This is a helper routine used to translate a URI into a full pathname
365** and a pointer to the appropriate VFS.
366*/
367static int getFilename(const char *zURI, sqlite3_vfs **ppVfs, char **pzName){
368 int rc;
369 char *zOpen = 0;
370 char *zFullname = 0;
371 unsigned int flags;
372 char *zErrmsg = 0;
373 sqlite3_vfs *pVfs = 0;
374
375 rc = sqlite3ParseUri(0, zURI, &flags, &pVfs, &zOpen, &zErrmsg);
376 sqlite3_free(zErrmsg);
377 if( rc ) goto getFilename_error;
378 zFullname = sqlite3_malloc( pVfs->mxPathname+1 );
379 if( zFullname==0 ){ rc = SQLITE_NOMEM; goto getFilename_error; }
380 rc = pVfs->xFullPathname(pVfs, zOpen, pVfs->mxPathname, zFullname);
381 if( rc ) goto getFilename_error;
382 sqlite3_free(zOpen);
383 zOpen = 0;
384 *pzName = sqlite3_realloc(zFullname, sqlite3Strlen30(zFullname)+1);
385 if( *pzName==0 ) goto getFilename_error;
386 zFullname = 0;
387 *ppVfs = pVfs;
388 return SQLITE_OK;
389
390getFilename_error:
391 sqlite3_free(zOpen);
392 sqlite3_free(zFullname);
393 *pzName = 0;
394 *ppVfs = 0;
395 return rc;
396}
397
398/*
399** Open a file for stdio-like reading and writing. The file is identified
400** by the URI in the first parameter. The access mode can be "r", "r+",
401** "w", "w+", "a", or "a+" with the usual meanings.
402**
403** On success, a pointer to a new sqlite3_FILE object is returned. On
404** failure, NULL is returned. Unfortunately, there is no way to recover
405** detailed error information after a failure.
406*/
407sqlite3_FILE *sqlite3_fopen(const char *zURI, const char *zMode){
408 char *zFile = 0;
409 sqlite3_vfs *pVfs = 0;
410 int rc;
411 int openFlags;
412 int doTruncate = 0;
413 int seekEnd = 0;
414 int alwaysAppend = 0;
415 int nToAlloc;
416 sqlite3_FILE *p;
417
418 if( zMode[0]==0 ) return 0;
419 if( zMode[0]=='r' ){
420 if( zMode[1]=='+' ){
421 openFlags = SQLITE_OPEN_READWRITE;
422 }else{
423 openFlags = SQLITE_OPEN_READONLY;
424 }
425 }else if( zMode[0]=='w' ){
426 openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
427 doTruncate = 1;
428 }else if( zMode[0]=='a' ){
429 openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
430 if( zMode[1]=='+' ){
431 alwaysAppend = 1;
432 }else{
433 seekEnd = 1;
434 }
435 }else{
436 return 0;
437 }
438 rc = getFilename(zURI, &pVfs, &zFile);
439 if( rc ) return 0;
440 nToAlloc = sizeof(*p) + ROUND8(pVfs->szOsFile);
441 p = sqlite3_malloc( nToAlloc );
442 if( p==0 ){
443 sqlite3_free(zFile);
444 return 0;
445 }
446 memset(p, 0, nToAlloc);
447 p->zFilename = zFile;
448 rc = pVfs->xOpen(pVfs, zFile, &p->sFile, openFlags, &openFlags);
449 if( rc!=SQLITE_OK ){
450 sqlite3_free(zFile);
451 sqlite3_free(p);
452 return 0;
453 }
454 p->pVfs = pVfs;
455 p->alwaysAppend = alwaysAppend;
456 if( seekEnd ) sqlite3_fseek(p, 0, SQLITE_SEEK_END);
457 if( doTruncate ) sqlite3_ftruncate(p, 0);
458 return p;
459}
460
461/*
462** Close a file perviously opened by sqlite3_fopen().
463*/
464int sqlite3_fclose(sqlite3_FILE *p){
465 p->sFile.pMethods->xClose(&p->sFile);
466 sqlite3_free(p);
467 return SQLITE_OK;
468}
469
470/*
471** Read iAmt bytes from the file p into pBuf.
472**
473** Return 0 on success or an error code if the full amount could
474** not be read.
475*/
476int sqlite3_fread(
477 void *pBuf, /* Write content read into this buffer */
478 sqlite3_int64 iAmt, /* Number of bytes to read */
479 sqlite3_FILE *p /* Read from this file */
480){
481 int rc = p->sFile.pMethods->xRead(&p->sFile, pBuf, iAmt, p->iOfst);
482 if( rc==SQLITE_OK ){
483 p->iOfst += iAmt;
484 }
485 return rc;
486}
487
488/*
489** Write iAmt bytes from buffer pBuf into the file p.
490**
491** Return 0 on success or an error code if anything goes wrong.
492*/
493int sqlite3_fwrite(
494 const void *pBuf, /* Take content to be written from this buffer */
495 sqlite3_int64 iAmt, /* Number of bytes to write */
496 sqlite3_FILE *p /* Write into this file */
497){
498 int rc;
499
500 if( p->alwaysAppend ) sqlite3_fseek(p, 0, SQLITE_SEEK_END);
501 rc = p->sFile.pMethods->xWrite(&p->sFile, pBuf, iAmt, p->iOfst);
502 if( rc==SQLITE_OK ){
503 p->iOfst += iAmt;
504 }
505 return rc;
506}
507
508/*
509** Truncate an open file to newSize bytes.
510*/
511int sqlite3_ftruncate(sqlite3_FILE *p, sqlite3_int64 newSize){
512 int rc;
513 rc = p->sFile.pMethods->xTruncate(&p->sFile, newSize);
514 return rc;
515}
516
517/*
518** Return the current position of the file pointer.
519*/
520sqlite3_int64 sqlite3_ftell(sqlite3_FILE *p){
521 return p->iOfst;
522}
523
524/*
525** Move the file pointer to a new position in the file.
526*/
527int sqlite3_fseek(sqlite3_FILE *p, sqlite3_int64 ofst, int whence){
528 int rc = SQLITE_OK;
529 if( whence==SQLITE_SEEK_SET ){
530 p->iOfst = ofst;
531 }else if( whence==SQLITE_SEEK_CUR ){
532 p->iOfst += ofst;
533 }else{
534 sqlite3_int64 iCur = 0;
535 rc = p->sFile.pMethods->xFileSize(&p->sFile, &iCur);
536 if( rc==SQLITE_OK ){
537 p->iOfst = iCur + ofst;
538 }
539 }
540 return rc;
541}
542
543/*
544** Rewind the file pointer to the beginning of the file.
545*/
546int sqlite3_rewind(sqlite3_FILE *p){
547 p->iOfst = 0;
548 return SQLITE_OK;
549}
550
551/*
552** Flush the content of OS cache buffers to disk. (fsync())
553*/
554int sqlite3_fflush(sqlite3_FILE *p){
555 return p->sFile.pMethods->xSync(&p->sFile, SQLITE_SYNC_NORMAL);
556}
557
558/*
559** Delete the file identified by the URI in the first parameter
560*/
561int sqlite3_remove(const char *zURI){
562 sqlite3_vfs *pVfs = 0;
563 char *zFilename = 0;
564 int rc;
565
566 rc = getFilename(zURI, &pVfs, &zFilename);
567 if( rc==SQLITE_OK ){
568 rc = pVfs->xDelete(pVfs, zFilename, 0);
569 }
570 sqlite3_free(zFilename);
571 return rc;
572}
573
574#endif /* SQLITE_OMIT_VFS_STDIO */