From: drh Date: Tue, 10 Apr 2012 17:53:47 +0000 (+0000) Subject: Add new interfaces to the test_quota.c module: sqlite3_quota_ftruncate(), X-Git-Tag: version-3.7.12~40 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c00ce490c59a3466063d70ea800e01aba6994cee;p=thirdparty%2Fsqlite.git Add new interfaces to the test_quota.c module: sqlite3_quota_ftruncate(), sqlite3_quota_file_size(), sqlite3_quota_file_truesize(), and sqlite3_quota_file_mtime(). FossilOrigin-Name: 2fa9f54309aea9927fb3695a986febd4963df7d1 --- diff --git a/manifest b/manifest index acbdddb62b..183c09e20e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scopy/paste\serror\sin\sa\scomment\sin\sthe\sfuzzer.\s\sNo\schanges\sto\scode. -D 2012-04-10T16:05:27.567 +C Add\snew\sinterfaces\sto\sthe\stest_quota.c\smodule:\s\ssqlite3_quota_ftruncate(),\nsqlite3_quota_file_size(),\ssqlite3_quota_file_truesize(),\sand\nsqlite3_quota_file_mtime(). +D 2012-04-10T17:53:47.880 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -221,8 +221,8 @@ F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 5e1382e7844c703c77c4c2aee82f8359555b5a8e F src/test_osinst.c 7f790ac89c5a585d51b341274d9691c3391e0923 F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00 -F src/test_quota.c a545115f837da4ef32f6b5578f147b44cfb13fd7 -F src/test_quota.h 9ffa1d3ad6d0a6a24e8670ea64b909c717ec3358 +F src/test_quota.c 2ab468f5817b84f7105f78b77c300649ea5af8d1 +F src/test_quota.h ee5da2ae7f84d1c8e0e0e2ab33f01d69f10259b5 F src/test_rtree.c aba603c949766c4193f1068b91c787f57274e0d9 F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0 F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f @@ -651,7 +651,7 @@ F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26 F test/quota.test c2f778dab4c7fb07bcfa962cc5c762f36d8061dc -F test/quota2.test 7e1c84f71f59388963fa8181a1292c87ae814d2d +F test/quota2.test bc9fdb2e46aace691c1a01a9cc8d097bd4d7c1ab F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 09d5581c81fb6a9bf6a369d0abf5ef6b54637576 -R 943f4e1c7aaa43ed0d8f52aacf8c1af9 +P 7433f2b5508ebf09d0e3e32a995f1126eaab8999 +R 85564f41a960bd198f1c0cd3cc4e501c U drh -Z bb1afab0a69bf02921a229d11d9f81e5 +Z b7da54f2c32a033935fc1a3628198083 diff --git a/manifest.uuid b/manifest.uuid index 0184cf7589..a6e3677ea1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7433f2b5508ebf09d0e3e32a995f1126eaab8999 \ No newline at end of file +2fa9f54309aea9927fb3695a986febd4963df7d1 \ No newline at end of file diff --git a/src/test_quota.c b/src/test_quota.c index e749851238..6514a28a13 100644 --- a/src/test_quota.c +++ b/src/test_quota.c @@ -120,6 +120,9 @@ struct quota_FILE { FILE *f; /* Open stdio file pointer */ sqlite3_int64 iOfst; /* Current offset into the file */ quotaFile *pFile; /* The file record in the quota system */ +#if SQLITE_OS_WIN + char *zMbcsName; /* Full MBCS pathname of the file */ +#endif }; @@ -979,7 +982,7 @@ int sqlite3_quota_file(const char *zFilename){ quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode){ quota_FILE *p = 0; char *zFull = 0; - char *zFullTranslated; + char *zFullTranslated = 0; int rc; quotaGroup *pGroup; quotaFile *pFile; @@ -995,7 +998,6 @@ quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode){ zFullTranslated = quota_utf8_to_mbcs(zFull); if( zFullTranslated==0 ) goto quota_fopen_error; p->f = fopen(zFullTranslated, zMode); - quota_mbcs_free(zFullTranslated); if( p->f==0 ) goto quota_fopen_error; quotaEnter(); pGroup = quotaGroupFind(zFull); @@ -1010,9 +1012,13 @@ quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode){ } quotaLeave(); sqlite3_free(zFull); +#if SQLITE_OS_WIN + p->zMbcsName = zFullTranslated; +#endif return p; quota_fopen_error: + quota_mbcs_free(zFullTranslated); sqlite3_free(zFull); if( p && p->f ) fclose(p->f); sqlite3_free(p); @@ -1045,6 +1051,7 @@ size_t sqlite3_quota_fwrite( sqlite3_int64 iEnd; sqlite3_int64 szNew; quotaFile *pFile; + size_t rc; iOfst = ftell(p->f); iEnd = iOfst + size*nmemb; @@ -1068,8 +1075,23 @@ size_t sqlite3_quota_fwrite( pGroup->iSize = szNew; pFile->iSize = iEnd; quotaLeave(); + }else{ + pFile = 0; + } + rc = fwrite(pBuf, size, nmemb, p->f); + + /* If the write was incomplete, adjust the file size and group size + ** downward */ + if( rc=0 ? rc : 0; + sqlite3_int64 iNewEnd = iOfst + size*nWritten; + if( iNewEndpGroup->iSize += iNewEnd - pFile->iSize; + pFile->iSize = iNewEnd; + quotaLeave(); } - return fwrite(pBuf, size, nmemb, p->f); + return rc; } /* @@ -1093,6 +1115,9 @@ int sqlite3_quota_fclose(quota_FILE *p){ } quotaLeave(); } +#if SQLITE_OS_WIN + quota_mbcs_free(p->zMbcsName); +#endif sqlite3_free(p); return rc; } @@ -1135,6 +1160,83 @@ long sqlite3_quota_ftell(quota_FILE *p){ return ftell(p->f); } +/* +** Truncate a file to szNew bytes. +*/ +int sqlite3_quota_ftruncate(quota_FILE *p, sqlite3_int64 szNew){ + quotaFile *pFile = p->pFile; + int rc; + if( (pFile = p->pFile)!=0 && pFile->iSizeiSizepGroup; + quotaEnter(); + pGroup->iSize += szNew - pFile->iSize; + quotaLeave(); + } +#if SQLITE_OS_UNIX + rc = ftruncate(fileno(p->f), szNew); +#endif +#if SQLITE_OS_WIN + rc = _chsize_s(_fileno(p->f), szNew); +#endif + if( pFile && rc==0 ){ + quotaGroup *pGroup = pFile->pGroup; + quotaEnter(); + pGroup->iSize += szNew - pFile->iSize; + pFile->iSize = szNew; + quotaLeave(); + } + return rc; +} + +/* +** Determine the time that the given file was last modified, in +** seconds size 1970. Write the result into *pTime. Return 0 on +** success and non-zero on any kind of error. +*/ +int sqlite3_quota_file_mtime(quota_FILE *p, time_t *pTime){ + int rc; +#if SQLITE_OS_UNIX + struct stat buf; + rc = fstat(fileno(p->f), &buf); +#endif +#if SQLITE_OS_WIN + struct _stati64 buf; + rc = _stati64(p->zMbcsName, &buf); +#endif + if( rc==0 ) *pTime = buf.st_mtime; + return rc; +} + +/* +** Return the true size of the file, as reported by the operating +** system. +*/ +sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE *p){ + int rc; +#if SQLITE_OS_UNIX + struct stat buf; + rc = fstat(fileno(p->f), &buf); +#endif +#if SQLITE_OS_WIN + struct _stati64 buf; + rc = _stati64(p->zMbcsName, &buf); +#endif + return rc==0 ? buf.st_size : -1; +} + +/* +** Return the size of the file, as it is known to the quota subsystem. +*/ +sqlite3_int64 sqlite3_quota_file_size(quota_FILE *p){ + return p->pFile ? p->pFile->iSize : -1; +} + /* ** Remove a managed file. Update quotas accordingly. */ @@ -1656,6 +1758,96 @@ static int test_quota_ftell( return TCL_OK; } +/* +** tclcmd: sqlite3_quota_ftruncate HANDLE SIZE +*/ +static int test_quota_ftruncate( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + quota_FILE *p; + sqlite3_int64 x; + Tcl_WideInt w; + int rc; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HANDLE SIZE"); + return TCL_ERROR; + } + p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); + if( Tcl_GetWideIntFromObj(interp, objv[2], &w) ) return TCL_ERROR; + x = (sqlite3_int64)w; + rc = sqlite3_quota_ftruncate(p, x); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return TCL_OK; +} + +/* +** tclcmd: sqlite3_quota_file_size HANDLE +*/ +static int test_quota_file_size( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + quota_FILE *p; + sqlite3_int64 x; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); + return TCL_ERROR; + } + p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); + x = sqlite3_quota_file_size(p); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); + return TCL_OK; +} + +/* +** tclcmd: sqlite3_quota_file_truesize HANDLE +*/ +static int test_quota_file_truesize( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + quota_FILE *p; + sqlite3_int64 x; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); + return TCL_ERROR; + } + p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); + x = sqlite3_quota_file_truesize(p); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); + return TCL_OK; +} + +/* +** tclcmd: sqlite3_quota_file_mtime HANDLE +*/ +static int test_quota_file_mtime( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + quota_FILE *p; + time_t t; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); + return TCL_ERROR; + } + p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); + t = 0; + sqlite3_quota_file_mtime(p, &t); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t)); + return TCL_OK; +} + + /* ** tclcmd: sqlite3_quota_remove FILENAME */ @@ -1713,21 +1905,25 @@ int Sqlitequota_Init(Tcl_Interp *interp){ char *zName; Tcl_ObjCmdProc *xProc; } aCmd[] = { - { "sqlite3_quota_initialize", test_quota_initialize }, - { "sqlite3_quota_shutdown", test_quota_shutdown }, - { "sqlite3_quota_set", test_quota_set }, - { "sqlite3_quota_file", test_quota_file }, - { "sqlite3_quota_dump", test_quota_dump }, - { "sqlite3_quota_fopen", test_quota_fopen }, - { "sqlite3_quota_fread", test_quota_fread }, - { "sqlite3_quota_fwrite", test_quota_fwrite }, - { "sqlite3_quota_fclose", test_quota_fclose }, - { "sqlite3_quota_fflush", test_quota_fflush }, - { "sqlite3_quota_fseek", test_quota_fseek }, - { "sqlite3_quota_rewind", test_quota_rewind }, - { "sqlite3_quota_ftell", test_quota_ftell }, - { "sqlite3_quota_remove", test_quota_remove }, - { "sqlite3_quota_glob", test_quota_glob }, + { "sqlite3_quota_initialize", test_quota_initialize }, + { "sqlite3_quota_shutdown", test_quota_shutdown }, + { "sqlite3_quota_set", test_quota_set }, + { "sqlite3_quota_file", test_quota_file }, + { "sqlite3_quota_dump", test_quota_dump }, + { "sqlite3_quota_fopen", test_quota_fopen }, + { "sqlite3_quota_fread", test_quota_fread }, + { "sqlite3_quota_fwrite", test_quota_fwrite }, + { "sqlite3_quota_fclose", test_quota_fclose }, + { "sqlite3_quota_fflush", test_quota_fflush }, + { "sqlite3_quota_fseek", test_quota_fseek }, + { "sqlite3_quota_rewind", test_quota_rewind }, + { "sqlite3_quota_ftell", test_quota_ftell }, + { "sqlite3_quota_ftruncate", test_quota_ftruncate }, + { "sqlite3_quota_file_size", test_quota_file_size }, + { "sqlite3_quota_file_truesize", test_quota_file_truesize }, + { "sqlite3_quota_file_mtime", test_quota_file_mtime }, + { "sqlite3_quota_remove", test_quota_remove }, + { "sqlite3_quota_glob", test_quota_glob }, }; int i; diff --git a/src/test_quota.h b/src/test_quota.h index a2fddbbc43..9bd4312c6c 100644 --- a/src/test_quota.h +++ b/src/test_quota.h @@ -29,6 +29,14 @@ #ifndef _QUOTA_H_ #include "sqlite3.h" #include +#include +#include +#if SQLITE_OS_UNIX +# include +#endif +#if SQLITE_OS_WIN +# include +#endif /* Make this callable from C++ */ #ifdef __cplusplus @@ -182,6 +190,48 @@ int sqlite3_quota_fseek(quota_FILE*, long, int); void sqlite3_quota_rewind(quota_FILE*); long sqlite3_quota_ftell(quota_FILE*); +/* +** Truncate a file previously opened by sqlite3_quota_fopen(). Return +** zero on success and non-zero on any kind of failure. +** +** The newSize argument must be less than or equal to the current file size. +** Any attempt to "truncate" a file to a larger size results in +** undefined behavior. +*/ +int sqlite3_quota_ftrunate(quota_FILE*, sqlite3_int64 newSize); + +/* +** Return the last modification time of the opened file, in seconds +** since 1970. +*/ +int sqlite3_quota_file_mtime(quota_FILE*, time_t *pTime); + +/* +** Return the size of the file as it is known to the quota system. +** +** This size might be different from the true size of the file on +** disk if some outside process has modified the file without using the +** quota mechanism, or if calls to sqlite3_quota_fwrite() have occurred +** which have increased the file size, but those writes have not yet been +** forced to disk using sqlite3_quota_fflush(). +** +** Return -1 if the file is not participating in quota management. +*/ +sqlite3_int64 sqlite3_quota_file_size(quota_FILE*); + +/* +** Return the true size of the file. +** +** The true size should be the same as the size of the file as known +** to the quota system, however the sizes might be different if the +** file has been extended or truncated via some outside process or if +** pending writes have not yet been flushed to disk. +** +** Return -1 if the file does not exist or if the size of the file +** cannot be determined for some reason. +*/ +sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE*); + /* ** Delete a file from the disk, if that file is under quota management. ** Adjust quotas accordingly. diff --git a/test/quota2.test b/test/quota2.test index fae4d2dbd7..5bb50d7ce0 100644 --- a/test/quota2.test +++ b/test/quota2.test @@ -76,6 +76,13 @@ do_test quota2-1.1 { do_test quota2-1.2 { set ::quota } {PWD/quota2a/xyz.txt 4000 7000} +do_test quota2-1.2.1 { + sqlite3_quota_file_size $::h1 +} {4000} +do_test quota2-1.2.2 { + sqlite3_quota_fflush $::h1 1 + sqlite3_quota_file_truesize $::h1 +} {4000} do_test quota2-1.3 { sqlite3_quota_rewind $::h1 set ::x [sqlite3_quota_fread $::h1 1001 7] @@ -112,15 +119,43 @@ do_test quota2-1.11 { standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 4000 {PWD/quota2a/xyz.txt 4000 1 0}}} do_test quota2-1.12 { + sqlite3_quota_ftruncate $::h1 3500 + sqlite3_quota_file_size $::h1 +} {3500} +do_test quota2-1.13 { + sqlite3_quota_file_truesize $::h1 +} {3500} +do_test quota2-1.14 { + standard_path [sqlite3_quota_dump] +} {{*/quota2b/* 5000 0} {*/quota2a/* 4000 3500 {PWD/quota2a/xyz.txt 3500 1 0}}} +do_test quota2-1.15 { + sqlite3_quota_fseek $::h1 0 SEEK_END + sqlite3_quota_ftell $::h1 +} {3500} +do_test quota2-1.16 { + sqlite3_quota_fwrite $::h1 1 7000 $bigtext +} {500} +do_test quota2-1.17 { + sqlite3_quota_ftell $::h1 +} {4000} +do_test quota2-1.18 { + sqlite3_quota_file_size $::h1 +} {4000} +do_test quota2-1.19 { + sqlite3_quota_fflush $::h1 1 + sqlite3_quota_file_truesize $::h1 +} {4000} +do_test quota2-1.20 { sqlite3_quota_fclose $::h1 standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 4000 {PWD/quota2a/xyz.txt 4000 0 0}}} -do_test quota2-1.13 { +do_test quota2-1.21 { sqlite3_quota_remove quota2a/xyz.txt standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 0}} + set quota {} do_test quota2-2.1 { set ::h1 [sqlite3_quota_fopen quota2c/xyz.txt w+b]