static bool ShouldReplaceWith(const VfsFile& previousFile, const VfsFile& newFile) { // 1) priority (override mods) if(newFile.Priority() < previousFile.Priority()) return false; if(newFile.Priority() > previousFile.Priority()) return true; // 2) timestamp { const double howMuchNewer = difftime(newFile.MTime(), previousFile.MTime()); const double threshold = 2.0; // FAT timestamp resolution [seconds] if(howMuchNewer > threshold) // newer return true; if(howMuchNewer < -threshold) // older return false; // else: "equal" (tolerating small differences due to FAT's low // mtime resolution) } // 3) precedence (efficiency of file provider) if(newFile.Loader()->Precedence() < previousFile.Loader()->Precedence()) return false; return true; }
virtual Status GetRealPath(const VfsPath& pathname, OsPath& realPathname) { ScopedLock s; VfsDirectory* directory; VfsFile* file; WARN_RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, &file)); realPathname = file->Loader()->Path() / pathname.Filename(); return INFO::OK; }
std::wstring FileDescription(const VfsFile& file) { wchar_t timestamp[25]; const time_t mtime = file.MTime(); wcsftime(timestamp, ARRAY_SIZE(timestamp), L"%a %b %d %H:%M:%S %Y", localtime(&mtime)); wchar_t buf[200]; swprintf_s(buf, ARRAY_SIZE(buf), L"(%c; %6lu; %ls) %ls", file.Loader()->LocationCode(), (unsigned long)file.Size(), timestamp, file.Name().string().c_str()); return buf; }
virtual Status LoadFile(const VfsPath& pathname, shared_ptr<u8>& fileContents, size_t& size) { ScopedLock s; const bool isCacheHit = m_fileCache.Retrieve(pathname, fileContents, size); if(!isCacheHit) { VfsDirectory* directory; VfsFile* file; // per 2010-05-01 meeting, this shouldn't raise 'scary error // dialogs', which might fail to display the culprit pathname // instead, callers should log the error, including pathname. RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, &file)); fileContents = DummySharedPtr((u8*)0); size = file->Size(); if(size != 0) // (the file cache can't handle zero-length allocations) { if(size < m_cacheSize/2) // (avoid evicting lots of previous data) fileContents = m_fileCache.Reserve(size); if(fileContents) { RETURN_STATUS_IF_ERR(file->Loader()->Load(file->Name(), fileContents, file->Size())); m_fileCache.Add(pathname, fileContents, size); } else { RETURN_STATUS_IF_ERR(AllocateAligned(fileContents, size, maxSectorSize)); RETURN_STATUS_IF_ERR(file->Loader()->Load(file->Name(), fileContents, file->Size())); } } } stats_io_user_request(size); stats_cache(isCacheHit? CR_HIT : CR_MISS, size); m_trace->NotifyLoad(pathname, size); return INFO::OK; }