/ Check-in [8936542b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add a prototype implementation of stdio-like routines for accessing the VFS. This is intended as documentation. The code is untested. There is no guarantee that any of this will ever make it into trunk. Substantial revision is possible prior to reaching trunk, if it ever does.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | vfs-stdio
Files: files | file ages | folders
SHA1: 8936542b225836f5f4a789e1ecc1451f6a1e120d
User & Date: drh 2011-12-01 02:32:12
Context
2011-12-01
02:32
Add a prototype implementation of stdio-like routines for accessing the VFS. This is intended as documentation. The code is untested. There is no guarantee that any of this will ever make it into trunk. Substantial revision is possible prior to reaching trunk, if it ever does. Closed-Leaf check-in: 8936542b user: drh tags: vfs-stdio
2011-11-29
15:40
Remove unused fields from the Parse object. Documentation and formatting improvements on data structure definitions. check-in: 431556ca user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os.c.

336
337
338
339
340
341
342








































































































































































































































  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  sqlite3_mutex_enter(mutex);
  vfsUnlink(pVfs);
  sqlite3_mutex_leave(mutex);
  return SQLITE_OK;
}















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  sqlite3_mutex_enter(mutex);
  vfsUnlink(pVfs);
  sqlite3_mutex_leave(mutex);
  return SQLITE_OK;
}

#ifndef SQLITE_OMIT_VFS_STDIO
/*****************************************************************************
** The remainder of this file contains a simplified stdio-like interface
** to the VFS layer.
*/

/*
** An instance of the following object records the state of an
** open file.  This object is opaque to all users - the internal
** structure is only visible to the functions below.
*/
struct sqlite3_FILE {
  char *zFilename;        /* Full pathname of the open file */
  sqlite3_int64 iOfst;    /* Current offset into the file */
  sqlite3_vfs *pVfs;      /* The VFS used for this file */
  u8 alwaysAppend;        /* Always append if true */
  sqlite3_file sFile;     /* Open file.  MUST BE LAST */
};

/*
** This is a helper routine used to translate a URI into a full pathname
** and a pointer to the appropriate VFS.
*/
static int getFilename(const char *zURI, sqlite3_vfs **ppVfs, char **pzName){
  int rc;
  char *zOpen = 0;
  char *zFullname = 0;
  unsigned int flags;
  char *zErrmsg = 0;
  sqlite3_vfs *pVfs = 0;

  rc = sqlite3ParseUri(0, zURI, &flags, &pVfs, &zOpen, &zErrmsg);
  sqlite3_free(zErrmsg);
  if( rc ) goto getFilename_error;
  zFullname = sqlite3_malloc( pVfs->mxPathname+1 );
  if( zFullname==0 ){ rc = SQLITE_NOMEM;  goto getFilename_error; }
  rc = pVfs->xFullPathname(pVfs, zOpen, pVfs->mxPathname, zFullname);
  if( rc ) goto getFilename_error;
  sqlite3_free(zOpen);
  zOpen = 0;
  *pzName = sqlite3_realloc(zFullname, sqlite3Strlen30(zFullname)+1);
  if( *pzName==0 ) goto getFilename_error;
  zFullname = 0;
  *ppVfs = pVfs;
  return SQLITE_OK;

getFilename_error:
  sqlite3_free(zOpen);
  sqlite3_free(zFullname);
  *pzName = 0;
  *ppVfs = 0;
  return rc;
}

/*
** Open a file for stdio-like reading and writing.  The file is identified
** by the URI in the first parameter.  The access mode can be "r", "r+",
** "w", "w+", "a", or "a+" with the usual meanings.
**
** On success, a pointer to a new sqlite3_FILE object is returned.  On
** failure, NULL is returned.  Unfortunately, there is no way to recover
** detailed error information after a failure.
*/
sqlite3_FILE *sqlite3_fopen(const char *zURI, const char *zMode){
  char *zFile = 0;
  sqlite3_vfs *pVfs = 0;
  int rc;
  int openFlags;
  int doTruncate = 0;
  int seekEnd = 0;
  int alwaysAppend = 0;
  int nToAlloc;
  sqlite3_FILE *p;

  if( zMode[0]==0 ) return 0;
  if( zMode[0]=='r' ){
    if( zMode[1]=='+' ){
      openFlags = SQLITE_OPEN_READWRITE;
    }else{
      openFlags = SQLITE_OPEN_READONLY;
    }
  }else if( zMode[0]=='w' ){
    openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
    doTruncate = 1;
  }else if( zMode[0]=='a' ){
    openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
    if( zMode[1]=='+' ){
      alwaysAppend = 1;
    }else{
      seekEnd = 1;
    }
  }else{
    return 0;
  }
  rc = getFilename(zURI, &pVfs, &zFile);
  if( rc ) return 0;
  nToAlloc = sizeof(*p) + ROUND8(pVfs->szOsFile);
  p = sqlite3_malloc( nToAlloc );
  if( p==0 ){
    sqlite3_free(zFile);
    return 0;
  }
  memset(p, 0, nToAlloc);
  p->zFilename = zFile;
  rc = pVfs->xOpen(pVfs, zFile, &p->sFile, openFlags, &openFlags);
  if( rc!=SQLITE_OK ){
    sqlite3_free(zFile);
    sqlite3_free(p);
    return 0;
  }
  p->pVfs = pVfs;
  p->alwaysAppend = alwaysAppend;
  if( seekEnd ) sqlite3_fseek(p, 0, SQLITE_SEEK_END);
  if( doTruncate ) sqlite3_ftruncate(p, 0);
  return p;
}

