SQLite

Check-in [61669c9585]
Login

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

Overview
Comment:Add sqlite3_quota_ferror() and sqlite3_quota_file_available() interfaces to test_quota.c. Change sqlite3_quota_fwrite() to use a const input buffer.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 61669c95859e187618fb2fb4249306a947ae8d26
User & Date: drh 2012-06-05 13:56:15.352
Context
2012-06-06
19:01
Avoid resetting the shared-cache schema when on of the connections using the shared cache closes. Delay resetting the schema until the last connection closes. (check-in: 635e3a762d user: drh tags: trunk)
2012-06-05
19:20
Merge the latest trunk changes into shared-schema branch. Also fix a C99-ism in that branch. (check-in: 42338e9e69 user: drh tags: shared-schema)
13:56
Add sqlite3_quota_ferror() and sqlite3_quota_file_available() interfaces to test_quota.c. Change sqlite3_quota_fwrite() to use a const input buffer. (check-in: 61669c9585 user: drh tags: trunk)
2012-05-31
13:10
Avoid calling fchown() if the process is not running as root. (check-in: 70c419a434 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/test_quota.c.
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
}

/*
** Write content into a quota_FILE.  Invoke the quota callback and block
** the write if we exceed quota.
*/
size_t sqlite3_quota_fwrite(
  void *pBuf,            /* Take content to write from here */
  size_t size,           /* Size of each element */
  size_t nmemb,          /* Number of elements */
  quota_FILE *p          /* Write to this quota_FILE objecct */
){
  sqlite3_int64 iOfst;
  sqlite3_int64 iEnd;
  sqlite3_int64 szNew;
  quotaFile *pFile;
  size_t rc;
  
  iOfst = ftell(p->f);
  iEnd = iOfst + size*nmemb;
  pFile = p->pFile;
  if( pFile && pFile->iSize<iEnd ){
    quotaGroup *pGroup = pFile->pGroup;
    quotaEnter();
    szNew = pGroup->iSize - pFile->iSize + iEnd;







|









|







1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
}

/*
** Write content into a quota_FILE.  Invoke the quota callback and block
** the write if we exceed quota.
*/
size_t sqlite3_quota_fwrite(
  const void *pBuf,      /* Take content to write from here */
  size_t size,           /* Size of each element */
  size_t nmemb,          /* Number of elements */
  quota_FILE *p          /* Write to this quota_FILE objecct */
){
  sqlite3_int64 iOfst;
  sqlite3_int64 iEnd;
  sqlite3_int64 szNew;
  quotaFile *pFile;
  size_t rc;

  iOfst = ftell(p->f);
  iEnd = iOfst + size*nmemb;
  pFile = p->pFile;
  if( pFile && pFile->iSize<iEnd ){
    quotaGroup *pGroup = pFile->pGroup;
    quotaEnter();
    szNew = pGroup->iSize - pFile->iSize + iEnd;
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
    sqlite3_int64 iNewEnd = iOfst + size*nWritten;
    if( iNewEnd<iEnd ) iNewEnd = iEnd;
    quotaEnter();
    pFile->pGroup->iSize += iNewEnd - pFile->iSize;
    pFile->iSize = iNewEnd;
    quotaLeave();
  }
  return rc;    
}

/*
** Close an open quota_FILE stream.
*/
int sqlite3_quota_fclose(quota_FILE *p){
  int rc;







|







1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
    sqlite3_int64 iNewEnd = iOfst + size*nWritten;
    if( iNewEnd<iEnd ) iNewEnd = iEnd;
    quotaEnter();
    pFile->pGroup->iSize += iNewEnd - pFile->iSize;
    pFile->iSize = iNewEnd;
    quotaLeave();
  }
  return rc;
}

