2
|
1 |
/*
|
|
2 |
** 2008 February 09
|
|
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 code that is specific to windows.
|
|
14 |
*/
|
|
15 |
#include "sqliteInt.h"
|
|
16 |
#if OS_SYMBIAN /* This file is used for symbian only */
|
|
17 |
|
|
18 |
#define MAX_PATH 260
|
|
19 |
/*
|
|
20 |
** A Note About Memory Allocation:
|
|
21 |
**
|
|
22 |
** This driver uses malloc()/free() directly rather than going through
|
|
23 |
** the SQLite-wrappers sqlite3_malloc()/sqlite3_free(). Those wrappers
|
|
24 |
** are designed for use on embedded systems where memory is scarce and
|
|
25 |
** malloc failures happen frequently. Win32 does not typically run on
|
|
26 |
** embedded systems, and when it does the developers normally have bigger
|
|
27 |
** problems to worry about than running out of memory. So there is not
|
|
28 |
** a compelling need to use the wrappers.
|
|
29 |
**
|
|
30 |
** But there is a good reason to not use the wrappers. If we use the
|
|
31 |
** wrappers then we will get simulated malloc() failures within this
|
|
32 |
** driver. And that causes all kinds of problems for our tests. We
|
|
33 |
** could enhance SQLite to deal with simulated malloc failures within
|
|
34 |
** the OS driver, but the code to deal with those failure would not
|
|
35 |
** be exercised on Linux (which does not need to malloc() in the driver)
|
|
36 |
** and so we would have difficulty writing coverage tests for that
|
|
37 |
** code. Better to leave the code out, we think.
|
|
38 |
**
|
|
39 |
** The point of this discussion is as follows: When creating a new
|
|
40 |
** OS layer for an embedded system, if you use this file as an example,
|
|
41 |
** avoid the use of malloc()/free(). Those routines work ok on windows
|
|
42 |
** desktops but not so well in embedded systems.
|
|
43 |
*/
|
|
44 |
|
|
45 |
#include <stdlib.h>
|
|
46 |
#include <string.h>
|
|
47 |
#include <time.h>
|
|
48 |
#include <e32std.h>
|
|
49 |
#include <f32file.h>
|
|
50 |
#include <charconv.h>
|
|
51 |
#include <bautils.h>
|
|
52 |
#include <unistd.h>
|
|
53 |
|
|
54 |
/*
|
|
55 |
** Macros used to determine whether or not to use threads.
|
|
56 |
*/
|
|
57 |
#if defined(THREADSAFE) && THREADSAFE
|
|
58 |
# define SQLITE_W32_THREADS 1
|
|
59 |
#endif
|
|
60 |
|
|
61 |
/*
|
|
62 |
** Include code that is common to all os_*.c files
|
|
63 |
*/
|
|
64 |
#include "os_common.h"
|
|
65 |
|
|
66 |
/*
|
|
67 |
** The symbianFile structure is a subclass of sqlite3_file* specific to the win32
|
|
68 |
** portability layer.
|
|
69 |
*/
|
|
70 |
|
|
71 |
typedef struct symbianFile symbianFile;
|
|
72 |
struct symbianFile {
|
|
73 |
int isOpen;
|
|
74 |
unsigned char locktype; /* Type of lock currently held on this file */
|
|
75 |
short sharedLockByte; /* Randomly chosen byte used as a shared lock */
|
|
76 |
char fileName[512];
|
|
77 |
RFs session;
|
|
78 |
RFile file;
|
|
79 |
};
|
|
80 |
|
|
81 |
/*****************************************************************************
|
|
82 |
** The next group of routines implement the I/O methods specified
|
|
83 |
** by the sqlite3_io_methods object.
|
|
84 |
******************************************************************************/
|
|
85 |
|
|
86 |
/*
|
|
87 |
** Close a file.
|
|
88 |
**
|
|
89 |
** It is reported that an attempt to close a handle might sometimes
|
|
90 |
** fail. This is a very unreasonable result, but windows is notorious
|
|
91 |
** for being unreasonable so I do not doubt that it might happen. If
|
|
92 |
** the close fails, we pause for 100 milliseconds and try again. As
|
|
93 |
** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
|
|
94 |
** giving up and returning an error.
|
|
95 |
*/
|
|
96 |
#define MX_CLOSE_ATTEMPT 3
|
|
97 |
int winClose(sqlite3_file *id){
|
|
98 |
int rc, cnt = 0;
|
|
99 |
symbianFile *pFile = (symbianFile*)id;
|
|
100 |
pFile->file.Close();
|
|
101 |
pFile->session.Close();
|
|
102 |
return SQLITE_OK;
|
|
103 |
}
|
|
104 |
|
|
105 |
/*
|
|
106 |
** Some microsoft compilers lack this definition.
|
|
107 |
*/
|
|
108 |
#ifndef INVALID_SET_FILE_POINTER
|
|
109 |
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
|
110 |
#endif
|
|
111 |
|
|
112 |
/*
|
|
113 |
** Read data from a file into a buffer. Return SQLITE_OK if all
|
|
114 |
** bytes were read successfully and SQLITE_IOERR if anything goes
|
|
115 |
** wrong.
|
|
116 |
*/
|
|
117 |
int winRead(
|
|
118 |
sqlite3_file *id, /* File to read from */
|
|
119 |
void *pBuf, /* Write content into this buffer */
|
|
120 |
int amt, /* Number of bytes to read */
|
|
121 |
sqlite3_int64 offset /* Begin reading at this offset */
|
|
122 |
){
|
|
123 |
int rc;
|
|
124 |
size_t got;
|
|
125 |
symbianFile *pFile = (symbianFile*)id;
|
|
126 |
assert( id!=0 );
|
|
127 |
SimulateIOError(return SQLITE_IOERR_READ);
|
|
128 |
TInt tOffset = (TInt)offset;
|
|
129 |
rc = pFile->file.Seek(ESeekStart, tOffset);
|
|
130 |
if( rc!= KErrNone){
|
|
131 |
return SQLITE_FULL;
|
|
132 |
}
|
|
133 |
|
|
134 |
HBufC8* buf = HBufC8::NewL(amt) ;
|
|
135 |
TPtr8 ptr = buf->Des();
|
|
136 |
|
|
137 |
if (pFile->file.Read(ptr, amt) != KErrNone)
|
|
138 |
{
|
|
139 |
delete buf;
|
|
140 |
return SQLITE_IOERR_READ;
|
|
141 |
}
|
|
142 |
|
|
143 |
got = buf->Length();
|
|
144 |
|
|
145 |
if( got == 0 ){
|
|
146 |
delete buf;
|
|
147 |
TInt size = 0;
|
|
148 |
if (pFile->file.Size(size) != KErrNone)
|
|
149 |
{
|
|
150 |
return SQLITE_IOERR_READ;
|
|
151 |
}
|
|
152 |
if (size == 0)
|
|
153 |
{
|
|
154 |
return SQLITE_IOERR_SHORT_READ;
|
|
155 |
}
|
|
156 |
return SQLITE_IOERR_READ;
|
|
157 |
}
|
|
158 |
memcpy(pBuf, ptr.Ptr(), got);
|
|
159 |
delete buf;
|
|
160 |
if( got == amt ){
|
|
161 |
return SQLITE_OK;
|
|
162 |
}else{
|
|
163 |
memset(&((char*)pBuf)[got], 0, amt-got);
|
|
164 |
return SQLITE_IOERR_SHORT_READ;
|
|
165 |
}
|
|
166 |
}
|
|
167 |
|
|
168 |
/*
|
|
169 |
** Write data from a buffer into a file. Return SQLITE_OK on success
|
|
170 |
** or some other error code on failure.
|
|
171 |
*/
|
|
172 |
int winWrite(
|
|
173 |
sqlite3_file *id, /* File to write into */
|
|
174 |
const void *pBuf, /* The bytes to be written */
|
|
175 |
int amt, /* Number of bytes to write */
|
|
176 |
sqlite3_int64 offset /* Offset into the file to begin writing at */
|
|
177 |
){
|
|
178 |
int rc;
|
|
179 |
symbianFile *pFile = (symbianFile*)id;
|
|
180 |
assert( id!=0 );
|
|
181 |
SimulateIOError(return SQLITE_IOERR_WRITE);
|
|
182 |
SimulateDiskfullError(return SQLITE_FULL);
|
|
183 |
TInt tOffset = (TInt)offset;
|
|
184 |
rc = pFile->file.Seek(ESeekStart, tOffset);
|
|
185 |
if( rc!= KErrNone){
|
|
186 |
return SQLITE_FULL;
|
|
187 |
}
|
|
188 |
|
|
189 |
assert( amt>0 );
|
|
190 |
|
|
191 |
rc = SQLITE_OK;
|
|
192 |
TPtrC8 ptr((TUint8 *)pBuf,amt);
|
|
193 |
|
|
194 |
if (pFile->file.Write(ptr, amt) != KErrNone) rc = SQLITE_FULL;
|
|
195 |
|
|
196 |
return rc;
|
|
197 |
}
|
|
198 |
|
|
199 |
/*
|
|
200 |
** Truncate an open file to a specified size
|
|
201 |
*/
|
|
202 |
int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
|
|
203 |
symbianFile *pFile = (symbianFile*)id;
|
|
204 |
|
|
205 |
if (pFile->file.SetSize(nByte) != KErrNone)
|
|
206 |
{
|
|
207 |
return SQLITE_IOERR;
|
|
208 |
}
|
|
209 |
|
|
210 |
return SQLITE_OK;
|
|
211 |
}
|
|
212 |
|
|
213 |
#ifdef SQLITE_TEST
|
|
214 |
/*
|
|
215 |
** Count the number of fullsyncs and normal syncs. This is used to test
|
|
216 |
** that syncs and fullsyncs are occuring at the right times.
|
|
217 |
*/
|
|
218 |
int sqlite3_sync_count = 0;
|
|
219 |
int sqlite3_fullsync_count = 0;
|
|
220 |
#endif
|
|
221 |
|
|
222 |
/*
|
|
223 |
** Make sure all writes to a particular file are committed to disk.
|
|
224 |
*/
|
|
225 |
int winSync(sqlite3_file *id, int flags){
|
|
226 |
symbianFile *pFile = (symbianFile*)id;
|
|
227 |
OSTRACE3("SYNC %d lock=%d\n", pFile->h, pFile->locktype);
|
|
228 |
#ifdef SQLITE_TEST
|
|
229 |
if( flags & SQLITE_SYNC_FULL ){
|
|
230 |
sqlite3_fullsync_count++;
|
|
231 |
}
|
|
232 |
sqlite3_sync_count++;
|
|
233 |
#endif
|
|
234 |
TInt error = pFile->file.Flush();
|
|
235 |
if (error != KErrNone)
|
|
236 |
{
|
|
237 |
return SQLITE_IOERR;
|
|
238 |
}else{
|
|
239 |
return SQLITE_OK;
|
|
240 |
}
|
|
241 |
}
|
|
242 |
|
|
243 |
/*
|
|
244 |
** Determine the current size of a file in bytes
|
|
245 |
*/
|
|
246 |
int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
|
|
247 |
symbianFile *pFile = (symbianFile*)id;
|
|
248 |
|
|
249 |
TInt size = 0;
|
|
250 |
if (pFile->file.Size(size) != KErrNone)
|
|
251 |
{
|
|
252 |
return SQLITE_IOERR;
|
|
253 |
}
|
|
254 |
|
|
255 |
*pSize = size;
|
|
256 |
|
|
257 |
return SQLITE_OK;
|
|
258 |
}
|
|
259 |
|
|
260 |
|
|
261 |
/*
|
|
262 |
** Lock the file with the lock specified by parameter locktype - one
|
|
263 |
** of the following:
|
|
264 |
**
|
|
265 |
** (1) SHARED_LOCK
|
|
266 |
** (2) RESERVED_LOCK
|
|
267 |
** (3) PENDING_LOCK
|
|
268 |
** (4) EXCLUSIVE_LOCK
|
|
269 |
**
|
|
270 |
** Sometimes when requesting one lock state, additional lock states
|
|
271 |
** are inserted in between. The locking might fail on one of the later
|
|
272 |
** transitions leaving the lock state different from what it started but
|
|
273 |
** still short of its goal. The following chart shows the allowed
|
|
274 |
** transitions and the inserted intermediate states:
|
|
275 |
**
|
|
276 |
** UNLOCKED -> SHARED
|
|
277 |
** SHARED -> RESERVED
|
|
278 |
** SHARED -> (PENDING) -> EXCLUSIVE
|
|
279 |
** RESERVED -> (PENDING) -> EXCLUSIVE
|
|
280 |
** PENDING -> EXCLUSIVE
|
|
281 |
**
|
|
282 |
** This routine will only increase a lock. The winUnlock() routine
|
|
283 |
** erases all locks at once and returns us immediately to locking level 0.
|
|
284 |
** It is not possible to lower the locking level one step at a time. You
|
|
285 |
** must go straight to locking level 0.
|
|
286 |
*/
|
|
287 |
int winLock(sqlite3_file *id, int locktype){
|
|
288 |
int rc = SQLITE_OK; /* Return code from subroutines */
|
|
289 |
int res = 1; /* Result of a windows lock call */
|
|
290 |
int newLocktype; /* Set pFile->locktype to this value before exiting */
|
|
291 |
int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
|
|
292 |
symbianFile *pFile = (symbianFile*)id;
|
|
293 |
|
|
294 |
assert( pFile!=0 );
|
|
295 |
OSTRACE5("LOCK %d %d was %d(%d)\n",
|
|
296 |
pFile->h, locktype, pFile->locktype, pFile->sharedLockByte);
|
|
297 |
|
|
298 |
// one smartphone only one application can control the database
|
|
299 |
|
|
300 |
TInt size = 0;
|
|
301 |
if (pFile->file.Size(size) == KErrNone) return SQLITE_OK;
|
|
302 |
|
|
303 |
return SQLITE_BUSY;
|
|
304 |
}
|
|
305 |
|
|
306 |
/*
|
|
307 |
** This routine checks if there is a RESERVED lock held on the specified
|
|
308 |
** file by this or any other process. If such a lock is held, return
|
|
309 |
** non-zero, otherwise zero.
|
|
310 |
*/
|
|
311 |
int winCheckReservedLock(sqlite3_file *id){
|
|
312 |
int rc;
|
|
313 |
symbianFile *pFile = (symbianFile*)id;
|
|
314 |
assert( pFile!=0 );
|
|
315 |
if( pFile->locktype>=RESERVED_LOCK ){
|
|
316 |
rc = 1;
|
|
317 |
OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
|
|
318 |
}else{
|
|
319 |
TInt size = 0;
|
|
320 |
if (pFile->file.Size(size) == KErrNone) rc = 1;
|
|
321 |
OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc);
|
|
322 |
}
|
|
323 |
return rc;
|
|
324 |
}
|
|
325 |
|
|
326 |
/*
|
|
327 |
** Lower the locking level on file descriptor id to locktype. locktype
|
|
328 |
** must be either NO_LOCK or SHARED_LOCK.
|
|
329 |
**
|
|
330 |
** If the locking level of the file descriptor is already at or below
|
|
331 |
** the requested locking level, this routine is a no-op.
|
|
332 |
**
|
|
333 |
** It is not possible for this routine to fail if the second argument
|
|
334 |
** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
|
|
335 |
** might return SQLITE_IOERR;
|
|
336 |
*/
|
|
337 |
int winUnlock(sqlite3_file *id, int locktype){
|
|
338 |
int type;
|
|
339 |
symbianFile *pFile = (symbianFile*)id;
|
|
340 |
int rc = SQLITE_OK;
|
|
341 |
assert( pFile!=0 );
|
|
342 |
return rc;
|
|
343 |
}
|
|
344 |
|
|
345 |
/*
|
|
346 |
** Control and query of the open file handle.
|
|
347 |
*/
|
|
348 |
int winFileControl(sqlite3_file *id, int op, void *pArg){
|
|
349 |
switch( op ){
|
|
350 |
case SQLITE_FCNTL_LOCKSTATE: {
|
|
351 |
*(int*)pArg = ((symbianFile*)id)->locktype;
|
|
352 |
return SQLITE_OK;
|
|
353 |
}
|
|
354 |
}
|
|
355 |
return SQLITE_ERROR;
|
|
356 |
}
|
|
357 |
|
|
358 |
/*
|
|
359 |
** Return the sector size in bytes of the underlying block device for
|
|
360 |
** the specified file. This is almost always 512 bytes, but may be
|
|
361 |
** larger for some devices.
|
|
362 |
**
|
|
363 |
** SQLite code assumes this function cannot fail. It also assumes that
|
|
364 |
** if two files are created in the same file-system directory (i.e.
|
|
365 |
** a database and its journal file) that the sector size will be the
|
|
366 |
** same for both.
|
|
367 |
*/
|
|
368 |
int winSectorSize(sqlite3_file *id){
|
|
369 |
return SQLITE_DEFAULT_SECTOR_SIZE;
|
|
370 |
}
|
|
371 |
|
|
372 |
/*
|
|
373 |
** Return a vector of device characteristics.
|
|
374 |
*/
|
|
375 |
int winDeviceCharacteristics(sqlite3_file *id){
|
|
376 |
return 0;
|
|
377 |
}
|
|
378 |
|
|
379 |
|
|
380 |
/***************************************************************************
|
|
381 |
** Here ends the I/O methods that form the sqlite3_io_methods object.
|
|
382 |
**
|
|
383 |
** The next block of code implements the VFS methods.
|
|
384 |
****************************************************************************/
|
|
385 |
|
|
386 |
void ConvertToUnicode(RFs session, TDes16& aUnicode, const char *str)
|
|
387 |
{
|
|
388 |
CCnvCharacterSetConverter *converter = CCnvCharacterSetConverter::NewL();
|
|
389 |
converter->PrepareToConvertToOrFromL(KCharacterSetIdentifierUtf8, session);
|
|
390 |
|
|
391 |
TPtrC8 ptr((const unsigned char*)str);
|
|
392 |
|
|
393 |
int state = CCnvCharacterSetConverter::KStateDefault;
|
|
394 |
converter->ConvertToUnicode(aUnicode, ptr, state);
|
|
395 |
delete converter;
|
|
396 |
}
|
|
397 |
|
|
398 |
/*
|
|
399 |
** Open a file.
|
|
400 |
*/
|
|
401 |
int winOpen(
|
|
402 |
sqlite3_vfs *pVfs, /* Not used */
|
|
403 |
const char *zName, /* Name of the file (UTF-8) */
|
|
404 |
sqlite3_file *id, /* Write the SQLite file handle here */
|
|
405 |
int flags, /* Open mode flags */
|
|
406 |
int *pOutFlags /* Status return flags */
|
|
407 |
){
|
|
408 |
symbianFile *pFile = (symbianFile*)id;
|
|
409 |
TBuf16<MAX_PATH> filename;
|
|
410 |
|
|
411 |
pFile->isOpen = 0;
|
|
412 |
memset(pFile, 0, sizeof(*pFile));
|
|
413 |
strcpy(pFile->fileName, zName);
|
|
414 |
pFile->session.Connect();
|
|
415 |
|
|
416 |
ConvertToUnicode(pFile->session, filename, zName);
|
|
417 |
|
|
418 |
int ret = 0;
|
|
419 |
if( flags & SQLITE_OPEN_CREATE ){
|
|
420 |
if (BaflUtils::FileExists(pFile->session, filename) == 1)
|
|
421 |
{
|
|
422 |
ret = pFile->file.Open(pFile->session, filename, EFileStream | EFileWrite);
|
|
423 |
}
|
|
424 |
else
|
|
425 |
{
|
|
426 |
ret = pFile->file.Create(pFile->session, filename, EFileStream | EFileWrite);
|
|
427 |
}
|
|
428 |
}
|
|
429 |
else
|
|
430 |
if( flags & SQLITE_OPEN_READWRITE ){
|
|
431 |
ret = pFile->file.Open(pFile->session, filename, EFileStream | EFileWrite);
|
|
432 |
}else{
|
|
433 |
ret = pFile->file.Open(pFile->session, filename, EFileStream | EFileRead);
|
|
434 |
}
|
|
435 |
|
|
436 |
OpenCounter(+1);
|
|
437 |
|
|
438 |
if (ret != KErrNone)
|
|
439 |
{
|
|
440 |
return SQLITE_IOERR;
|
|
441 |
}
|
|
442 |
|
|
443 |
pFile->isOpen = 1;
|
|
444 |
return SQLITE_OK;
|
|
445 |
}
|
|
446 |
|
|
447 |
/*
|
|
448 |
** Delete the named file.
|
|
449 |
**
|
|
450 |
** Note that windows does not allow a file to be deleted if some other
|
|
451 |
** process has it open. Sometimes a virus scanner or indexing program
|
|
452 |
** will open a journal file shortly after it is created in order to do
|
|
453 |
** whatever does. While this other process is holding the
|
|
454 |
** file open, we will be unable to delete it. To work around this
|
|
455 |
** problem, we delay 100 milliseconds and try to delete again. Up
|
|
456 |
** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
|
|
457 |
** up and returning an error.
|
|
458 |
*/
|
|
459 |
#define MX_DELETION_ATTEMPTS 5
|
|
460 |
int winDelete(
|
|
461 |
sqlite3_vfs *pVfs, /* Not used on win32 */
|
|
462 |
const char *zFilename, /* Name of file to delete */
|
|
463 |
int syncDir /* Not used on win32 */
|
|
464 |
){
|
|
465 |
SimulateIOError(return SQLITE_IOERR_DELETE);
|
|
466 |
TBuf16<MAX_PATH> filename;
|
|
467 |
|
|
468 |
RFs session;
|
|
469 |
session.Connect();
|
|
470 |
ConvertToUnicode(session, filename, zFilename);
|
|
471 |
BaflUtils::DeleteFile(session, filename);
|
|
472 |
OSTRACE2("DELETE \"%s\"\n", zFilename);
|
|
473 |
session.Close();
|
|
474 |
return SQLITE_OK;
|
|
475 |
}
|
|
476 |
|
|
477 |
/*
|
|
478 |
** Check the existance and status of a file.
|
|
479 |
*/
|
|
480 |
int winAccess(
|
|
481 |
sqlite3_vfs *pVfs, /* Not used on win32 */
|
|
482 |
const char *zFilename, /* Name of file to check */
|
|
483 |
int flags /* Type of test to make on this file */
|
|
484 |
){
|
|
485 |
TBuf16<MAX_PATH> filename;
|
|
486 |
|
|
487 |
RFs session;
|
|
488 |
session.Connect();
|
|
489 |
ConvertToUnicode(session, filename, zFilename);
|
|
490 |
int ret = BaflUtils::FileExists(session, filename);
|
|
491 |
session.Close();
|
|
492 |
|
|
493 |
return ret;
|
|
494 |
}
|
|
495 |
|
|
496 |
|
|
497 |
/*
|
|
498 |
** Create a temporary file name in zBuf. zBuf must be big enough to
|
|
499 |
** hold at pVfs->mxPathname characters.
|
|
500 |
*/
|
|
501 |
int winGetTempname(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
|
|
502 |
static char zChars[] =
|
|
503 |
"abcdefghijklmnopqrstuvwxyz"
|
|
504 |
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
505 |
"0123456789";
|
|
506 |
int i, j;
|
|
507 |
char zTempPath[MAX_PATH+1];
|
|
508 |
if( sqlite3_temp_directory ){
|
|
509 |
sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
|
|
510 |
}
|
|
511 |
else
|
|
512 |
{
|
|
513 |
}
|
|
514 |
|
|
515 |
for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
|
|
516 |
zTempPath[i] = 0;
|
|
517 |
sqlite3_snprintf(nBuf-30, zBuf,
|
|
518 |
"%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
|
|
519 |
j = strlen(zBuf);
|
|
520 |
sqlite3Randomness(20, &zBuf[j]);
|
|
521 |
for(i=0; i<20; i++, j++){
|
|
522 |
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
|
|
523 |
}
|
|
524 |
zBuf[j] = 0;
|
|
525 |
OSTRACE2("TEMP FILENAME: %s\n", zBuf);
|
|
526 |
return SQLITE_OK;
|
|
527 |
}
|
|
528 |
|
|
529 |
/*
|
|
530 |
** Turn a relative pathname into a full pathname. Write the full
|
|
531 |
** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname
|
|
532 |
** bytes in size.
|
|
533 |
*/
|
|
534 |
int winFullPathname(
|
|
535 |
sqlite3_vfs *pVfs, /* Pointer to vfs object */
|
|
536 |
const char *zRelative, /* Possibly relative input path */
|
|
537 |
int nFull, /* Size of output buffer in bytes */
|
|
538 |
char *zFull /* Output buffer */
|
|
539 |
){
|
|
540 |
|
|
541 |
/* WinCE has no concept of a relative pathname, or so I am told. */
|
|
542 |
sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative);
|
|
543 |
return SQLITE_OK;
|
|
544 |
}
|
|
545 |
|
|
546 |
#define winDlOpen 0
|
|
547 |
#define winDlError 0
|
|
548 |
#define winDlSym 0
|
|
549 |
#define winDlClose 0
|
|
550 |
|
|
551 |
|
|
552 |
/*
|
|
553 |
** Write up to nBuf bytes of randomness into zBuf.
|
|
554 |
*/
|
|
555 |
int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
|
|
556 |
|
|
557 |
int i;
|
|
558 |
for (i=0; i<nBuf; ++i)
|
|
559 |
{
|
|
560 |
zBuf[i] = rand() % 255;
|
|
561 |
}
|
|
562 |
return nBuf;
|
|
563 |
}
|
|
564 |
|
|
565 |
|
|
566 |
/*
|
|
567 |
** Sleep for a little while. Return the amount of time slept.
|
|
568 |
*/
|
|
569 |
int winSleep(sqlite3_vfs *pVfs, int microsec){
|
|
570 |
return sleep(microsec / 1000);
|
|
571 |
}
|
|
572 |
|
|
573 |
/*
|
|
574 |
** The following variable, if set to a non-zero value, becomes the result
|
|
575 |
** returned from sqlite3OsCurrentTime(). This is used for testing.
|
|
576 |
*/
|
|
577 |
#ifdef SQLITE_TEST
|
|
578 |
int sqlite3_current_time = 0;
|
|
579 |
#endif
|
|
580 |
|
|
581 |
/*
|
|
582 |
** Find the current time (in Universal Coordinated Time). Write the
|
|
583 |
** current time and date as a Julian Day number into *prNow and
|
|
584 |
** return 0. Return 1 if the time and date cannot be found.
|
|
585 |
*/
|
|
586 |
int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
|
|
587 |
double now;
|
|
588 |
|
|
589 |
now = time(NULL);
|
|
590 |
*prNow = now;
|
|
591 |
|
|
592 |
return 0;
|
|
593 |
}
|
|
594 |
|
|
595 |
|
|
596 |
/*
|
|
597 |
** Return a pointer to the sqlite3DefaultVfs structure. We use
|
|
598 |
** a function rather than give the structure global scope because
|
|
599 |
** some compilers (MSVC) do not allow forward declarations of
|
|
600 |
** initialized structures.
|
|
601 |
*/
|
|
602 |
sqlite3_vfs *sqlite3OsDefaultVfs(void){
|
|
603 |
static sqlite3_vfs winVfs = {
|
|
604 |
1, /* iVersion */
|
|
605 |
-1, /* szOsFile */
|
|
606 |
MAX_PATH, /* mxPathname */
|
|
607 |
0, /* pNext */
|
|
608 |
"symbian", /* zName */
|
|
609 |
0, /* pAppData */
|
|
610 |
};
|
|
611 |
|
|
612 |
winVfs.szOsFile = sizeof(symbianFile);
|
|
613 |
return &winVfs;
|
|
614 |
}
|
|
615 |
|
|
616 |
#endif /* OS_SYMBIAN */
|