/*
** Close a file perviously opened by sqlite3_fopen().
*/
int sqlite3_fclose(sqlite3_FILE *p){
  p->sFile.pMethods->xClose(&p->sFile);
  sqlite3_free(p);
  return SQLITE_OK;
}

/*
** Read iAmt bytes from the file p into pBuf.  
**
** Return 0 on success or an error code if the full amount could
** not be read.
*/
int sqlite3_fread(
  void *pBuf,            /* Write content read into this buffer */
  sqlite3_int64 iAmt,    /* Number of bytes to read */
  sqlite3_FILE *p        /* Read from this file */
){
  int rc = p->sFile.pMethods->xRead(&p->sFile, pBuf, iAmt, p->iOfst);
  if( rc==SQLITE_OK ){
    p->iOfst += iAmt;
  }
  return rc;
}

/*
** Write iAmt bytes from buffer pBuf into the file p.
**
** Return 0 on success or an error code if anything goes wrong.
*/
int sqlite3_fwrite(
  const void *pBuf,      /* Take content to be written from this buffer */
  sqlite3_int64 iAmt,    /* Number of bytes to write */
  sqlite3_FILE *p        /* Write into this file */
){
  int rc;

  if( p->alwaysAppend ) sqlite3_fseek(p, 0, SQLITE_SEEK_END);
  rc = p->sFile.pMethods->xWrite(&p->sFile, pBuf, iAmt, p->iOfst);
  if( rc==SQLITE_OK ){
    p->iOfst += iAmt;
  }
  return rc;
}

/*
** Truncate an open file to newSize bytes.
*/
int sqlite3_ftruncate(sqlite3_FILE *p, sqlite3_int64 newSize){
  int rc;
  rc = p->sFile.pMethods->xTruncate(&p->sFile, newSize);
  return rc;
}

/*
** Return the current position of the file pointer.
*/
sqlite3_int64 sqlite3_ftell(sqlite3_FILE *p){
  return p->iOfst;
}

/*
** Move the file pointer to a new position in the file.
*/
int sqlite3_fseek(sqlite3_FILE *p, sqlite3_int64 ofst, int whence){
  int rc = SQLITE_OK;
  if( whence==SQLITE_SEEK_SET ){
    p->iOfst = ofst;
  }else if( whence==SQLITE_SEEK_CUR ){
    p->iOfst += ofst;
  }else{
    sqlite3_int64 iCur = 0;
    rc = p->sFile.pMethods->xFileSize(&p->sFile, &iCur);
    if( rc==SQLITE_OK ){
      p->iOfst = iCur + ofst;
    }
  }
  return rc;
}

/*
** Rewind the file pointer to the beginning of the file.
*/
int sqlite3_rewind(sqlite3_FILE *p){
  p->iOfst = 0;
  return SQLITE_OK;
}

/*
** Flush the content of OS cache buffers to disk.  (fsync())
*/
int sqlite3_fflush(sqlite3_FILE *p){
  return p->sFile.pMethods->xSync(&p->sFile, SQLITE_SYNC_NORMAL);
}

/*
** Delete the file identified by the URI in the first parameter
*/
int sqlite3_remove(const char *zURI){
  sqlite3_vfs *pVfs = 0;
  char *zFilename = 0;
  int rc;

  rc = getFilename(zURI, &pVfs, &zFilename);
  if( rc==SQLITE_OK ){
    rc = pVfs->xDelete(pVfs, zFilename, 0);
  }
  sqlite3_free(zFilename);
  return rc;
}

#endif /* SQLITE_OMIT_VFS_STDIO */

Changes to src/sqlite.h.in.

568
569
570
571
572
573
574




575
576
577
578
579
580
581
....
6819
6820
6821
6822
6823
6824
6825















































6826














































































































































6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
** An [sqlite3_file] object represents an open file in the 
** [sqlite3_vfs | OS interface layer].  Individual OS interface
** implementations will
** want to subclass this object by appending additional fields
** for their own use.  The pMethods entry is a pointer to an
** [sqlite3_io_methods] object that defines methods for performing
** I/O operations on the open file.




