Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8931 | turbocat | 1 | #if !defined(SQLITE_TEST) || _KOLIBRI |
2 | |||
3 | #include "sqlite3.h" |
||
4 | |||
5 | #include |
||
6 | #include |
||
7 | #include |
||
8 | #include |
||
9 | #include |
||
10 | #include |
||
11 | #include |
||
12 | #include |
||
13 | #include |
||
14 | #include |
||
15 | |||
16 | /* |
||
17 | ** Size of the write buffer used by journal files in bytes. |
||
18 | */ |
||
19 | #ifndef SQLITE_DEMOVFS_BUFFERSZ |
||
20 | # define SQLITE_DEMOVFS_BUFFERSZ 8192 |
||
21 | #endif |
||
22 | |||
23 | /* |
||
24 | ** The maximum pathname length supported by this VFS. |
||
25 | */ |
||
26 | #define MAXPATHNAME 512 |
||
27 | |||
28 | sqlite3_vfs *sqlite3_kosvfs(void); |
||
29 | |||
30 | /* |
||
31 | ** When using this VFS, the sqlite3_file* handles that SQLite uses are |
||
32 | ** actually pointers to instances of type KosFile. |
||
33 | */ |
||
34 | typedef struct KosFile KosFile; |
||
35 | struct KosFile { |
||
36 | sqlite3_file base; /* Base class. Must be first. */ |
||
37 | int fd; /* File descriptor */ |
||
38 | |||
39 | char *aBuffer; /* Pointer to malloc'd buffer */ |
||
40 | int nBuffer; /* Valid bytes of data in zBuffer */ |
||
41 | sqlite3_int64 iBufferOfst; /* Offset in file of zBuffer[0] */ |
||
42 | }; |
||
43 | |||
44 | /* |
||
45 | ** Write directly to the file passed as the first argument. Even if the |
||
46 | ** file has a write-buffer (KosFile.aBuffer), ignore it. |
||
47 | */ |
||
48 | static int kosDirectWrite( |
||
49 | KosFile *p, /* File handle */ |
||
50 | const void *zBuf, /* Buffer containing data to write */ |
||
51 | int iAmt, /* Size of data to write in bytes */ |
||
52 | sqlite_int64 iOfst /* File offset to write to */ |
||
53 | ){ |
||
54 | off_t ofst; /* Return value from lseek() */ |
||
55 | size_t nWrite; /* Return value from write() */ |
||
56 | |||
57 | ofst = lseek(p->fd, iOfst, SEEK_SET); |
||
58 | if( ofst!=iOfst ){ |
||
59 | return SQLITE_IOERR_WRITE; |
||
60 | } |
||
61 | |||
62 | nWrite = write(p->fd, zBuf, iAmt); |
||
63 | if( nWrite!=iAmt ){ |
||
64 | return SQLITE_IOERR_WRITE; |
||
65 | } |
||
66 | |||
67 | return SQLITE_OK; |
||
68 | } |
||
69 | |||
70 | /* |
||
71 | ** Flush the contents of the KosFile.aBuffer buffer to disk. This is a |
||
72 | ** no-op if this particular file does not have a buffer (i.e. it is not |
||
73 | ** a journal file) or if the buffer is currently empty. |
||
74 | */ |
||
75 | |||
76 | int sqlite3_os_init(){ |
||
77 | return sqlite3_vfs_register(sqlite3_kosvfs(), 0); |
||
78 | } |
||
79 | |||
80 | static int kosFlushBuffer(KosFile *p){ |
||
81 | int rc = SQLITE_OK; |
||
82 | if( p->nBuffer ){ |
||
83 | rc = kosDirectWrite(p, p->aBuffer, p->nBuffer, p->iBufferOfst); |
||
84 | p->nBuffer = 0; |
||
85 | } |
||
86 | return rc; |
||
87 | } |
||
88 | |||
89 | /* |
||
90 | ** Close a file. |
||
91 | */ |
||
92 | static int kosClose(sqlite3_file *pFile){ |
||
93 | int rc; |
||
94 | KosFile *p = (KosFile*)pFile; |
||
95 | rc = kosFlushBuffer(p); |
||
96 | sqlite3_free(p->aBuffer); |
||
97 | close(p->fd); |
||
98 | return rc; |
||
99 | } |
||
100 | |||
101 | /* |
||
102 | ** Read data from a file. |
||
103 | */ |
||
104 | static int kosRead( |
||
105 | sqlite3_file *pFile, |
||
106 | void *zBuf, |
||
107 | int iAmt, |
||
108 | sqlite_int64 iOfst |
||
109 | ){ |
||
110 | KosFile *p = (KosFile*)pFile; |
||
111 | off_t ofst; /* Return value from lseek() */ |
||
112 | int nRead; /* Return value from read() */ |
||
113 | int rc; /* Return code from kosFlushBuffer() */ |
||
114 | |||
115 | /* Flush any data in the write buffer to disk in case this operation |
||
116 | ** is trying to read data the file-region currently cached in the buffer. |
||
117 | ** It would be possible to detect this case and possibly save an |
||
118 | ** unnecessary write here, but in practice SQLite will rarely read from |
||
119 | ** a journal file when there is data cached in the write-buffer. |
||
120 | */ |
||
121 | rc = kosFlushBuffer(p); |
||
122 | if( rc!=SQLITE_OK ){ |
||
123 | return rc; |
||
124 | } |
||
125 | |||
126 | ofst = lseek(p->fd, iOfst, SEEK_SET); |
||
127 | if( ofst!=iOfst ){ |
||
128 | return SQLITE_IOERR_READ; |
||
129 | } |
||
130 | nRead = read(p->fd, zBuf, iAmt); |
||
131 | |||
132 | if( nRead==iAmt ){ |
||
133 | return SQLITE_OK; |
||
134 | }else if( nRead>=0 ){ |
||
135 | if( nRead |
||
136 | memset(&((char*)zBuf)[nRead], 0, iAmt-nRead); |
||
137 | } |
||
138 | return SQLITE_IOERR_SHORT_READ; |
||
139 | } |
||
140 | |||
141 | return SQLITE_IOERR_READ; |
||
142 | } |
||
143 | |||
144 | /* |
||
145 | ** Write data to a crash-file. |
||
146 | */ |
||
147 | static int kosWrite( |
||
148 | sqlite3_file *pFile, |
||
149 | const void *zBuf, |
||
150 | int iAmt, |
||
151 | sqlite_int64 iOfst |
||
152 | ){ |
||
153 | KosFile *p = (KosFile*)pFile; |
||
154 | |||
155 | if( p->aBuffer ){ |
||
156 | char *z = (char *)zBuf; /* Pointer to remaining data to write */ |
||
157 | int n = iAmt; /* Number of bytes at z */ |
||
158 | sqlite3_int64 i = iOfst; /* File offset to write to */ |
||
159 | |||
160 | while( n>0 ){ |
||
161 | int nCopy; /* Number of bytes to copy into buffer */ |
||
162 | |||
163 | /* If the buffer is full, or if this data is not being written directly |
||
164 | ** following the data already buffered, flush the buffer. Flushing |
||
165 | ** the buffer is a no-op if it is empty. |
||
166 | */ |
||
167 | if( p->nBuffer==SQLITE_DEMOVFS_BUFFERSZ || p->iBufferOfst+p->nBuffer!=i ){ |
||
168 | int rc = kosFlushBuffer(p); |
||
169 | if( rc!=SQLITE_OK ){ |
||
170 | return rc; |
||
171 | } |
||
172 | } |
||
173 | assert( p->nBuffer==0 || p->iBufferOfst+p->nBuffer==i ); |
||
174 | p->iBufferOfst = i - p->nBuffer; |
||
175 | |||
176 | /* Copy as much data as possible into the buffer. */ |
||
177 | nCopy = SQLITE_DEMOVFS_BUFFERSZ - p->nBuffer; |
||
178 | if( nCopy>n ){ |
||
179 | nCopy = n; |
||
180 | } |
||
181 | memcpy(&p->aBuffer[p->nBuffer], z, nCopy); |
||
182 | p->nBuffer += nCopy; |
||
183 | |||
184 | n -= nCopy; |
||
185 | i += nCopy; |
||
186 | z += nCopy; |
||
187 | } |
||
188 | }else{ |
||
189 | return kosDirectWrite(p, zBuf, iAmt, iOfst); |
||
190 | } |
||
191 | |||
192 | return SQLITE_OK; |
||
193 | } |
||
194 | |||
195 | /* |
||
196 | ** Truncate a file. This is a no-op for this VFS (see header comments at |
||
197 | ** the top of the file). |
||
198 | */ |
||
199 | static int kosTruncate(sqlite3_file *pFile, sqlite_int64 size){ |
||
200 | #if 0 |
||
201 | if( ftruncate(((KosFile *)pFile)->fd, size) ) return SQLITE_IOERR_TRUNCATE; |
||
202 | #endif |
||
203 | return SQLITE_OK; |
||
204 | } |
||
205 | |||
206 | /* |
||
207 | ** Sync the contents of the file to the persistent media. |
||
208 | */ |
||
209 | static int kosSync(sqlite3_file *pFile, int flags){ |
||
210 | KosFile *p = (KosFile*)pFile; |
||
211 | int rc; |
||
212 | |||
213 | rc = kosFlushBuffer(p); |
||
214 | if( rc!=SQLITE_OK ){ |
||
215 | return rc; |
||
216 | } |
||
217 | |||
218 | rc = fsync(p->fd); |
||
219 | return (rc==0 ? SQLITE_OK : SQLITE_IOERR_FSYNC); |
||
220 | } |
||
221 | |||
222 | /* |
||
223 | ** Write the size of the file in bytes to *pSize. |
||
224 | */ |
||
225 | static int kosFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ |
||
226 | KosFile *p = (KosFile*)pFile; |
||
227 | int rc; /* Return code from fstat() call */ |
||
228 | struct stat sStat; /* Output of fstat() call */ |
||
229 | |||
230 | /* Flush the contents of the buffer to disk. As with the flush in the |
||
231 | ** kosRead() method, it would be possible to avoid this and save a write |
||
232 | ** here and there. But in practice this comes up so infrequently it is |
||
233 | ** not worth the trouble. |
||
234 | */ |
||
235 | rc = kosFlushBuffer(p); |
||
236 | if( rc!=SQLITE_OK ){ |
||
237 | return rc; |
||
238 | } |
||
239 | |||
240 | rc = fstat(p->fd, &sStat); |
||
241 | if( rc!=0 ) return SQLITE_IOERR_FSTAT; |
||
242 | *pSize = sStat.st_size; |
||
243 | return SQLITE_OK; |
||
244 | } |
||
245 | |||
246 | /* |
||
247 | ** Locking functions. The xLock() and xUnlock() methods are both no-ops. |
||
248 | ** The xCheckReservedLock() always indicates that no other process holds |
||
249 | ** a reserved lock on the database file. This ensures that if a hot-journal |
||
250 | ** file is found in the file-system it is rolled back. |
||
251 | */ |
||
252 | static int kosLock(sqlite3_file *pFile, int eLock){ |
||
253 | return SQLITE_OK; |
||
254 | } |
||
255 | static int kosUnlock(sqlite3_file *pFile, int eLock){ |
||
256 | return SQLITE_OK; |
||
257 | } |
||
258 | static int kosCheckReservedLock(sqlite3_file *pFile, int *pResOut){ |
||
259 | *pResOut = 0; |
||
260 | return SQLITE_OK; |
||
261 | } |
||
262 | |||
263 | /* |
||
264 | ** No xFileControl() verbs are implemented by this VFS. |
||
265 | */ |
||
266 | static int kosFileControl(sqlite3_file *pFile, int op, void *pArg){ |
||
267 | return SQLITE_NOTFOUND; |
||
268 | } |
||
269 | |||
270 | /* |
||
271 | ** The xSectorSize() and xDeviceCharacteristics() methods. These two |
||
272 | ** may return special values allowing SQLite to optimize file-system |
||
273 | ** access to some extent. But it is also safe to simply return 0. |
||
274 | */ |
||
275 | static int kosSectorSize(sqlite3_file *pFile){ |
||
276 | return 0; |
||
277 | } |
||
278 | static int kosDeviceCharacteristics(sqlite3_file *pFile){ |
||
279 | return 0; |
||
280 | } |
||
281 | |||
282 | /* |
||
283 | ** Open a file handle. |
||
284 | */ |
||
285 | static int kosOpen( |
||
286 | sqlite3_vfs *pVfs, /* VFS */ |
||
287 | const char *zName, /* File to open, or 0 for a temp file */ |
||
288 | sqlite3_file *pFile, /* Pointer to KosFile struct to populate */ |
||
289 | int flags, /* Input SQLITE_OPEN_XXX flags */ |
||
290 | int *pOutFlags /* Output SQLITE_OPEN_XXX flags (or NULL) */ |
||
291 | ){ |
||
292 | static const sqlite3_io_methods kosio = { |
||
293 | 1, /* iVersion */ |
||
294 | kosClose, /* xClose */ |
||
295 | kosRead, /* xRead */ |
||
296 | kosWrite, /* xWrite */ |
||
297 | kosTruncate, /* xTruncate */ |
||
298 | kosSync, /* xSync */ |
||
299 | kosFileSize, /* xFileSize */ |
||
300 | kosLock, /* xLock */ |
||
301 | kosUnlock, /* xUnlock */ |
||
302 | kosCheckReservedLock, /* xCheckReservedLock */ |
||
303 | kosFileControl, /* xFileControl */ |
||
304 | kosSectorSize, /* xSectorSize */ |
||
305 | kosDeviceCharacteristics /* xDeviceCharacteristics */ |
||
306 | }; |
||
307 | |||
308 | KosFile *p = (KosFile*)pFile; /* Populate this structure */ |
||
309 | int oflags = 0; /* flags to pass to open() call */ |
||
310 | char *aBuf = 0; |
||
311 | |||
312 | if( zName==0 ){ |
||
313 | return SQLITE_IOERR; |
||
314 | } |
||
315 | |||
316 | if( flags&SQLITE_OPEN_MAIN_JOURNAL ){ |
||
317 | aBuf = (char *)sqlite3_malloc(SQLITE_DEMOVFS_BUFFERSZ); |
||
318 | if( !aBuf ){ |
||
319 | return SQLITE_NOMEM; |
||
320 | } |
||
321 | } |
||
322 | |||
323 | if( flags&SQLITE_OPEN_EXCLUSIVE ) oflags |= O_EXCL; |
||
324 | if( flags&SQLITE_OPEN_CREATE ) oflags |= O_CREAT; |
||
325 | if( flags&SQLITE_OPEN_READONLY ) oflags |= O_RDONLY; |
||
326 | if( flags&SQLITE_OPEN_READWRITE ) oflags |= O_RDWR; |
||
327 | |||
328 | memset(p, 0, sizeof(KosFile)); |
||
329 | p->fd = open(zName, oflags, 0600); |
||
330 | if( p->fd<0 ){ |
||
331 | sqlite3_free(aBuf); |
||
332 | return SQLITE_CANTOPEN; |
||
333 | } |
||
334 | p->aBuffer = aBuf; |
||
335 | |||
336 | if( pOutFlags ){ |
||
337 | *pOutFlags = flags; |
||
338 | } |
||
339 | p->base.pMethods = &kosio; |
||
340 | return SQLITE_OK; |
||
341 | } |
||
342 | |||
343 | /* |
||
344 | ** Delete the file identified by argument zPath. If the dirSync parameter |
||
345 | ** is non-zero, then ensure the file-system modification to delete the |
||
346 | ** file has been synced to disk before returning. |
||
347 | */ |
||
348 | static int kosDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
||
349 | int rc; /* Return code */ |
||
350 | |||
351 | rc = unlink(zPath); |
||
352 | if( rc!=0 && errno==ENOENT ) return SQLITE_OK; |
||
353 | |||
354 | if( rc==0 && dirSync ){ |
||
355 | int dfd; /* File descriptor open on directory */ |
||
356 | int i; /* Iterator variable */ |
||
357 | char zDir[MAXPATHNAME+1]; /* Name of directory containing file zPath */ |
||
358 | |||
359 | /* Figure out the directory name from the path of the file deleted. */ |
||
360 | sqlite3_snprintf(MAXPATHNAME, zDir, "%s", zPath); |
||
361 | zDir[MAXPATHNAME] = '\0'; |
||
362 | for(i=strlen(zDir); i>1 && zDir[i]!='/'; i++); |
||
363 | zDir[i] = '\0'; |
||
364 | |||
365 | /* Open a file-descriptor on the directory. Sync. Close. */ |
||
366 | dfd = open(zDir, O_RDONLY, 0); |
||
367 | if( dfd<0 ){ |
||
368 | rc = -1; |
||
369 | }else{ |
||
370 | rc = fsync(dfd); |
||
371 | close(dfd); |
||
372 | } |
||
373 | } |
||
374 | return (rc==0 ? SQLITE_OK : SQLITE_IOERR_DELETE); |
||
375 | } |
||
376 | |||
377 | #ifndef F_OK |
||
378 | # define F_OK 0 |
||
379 | #endif |
||
380 | #ifndef R_OK |
||
381 | # define R_OK 4 |
||
382 | #endif |
||
383 | #ifndef W_OK |
||
384 | # define W_OK 2 |
||
385 | #endif |
||
386 | |||
387 | /* |
||
388 | ** Query the file-system to see if the named file exists, is readable or |
||
389 | ** is both readable and writable. |
||
390 | */ |
||
391 | static int kosAccess( |
||
392 | sqlite3_vfs *pVfs, |
||
393 | const char *zPath, |
||
394 | int flags, |
||
395 | int *pResOut |
||
396 | ){ |
||
397 | int rc; /* access() return code */ |
||
398 | int eAccess = F_OK; /* Second argument to access() */ |
||
399 | |||
400 | assert( flags==SQLITE_ACCESS_EXISTS /* access(zPath, F_OK) */ |
||
401 | || flags==SQLITE_ACCESS_READ /* access(zPath, R_OK) */ |
||
402 | || flags==SQLITE_ACCESS_READWRITE /* access(zPath, R_OK|W_OK) */ |
||
403 | ); |
||
404 | |||
405 | if( flags==SQLITE_ACCESS_READWRITE ) eAccess = R_OK|W_OK; |
||
406 | if( flags==SQLITE_ACCESS_READ ) eAccess = R_OK; |
||
407 | |||
408 | rc = access(zPath, eAccess); |
||
409 | *pResOut = (rc==0); |
||
410 | return SQLITE_OK; |
||
411 | } |
||
412 | |||
413 | /* |
||
414 | ** Argument zPath points to a nul-terminated string containing a file path. |
||
415 | ** If zPath is an absolute path, then it is copied as is into the output |
||
416 | ** buffer. Otherwise, if it is a relative path, then the equivalent full |
||
417 | ** path is written to the output buffer. |
||
418 | ** |
||
419 | ** This function assumes that paths are UNIX style. Specifically, that: |
||
420 | ** |
||
421 | ** 1. Path components are separated by a '/'. and |
||
422 | ** 2. Full paths begin with a '/' character. |
||
423 | */ |
||
424 | static int kosFullPathname( |
||
425 | sqlite3_vfs *pVfs, /* VFS */ |
||
426 | const char *zPath, /* Input path (possibly a relative path) */ |
||
427 | int nPathOut, /* Size of output buffer in bytes */ |
||
428 | char *zPathOut /* Pointer to output buffer */ |
||
429 | ){ |
||
430 | char zDir[MAXPATHNAME+1]; |
||
431 | if( zPath[0]=='/' ){ |
||
432 | zDir[0] = '\0'; |
||
433 | }else{ |
||
434 | if( getcwd(zDir, sizeof(zDir))==0 ) return SQLITE_IOERR; |
||
435 | } |
||
436 | zDir[MAXPATHNAME] = '\0'; |
||
437 | |||
438 | sqlite3_snprintf(nPathOut, zPathOut, "%s/%s", zDir, zPath); |
||
439 | zPathOut[nPathOut-1] = '\0'; |
||
440 | |||
441 | return SQLITE_OK; |
||
442 | } |
||
443 | |||
444 | /* |
||
445 | ** The following four VFS methods: |
||
446 | ** |
||
447 | ** xDlOpen |
||
448 | ** xDlError |
||
449 | ** xDlSym |
||
450 | ** xDlClose |
||
451 | ** |
||
452 | ** are supposed to implement the functionality needed by SQLite to load |
||
453 | ** extensions compiled as shared objects. This simple VFS does not support |
||
454 | ** this functionality, so the following functions are no-ops. |
||
455 | */ |
||
456 | static void *kosDlOpen(sqlite3_vfs *pVfs, const char *zPath){ |
||
457 | return 0; |
||
458 | } |
||
459 | static void kosDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ |
||
460 | sqlite3_snprintf(nByte, zErrMsg, "Loadable extensions are not supported"); |
||
461 | zErrMsg[nByte-1] = '\0'; |
||
462 | } |
||
463 | static void (*kosDlSym(sqlite3_vfs *pVfs, void *pH, const char *z))(void){ |
||
464 | return 0; |
||
465 | } |
||
466 | static void kosDlClose(sqlite3_vfs *pVfs, void *pHandle){ |
||
467 | return; |
||
468 | } |
||
469 | |||
470 | /* |
||
471 | ** Parameter zByte points to a buffer nByte bytes in size. Populate this |
||
472 | ** buffer with pseudo-random data. |
||
473 | */ |
||
474 | static int kosRandomness(sqlite3_vfs *pVfs, int nByte, char *zByte){ |
||
475 | return SQLITE_OK; |
||
476 | } |
||
477 | |||
478 | /* |
||
479 | ** Sleep for at least nMicro microseconds. Return the (approximate) number |
||
480 | ** of microseconds slept for. |
||
481 | */ |
||
482 | static int kosSleep(sqlite3_vfs *pVfs, int nMicro){ |
||
483 | sleep(nMicro / 1000000); |
||
484 | usleep(nMicro % 1000000); |
||
485 | return nMicro; |
||
486 | } |
||
487 | |||
488 | /* |
||
489 | ** Set *pTime to the current UTC time expressed as a Julian day. Return |
||
490 | ** SQLITE_OK if successful, or an error code otherwise. |
||
491 | ** |
||
492 | ** http://en.wikipedia.org/wiki/Julian_day |
||
493 | ** |
||
494 | ** This implementation is not very good. The current time is rounded to |
||
495 | ** an integer number of seconds. Also, assuming time_t is a signed 32-bit |
||
496 | ** value, it will stop working some time in the year 2038 AD (the so-called |
||
497 | ** "year 2038" problem that afflicts systems that store time this way). |
||
498 | */ |
||
499 | static int kosCurrentTime(sqlite3_vfs *pVfs, double *pTime){ |
||
500 | time_t t = time(0); |
||
501 | *pTime = t/86400.0 + 2440587.5; |
||
502 | return SQLITE_OK; |
||
503 | } |
||
504 | |||
505 | /* |
||
506 | ** This function returns a pointer to the VFS implemented in this file. |
||
507 | ** To make the VFS available to SQLite: |
||
508 | ** |
||
509 | ** sqlite3_vfs_register(sqlite3_kosvfs(), 0); |
||
510 | */ |
||
511 | sqlite3_vfs *sqlite3_kosvfs(void){ |
||
512 | static sqlite3_vfs kosvfs = { |
||
513 | 1, /* iVersion */ |
||
514 | sizeof(KosFile), /* szOsFile */ |
||
515 | MAXPATHNAME, /* mxPathname */ |
||
516 | 0, /* pNext */ |
||
517 | "kos", /* zName */ |
||
518 | 0, /* pAppData */ |
||
519 | kosOpen, /* xOpen */ |
||
520 | kosDelete, /* xDelete */ |
||
521 | kosAccess, /* xAccess */ |
||
522 | kosFullPathname, /* xFullPathname */ |
||
523 | kosDlOpen, /* xDlOpen */ |
||
524 | kosDlError, /* xDlError */ |
||
525 | kosDlSym, /* xDlSym */ |
||
526 | kosDlClose, /* xDlClose */ |
||
527 | kosRandomness, /* xRandomness */ |
||
528 | kosSleep, /* xSleep */ |
||
529 | kosCurrentTime, /* xCurrentTime */ |
||
530 | }; |
||
531 | return &kosvfs; |
||
532 | } |
||
533 | |||
534 | SQLITE_API int sqlite3_os_end(void){ |
||
535 | return SQLITE_OK; |
||
536 | } |
||
537 | |||
538 | void _ksys_sleep(unsigned time) |
||
539 | { |
||
540 | __asm__ __volatile__( |
||
541 | "int $0x40" |
||
542 | ::"a"(5), "b"(time) |
||
543 | :"memory"); |
||
544 | }; |
||
545 | |||
546 | unsigned sleep(unsigned time){ |
||
547 | _ksys_sleep(time*100); |
||
548 | return 0; |
||
549 | } |
||
550 | |||
551 | int usleep(useconds_t usec){ |
||
552 | _ksys_sleep(usec); |
||
553 | return 0; |
||
554 | } |
||
555 | |||
556 | int fsync(int fd){ |
||
557 | return 0; |
||
558 | } |
||
559 | |||
560 | |||
561 | #endif /* !defined(SQLITE_TEST) || SQLITE_OS_UNIX */ |
||
562 | |||
563 | |||
564 | #ifdef SQLITE_TEST |
||
565 | |||
566 | #if defined(INCLUDE_SQLITE_TCL_H) |
||
567 | # include "sqlite_tcl.h" |
||
568 | #else |
||
569 | # include "tcl.h" |
||
570 | # ifndef SQLITE_TCLAPI |
||
571 | # define SQLITE_TCLAPI |
||
572 | # endif |
||
573 | #endif |
||
574 | |||
575 | #if SQLITE_OS_UNIX |
||
576 | static int SQLITE_TCLAPI register_kosvfs( |
||
577 | ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |
||
578 | Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ |
||
579 | int objc, /* Number of arguments */ |
||
580 | Tcl_Obj *CONST objv[] /* Command arguments */ |
||
581 | ){ |
||
582 | sqlite3_vfs_register(sqlite3_kosvfs(), 1); |
||
583 | return TCL_OK; |
||
584 | } |
||
585 | static int SQLITE_TCLAPI unregister_kosvfs( |
||
586 | ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |
||
587 | Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ |
||
588 | int objc, /* Number of arguments */ |
||
589 | Tcl_Obj *CONST objv[] /* Command arguments */ |
||
590 | ){ |
||
591 | sqlite3_vfs_unregister(sqlite3_kosvfs()); |
||
592 | return TCL_OK; |
||
593 | } |
||
594 | |||
595 | /* |
||
596 | ** Register commands with the TCL interpreter. |
||
597 | */ |
||
598 | int Sqlitetest_kosvfs_Init(Tcl_Interp *interp){ |
||
599 | Tcl_CreateObjCommand(interp, "register_kosvfs", register_kosvfs, 0, 0); |
||
600 | Tcl_CreateObjCommand(interp, "unregister_kosvfs", unregister_kosvfs, 0, 0); |
||
601 | return TCL_OK; |
||
602 | } |
||
603 | |||
604 | #else |
||
605 | int Sqlitetest_kosvfs_Init(Tcl_Interp *interp){ return TCL_OK; } |
||
606 | #endif |
||
607 | |||
608 | #endif /* SQLITE_TEST */0>0> |