bool TranslationManager::openTranslationsFile(const FSNode &node, File &inFile, int depth) { if (!node.exists() || !node.isReadable() || !node.isDirectory()) return false; // Check if we can find the file in this directory // Since File::open(FSNode) makes all the needed tests, it is not really // necessary to make them here. But it avoid printing warnings. FSNode fileNode = node.getChild("translations.dat"); if (fileNode.exists() && fileNode.isReadable() && !fileNode.isDirectory()) { if (inFile.open(fileNode)) { if (checkHeader(inFile)) return true; inFile.close(); } } // Check if we exceeded the given recursion depth if (depth - 1 == -1) return false; // Otherwise look for it in sub-directories FSList fileList; if (!node.getChildren(fileList, FSNode::kListDirectoriesOnly)) return false; for (FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) { if (openTranslationsFile(*i, inFile, depth == -1 ? - 1 : depth - 1)) return true; } // Not found in this directory or its sub-directories return false; }
void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority) { FSList subDirs; if (!directory.getChildren(subDirs)) return; String nextPattern, pattern; String::const_iterator sep = Common::find(origPattern.begin(), origPattern.end(), '/'); if (sep != origPattern.end()) { pattern = String(origPattern.begin(), sep); ++sep; if (sep != origPattern.end()) nextPattern = String(sep, origPattern.end()); } else { pattern = origPattern; } // TODO: The code we have for displaying all matches, which vary only in case, might // be a bit overhead, but as long as we want to display all useful information to the // user we will need to keep track of all directory names added so far. We might // want to reconsider this though. typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> MatchList; MatchList multipleMatches; MatchList::iterator matchIter; for (FSList::const_iterator i = subDirs.begin(); i != subDirs.end(); ++i) { String name = i->getName(); if (Common::matchString(name.c_str(), pattern.c_str(), ignoreCase)) { matchIter = multipleMatches.find(name); if (matchIter == multipleMatches.end()) { multipleMatches[name] = true; } else { if (matchIter->_value) { warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), matchIter->_key.c_str()); matchIter->_value = false; } warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), name.c_str()); } if (nextPattern.empty()) addDirectory(name, *i, priority); else addSubDirectoriesMatching(*i, nextPattern, ignoreCase, priority); } } }
bool OperCFThread::DeleteList( FS* fs, FSPath& _path, FSList& list ) { if ( Info()->Stopped() ) { return false; } FSPath path = _path; int cnt = path.Count(); for ( FSNode* node = list.First(); node; node = node->next ) { if ( node->extType ) { continue; } path.SetItemStr( cnt, node->Name() ); if ( node->IsDir() && !node->st.IsLnk() ) { if ( !DeleteDir( fs, path ) ) { return false; } if ( !RmDir( fs, path ) ) { return false; } continue; } if ( !DeleteFile( fs, path ) ) { return false; } } return true; }
bool FSNode::getChildren(FSList &fslist, ListMode mode, bool hidden) const { if (!_realNode || !_realNode->isDirectory()) return false; AbstractFSList tmp; if (!_realNode->getChildren(tmp, mode, hidden)) return false; fslist.clear(); for (AbstractFSList::iterator i = tmp.begin(); i != tmp.end(); ++i) { fslist.push_back(FSNode(*i)); } return true; }
bool DeleteListRecursively( FS* fs, FSPath path, FSList& list ) { const int cnt = path.Count(); int ret_err; for ( FSNode* node = list.First(); node; node = node->next ) { if ( node->extType ) { continue; } path.SetItemStr( cnt, node->Name() ); if ( node->IsDir() && !node->st.IsLnk() ) { if ( !DeleteDirRecursively( fs, path ) ) { return false; } } else if ( fs->Delete( path, &ret_err, nullptr ) != 0 ) { return false; } } return true; }
bool FilesystemNode::listDir(FSList &fslist, ListMode mode) const { if (!_realNode || !_realNode->isDirectory()) return false; AbstractFSList tmp; if (!_realNode->listDir(tmp, mode)) return false; fslist.clear(); for (AbstractFSList::iterator i = tmp.begin(); i != tmp.end(); ++i) { fslist.push_back(FilesystemNode(*i)); } return true; }
bool OperCFThread::CopyDir(FS *srcFs, FSPath &__srcPath, FSNode *srcNode, FS *destFs, FSPath &__destPath, bool move) { if (Info()->Stopped()) return false; FSList list; int ret_error; while (true) { int ret = srcFs->ReadDir(&list, __srcPath, &ret_error, Info()); if (ret == -2) return false; if (!ret) break; switch ( RedMessage( _LT("Can`t open directory:\n") , srcFs->Uri(__srcPath).GetUtf8(), bRetrySkipCancel, srcFs->StrError(ret_error).GetUtf8()) ) { case CMD_SKIP: return true; case CMD_RETRY: continue; default: return false; } } while (destFs->MkDir(__destPath, MkDirMode, &ret_error, Info()) && !destFs->IsEEXIST(ret_error)) { switch (RedMessage( _LT("Can't create the directory:\n"), destFs->Uri(__destPath).GetUtf8(), bRetrySkipCancel, destFs->StrError(ret_error).GetUtf8())) { case CMD_CANCEL: return false; case CMD_SKIP: return true; } } FSPath srcPath = __srcPath; int srcPos = srcPath.Count(); FSPath destPath = __destPath; int destPos = destPath.Count(); for (FSNode *node = list.First(); node; node = node->next) { if (Info()->Stopped()) return false; srcPath.SetItemStr(srcPos, node->Name()); destPath.SetItemStr(destPos, node->Name()); if (!CopyNode(srcFs, srcPath, node, destFs, destPath, move)) return false; } destFs->SetFileTime(destPath, srcNode->st.mtime, srcNode->st.mtime, 0, Info()); return !move || RmDir(srcFs, __srcPath); }
void Sword1CheckDirectory(const FSList &fslist, bool *filesFound) { for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (!file->isDirectory()) { const char *fileName = file->displayName().c_str(); for (int cnt = 0; cnt < NUM_FILES_TO_CHECK; cnt++) if (scumm_stricmp(fileName, g_filesToCheck[cnt]) == 0) filesFound[cnt] = true; } else { for (int cnt = 0; cnt < ARRAYSIZE(g_dirNames); cnt++) if (scumm_stricmp(file->displayName().c_str(), g_dirNames[cnt]) == 0) { FSList fslist2; if (file->listDir(fslist2, FilesystemNode::kListFilesOnly)) Sword1CheckDirectory(fslist2, filesFound); } } } }
DetectedGameList Engine_GOB_detectGames(const FSList &fslist) { DetectedGameList detectedGames; const GameSettings *g; FSList::const_iterator file; // Iterate over all files in the given directory for (file = fslist.begin(); file != fslist.end(); file++) { if (file->isDirectory()) continue; // All the supported games have an intro.stk file. if (scumm_stricmp(file->displayName().c_str(), "intro.stk") == 0) break; } if (file == fslist.end()) return detectedGames; uint8 md5sum[16]; char md5str[32 + 1]; if (Common::md5_file(file->path().c_str(), md5sum, kMD5FileSizeLimit)) { for (int i = 0; i < 16; i++) { sprintf(md5str + i * 2, "%02x", (int)md5sum[i]); } for (g = gob_games; g->gameid; g++) { if (strcmp(g->md5sum, (char *)md5str) == 0) { detectedGames.push_back(DetectedGame(g->gameid, g->description)); } } if (detectedGames.empty()) { printf("Unknown MD5 (%s)! Please report the details (language, platform, etc.) of this game to the ScummVM team\n", md5str); const PlainGameDescriptor *g1 = gob_list; while (g1->gameid) { detectedGames.push_back(*g1); g1++; } } } return detectedGames; }
void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level, const String &prefix) { if (level <= 0) return; FSList fslist; if (!dir.listDir(fslist, FilesystemNode::kListAll)) { // Failed listing the contents of this node, so it is either not a // directory, or just doesn't exist at all. return; } if (!_defaultDirectories) _defaultDirectories = new StringIntMap; // Do not add directories multiple times, unless this time they are added // with a bigger depth. const String &directory(dir.path()); if (_defaultDirectories->contains(directory) && (*_defaultDirectories)[directory] >= level) return; (*_defaultDirectories)[directory] = level; if (!_filesMap) _filesMap = new FilesMap; for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (file->isDirectory()) { addDefaultDirectoryRecursive(file->path(), level - 1, prefix + file->displayName() + "/"); } else { String lfn(prefix); lfn += file->displayName(); lfn.toLowercase(); if (!_filesMap->contains(lfn)) { (*_filesMap)[lfn] = file->path(); } } } }
void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& prefix) const { if (depth <= 0) return; FSList list; node.getChildren(list, FSNode::kListAll, true); FSList::iterator it = list.begin(); for ( ; it != list.end(); ++it) { String name = prefix + it->getName(); // don't touch name as it might be used for warning messages String lowercaseName = name; lowercaseName.toLowercase(); // since the hashmap is case insensitive, we need to check for clashes when caching if (it->isDirectory()) { if (!_flat && _subDirCache.contains(lowercaseName)) { warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring sub-directory '%s'", name.c_str()); } else { if (_subDirCache.contains(lowercaseName)) { warning("FSDirectory::cacheDirectory: name clash when building subDirCache with subdirectory '%s'", name.c_str()); } cacheDirectoryRecursive(*it, depth - 1, _flat ? prefix : lowercaseName + "/"); _subDirCache[lowercaseName] = *it; } } else { if (_fileCache.contains(lowercaseName)) { warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring file '%s'", name.c_str()); } else { _fileCache[lowercaseName] = *it; } } } }
int OperCFThread::MoveDir( FS* srcFs, FSPath& __srcPath, FSNode* srcNode, FS* destFs, FSPath& __destPath ) { if ( Info()->Stopped() ) { return -1; } if ( srcFs != destFs ) { return 1; } FSPath srcPath = __srcPath; int srcPos = srcPath.Count(); FSPath destPath = __destPath; int destPos = destPath.Count(); if ( IsSameFile( srcFs, srcPath, &( srcNode->st ), destFs, destPath ) ) { RedMessage( _LT( "Can't move directory to itself:\n" ), srcFs->Uri( __srcPath ).GetUtf8() ); return -1; } FSStat st; int ret_error; if ( !destFs->Stat( destPath, &st, &ret_error, Info() ) ) { if ( !st.IsDir() ) { switch ( RedMessage( _LT( "Can't copy directory\n" ), srcFs->Uri( srcPath ).GetUtf8(), _LT( "to file" ), "\n", _LT( "Delete the file?" ), destFs->Uri( destPath ).GetUtf8(), bOkSkipCancel ) ) { case CMD_CANCEL: return -1; case CMD_SKIP: return 0; } if ( !Unlink( destFs, destPath ) ) { return -1; } } else { FSList list; while ( true ) { int ret = srcFs->ReadDir( &list, srcPath, &ret_error, Info() ); if ( ret == -2 ) { return -1; } if ( !ret ) { break; } switch ( RedMessage( _LT( "Can`t open directory:\n" ), srcFs->Uri( __srcPath ).GetUtf8(), bRetrySkipCancel, srcFs->StrError( ret_error ).GetUtf8() ) ) { case CMD_SKIP: return 0; case CMD_RETRY: continue; default: return -1; } } for ( FSNode* node = list.First(); node; node = node->next ) { if ( Info()->Stopped() ) { return -1; } srcPath.SetItemStr( srcPos, node->Name() ); destPath.SetItemStr( destPos, node->Name() ); if ( !MoveFile( srcFs, srcPath, node, destFs, destPath ) ) { return -1; } } destFs->SetFileTime( destPath, srcNode->st.m_CreationTime, srcNode->st.m_LastWriteTime, srcNode->st.m_LastWriteTime, 0, Info() ); return RmDir( srcFs, srcPath ) ? 0 : -1; } } if ( srcFs->Rename( srcPath, destPath, &ret_error, Info() ) ) { if ( srcFs->IsEXDEV( ret_error ) ) { return 1; } return RedMessage( _LT( "Can't rename the directory:\n" ), srcFs->Uri( srcPath ).GetUtf8(), "\nto\n", destFs->Uri( destPath ).GetUtf8(), bSkipCancel, srcFs->StrError( ret_error ).GetUtf8() ) == CMD_SKIP ? 0 : -1; } return 0; }
int64_t OperDirCalcThread::CalcDir( FS* fs, FSPath path ) { if ( Info()->Stopped() ) { return -1; } { //lock MutexLock lock( Node().GetMutex() ); if ( !Node().Data() ) { return -1; } OperDirCalcData* data = ( OperDirCalcData* )Node().Data(); MutexLock l1( &data->resMutex ); data->currentPath = path; } Node().SendSignal( 10 ); FSList list; int err; if ( fs->ReadDir( &list, path, &err, Info() ) ) { MutexLock lock( Node().GetMutex() ); if ( !Node().Data() ) { return -1; } MutexLock l1( &( ( OperDirCalcData* )Node().Data() )->resMutex ); ( ( OperDirCalcData* )Node().Data() )->badDirs++; return -1; }; int count = list.Count(); std::vector<FSNode*> p = list.GetArray(); //list.SortByName(p.ptr(), count, true, false); int lastPathPos = path.Count(); FSPath filePath = path; int64_t fileCount = 0; int64_t folderCount = 0; int64_t sumSize = 0; int i; for ( i = 0; i < count; i++ ) { if ( p[i]->IsDir() ) { folderCount++; continue; }; fileCount++; if ( p[i]->IsReg() && !p[i]->IsLnk() ) { sumSize += p[i]->Size(); } } { //lock MutexLock lock( Node().GetMutex() ); if ( !Node().Data() ) { return -1; } OperDirCalcData* data = ( OperDirCalcData* )Node().Data(); MutexLock l1( &data->resMutex ); data->fileCount += fileCount; data->folderCount += folderCount; data->sumSize += sumSize; } Node().SendSignal( 20 ); for ( i = 0; i < count; i++ ) { if ( p[i]->IsDir() && !p[i]->extType && p[i]->st.link.IsEmpty() ) { if ( Info()->Stopped() ) { return -1; } path.SetItemStr( lastPathPos, p[i]->Name() ); sumSize += CalcDir( fs, path ); } } return sumSize; }