We should add a new output argument for xRead method which is in 
sqlite3_io_methods structure like this:

int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst, int* 
piRealAmt);

The new 'piRealAmt' could be used to report the actual read data, this argument 
will greatly boost the ability of VFS Shims. For example, with this argument, 
we can write a encryption shim easily.

It's very simple. Basically, you only need adding just one line code per xRead 
driver like this:

  }else{
    pFile->lastErrno = 0; /* not a system error */
    /* Unread parts of the buffer must be zero-filled */
    memset(&((char*)pBuf)[got], 0, amt-got);
    if (piRealAmt) *piRealAmt = (int)got; // <----
    return SQLITE_IOERR_SHORT_READ;
  }

By using this simple extension, we can write code like this:

//! shim xRead driver for encryption
BAIY_LOCAL int
ReadMethod(
    IN OUT       sqlite3_file* piFile, 
    OUT          void*         pbBuf, 
    IN           int           nAmt, 
    IN           sqlite_int64  nnOfst,
    OPTIONAL OUT int*          piRealAmt)
{
    // =========================================================================
    // = Init, Guard
    ENCVFS_FILE* piOriFile = reinterpret_cast<ENCVFS_FILE*>(piFile);
    if (piOriFile->btUnder.empty() || !piOriFile->thCipher.IsValid())
    {
        return SQLITE_IOERR_READ;
    }
    
    sqlite3_file* const piUnder = reinterpret_cast<sqlite3_file*>(
        piOriFile->btUnder.ref()
        );

    // =========================================================================
    // = Read
    int nReadLen;
    piOriFile->btBuf.reserve(nAmt);
    
    const int r = piUnder->pMethods->xRead(
        piUnder, piOriFile->btBuf.ref(), nAmt, nnOfst, &nReadLen
        );
    
    switch (r)
    {
    case SQLITE_OK:
        nReadLen = nAmt;
        break;
    case SQLITE_IOERR_SHORT_READ:
        break;
    default:
        return r; // <----
    }
    
    // =========================================================================
    // = Decrypt
    try
    {
        piOriFile->thCipher->SeekDecryptor(nnOfst);
        piOriFile->thCipher->IterDecrypt(
            bySBn((BYTE*)pbBuf, nReadLen), piOriFile->btBuf
        );
    
        if (SQLITE_IOERR_SHORT_READ == r)
        {
            memset(((BYTE*)pbBuf)+nReadLen, 0, nAmt-nReadLen);
            if (piRealAmt)
            {
                *piRealAmt = nReadLen;
            }
            return SQLITE_IOERR_SHORT_READ;
        }
        else
        {
            return SQLITE_OK;
        }
    }
    catch (...)
    {
        LogError(byT("ReadMethod"));
        return SQLITE_IOERR_READ;
    }
}

--
  Best Regards
  BaiYang
  baiy...@263.net.cn
  http://baiy.cn
**** < END OF EMAIL > ****
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to