/*
** Close an open quota_FILE stream.
*/
int sqlite3_quota_fclose(quota_FILE *p){
  int rc;
1155
1156
1157
1158
1159
1160
1161







1162
1163
1164
1165
1166
1167
1168

/*
** Tell the current location of a quota_FILE stream.
*/
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;







>
>
>
>
>
>
>







1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175

/*
** Tell the current location of a quota_FILE stream.
*/
long sqlite3_quota_ftell(quota_FILE *p){
  return ftell(p->f);
}

/*
** Test the error indicator for the given file.
*/
int sqlite3_quota_ferror(quota_FILE *p){
  return ferror(p->f);
}

/*
** Truncate a file to szNew bytes.
*/
int sqlite3_quota_ftruncate(quota_FILE *p, sqlite3_int64 szNew){
  quotaFile *pFile = p->pFile;
  int rc;
1232
1233
1234
1235
1236
1237
1238



















1239
1240
1241
1242
1243
1244
1245

/*
** 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.
*/
int sqlite3_quota_remove(const char *zFilename){
  char *zFull;            /* Full pathname for zFilename */
  size_t nFull;           /* Number of bytes in zFilename */







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







1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271

/*
** 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;
}
 
/*
** Determine the amount of data in bytes available for reading
** in the given file.
*/
long sqlite3_quota_file_available(quota_FILE *p){
  FILE* f = p->f;
  long pos1, pos2;
  int rc;
  pos1 = ftell(f);
  if ( pos1 < 0 ) return -1;
  rc = fseek(f, 0, SEEK_END);
  if ( rc != 0 ) return -1;
  pos2 = ftell(f);
  if ( pos2 < 0 ) return -1;
  rc = fseek(f, pos1, SEEK_SET);
  if ( rc != 0 ) return -1;
  return pos2 - pos1;
}

/*
** Remove a managed file.  Update quotas accordingly.
*/
int sqlite3_quota_remove(const char *zFilename){
  char *zFull;            /* Full pathname for zFilename */
  size_t nFull;           /* Number of bytes in zFilename */
1890
1891
1892
1893
1894
1895
1896















































1897
1898
1899
1900
1901
1902
1903
  }
  zPattern = Tcl_GetString(objv[1]);
  zText = Tcl_GetString(objv[2]);
  rc = quotaStrglob(zPattern, zText);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return TCL_OK;
}
















































/*
** This routine registers the custom TCL commands defined in this
** module.  This should be the only procedure visible from outside
** of this module.
*/
int Sqlitequota_Init(Tcl_Interp *interp){







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







1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
  }
  zPattern = Tcl_GetString(objv[1]);
  zText = Tcl_GetString(objv[2]);
  rc = quotaStrglob(zPattern, zText);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return TCL_OK;
}

/*
** tclcmd: sqlite3_quota_file_available HANDLE
**
** Return the number of bytes from the current file point to the end of
** the file.
*/
static int test_quota_file_available(
  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_available(p);
  Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x));
  return TCL_OK;
}

/*
** tclcmd: sqlite3_quota_ferror HANDLE
**
** Return true if the file handle is in the error state.
*/
static int test_quota_ferror(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  quota_FILE *p;
  int x;
  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
    return TCL_ERROR;
  }
  p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
  x = sqlite3_quota_ferror(p);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(x));
  return TCL_OK;
}

/*
** This routine registers the custom TCL commands defined in this
** module.  This should be the only procedure visible from outside
** of this module.
*/
int Sqlitequota_Init(Tcl_Interp *interp){
1920
1921
1922
1923
1924
1925
1926


1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
    { "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;

  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
  }

  return TCL_OK;
}
#endif







>
>










1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
    { "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 },
    { "sqlite3_quota_file_available",test_quota_file_available },
    { "sqlite3_quota_ferror",        test_quota_ferror },
  };
  int i;

  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
  }

  return TCL_OK;
}
#endif
Changes to src/test_quota.h.
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

/*
** Perform I/O against a quota_FILE object.  When doing writes, the
** quota mechanism may result in a short write, in order to prevent
** the sum of sizes of all files from going over quota.
*/
size_t sqlite3_quota_fread(void*, size_t, size_t, quota_FILE*);
size_t sqlite3_quota_fwrite(void*, size_t, size_t, quota_FILE*);

/*
** Flush all written content held in memory buffers out to disk.
** This is the equivalent of fflush() in the standard library.
**
** If the hardSync parameter is true (non-zero) then this routine
** also forces OS buffers to disk - the equivalent of fsync().







|







158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

/*
** Perform I/O against a quota_FILE object.  When doing writes, the
** quota mechanism may result in a short write, in order to prevent
** the sum of sizes of all files from going over quota.
*/
size_t sqlite3_quota_fread(void*, size_t, size_t, quota_FILE*);
size_t sqlite3_quota_fwrite(const void*, size_t, size_t, quota_FILE*);

/*
** Flush all written content held in memory buffers out to disk.
** This is the equivalent of fflush() in the standard library.
**
** If the hardSync parameter is true (non-zero) then this routine
** also forces OS buffers to disk - the equivalent of fsync().
186
187
188
189
190
191
192







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
** Move the read/write pointer for a quota_FILE object.  Or tell the
** current location of the read/write pointer.
*/
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);








>
>
>
>
>
>
>








|







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
** Move the read/write pointer for a quota_FILE object.  Or tell the
** current location of the read/write pointer.
*/
int sqlite3_quota_fseek(quota_FILE*, long, int);
void sqlite3_quota_rewind(quota_FILE*);
long sqlite3_quota_ftell(quota_FILE*);

/*
** Test the error indicator for the given file.
**
** Return non-zero if the error indicator is set.
*/
int sqlite3_quota_ferror(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_ftruncate(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);

228
229
230
231
232
233
234








235
236
237
238
239
240
241
** 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.
**
** If zFilename is the name of a directory that matches one of the
** quota glob patterns, then all files under quota management that
** are contained within that directory are deleted.







>
>
>
>
>
>
>
>







235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
** 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*);

/*
** Determine the amount of data in bytes available for reading
** in the given file.
**
** Return -1 if the amount cannot be determined for some reason.
*/
long sqlite3_quota_file_available(quota_FILE*);