*/
typedef struct sqlite3_file sqlite3_file;
struct sqlite3_file {
  const struct sqlite3_io_methods *pMethods;  /* Methods for an open file */
};

/*
................................................................................
*/
#define SQLITE_ROLLBACK 1
/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
#define SQLITE_FAIL     3
/* #define SQLITE_ABORT 4  // Also an error code */
#define SQLITE_REPLACE  5
































































































































































































/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
*/
#ifdef SQLITE_OMIT_FLOATING_POINT
# undef double
#endif

#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif







>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
....
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
** An [sqlite3_file] object represents an open file in the 
** [sqlite3_vfs | OS interface layer].  Individual OS interface
** implementations will
** want to subclass this object by appending additional fields
** for their own use.  The pMethods entry is a pointer to an
** [sqlite3_io_methods] object that defines methods for performing
** I/O operations on the open file.
**
** Do not confuse the low-level sqlite3_file object described here
** and used by the [VFS] with the high-level [sqlite3_FILE object]
** that provides a stdio-like interface for use by application programs.
*/
typedef struct sqlite3_file sqlite3_file;
struct sqlite3_file {
  const struct sqlite3_io_methods *pMethods;  /* Methods for an open file */
};

/*
................................................................................
*/
#define SQLITE_ROLLBACK 1
/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
#define SQLITE_FAIL     3
/* #define SQLITE_ABORT 4  // Also an error code */
#define SQLITE_REPLACE  5

/*
** CAPI3REF: Simplified Interface To The VFS
** KEYWORDS: *sqlite3_FILE {*sqlite3_FILE object}
**
** An instance of this object represents an open file in a [VFS].
** This object is used by simplified I/O routines such as 
** [sqlite3_fopen()] and [sqlite3_fread()] and [sqlite3_fwrite()].
**
** The sqlite3_FILE object provides a simple means to access
** the filesystem through an SQLite [VFS].  This allows, for example,
** ordinary file I/O to occur through VFS shims such as the quota or
** multiplexor or vfstrace, or for I/O to occur on specialized
** application-specific VFSes.  The sqlite3_FILE object also provides
** a safe way for the application to read directly from an SQLite database
** file, without the risk of cancelling posix advisory locks when the
** connection is closed, as would happen using stdio or direct OS
** I/O interfaces.
**
** The simplified I/O routines a similar to the "fopen()" family
** of I/O routines in the standard C library, though there are some
** minor differences.  Note in particular that [sqlite3_fread()] and
** [sqlite3_fwrite()] have 3 instead of 4 parameters and return a
** success code rather than the number of elements read or written.
** Also, standard C library numeric datatypes such as size_t and off_t are
** replaced in this interface with the 64-bit signed integer type
** [sqlite3_int64].
**
** The sqlite3_FILE object is not intended to be a general-purpose 
** replacement for stdio, but it can be very useful in some
** circumstances.
**
** Do not confuse the high-level sqlite3_FILE object described here
** with the low-level [sqlite3_file] object used by the [VFS].
**
** See also:
** [sqlite3_fopen()],
** [sqlite3_fread()],
** [sqlite3_fwrite()],
** [sqlite3_fseek()],
** [sqlite3_ftell()],
** [sqlite3_rewind()],
** [sqlite3_fflush()],
** [sqlite3_ftruncate()],
** [sqlite3_close()],
** [sqlite3_remove()].
*/
typedef struct sqlite3_FILE sqlite3_FILE;

/*
** CAPI3REF: Open A File Object
**
** The sqlite3_fopen(F,M) routine opens an [sqlite3_FILE object] on the
** the file identified by [URI filename] F with mode M.  Return a pointer
** to the [sqlite3_FILE object] created, or a NULL pointer if the open failed.
**
** The mode M can be one of the following:
**
** <dl>
** <dt><b>"r"</b>
** <dd>Open the file read-only.  Fail if the file does not already exist.
** <dt><b>"r+"</b>
** <dd>Open the file read and writing, but fail if the file does not
** already exist.
** <dt><b>"w"</b>
** <dd>Open for reading and writing.  Create the file if it does not
** already exist.  If the file does already exist, truncate it to zero
** bytes in size immediately after opening.
** <dt><b>"w+"</b>
** <dd>This works the same as "w".
** <dt><b>"a"</b>
** <dd>Open for reading and writing.  Create the file if it does not
** already exist.  Set the file cursor to the end of the file so that
** any write operations that occur prior to an [sqlite3_fseek()] or
** [sqlite3_rewind()] will append to the file.
** <dt><b>"a+"</b>
** <dd>Open for reading and writing.  Create the file if it does not
** already exist.  The file cursor is positioned at the beginning of
** the file for reading purposes.  However, any writes on the file
** cause the file cursor to move to the end of the file prior to the
** write (and thus append to the file).
** </dl>
**
** Any value for the mode M other than those listed above cause the
** sqlite3_fopen() call to fail.
**
** See also:
** [sqlite3_fread()],
** [sqlite3_fwrite()],
** [sqlite3_fseek()],
** [sqlite3_ftell()],
** [sqlite3_rewind()],
** [sqlite3_fflush()],
** [sqlite3_close()],
** [sqlite3_remove()].
*/
sqlite3_FILE *sqlite3_fopen(const char *zURI, const char *zMode);

