840 static int FullPathName(sqlite3_vfs* aVfs, const char* aRelative, int aBufLen, char* aBuf); |
845 static int FullPathName(sqlite3_vfs* aVfs, const char* aRelative, int aBufLen, char* aBuf); |
841 static int Randomness(sqlite3_vfs* aVfs, int aBufLen, char* aBuf); |
846 static int Randomness(sqlite3_vfs* aVfs, int aBufLen, char* aBuf); |
842 static int Sleep(sqlite3_vfs* aVfs, int aMicrosec); |
847 static int Sleep(sqlite3_vfs* aVfs, int aMicrosec); |
843 static int CurrentTime(sqlite3_vfs* aVfs, double* aNow); |
848 static int CurrentTime(sqlite3_vfs* aVfs, double* aNow); |
844 static int GetLastError(sqlite3_vfs *sVfs, int aBufLen, char* aBuf); |
849 static int GetLastError(sqlite3_vfs *sVfs, int aBufLen, char* aBuf); |
|
850 static TInt DoGetDeviceCharacteristicsAndSectorSize(TDbFile& aDbFile, TInt& aRecReadBufSize); |
|
851 |
845 private: |
852 private: |
846 static TInt DoOpenFromHandle(TDbFile& aDbFile, const RMessage2& aMsg, TBool aReadOnly); |
853 static TInt DoOpenFromHandle(TDbFile& aDbFile, const RMessage2& aMsg, TBool aReadOnly); |
847 static inline TInt DoGetVolumeIoParamInfo(RFs& aFs, TInt aDriveNo, TVolumeIOParamInfo& aVolumeInfo); |
854 static inline TInt DoGetVolumeIoParamInfo(RFs& aFs, TInt aDriveNo, TVolumeIOParamInfo& aVolumeInfo); |
848 static TInt DoGetDeviceCharacteristics(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo); |
855 static TInt DoGetDeviceCharacteristics(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo); |
849 static TInt DoGetSectorSize(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo); |
856 static TInt DoGetSectorSize(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo); |
850 static TInt DoGetDeviceCharacteristicsAndSectorSize(TDbFile& aDbFile, TInt& aRecReadBufSize); |
|
851 static TInt DoFileSizeCorruptionCheck(TDbFile& aDbFile, const TDesC& aFname, TInt aFmode); |
857 static TInt DoFileSizeCorruptionCheck(TDbFile& aDbFile, const TDesC& aFname, TInt aFmode); |
852 }; |
858 }; |
853 |
859 |
854 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
860 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
855 ///////////////////// Global variables, constants //////////////////////////////////////////////////////////////////// |
861 ///////////////////// Global variables, constants //////////////////////////////////////////////////////////////////// |
1571 } |
1576 } |
1572 COsLayerData::Instance().SetOsErrorCode(err); |
1577 COsLayerData::Instance().SetOsErrorCode(err); |
1573 return sqliteErr; |
1578 return sqliteErr; |
1574 } |
1579 } |
1575 |
1580 |
|
1581 //Creates a temporary file in "\temp" subdirectory of osLayerData.iSysPrivDir directory. |
|
1582 //If the function fails, the temp file will be closed and deleted, |
|
1583 //the related Symbian OS error will be returned to the caller. |
|
1584 /* static */TInt TFileIo::DoCreateTempFile(TDbFile& aDbFile) |
|
1585 { |
|
1586 COsLayerData& osLayerData = COsLayerData::Instance(); |
|
1587 //TParse2 is used in order to avoid the need of another TFileName stack based variable |
|
1588 class TParse2 : public TParse |
|
1589 { |
|
1590 public: |
|
1591 inline TFileName& FileName() |
|
1592 { |
|
1593 return static_cast <TFileName&> (NameBuf()); |
|
1594 } |
|
1595 }; |
|
1596 TParse2 parse; |
|
1597 (void)parse.Set(osLayerData.iSysPrivDir, 0, 0);//this call can't fail |
|
1598 (void)parse.AddDir(KTempFileDir);//this call can't fail |
|
1599 __FS_CALL(EFsOpFileCreateTemp, 0); |
|
1600 TInt err = aDbFile.iFileBuf.Temp(osLayerData.iFs, parse.FullName(), parse.FileName(), EFileRead|EFileWrite|EDeleteOnClose); |
|
1601 if(err == KErrPathNotFound) |
|
1602 { |
|
1603 err = osLayerData.iFs.MkDirAll(parse.DriveAndPath()); |
|
1604 if(err == KErrNone) |
|
1605 { |
|
1606 err = aDbFile.iFileBuf.Temp(osLayerData.iFs, parse.FullName(), parse.FileName(), EFileRead|EFileWrite|EDeleteOnClose); |
|
1607 } |
|
1608 } |
|
1609 if(err == KErrNone) |
|
1610 { |
|
1611 TInt recReadBufSize = -1; |
|
1612 err = TVfs::DoGetDeviceCharacteristicsAndSectorSize(aDbFile, recReadBufSize); |
|
1613 if(err != KErrNone) |
|
1614 { |
|
1615 aDbFile.iFileBuf.Close();//With EDeleteOnClose flag set, the file will be deleted |
|
1616 } |
|
1617 else |
|
1618 { |
|
1619 (void)aDbFile.iFileBuf.SetReadAheadSize(aDbFile.iSectorSize, recReadBufSize); |
|
1620 aDbFile.iIsFileCreated = ETrue; |
|
1621 } |
|
1622 } |
|
1623 return err; |
|
1624 } |
|
1625 |
1576 /** |
1626 /** |
1577 SQLite OS porting layer API. |
1627 SQLite OS porting layer API. |
1578 |
1628 |
1579 Writes to the file referred by the aDbFile parameter. |
1629 Writes to the file referred by the aDbFile parameter. |
1580 "Write beyond the end of the file" operations are allowed. |
1630 "Write beyond the end of the file" operations are allowed. |
1581 |
1631 |
1582 If the write operation is in the 1st db file page and there is a registered "free pages" callback |
1632 If the write operation is in the 1st db file page and there is a registered "free pages" callback |
1583 (TDbFile::iFreePageCallback) and the free pages count is above the defined value, |
1633 (TDbFile::iFreePageCallback) and the free pages count is above the defined value, |
1584 then the callback will be called. |
1634 then the callback will be called. |
|
1635 |
|
1636 If the file to be written to is a temp file, which is not created yet, then the file will be created. |
1585 |
1637 |
1586 @param aDbFile A pointer to a TDbFile instance, that contains the file handle to be written to. |
1638 @param aDbFile A pointer to a TDbFile instance, that contains the file handle to be written to. |
1587 @param aData The data to be written to the file. The buffer size must be at least aAmt bytes. |
1639 @param aData The data to be written to the file. The buffer size must be at least aAmt bytes. |
1588 @param aAmt The amount of data to be written to the file. |
1640 @param aAmt The amount of data to be written to the file. |
1589 @param aOffset The offset in the file where the write operation should start. |
1641 @param aOffset The offset in the file where the write operation should start. |
1602 /* static */ int TFileIo::Write(sqlite3_file* aDbFile, const void* aData, int aAmt, sqlite3_int64 aOffset) |
1654 /* static */ int TFileIo::Write(sqlite3_file* aDbFile, const void* aData, int aAmt, sqlite3_int64 aOffset) |
1603 { |
1655 { |
1604 SQLUTRACE_PROFILER(aDbFile); |
1656 SQLUTRACE_PROFILER(aDbFile); |
1605 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileWrite, aAmt, aOffset)); |
1657 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileWrite, aAmt, aOffset)); |
1606 TDbFile& dbFile = ::DbFile(aDbFile); |
1658 TDbFile& dbFile = ::DbFile(aDbFile); |
1607 __OS_CALL(EOsFileWrite, 0, 0); |
1659 TInt err = KErrNone; |
|
1660 if(!dbFile.iIsFileCreated) |
|
1661 {//Create a temp file if it has not been created. |
|
1662 err = TFileIo::DoCreateTempFile(dbFile); |
|
1663 } |
|
1664 if(err != KErrNone) |
|
1665 { |
|
1666 COsLayerData::Instance().SetOsErrorCode(err); |
|
1667 return err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_FULL; |
|
1668 } |
|
1669 |
|
1670 __OS_CALL(EOsFileWrite, 0, 0); |
1608 __COUNTER_INCR(TheSqlSrvProfilerFileWrite); |
1671 __COUNTER_INCR(TheSqlSrvProfilerFileWrite); |
1609 __OSTIME_COUNTER(TheOsCallTicks[EOsFileWrite], ::OsCallProfile(dbFile.iIsJournal, EOsFileWrite), aOffset, aAmt, aDbFile, 0); |
1672 __OSTIME_COUNTER(TheOsCallTicks[EOsFileWrite], ::OsCallProfile(dbFile.iIsJournal, EOsFileWrite), aOffset, aAmt, aDbFile, 0); |
1610 TInt err = KErrAccessDenied; |
1673 err = KErrAccessDenied; |
1611 if(!dbFile.iReadOnly) |
1674 if(!dbFile.iReadOnly) |
1612 { |
1675 { |
1613 TPtrC8 ptr((const TUint8*)aData, aAmt); |
1676 TPtrC8 ptr((const TUint8*)aData, aAmt); |
1614 err = dbFile.iFileBuf.Write(aOffset, ptr); |
1677 err = dbFile.iFileBuf.Write(aOffset, ptr); |
1615 } |
1678 } |
1616 COsLayerData::Instance().SetOsErrorCode(err); |
1679 COsLayerData::Instance().SetOsErrorCode(err); |
1617 |
1680 |
1618 const TInt KFreePageCountOffset = 36;//hard-coded constant. SQLite does not offer anything - a constant or #define. |
1681 const TInt KFreePageCountOffset = 36;//hard-coded constant. SQLite does not offer anything - a constant or #define. |
1619 //The checks in the "if" bellow do: |
1682 //The checks in the "if" bellow do: |
1620 // - "err == KErrNone" - check the free page count only after a successful "write"; |
1683 // - "err == KErrNone" - check the free page count only after a successful "write"; |
1621 // - "aOffset == 0" - check the free page count only if the write operation affects the system page (at aOffset = 0); |
1684 // - "aOffset == 0" - check the free page count only if the write operation affects the system page (at aOffset = 0); |
1622 // - "aAmt >= (KFreePageCountOffset + sizeof(int))" - check the free page count only if the amount of bytes to be written |
1685 // - "aAmt >= (KFreePageCountOffset + sizeof(int))" - check the free page count only if the amount of bytes to be written |
1623 // is more than the offset of the free page counter (othewrise the free page counter is not affected |
1686 // is more than the offset of the free page counter (othewrise the free page counter is not affected |
1624 // by this write operation); |
1687 // by this write operation); |
1625 // - "dbFile.iFreePageCallback.IsValid()" - check the free page count only if there is a valid callback; |
1688 // - "dbFile.iFreePageCallback.IsValid()" - check the free page count only if there is a valid callback; |
1626 if(err == KErrNone && aOffset == 0 && aAmt >= (KFreePageCountOffset + sizeof(int)) && dbFile.iFreePageCallback.IsValid()) |
1689 if(err == KErrNone && aOffset == 0 && aAmt >= (KFreePageCountOffset + sizeof(int)) && dbFile.iFreePageCallback.IsValid()) |
1627 { |
1690 { |
1628 const TUint8* ptr = static_cast <const TUint8*> (aData) + KFreePageCountOffset; |
1691 const TUint8* ptr = static_cast <const TUint8*> (aData) + KFreePageCountOffset; |
1629 TInt freePageCount = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; |
1692 TInt freePageCount = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; |
1630 dbFile.iFreePageCallback.CheckAndCallback(freePageCount); |
1693 dbFile.iFreePageCallback.CheckAndCallback(freePageCount); |
1631 } |
1694 } |
1632 |
|
1633 return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_FULL); |
1695 return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_FULL); |
1634 } |
1696 } |
1635 |
1697 |
1636 /** |
1698 /** |
1637 SQLite OS porting layer API. |
1699 SQLite OS porting layer API. |
2231 |
2293 |
2232 @see COsLayerData::SetOsErrorCode() |
2294 @see COsLayerData::SetOsErrorCode() |
2233 @see TDbFile |
2295 @see TDbFile |
2234 */ |
2296 */ |
2235 /* static */ int TVfs::Open(sqlite3_vfs* aVfs, const char* aFileName, sqlite3_file* aDbFile, int aFlags, int* aOutFlags) |
2297 /* static */ int TVfs::Open(sqlite3_vfs* aVfs, const char* aFileName, sqlite3_file* aDbFile, int aFlags, int* aOutFlags) |
2236 { |
2298 { |
2237 SQLUTRACE_PROFILER(aVfs); |
2299 SQLUTRACE_PROFILER(aVfs); |
2238 __OS_CALL(EOsVfsOpen, 0, 0); |
2300 __OS_CALL(EOsVfsOpen, 0, 0); |
2239 __OSTIME_COUNTER(TheOsCallTicks[EOsVfsOpen], ::OsCallProfile(EFalse, EOsVfsOpen), 0, 0, aDbFile, aFileName); |
2301 __OSTIME_COUNTER(TheOsCallTicks[EOsVfsOpen], ::OsCallProfile(EFalse, EOsVfsOpen), 0, 0, aDbFile, aFileName); |
2240 COsLayerData& osLayerData = COsLayerData::Instance(); |
2302 |
2241 TFileName fname; |
2303 COsLayerData& osLayerData = COsLayerData::Instance(); |
2242 if(aFileName && !::ConvertToUnicode(aFileName, fname)) |
2304 TFhStrType fhStrType = ENotFhStr; |
2243 { |
2305 new (aDbFile) TDbFile; |
2244 osLayerData.SetOsErrorCode(KErrBadName); |
2306 TDbFile& dbFile = ::DbFile(aDbFile); |
2245 return SQLITE_CANTOPEN; |
2307 |
2246 } |
2308 if(!aFileName) |
2247 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileOpen, aDbFile, &fname)); |
2309 { |
2248 new (aDbFile) TDbFile; |
2310 //It is to create and open a temp file if aFileName is NULL. In this case, |
2249 TDbFile& dbFile = ::DbFile(aDbFile); |
2311 //we will defer the file creation util it is needed. |
2250 TFhStrType fhStrType = aFileName ? ::FhStringProps(aFileName) : ENotFhStr; |
2312 |
2251 if(aFileName && (aFlags & SQLITE_OPEN_DELETEONCLOSE)) |
2313 dbFile.pMethods = &TheFileIoApi; |
2252 { |
2314 dbFile.iIsFileCreated = EFalse; |
2253 dbFile.iFullName = fname.Alloc(); |
2315 if(aOutFlags) |
2254 if(!dbFile.iFullName) |
2316 { |
2255 { |
2317 *aOutFlags = SQLITE_OPEN_READWRITE; |
2256 osLayerData.SetOsErrorCode(KErrNoMemory); |
2318 } |
2257 return SQLITE_IOERR_NOMEM; |
2319 return SQLITE_OK; |
2258 } |
2320 } |
2259 } |
2321 |
2260 TInt recReadBufSize = -1; |
2322 TFileName fname; |
2261 TInt err = KErrNone; |
2323 if(!::ConvertToUnicode(aFileName, fname)) |
2262 if(fhStrType == EFhMainDbStr) |
2324 { |
2263 {//Main db file, open from handle |
2325 osLayerData.SetOsErrorCode(KErrBadName); |
2264 const RMessage2* msg; |
2326 return SQLITE_CANTOPEN; |
2265 TBool readOnly; |
2327 } |
2266 osLayerData.RetrieveAndResetFhData(msg, readOnly); |
2328 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileOpen, aDbFile, &fname)); |
2267 err = msg != NULL ? TVfs::DoOpenFromHandle(dbFile, *msg, readOnly) : KErrGeneral; |
2329 fhStrType = ::FhStringProps(aFileName); |
2268 } |
2330 TInt err = KErrNone; |
2269 else |
2331 TInt recReadBufSize = -1; |
2270 { |
2332 if(fhStrType == EFhMainDbStr) |
2271 if(fhStrType == EFhStr) |
2333 {//Main db file, open from handle |
2272 {//Not the main db file. Remove invalid characters in the file name |
2334 const RMessage2* msg; |
2273 ::FhConvertToFileName(fname, osLayerData.iSysPrivDir);//If fname does not have a path, iSysPrivDir will be used |
2335 TBool readOnly; |
2274 } |
2336 osLayerData.RetrieveAndResetFhData(msg, readOnly); |
2275 TInt fmode = EFileRead; |
2337 err = msg != NULL ? TVfs::DoOpenFromHandle(dbFile, *msg, readOnly) : KErrGeneral; |
2276 if(aFlags & SQLITE_OPEN_READWRITE) |
2338 } |
2277 { |
2339 else |
2278 fmode |= EFileWrite; |
2340 { |
2279 } |
2341 if(fhStrType == EFhStr) |
2280 if(aFlags & SQLITE_OPEN_EXCLUSIVE) |
2342 {//Not the main db file. Remove invalid characters in the file name |
2281 { |
2343 ::FhConvertToFileName(fname, osLayerData.iSysPrivDir);//If fname does not have a path, iSysPrivDir will be used |
2282 fmode |= EFileShareExclusive; |
2344 } |
2283 } |
2345 TInt fmode = EFileRead; |
2284 if(!aFileName) |
2346 if(aFlags & SQLITE_OPEN_READWRITE) |
2285 { |
2347 { |
2286 __FS_CALL(EFsOpFileCreateTemp, 0); |
2348 fmode |= EFileWrite; |
2287 err = dbFile.iFileBuf.Temp(osLayerData.iFs, osLayerData.iSysPrivDir, fname, fmode); |
2349 } |
2288 if(err == KErrNone) |
2350 if(aFlags & SQLITE_OPEN_EXCLUSIVE) |
2289 { |
2351 { |
2290 dbFile.iFullName = fname.Alloc(); |
2352 fmode |= EFileShareExclusive; |
2291 if(!dbFile.iFullName) |
2353 } |
2292 { |
2354 err = KErrAccessDenied; |
2293 err = KErrNoMemory; |
2355 TInt prevErr = KErrNone; |
2294 } |
2356 if(aFlags & SQLITE_OPEN_DELETEONCLOSE) |
2295 } |
2357 { |
2296 } |
2358 fmode |= EDeleteOnClose; |
2297 else |
2359 } |
2298 { |
2360 if(aFlags & SQLITE_OPEN_CREATE) |
2299 err = KErrAccessDenied; |
2361 { |
2300 TInt prevErr = KErrNone; |
2362 __FS_CALL(EFsOpFileCreate, 0); |
2301 if(aFlags & SQLITE_OPEN_CREATE) |
2363 prevErr = err = dbFile.iFileBuf.Create(osLayerData.iFs, fname, fmode); |
2302 { |
2364 } |
2303 __FS_CALL(EFsOpFileCreate, 0); |
2365 if(err != KErrNone && err != KErrNoMemory && err != KErrDiskFull) |
2304 prevErr = err = dbFile.iFileBuf.Create(osLayerData.iFs, fname, fmode); |
2366 { |
2305 } |
2367 __FS_CALL(EFsOpFileOpen, 0); |
2306 if(err != KErrNone && err != KErrNoMemory && err != KErrDiskFull) |
2368 err = dbFile.iFileBuf.Open(osLayerData.iFs, fname, fmode); |
2307 { |
2369 |
2308 __FS_CALL(EFsOpFileOpen, 0); |
2370 if(err == KErrNone && (aFlags & KJournalFileTypeBitMask)) |
2309 err = dbFile.iFileBuf.Open(osLayerData.iFs, fname, fmode); |
2371 { |
2310 |
|
2311 if(err == KErrNone && (aFlags & KJournalFileTypeBitMask)) |
|
2312 { |
|
2313 err = TVfs::DoFileSizeCorruptionCheck(dbFile, fname, fmode); |
2372 err = TVfs::DoFileSizeCorruptionCheck(dbFile, fname, fmode); |
2314 } |
2373 } |
2315 } |
2374 } |
2316 if((err != KErrNone && err != KErrNoMemory && err != KErrDiskFull) && (aFlags & SQLITE_OPEN_READWRITE)) |
2375 if((err != KErrNone && err != KErrNoMemory && err != KErrDiskFull) && (aFlags & SQLITE_OPEN_READWRITE)) |
2317 { |
2376 { |
2318 aFlags &= ~SQLITE_OPEN_READWRITE; |
2377 aFlags &= ~SQLITE_OPEN_READWRITE; |
2319 aFlags |= SQLITE_OPEN_READONLY; |
2378 aFlags |= SQLITE_OPEN_READONLY; |
2320 fmode &= ~EFileWrite; |
2379 fmode &= ~EFileWrite; |
2321 __FS_CALL(EFsOpFileOpen, 0); |
2380 __FS_CALL(EFsOpFileOpen, 0); |
2322 err = dbFile.iFileBuf.Open(osLayerData.iFs, fname, fmode); |
2381 err = dbFile.iFileBuf.Open(osLayerData.iFs, fname, fmode); |
2323 } |
2382 } |
2324 if(err != KErrNone && prevErr == KErrAccessDenied) |
2383 if(err != KErrNone && prevErr == KErrAccessDenied) |
2325 { |
2384 { |
2326 err = KErrAccessDenied; |
2385 err = KErrAccessDenied; |
2327 } |
2386 } |
2328 } |
2387 } |
2329 } |
2388 if(err == KErrNone) |
2330 if(err == KErrNone) |
2389 { |
2331 { |
2390 err = TVfs::DoGetDeviceCharacteristicsAndSectorSize(dbFile, recReadBufSize); |
2332 err = TVfs::DoGetDeviceCharacteristicsAndSectorSize(dbFile, recReadBufSize); |
2391 } |
2333 } |
2392 |
2334 osLayerData.SetOsErrorCode(err); |
2393 osLayerData.SetOsErrorCode(err); |
2335 if(err != KErrNone) |
2394 if(err != KErrNone) |
2336 { |
2395 { |
2337 __FS_CALL(EFsOpFileClose, 0); |
2396 __FS_CALL(EFsOpFileClose, 0); |
2338 dbFile.iFileBuf.Close(); |
2397 dbFile.iFileBuf.Close(); |
2339 delete dbFile.iFullName; |
|
2340 dbFile.iFullName = NULL; |
|
2341 if(!aFileName && fname.Length() > 0) |
|
2342 {//temporary file, the error is not KErrNone. Then delete the file (after a successfull |
|
2343 //temporary file creation there could be a failed memory allocation) |
|
2344 (void)osLayerData.iFs.Delete(fname); |
|
2345 } |
|
2346 } |
2398 } |
2347 else |
2399 else |
2348 { |
2400 { |
2349 dbFile.pMethods = &TheFileIoApi; |
2401 dbFile.pMethods = &TheFileIoApi; |
2350 if(fhStrType != EFhMainDbStr) |
2402 if(fhStrType != EFhMainDbStr) |