Subversion Repositories Kolibri OS

Rev

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 */