/*
** Delete a file from the disk, if that file is under quota management.
** Adjust quotas accordingly.
**
** If zFilename is the name of a directory that matches one of the
** quota glob patterns, then all files under quota management that
** are contained within that directory are deleted.
Changes to test/quota2.test.
160
161
162
163
164
165
166
167
168



169
170
171



172
173
174
175
176
177
178
179
180
181
182



183
184
185
186



187
188
189
190



191
192
193
194



195
196
197
198






199
200
201
202
203
204
205
do_test quota2-2.1 {
  set ::h1 [sqlite3_quota_fopen quota2c/xyz.txt w+b]
  sqlite3_quota_fwrite $::h1 1 7000 $bigtext
} {7000}
do_test quota2-2.2 {
  set ::quota
} {}
do_test quota2-2.3 {
  sqlite3_quota_rewind $::h1



  set ::x [sqlite3_quota_fread $::h1 1001 7]
  string length $::x
} {6006}



do_test quota2-2.4 {
  string match $::x [string range $::bigtext 0 6005]
} {1}
do_test quota2-2.5 {
  sqlite3_quota_fseek $::h1 0 SEEK_END
  sqlite3_quota_ftell $::h1
} {7000}
do_test quota2-2.6 {
  sqlite3_quota_fseek $::h1 -100 SEEK_END
  sqlite3_quota_ftell $::h1
} {6900}



do_test quota2-2.7 {
  sqlite3_quota_fseek $::h1 -100 SEEK_CUR
  sqlite3_quota_ftell $::h1
} {6800}



do_test quota2-2.8 {
  sqlite3_quota_fseek $::h1 50 SEEK_CUR
  sqlite3_quota_ftell $::h1
} {6850}



do_test quota2-2.9 {
  sqlite3_quota_fseek $::h1 50 SEEK_SET
  sqlite3_quota_ftell $::h1
} {50}



do_test quota2-2.10 {
  sqlite3_quota_rewind $::h1
  sqlite3_quota_ftell $::h1
} {0}






do_test quota2-2.11 {
  standard_path [sqlite3_quota_dump]
} {{*/quota2b/* 5000 0} {*/quota2a/* 4000 0}}
do_test quota2-2.12 {
  sqlite3_quota_fclose $::h1
  standard_path [sqlite3_quota_dump]
} {{*/quota2b/* 5000 0} {*/quota2a/* 4000 0}}







|

>
>
>



>
>
>











>
>
>




>
>
>




>
>
>




>
>
>




>
>
>
>
>
>







160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
do_test quota2-2.1 {
  set ::h1 [sqlite3_quota_fopen quota2c/xyz.txt w+b]
  sqlite3_quota_fwrite $::h1 1 7000 $bigtext
} {7000}
do_test quota2-2.2 {
  set ::quota
} {}
do_test quota2-2.3.1 {
  sqlite3_quota_rewind $::h1
  sqlite3_quota_file_available $::h1
} {7000}
do_test quota2-2.3.2 {
  set ::x [sqlite3_quota_fread $::h1 1001 7]
  string length $::x
} {6006}
do_test quota2-2.3.3 {
  sqlite3_quota_file_available $::h1
} {0}
do_test quota2-2.4 {
  string match $::x [string range $::bigtext 0 6005]
} {1}
do_test quota2-2.5 {
  sqlite3_quota_fseek $::h1 0 SEEK_END
  sqlite3_quota_ftell $::h1
} {7000}
do_test quota2-2.6 {
  sqlite3_quota_fseek $::h1 -100 SEEK_END
  sqlite3_quota_ftell $::h1
} {6900}
do_test quota2-2.6.1 {
  sqlite3_quota_file_available $::h1
} {100}
do_test quota2-2.7 {
  sqlite3_quota_fseek $::h1 -100 SEEK_CUR
  sqlite3_quota_ftell $::h1
} {6800}
do_test quota2-2.7.1 {
  sqlite3_quota_file_available $::h1
} {200}
do_test quota2-2.8 {
  sqlite3_quota_fseek $::h1 50 SEEK_CUR
  sqlite3_quota_ftell $::h1
} {6850}
do_test quota2-2.8.1 {
  sqlite3_quota_file_available $::h1
} {150}
do_test quota2-2.9 {
  sqlite3_quota_fseek $::h1 50 SEEK_SET
  sqlite3_quota_ftell $::h1
} {50}
do_test quota2-2.9.1 {
  sqlite3_quota_file_available $::h1
} {6950}
do_test quota2-2.10 {
  sqlite3_quota_rewind $::h1
  sqlite3_quota_ftell $::h1
} {0}
do_test quota2-2.10.1 {
  sqlite3_quota_file_available $::h1
} {7000}
do_test quota2-2.10.2 {
  sqlite3_quota_ferror $::h1
} {0}
do_test quota2-2.11 {
  standard_path [sqlite3_quota_dump]
} {{*/quota2b/* 5000 0} {*/quota2a/* 4000 0}}
do_test quota2-2.12 {
  sqlite3_quota_fclose $::h1
  standard_path [sqlite3_quota_dump]
} {{*/quota2b/* 5000 0} {*/quota2a/* 4000 0}}