Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #if !defined(SQLITE_TEST) || _KOLIBRI
  2.  
  3. #include "sqlite3.h"
  4.  
  5. #include <assert.h>
  6. #include <string.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <sys/file.h>
  10. #include <sys/param.h>
  11. #include <unistd.h>
  12. #include <time.h>
  13. #include <errno.h>
  14. #include <fcntl.h>
  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<iAmt ){
  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 */
  609.