inline bool FindModule(std::string baseName, std::string *fileName, Module *hint) { // Try first in the current directory. if(ExistsFile(baseName)) { *fileName = baseName; return true; } // Now, use the hint. if(hint) { // Check in the same directory as the module. std::string modDir = DirName(hint->GetName().filename); *fileName = JoinPath(modDir, baseName); if(ExistsFile(*fileName)) return true; // Check in the library search path. for(size_t i = 0; i < hint->GetLibraryPathCount(); ++i) { *fileName = JoinPath(hint->GetLibraryPath(i), baseName); if(ExistsFile(*fileName)) return true; } } return false; }
int CompressPath(char *dest, const char *src) { char node[CF_BUFSIZE]; int nodelen; int rootlen; memset(dest, 0, CF_BUFSIZE); rootlen = RootDirLength(src); strncpy(dest, src, rootlen); for (const char *sp = src + rootlen; *sp != '\0'; sp++) { if (IsFileSep(*sp)) { continue; } for (nodelen = 0; (sp[nodelen] != '\0') && (!IsFileSep(sp[nodelen])); nodelen++) { if (nodelen > CF_MAXLINKSIZE) { Log(LOG_LEVEL_ERR, "Link in path suspiciously large"); return false; } } strncpy(node, sp, nodelen); node[nodelen] = '\0'; sp += nodelen - 1; if (strcmp(node, ".") == 0) { continue; } if (strcmp(node, "..") == 0) { if (!ChopLastNode(dest)) { Log(LOG_LEVEL_DEBUG, "used .. beyond top of filesystem!"); return false; } continue; } else { AddSlash(dest); } if (!JoinPath(dest, node)) { return false; } } return true; }
HelpWindow::HelpWindow() { resize( 600,500); QTextEdit* content = new QTextEdit(); content->setReadOnly(true); { QFile file( JoinPath(g_App->DataPath(), "help.html").c_str() ); if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { QString help_txt; help_txt = file.readAll(); content->setHtml(help_txt); } } QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); connect(buttonBox, SIGNAL(accepted()), this, SLOT(hide())); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(content); mainLayout->addWidget(buttonBox); setLayout(mainLayout); setWindowTitle(tr("Help")); }
bool CRConFiles::CheckParentFolders(LPCWSTR asParentDir, LPCWSTR asFilePath, CEStr& szFull) { bool bFound = false; // Try to go to parent folder (useful while browsing git-diff-s or #include-s) CEStr lsParent = asParentDir; MBoxAssert(lsParent.ms_Val && !wcschr(lsParent.ms_Val, L'/')); // WinPath is expected for (int i = 6; i >= 0; --i) { wchar_t* pszDirSlash = wcsrchr(lsParent.ms_Val, L'\\'); // Stop on the network server's root and drive letter if (!pszDirSlash || (pszDirSlash - lsParent.ms_Val) <= 2 || *(pszDirSlash-1) == L':') break; *pszDirSlash = 0; // Does it exist? if ((bFound = FileExistSubDir(lsParent, asFilePath, 1, szFull))) break; // Don't try to go upper, if current folder already contains ".git" (root of the repo) if (i > 0) { CEStr szGit(JoinPath(lsParent, L".git")); if (DirectoryExists(szGit)) break; } } return bFound; }
bool CConEmuStart::FindBashLocation(CEStr& lsBash) { wchar_t szRoot[MAX_PATH+32], *pszSlash; wcscpy_c(szRoot, gpConEmu->ms_ConEmuExeDir); LPCWSTR pszPlaces[] = { L"\\msys\\1.0\\bin\\bash.exe", // Msys/MinGW L"\\bin\\bash.exe", // Git-Bash L"\\usr\\bin\\bash.exe", // Git-For-Windows NULL }; // Before ConEmu.exe was intended to be in /bin/ folder // With Git-For-Windows it may be places in /opt/bin/ subfolder // So we do searching with two steps for (size_t i = 0; i <= 1; i++) { pszSlash = wcsrchr(szRoot, L'\\'); if (pszSlash) *pszSlash = 0; for (size_t j = 0; pszPlaces[j]; j++) { lsBash = JoinPath(szRoot, pszPlaces[j]); if (FileExists(lsBash)) { return true; } } } // Last chance, without path lsBash = L"bash.exe"; return false; }
void ForceDir(const char* dir) { if (dir != NULL) { const char* startDir = dir; #if defined(CFG_OS_WINDOWS) // Skip "X:" (if dir is Windows file path) if (startDir[0] != '\0' && startDir[1] == ':') startDir += 2; #endif // Skip \\ and // (if dir is network path) while (IsPathDelimiter(*startDir)) ++startDir; // Split path into parts and add server name if dir is network path MultiString dirs(startDir, FILE_PATH_DELIMITERS, NULL); std::string path(dir, startDir - dir); int i = 0; if (startDir != dir && dirs.word_count() > 0) // if dir is network path { path.append(dirs.word(0)); i = 1; } // Create directories while (i < dirs.word_count()) { path = JoinPath(path.c_str(), dirs.word(i)); if (!DirExists(path.c_str())) CreateDir(path.c_str()); ++i; } } else throw CreateArgumentNullException(); }
bool FileEnumerator::MoveNext() { bool result = false; if (!m_StartupDir.empty()) { if (m_CurrentNonRecursiveEnumerator == NULL) m_CurrentNonRecursiveEnumerator = new NonRecursiveFileEnumerator(NULL, m_StartupDir.c_str()); // Enter directory if mode is recursive if ((m_Flags & DIRENUM_RECURSIVE_MODE) != 0 && !m_CurrentNonRecursiveEnumerator->Bof() && !m_CurrentNonRecursiveEnumerator->Eof() && IsDir(CurrentPath())) { //std::string s = m_EntriesEnumerator->StartupDir(); std::string s = JoinPath(CurrentDir(), m_CurrentNonRecursiveEnumerator->CurrentFileName()); m_CurrentNonRecursiveEnumerator = new NonRecursiveFileEnumerator(m_CurrentNonRecursiveEnumerator, s.c_str()); } // Find next entry result = m_CurrentNonRecursiveEnumerator->MoveNext(); while (!result && m_CurrentNonRecursiveEnumerator->Parent() != NULL) { // Go to the parent directory NonRecursiveFileEnumerator* p = m_CurrentNonRecursiveEnumerator; m_CurrentNonRecursiveEnumerator = p->Parent(); delete p; result = m_CurrentNonRecursiveEnumerator->MoveNext(); } m_Flags &= ~DIRENUM_CURRENT_CACHED; } return result; }
bool GetRepositoryPath(const char *file, Attributes attr, char *destination) { if ((attr.repository == NULL) && (VREPOSITORY == NULL)) { return false; } size_t repopathlen; if (attr.repository != NULL) { repopathlen = strlcpy(destination, attr.repository, CF_BUFSIZE); } else { repopathlen = strlcpy(destination, VREPOSITORY, CF_BUFSIZE); } if (!JoinPath(destination, file)) { Log(LOG_LEVEL_ERR, "Internal limit, buffer ran out of space for long filename"); return false; } for (char *s = destination + repopathlen; *s; s++) { if (*s == FILE_SEPARATOR) { *s = REPOSCHAR; } } return true; }
void UnitFileNamesTest() { _ASSERTE(IsDotsName(L".")); _ASSERTE(IsDotsName(L"..")); _ASSERTE(!IsDotsName(L"...")); _ASSERTE(!IsDotsName(L"")); struct { LPCWSTR asPath, asPart1, asPart2, asResult; } Tests[] = { {L"C:", L"Dir", L"File.txt", L"C:\\Dir\\File.txt"}, {L"C:\\", L"\\Dir\\", L"\\File.txt", L"C:\\Dir\\File.txt"}, {L"C:\\", L"\\File.txt", NULL, L"C:\\File.txt"}, {L"C:", L"\\File.txt", NULL, L"C:\\File.txt"}, {L"C:\\", L"File.txt", NULL, L"C:\\File.txt"}, {NULL} }; bool bCheck; wchar_t* pszJoin; for (size_t i = 0; Tests[i].asPath; i++) { pszJoin = JoinPath(Tests[i].asPath, Tests[i].asPart1, Tests[i].asPart2); bCheck = (pszJoin && (lstrcmp(pszJoin, Tests[i].asResult) == 0)); _ASSERTE(bCheck); SafeFree(pszJoin); } bCheck = true; }
bool NonRecursiveFileEnumerator::DoMoveNext() { bool result = false; #ifdef CFG_WIN32 if (m_Data != NULL) { if (m_Handle == NULL_HANDLE) { std::string t = JoinPath(m_StartupDir.c_str(), "*"); // Windows always expects wildcard m_Handle = FindFirstFile(t.c_str(), m_Data); result = m_Handle != NULL_HANDLE; } else result = FindNextFile(m_Handle, m_Data) == TRUE; } #endif #ifdef CFG_POSIX if (m_Handle != NULL_HANDLE) { m_Data = readdir(m_Handle); result = m_Data != NULL; } #endif if (!result) Finalize(); return result; }
bool SBMLModelSimulation::SetModelFileName(const string& name) { if(ExtractFilePath(name).size() > 0) { mModelFilePath = ExtractFilePath(name); } mModelFileName = ExtractFileName(name); if(!FileExists(JoinPath(mModelFilePath, mModelFileName))) { Log(lError)<<"The file: "<<JoinPath(mModelFilePath, mModelFileName)<<" don't exist."; return false; } return true; }
int ArchiveToRepository(const char *file, Attributes attr, Promise *pp, const ReportContext *report_context) /* Returns true if the file was backup up and false if not */ { char destination[CF_BUFSIZE]; struct stat sb, dsb; if (!GetRepositoryPath(file, attr, destination)) { return false; } if (attr.copy.backup == cfa_nobackup) { return true; } if (IsItemIn(VREPOSLIST, file)) { CfOut(OUTPUT_LEVEL_INFORM, "", "The file %s has already been moved to the repository once. Multiple update will cause loss of backup.", file); return true; } ThreadLock(cft_getaddr); PrependItemList(&VREPOSLIST, file); ThreadUnlock(cft_getaddr); CfDebug("Repository(%s)\n", file); JoinPath(destination, CanonifyName(file)); if (!MakeParentDirectory(destination, attr.move_obstructions, report_context)) { } if (cfstat(file, &sb) == -1) { CfDebug("File %s promised to archive to the repository but it disappeared!\n", file); return true; } cfstat(destination, &dsb); CheckForFileHoles(&sb, pp); if (pp && CopyRegularFileDisk(file, destination, pp->makeholes)) { CfOut(OUTPUT_LEVEL_INFORM, "", "Moved %s to repository location %s\n", file, destination); return true; } else { CfOut(OUTPUT_LEVEL_INFORM, "", "Failed to move %s to repository location %s\n", file, destination); return false; } }
const char* FileEnumerator::CurrentPath() { if ((m_Flags & DIRENUM_CURRENT_CACHED) == 0) { m_Current = JoinPath(CurrentDir(), CurrentFileName()); m_Flags |= DIRENUM_CURRENT_CACHED; } return m_Current.c_str(); }
int ArchiveToRepository(const char *file, Attributes attr) /* Returns true if the file was backup up and false if not */ { char destination[CF_BUFSIZE]; struct stat sb, dsb; if (!GetRepositoryPath(file, attr, destination)) { return false; } if (attr.copy.backup == BACKUP_OPTION_NO_BACKUP) { return true; } if (IsItemIn(VREPOSLIST, file)) { Log(LOG_LEVEL_INFO, "The file '%s' has already been moved to the repository once. Multiple update will cause loss of backup.", file); return true; } ThreadLock(cft_getaddr); PrependItemList(&VREPOSLIST, file); ThreadUnlock(cft_getaddr); JoinPath(destination, CanonifyName(file)); if (!MakeParentDirectory(destination, attr.move_obstructions)) { } if (stat(file, &sb) == -1) { Log(LOG_LEVEL_DEBUG, "File '%s' promised to archive to the repository but it disappeared!", file); return true; } stat(destination, &dsb); if (CopyRegularFileDisk(file, destination)) { Log(LOG_LEVEL_INFO, "Moved '%s' to repository location '%s'", file, destination); return true; } else { Log(LOG_LEVEL_INFO, "Failed to move '%s' to repository location '%s'", file, destination); return false; } }
bool SBMLModelSimulation::SaveResult() { string resultFileName(JoinPath(mDataOutputFolder, "rr_" + mModelFileName)); resultFileName = ChangeFileExtensionTo(resultFileName, ".csv"); Log(lInfo)<<"Saving result to file: "<<resultFileName; SimulationData resultData = mEngine->getSimulationResult(); ofstream fs(resultFileName.c_str()); fs << resultData; fs.close(); return true; }
void MakeOptDest(const std::string &src, std::string &dest) { TSTLStrSize len = dest.length(); // Strip trailing /'s while (len && (dest[len-1] == '/')) { dest.erase(len-1, 1); len--; } if (IsDir(dest)) dest = JoinPath(dest, BaseName(src)); }
bool FileSourceFS::ReadDirectory(const std::string &dirpath, std::vector<FileInfo> &output) { const std::string fulldirpath = JoinPathBelow(GetRoot(), dirpath); DIR *dir = opendir(fulldirpath.c_str()); if (!dir) { return false; } struct dirent *entry; const size_t output_head_size = output.size(); while ((entry = readdir(dir))) { if (strcmp(entry->d_name, ".") == 0) continue; if (strcmp(entry->d_name, "..") == 0) continue; const std::string fullpath = JoinPath(fulldirpath, entry->d_name); FileInfo::FileType ty; switch (entry->d_type) { case DT_DIR: ty = FileInfo::FT_DIR; break; case DT_REG: ty = FileInfo::FT_FILE; break; case DT_LNK: case DT_UNKNOWN: { // if readdir() can't tell us whether we've got a file or directory then we need to stat // also stat for links to traverse them struct stat statinfo; if (stat(fullpath.c_str(), &statinfo) == 0) { if (S_ISREG(statinfo.st_mode)) { ty = FileInfo::FT_FILE; } else if (S_ISDIR(statinfo.st_mode)) { ty = FileInfo::FT_DIR; } else { ty = FileInfo::FT_SPECIAL; } } else { // XXX error out here? ty = FileInfo::FT_NON_EXISTENT; } break; } default: ty = FileInfo::FT_SPECIAL; break; } output.push_back(MakeFileInfo(fullpath.substr(GetRoot().size() + 1), ty)); } closedir(dir); std::sort(output.begin() + output_head_size, output.end()); return true; }
void Resources::Init() { char buf[PATH_MAX]; if( osx_get_resource_path(buf,PATH_MAX) ) { s_ResourcePath = JoinPath(buf,"data"); log_infof("data: %s\n", s_ResourcePath.c_str()); } else { log_infof("couldn't get path for data\n"); // uhoh... s_ResourcePath = "./data"; } }
gcc_malloc gcc_nonnull_all static char * FindInSearchPaths(const char *suffix) { const auto suffix_length = StringLength(suffix); for (const char *const* i = font_search_paths; *i != nullptr; ++i) { const char *path = *i; auto *full_path = JoinPath(path, suffix, suffix_length); if (File::Exists(full_path)) return full_path; delete[] full_path; } return nullptr; }
bool SBMLModelSimulation::SaveModelAsXML(const string& folder) { if(!mEngine) { return false; } string fName = JoinPath(folder, mModelFileName); fName = ChangeFileExtensionTo(fName, "xml"); fstream fs(fName.c_str(), fstream::out); if(!fs) { Log(lError)<<"Failed writing sbml to file "<< fName; return false; } fs<<mEngine->getSBML(); fs.close(); return true; }
void ZigConfig::Save() const { std::string outname = JoinPath( ZigUserDir(), "options" ); std::ofstream out( outname.c_str() ); if( !out.good() ) return; if( fullscreen ) out << "fullscreen" << std::endl; else out << "window" << std::endl; #if 0 out << "width " << width << std::endl; out << "height " << height << std::endl; out << "depth " << depth << std::endl; #endif }
// ac and av are commandline options passed along from main() // Commandline options override config file options. void ZigConfig::Init( int ac, char* av[] ) { // try to read in opts from file { std::string inname = JoinPath( ZigUserDir(), "options" ); std::ifstream in( inname.c_str() ); int linenum = 0; while( in.good() ) { std::string line; std::getline( in, line ); ++linenum; std::vector< std::string > opts; SplitLine( line, opts ); if( opts.empty() ) // ignore blank lines continue; ApplyOption( *this, opts ); } } // now apply commandline opts on top. int i=1; while( i<ac ) { std::vector< std::string > opt; if( av[i][0] != '-' ) throw Wobbly( "Syntax error: '%s'", av[i] ); opt.push_back( &av[i][1] ); ++i; // collect args for this option while( i<ac && av[i][0] != '-' ) { opt.push_back( av[i] ); ++i; } ApplyOption( *this, opt ); } }
CommandExecutionResults CatCommand::Execute(const ExecutionContext& context) { auto& currentDir = GetCurrentPath(this->context->UserData, context.Message->SourceProtocol, context.Message->Sender); std::string path = SanitizePath(context.ParseResults->GetParameter("file")); std::string newPath = JoinPath(currentDir, path); if (newPath.empty()) { throw Exceptions::ExecutionException(InvalidPath); } if (PathIsDirectoryA(newPath.c_str())) { throw Exceptions::ExecutionException(PathIsNotFile); } if (!PathFileExistsA(newPath.c_str())) { throw Exceptions::ExecutionException(FileDoesNotExist); } std::ifstream file(newPath, std::ios_base::binary); file.seekg(0, std::ios_base::end); int64_t length = file.tellg(); file.seekg(0, std::ios_base::beg); if (length == -1 || !file) { throw Exceptions::ExecutionException(CannotReadFile); } if (length > MaxFileLength) { length = MaxFileLength; } std::unique_ptr<char[]> buffer(new char[(unsigned)length + 1]); if (file.read(buffer.get(), length).bad()) { throw Exceptions::ExecutionException(CannotReadFile); } buffer.get()[length] = 0; return CommandExecutionResults(std::string(buffer.get())); }
CommandExecutionResults StoreTextCommand::Execute(const ExecutionContext& context) { auto& currentDir = GetCurrentPath(this->context->UserData, context.Message->SourceProtocol, context.Message->Sender); auto& content = context.ParseResults->GetParameter("content"); auto path = SanitizePath(context.ParseResults->GetParameter("file")); auto newPath = JoinPath(currentDir, path); if (newPath.empty()) { throw Exceptions::ExecutionException(InvalidPath); } if (PathIsDirectoryA(newPath.c_str())) { throw Exceptions::ExecutionException(PathIsNotFile); } std::ofstream file(newPath, std::ios_base::binary | std::ios_base::trunc); file.write(content.c_str(), content.size()); if (!file) { throw Exceptions::ExecutionException(CannotWriteToFile); } return CommandExecutionResults(FileWritten); }
bool FileSourceFS::ReadDirectory(const std::string &dirpath, std::vector<FileInfo> &output) { size_t output_head_size = output.size(); const std::wstring wsearchglob = transcode_utf8_to_utf16(JoinPathBelow(GetRoot(), dirpath)) + L"/*"; WIN32_FIND_DATAW findinfo; HANDLE dirhandle = FindFirstFileW(wsearchglob.c_str(), &findinfo); DWORD err; if (dirhandle == INVALID_HANDLE_VALUE) { err = GetLastError(); // if the directory was empty we succeeded even though FindFirstFile failed return (err == ERROR_FILE_NOT_FOUND); } do { std::string fname = transcode_utf16_to_utf8(findinfo.cFileName, wcslen(findinfo.cFileName)); if (fname != "." && fname != "..") { const FileInfo::FileType ty = file_type_for_attributes(findinfo.dwFileAttributes); const Time::DateTime modtime = datetime_for_filetime(findinfo.ftLastWriteTime); output.push_back(MakeFileInfo(JoinPath(dirpath, fname), ty, modtime)); } if (! FindNextFileW(dirhandle, &findinfo)) { err = GetLastError(); } else err = ERROR_SUCCESS; } while (err == ERROR_SUCCESS); FindClose(dirhandle); if (err != ERROR_NO_MORE_FILES) { output.resize(output_head_size); return false; } std::sort(output.begin() + output_head_size, output.end()); return true; }
int ExpandLinks(char *dest, const char *from, int level) { char buff[CF_BUFSIZE]; char node[CF_MAXLINKSIZE]; struct stat statbuf; int lastnode = false; memset(dest, 0, CF_BUFSIZE); if (level >= CF_MAXLINKLEVEL) { Log(LOG_LEVEL_ERR, "Too many levels of symbolic links to evaluate absolute path"); return false; } const char *sp = from; while (*sp != '\0') { if (*sp == FILE_SEPARATOR) { sp++; continue; } sscanf(sp, "%[^/]", node); sp += strlen(node); if (*sp == '\0') { lastnode = true; } if (strcmp(node, ".") == 0) { continue; } if (strcmp(node, "..") == 0) { continue; } else { strcat(dest, "/"); } strcat(dest, node); if (lstat(dest, &statbuf) == -1) /* File doesn't exist so we can stop here */ { Log(LOG_LEVEL_ERR, "Can't stat '%s' in ExpandLinks. (lstat: %s)", dest, GetErrorStr()); return false; } if (S_ISLNK(statbuf.st_mode)) { memset(buff, 0, CF_BUFSIZE); if (readlink(dest, buff, CF_BUFSIZE - 1) == -1) { Log(LOG_LEVEL_ERR, "Expand links can't stat '%s'. (readlink: %s)", dest, GetErrorStr()); return false; } else { if (buff[0] == '.') { ChopLastNode(dest); AddSlash(dest); if (!JoinPath(dest, buff)) { return false; } } else if (IsAbsoluteFileName(buff)) { strcpy(dest, buff); DeleteSlash(dest); if (strcmp(dest, from) == 0) { Log(LOG_LEVEL_DEBUG, "No links to be expanded"); return true; } if ((!lastnode) && (!ExpandLinks(buff, dest, level + 1))) { return false; } } else { ChopLastNode(dest); AddSlash(dest); strcat(dest, buff); DeleteSlash(dest); if (strcmp(dest, from) == 0) { Log(LOG_LEVEL_DEBUG, "No links to be expanded"); return true; } memset(buff, 0, CF_BUFSIZE); if ((!lastnode) && (!ExpandLinks(buff, dest, level + 1))) { return false; } } } } } return true; }
PromiseResult VerifyRelativeLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp) { char *sp, *commonto, *commonfrom; char buff[CF_BUFSIZE], linkto[CF_BUFSIZE], add[CF_BUFSIZE]; int levels = 0; if (*source == '.') { return VerifyLink(ctx, destination, source, attr, pp); } if (!CompressPath(linkto, source)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Failed to link %s to %s\n", destination, source); return PROMISE_RESULT_FAIL; } commonto = linkto; commonfrom = destination; if (strcmp(commonto, commonfrom) == 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Failed to link %s to %s - can't link file %s to itself\n", destination, source, commonto); return PROMISE_RESULT_FAIL; } while (*commonto == *commonfrom) { commonto++; commonfrom++; } while (!((IsAbsoluteFileName(commonto)) && (IsAbsoluteFileName(commonfrom)))) { commonto--; commonfrom--; } commonto++; for (sp = commonfrom; *sp != '\0'; sp++) { if (IsFileSep(*sp)) { levels++; } } memset(buff, 0, CF_BUFSIZE); strcat(buff, "."); strcat(buff, FILE_SEPARATOR_STR); while (--levels > 0) { snprintf(add, CF_BUFSIZE - 1, "..%c", FILE_SEPARATOR); if (!JoinPath(buff, add)) { return PROMISE_RESULT_FAIL; } } if (!JoinPath(buff, commonto)) { return PROMISE_RESULT_FAIL; } return VerifyLink(ctx, destination, buff, attr, pp); }
int DepthSearch(char *name, struct stat *sb, int rlevel, Attributes attr, Promise *pp) { Dir *dirh; int goback; const struct dirent *dirp; char path[CF_BUFSIZE]; struct stat lsb; if (!attr.havedepthsearch) /* if the search is trivial, make sure that we are in the parent dir of the leaf */ { char basedir[CF_BUFSIZE]; CfDebug(" -> Direct file reference %s, no search implied\n", name); snprintf(basedir, sizeof(basedir), "%s", name); ChopLastNode(basedir); chdir(basedir); return VerifyFileLeaf(name, sb, attr, pp); } if (rlevel > CF_RECURSION_LIMIT) { CfOut(cf_error, "", "WARNING: Very deep nesting of directories (>%d deep): %s (Aborting files)", rlevel, name); return false; } if (rlevel > CF_RECURSION_LIMIT) { CfOut(cf_error, "", "WARNING: Very deep nesting of directories (>%d deep): %s (Aborting files)", rlevel, name); return false; } memset(path, 0, CF_BUFSIZE); CfDebug("To iterate is Human, to recurse is Divine...(%s)\n", name); if (!PushDirState(name, sb)) { return false; } if ((dirh = OpenDirLocal(".")) == NULL) { CfOut(cf_inform, "opendir", "Could not open existing directory %s\n", name); return false; } for (dirp = ReadDir(dirh); dirp != NULL; dirp = ReadDir(dirh)) { if (!ConsiderFile(dirp->d_name, name, attr, pp)) { continue; } strcpy(path, name); AddSlash(path); if (!JoinPath(path, dirp->d_name)) { CloseDir(dirh); return true; } if (lstat(dirp->d_name, &lsb) == -1) { CfOut(cf_verbose, "lstat", "Recurse was looking at %s when an error occurred:\n", path); continue; } if (S_ISLNK(lsb.st_mode)) /* should we ignore links? */ { if (!KillGhostLink(path, attr, pp)) { VerifyFileLeaf(path, &lsb, attr, pp); } else { continue; } } /* See if we are supposed to treat links to dirs as dirs and descend */ if (attr.recursion.travlinks && S_ISLNK(lsb.st_mode)) { if (lsb.st_uid != 0 && lsb.st_uid != getuid()) { CfOut(cf_inform, "", "File %s is an untrusted link: cfengine will not follow it with a destructive operation", path); continue; } /* if so, hide the difference by replacing with actual object */ if (cfstat(dirp->d_name, &lsb) == -1) { CfOut(cf_error, "stat", "Recurse was working on %s when this failed:\n", path); continue; } } if (attr.recursion.xdev && DeviceBoundary(&lsb, pp)) { CfOut(cf_verbose, "", "Skipping %s on different device - use xdev option to change this\n", path); continue; } if (S_ISDIR(lsb.st_mode)) { if (SkipDirLinks(path, dirp->d_name, attr.recursion)) { continue; } if (attr.recursion.depth > 1 && rlevel <= attr.recursion.depth) { CfOut(cf_verbose, "", " ->> Entering %s (%d)\n", path, rlevel); goback = DepthSearch(path, &lsb, rlevel + 1, attr, pp); PopDirState(goback, name, sb, attr.recursion); VerifyFileLeaf(path, &lsb, attr, pp); } else { VerifyFileLeaf(path, &lsb, attr, pp); } } else { VerifyFileLeaf(path, &lsb, attr, pp); } } CloseDir(dirh); return true; }
namespace FileSystem { static FileSourceFS dataFilesApp(GetDataDir()); static FileSourceFS dataFilesUser(JoinPath(GetUserDir(), "data")); FileSourceUnion gameDataFiles; FileSourceFS userFiles(GetUserDir()); // note: some functions (GetUserDir(), GetDataDir()) are in FileSystem{Posix,Win32}.cpp std::string JoinPath(const std::string &a, const std::string &b) { if (!b.empty()) { if (b[0] == '/' || a.empty()) return b; else return a + "/" + b; } else return a; } static void normalise_path(std::string &result, const StringRange &path) { StringRange part(path.begin, path.begin); const char *c = path.begin; if ((c != path.end) && (*c == '/')) { result += '/'; ++c; ++part.begin; } const size_t initial_result_length = result.size(); while (true) { if ((*c == '/') || (c == path.end)) { part.end = c; if (part.Empty() || (part == ".")) { // skip this part } else if (part == "..") { // pop the last component if (result.size() <= initial_result_length) throw std::invalid_argument(path.ToString()); size_t pos = result.rfind('/', result.size()-2); ++pos; assert(pos >= initial_result_length); result.erase(pos); } else { // push the new component if (part.end != path.end) { assert(*part.end == '/'); ++part.end; } result.append(part.begin, part.Size()); } part.begin = c+1; } if (c == path.end) { break; } ++c; } } std::string NormalisePath(const std::string &path) { std::string result; result.reserve(path.size()); normalise_path(result, StringRange(path.c_str(), path.size())); return result; } std::string JoinPathBelow(const std::string &base, const std::string &path) { if (base.empty()) return path; if (!path.empty()) { if ((path[0] == '/') && (base != "/")) throw std::invalid_argument(path); else { std::string result(base); result.reserve(result.size() + 1 + path.size()); if (result[result.size()-1] != '/') result += '/'; StringRange rhs(path.c_str(), path.size()); if (path[0] == '/') { assert(base == "/"); ++rhs.begin; } normalise_path(result, rhs); return result; } } else return base; } void Init() { gameDataFiles.AppendSource(&dataFilesUser); gameDataFiles.AppendSource(&dataFilesApp); } void Uninit() { } FileInfo::FileInfo(FileSource *source, const std::string &path, FileType type): m_source(source), m_path(path), m_dirLen(0), m_type(type) { assert((m_path.size() <= 1) || (m_path[m_path.size()-1] != '/')); std::size_t slashpos = m_path.rfind('/'); if (slashpos != std::string::npos) { m_dirLen = slashpos + 1; } else { m_dirLen = 0; } } FileInfo FileSource::MakeFileInfo(const std::string &path, FileInfo::FileType fileType) { return FileInfo(this, path, fileType); } FileSourceUnion::FileSourceUnion(): FileSource(":union:") {} FileSourceUnion::~FileSourceUnion() {} void FileSourceUnion::PrependSource(FileSource *fs) { assert(fs); RemoveSource(fs); m_sources.insert(m_sources.begin(), fs); } void FileSourceUnion::AppendSource(FileSource *fs) { assert(fs); RemoveSource(fs); m_sources.push_back(fs); } void FileSourceUnion::RemoveSource(FileSource *fs) { std::vector<FileSource*>::iterator nend = std::remove(m_sources.begin(), m_sources.end(), fs); m_sources.erase(nend, m_sources.end()); } FileInfo FileSourceUnion::Lookup(const std::string &path) { for (std::vector<FileSource*>::const_iterator it = m_sources.begin(); it != m_sources.end(); ++it) { FileInfo info = (*it)->Lookup(path); if (info.Exists()) { return info; } } return MakeFileInfo(path, FileInfo::FT_NON_EXISTENT); } RefCountedPtr<FileData> FileSourceUnion::ReadFile(const std::string &path) { for (std::vector<FileSource*>::const_iterator it = m_sources.begin(); it != m_sources.end(); ++it) { RefCountedPtr<FileData> data = (*it)->ReadFile(path); if (data) { return data; } } return RefCountedPtr<FileData>(); } // Merge two sets of FileInfo's, by path. // Input vectors must be sorted. Output will be sorted. // Where a path is present in both inputs, directories are selected // in preference to non-directories; otherwise, the FileInfo from the // first vector is selected in preference to the second vector. static void file_union_merge( std::vector<FileInfo>::const_iterator a, std::vector<FileInfo>::const_iterator aend, std::vector<FileInfo>::const_iterator b, std::vector<FileInfo>::const_iterator bend, std::vector<FileInfo> &output) { while ((a != aend) && (b != bend)) { int order = a->GetPath().compare(b->GetPath()); int which = order; if (which == 0) { if (b->IsDir() && !a->IsDir()) { which = 1; } else { which = -1; } } if (which < 0) { output.push_back(*a++); if (order == 0) ++b; } else { output.push_back(*b++); if (order == 0) ++a; } } if (a != aend) { std::copy(a, aend, std::back_inserter(output)); } if (b != bend) { std::copy(b, bend, std::back_inserter(output)); } } bool FileSourceUnion::ReadDirectory(const std::string &path, std::vector<FileInfo> &output) { if (m_sources.empty()) { return false; } if (m_sources.size() == 1) { return m_sources.front()->ReadDirectory(path, output); } bool founddir = false; std::vector<FileInfo> merged; for (std::vector<FileSource*>::const_iterator it = m_sources.begin(); it != m_sources.end(); ++it) { std::vector<FileInfo> nextfiles; if ((*it)->ReadDirectory(path, nextfiles)) { founddir = true; std::vector<FileInfo> prevfiles; prevfiles.swap(merged); // merge order is important // file_union_merge selects from its first input preferentially file_union_merge( prevfiles.begin(), prevfiles.end(), nextfiles.begin(), nextfiles.end(), merged); } } output.reserve(output.size() + merged.size()); std::copy(merged.begin(), merged.end(), std::back_inserter(output)); return founddir; } FileEnumerator::FileEnumerator(FileSource &fs, int flags): m_source(&fs), m_flags(flags) {} FileEnumerator::FileEnumerator(FileSource &fs, const std::string &path, int flags): m_source(&fs), m_flags(flags) { AddSearchRoot(path); } FileEnumerator::~FileEnumerator() {} void FileEnumerator::AddSearchRoot(const std::string &path) { const FileInfo fi = m_source->Lookup(path); if (fi.IsDir()) { QueueDirectoryContents(fi); ExpandDirQueue(); } } void FileEnumerator::Next() { m_queue.pop_front(); ExpandDirQueue(); } void FileEnumerator::ExpandDirQueue() { while (m_queue.empty() && !m_dirQueue.empty()) { const FileInfo &nextDir = m_dirQueue.front(); assert(nextDir.IsDir()); QueueDirectoryContents(nextDir); m_dirQueue.pop_front(); } } void FileEnumerator::QueueDirectoryContents(const FileInfo &info) { assert(info.IsDir()); std::vector<FileInfo> entries; m_source->ReadDirectory(info.GetPath(), entries); for (std::vector<FileInfo>::const_iterator it = entries.begin(); it != entries.end(); ++it) { switch (it->GetType()) { case FileInfo::FT_DIR: if (m_flags & IncludeDirs) { m_queue.push_back(*it); } if (m_flags & Recurse) { m_dirQueue.push_back(*it); } break; case FileInfo::FT_FILE: if (!(m_flags & ExcludeFiles)) { m_queue.push_back(*it); } break; case FileInfo::FT_SPECIAL: if (m_flags & IncludeSpecials) { m_queue.push_back(*it); } break; default: assert(0); break; } } } } // namespace FileSystem
void CLngRc::Reload(bool bForce /*= false*/) { bool bChanged = bForce; bool bExists = false; CEStr lsNewLng, lsNewFile; // TODO: There would be gpSet member in future lsNewLng.Set(gpConEmu->opt.Language.GetStr()); // Language was requested? if (!lsNewLng.IsEmpty()) { if (ms_Lng.IsEmpty() || (0 != wcscmp(lsNewLng, ms_Lng))) { bChanged = true; } // We need a file if (gpConEmu->opt.LanguageFile.Exists) { // It may contain environment variables lsNewFile = ExpandEnvStr(gpConEmu->opt.LanguageFile.GetStr()); if (lsNewFile.IsEmpty()) lsNewFile.Set(gpConEmu->opt.LanguageFile.GetStr()); // Check if the file exists bExists = FileExists(lsNewFile); } else { lsNewFile = JoinPath(gpConEmu->ms_ConEmuExeDir, gsResourceFileName); if (!(bExists = FileExists(lsNewFile))) { lsNewFile = JoinPath(gpConEmu->ms_ConEmuBaseDir, gsResourceFileName); bExists = FileExists(lsNewFile); } } // File name was changed? if ((bExists == ms_l10n.IsEmpty()) || (bExists && (ms_l10n.IsEmpty() || (0 != wcscmp(lsNewFile, ms_l10n))) ) ) { bChanged = true; } } else if (!ms_Lng.IsEmpty()) { bChanged = true; } // Check if we have to reload data if (bChanged) { if (!bExists || !LoadResouces(lsNewLng, lsNewFile)) { ms_Lng.Empty(); ms_l10n.Empty(); Clean(m_CmnHints); Clean(m_MnuHints); Clean(m_Controls); } } }