In the source code of [fcntlSizeHint] in SQLite 3.9.2,
Its comment said that "If the database is already nBytes or larger, this 
routine is a no-op.”.
But if SQLITE_MAX_MMAP_SIZE0, there is no judgement about file size.


#if SQLITE_MAX_MMAP_SIZE0
 if( pFile-mmapSizeMax0  nBytepFile-mmapSize ){
  int rc;
  if( pFile-szChunk=0 ){
   if( robust_ftruncate(pFile-h, nByte) ){
    storeLastErrno(pFile, errno);
    return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile-zPath);
   }
  }


  rc = unixMapfile(pFile, nByte);
  return rc;
 }
#endif


The routinue [robust_ftruncate] will run and the file will be cut off if 
nBytefileSize.
This routine may (or may not) cause some problem in SQLite. But for someone 
hacking the source code of SQLite(What I’m doing), it may be a trap.


/*
** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
** file-control operation. Enlarge the database to nBytes in size
** (rounded up to the next chunk-size). If the database is already
** nBytes or larger, this routine is a no-op.
*/
static int fcntlSizeHint(unixFile *pFile, i64 nByte){
 if( pFile-szChunk0 ){
  i64 nSize;          /* Required file size */
  struct stat buf;       /* Used to hold return values of fstat() */
 
  if( osFstat(pFile-h, buf) ){
   return SQLITE_IOERR_FSTAT;
  }


  nSize = ((nByte+pFile-szChunk-1) / pFile-szChunk) * pFile-szChunk;
  if( nSize(i64)buf.st_size ){


#if defined(HAVE_POSIX_FALLOCATE)  HAVE_POSIX_FALLOCATE
   /* The code below is handling the return value of osFallocate()
   ** correctly. posix_fallocate() is defined to "returns zero on success,
   ** or an error number on failure". See the manpage for details. */
   int err;
   do{
    err = osFallocate(pFile-h, buf.st_size, nSize-buf.st_size);
   }while( err==EINTR );
   if( err ) return SQLITE_IOERR_WRITE;
#else
   /* If the OS does not have posix_fallocate(), fake it. Write a
   ** single byte to the last byte in each block that falls entirely
   ** within the extended region. Then, if required, a single byte
   ** at offset (nSize-1), to set the size of the file correctly.
   ** This is a similar technique to that used by glibc on systems
   ** that do not have a real fallocate() call.
   */
   int nBlk = buf.st_blksize; /* File-system block size */
   int nWrite = 0;       /* Number of bytes written by seekAndWrite */
   i64 iWrite;         /* Next offset to write to */


   iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
   assert( iWrite=buf.st_size );
   assert( (iWrite/nBlk)==((buf.st_size+nBlk-1)/nBlk) );
   assert( ((iWrite+1)%nBlk)==0 );
   for(/*no-op*/; iWritenSize; iWrite+=nBlk ){
    nWrite = seekAndWrite(pFile, iWrite, "", 1);
    if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
   }
   if( nWrite==0 || (nSize%nBlk) ){
    nWrite = seekAndWrite(pFile, nSize-1, "", 1);
    if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
   }
#endif
  }
 }


#if SQLITE_MAX_MMAP_SIZE0
 if( pFile-mmapSizeMax0  nBytepFile-mmapSize ){
  int rc;
  if( pFile-szChunk=0 ){
   if( robust_ftruncate(pFile-h, nByte) ){
    storeLastErrno(pFile, errno);
    return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile-zPath);
   }
  }


  rc = unixMapfile(pFile, nByte);
  return rc;
 }
#endif


 return SQLITE_OK;
}
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to