/*
** CAPI3REF:  Read and Write A File Object
**
** The [sqlite3_fread(B,N,P)] routine reads N bytes of content from 
** [sqlite3_FILE object] P and into buffer B.  
** The [sqlite3_fwrite(B,N,P)] routine writes N bytes of content from
** buffer B into [sqlite3_FILE object] P.  Both routines return
** SQLITE_OK on success or an [error code] on failure.
**
** Reading and writing always occur beginning at the file cursor.  The file
** cursor is advanced by N if the read or write is successful and unchanged
** if the read is not successful.  Not that the file cursor is
** unchanged by a partial read ([SQLITE_IOERR_SHORT_READ]).
** If the mode from [sqlite3_fopen()] was "a+" then the file cursor is
** always moved to the end of the file prior to every write.
**
** Note that these routines differ from stdio fread() and fwrite()
** functions in two significant ways:  These routines use 3 parameters
** instead of 4; these routines always assume an element size of one byte.
** And these routines return a success code, not the number of elements
** read or written.  With the routines described here, and unlike
** fread() and fwrite(), a partial read or write is considered an error.
*/
int sqlite3_fread(void*, sqlite3_int64, sqlite3_FILE*);
int sqlite3_fwrite(const void*, sqlite3_int64, sqlite3_FILE*);

/*
** CAPI3REF:  Whence Parameter For sqlite3_fseek()
**
** The 3rd parameter to [sqlite3_fseek(P,N,W)] can take on any of the
** following values.
*/
#define SQLITE_SEEK_SET  0
#define SQLITE_SEEK_CUR  1
#define SQLITE_SEEK_END  2

/*
** CAPI3REF:  Position The Cursor For An sqlite3_FILE object
**
** This routines move the current cursor position in an [sqlite3_FILE object].
** The sqlite3_fseek(P,N,W) call move the [sqlite3_FILE object] P to a new
** position N relative to W.  W is [SQLITE_SEEK_SET] for the beginning of
** the file, [SQLITE_SEEK_CUR] for the cursor position prior to the current
** move, or [SQLITE_SEEK_END] for the end of the file.
**
** The sqlite3_rewind(P) call move the cursor position to the beginning
** of the file.  It is equivalent to sqlite3_fseek(P,0,SQLITE_SEEK_SET).
**
** The sqlite3_ftell(P) call returns the current cursor position.
*/
int sqlite3_fseek(sqlite3_FILE*, sqlite3_int64, int whence);
int sqlite3_rewind(sqlite3_FILE*);
sqlite3_int64 sqlite3_ftell(sqlite3_FILE*);

/*
** CAPI3REF:  Flush OS File Cache Buffers
**
** A call to sqlite3_fflush(P) causes any writes previously made against
** [sqlite3_FILE object] P to be flushed from the operating-system cache
** to nonvolatile storage.
*/
int sqlite3_fflush(sqlite3_FILE*);

/*
** CAPI3REF:  Truncate An sqlite3_FILE object
**
** The sqlite3_ftruncate(P,N) interface calls the [sqlite3_FILE object] P
** to be truncated to N bytes in size.
**
** It is undefined what happens if N is larger than the current file size.
** Some [VFS] implementations will extend the file.  Others will fail.
** Still others will leave the file in an inconsistent state.
*/
int sqlite3_ftruncate(sqlite3_FILE*, sqlite3_int64);

/*
** CAPI3REF:  Close an sqlite3_FILE object
**
** Every successful call to [sqlite3_fopen()] should be eventually followed
** by a call to this routine to destroy the [sqlite3_FILE object] that
** [sqlite3_fopen()] created.  After calling this routine, the
** [sqlite3_FILE object] must not be used again.
*/
int sqlite3_fclose(sqlite3_FILE*);

/*
** CAPI3REF:  Remove A File
**
** The sqlite3_remove(U) interface attempts to delete the file identified
** by the [URI filename] U.  Query parameters on U can specify a particular
** [VFS] to use to do the deletion.
*/
int sqlite3_remove(const char *zURI);

/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
*/
#ifdef SQLITE_OMIT_FLOATING_POINT
# undef double
#endif

#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif