// renames file srcFilename to destFilename, returns true on success bool Rename(const std::string &srcFilename, const std::string &destFilename) { INFO_LOG(COMMON, "Rename: %s --> %s", srcFilename.c_str(), destFilename.c_str()); #ifdef _WIN32 auto sf = UTF8ToTStr(srcFilename); auto df = UTF8ToTStr(destFilename); // The Internet seems torn about whether ReplaceFile is atomic or not. // Hopefully it's atomic enough... if (ReplaceFile(df.c_str(), sf.c_str(), nullptr, REPLACEFILE_IGNORE_MERGE_ERRORS, nullptr, nullptr)) return true; // Might have failed because the destination doesn't exist. if (GetLastError() == ERROR_FILE_NOT_FOUND) { if (MoveFile(sf.c_str(), df.c_str())) return true; } #else if (rename(srcFilename.c_str(), destFilename.c_str()) == 0) return true; #endif ERROR_LOG(COMMON, "Rename: failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); return false; }
bool IOFile::Open(const std::string& filename, const char openmode[]) { Close(); #ifdef _WIN32 _tfopen_s(&m_file, UTF8ToTStr(filename).c_str(), UTF8ToTStr(openmode).c_str()); #else m_file = fopen(filename.c_str(), openmode); #endif m_good = IsOpen(); return m_good; }
// Default non library dependent panic alert bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style) { #ifdef _WIN32 int STYLE = MB_ICONINFORMATION; if (Style == QUESTION) STYLE = MB_ICONQUESTION; if (Style == WARNING) STYLE = MB_ICONWARNING; return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK)); #else printf("%s\n", text); return true; #endif }
// Returns true if successful, or path already exists. bool CreateDir(const std::string &path) { INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str()); #ifdef _WIN32 if (::CreateDirectory(UTF8ToTStr(path).c_str(), NULL)) return true; DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) { WARN_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: already exists", path.c_str()); return true; } ERROR_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: %i", path.c_str(), error); return false; #else if (mkdir(path.c_str(), 0755) == 0) return true; int err = errno; if (err == EEXIST) { WARN_LOG(COMMON, "CreateDir: mkdir failed on %s: already exists", path.c_str()); return true; } ERROR_LOG(COMMON, "CreateDir: mkdir failed on %s: %s", path.c_str(), strerror(err)); return false; #endif }
// Returns the size of filename (64bit) u64 GetSize(const std::string &filename) { if (!Exists(filename)) { WARN_LOG(COMMON, "GetSize: failed %s: No such file", filename.c_str()); return 0; } if (IsDirectory(filename)) { WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str()); return 0; } struct stat64 buf; #ifdef _WIN32 if (_tstat64(UTF8ToTStr(filename).c_str(), &buf) == 0) #else if (stat64(filename.c_str(), &buf) == 0) #endif { DEBUG_LOG(COMMON, "GetSize: %s: %lld", filename.c_str(), (long long)buf.st_size); return buf.st_size; } ERROR_LOG(COMMON, "GetSize: Stat failed %s: %s", filename.c_str(), GetLastErrorMsg()); return 0; }
// Deletes a directory filename, returns true on success bool DeleteDir(const std::string& filename) { INFO_LOG(COMMON, "DeleteDir: directory %s", filename.c_str()); // check if a directory if (!IsDirectory(filename)) { ERROR_LOG(COMMON, "DeleteDir: Not a directory %s", filename.c_str()); return false; } #ifdef _WIN32 if (::RemoveDirectory(UTF8ToTStr(filename).c_str())) return true; ERROR_LOG(COMMON, "DeleteDir: RemoveDirectory failed on %s: %s", filename.c_str(), GetLastErrorString().c_str()); #else if (rmdir(filename.c_str()) == 0) return true; ERROR_LOG(COMMON, "DeleteDir: rmdir failed on %s: %s", filename.c_str(), LastStrerrorString().c_str()); #endif return false; }
void MemArena::GrabSHMSegment(size_t size) { #ifdef _WIN32 const std::string name = "dolphin-emu." + std::to_string(GetCurrentProcessId()); hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, static_cast<DWORD>(size), UTF8ToTStr(name).c_str()); #elif defined(ANDROID) fd = AshmemCreateFileMapping(("dolphin-emu." + std::to_string(getpid())).c_str(), size); if (fd < 0) { NOTICE_LOG(MEMMAP, "Ashmem allocation failed"); return; } #else const std::string file_name = "/dolphin-emu." + std::to_string(getpid()); fd = shm_open(file_name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600); if (fd == -1) { ERROR_LOG(MEMMAP, "shm_open failed: %s", strerror(errno)); return; } shm_unlink(file_name.c_str()); if (ftruncate(fd, size) < 0) ERROR_LOG(MEMMAP, "Failed to allocate low memory space"); #endif }
// Create directory and copy contents (does not overwrite existing files) void CopyDir(const std::string& source_path, const std::string& dest_path, bool destructive) { if (source_path == dest_path) return; if (!Exists(source_path)) return; if (!Exists(dest_path)) File::CreateFullPath(dest_path); #ifdef _WIN32 WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(UTF8ToTStr(source_path + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return; } do { const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else DIR* dirp = opendir(source_path.c_str()); if (!dirp) return; while (dirent* result = readdir(dirp)) { const std::string virtualName(result->d_name); #endif // check for "." and ".." if (virtualName == "." || virtualName == "..") continue; std::string source = source_path + DIR_SEP + virtualName; std::string dest = dest_path + DIR_SEP + virtualName; if (IsDirectory(source)) { if (!Exists(dest)) File::CreateFullPath(dest + DIR_SEP); CopyDir(source, dest, destructive); } else if (!destructive && !Exists(dest)) { Copy(source, dest); } else if (destructive) { Rename(source, dest); } #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif }
// copies file source_path to destination_path, returns true on success bool Copy(const std::string& source_path, const std::string& destination_path) { INFO_LOG(COMMON, "Copy: %s --> %s", source_path.c_str(), destination_path.c_str()); #ifdef _WIN32 if (CopyFile(UTF8ToTStr(source_path).c_str(), UTF8ToTStr(destination_path).c_str(), FALSE)) return true; ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s", source_path.c_str(), destination_path.c_str(), GetLastErrorString().c_str()); return false; #else std::ifstream source{source_path, std::ios::binary}; std::ofstream destination{destination_path, std::ios::binary}; destination << source.rdbuf(); return source.good() && destination.good(); #endif }
// Default non library dependent panic alert bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style) { #ifdef _WIN32 int STYLE = MB_ICONINFORMATION; if (Style == QUESTION) STYLE = MB_ICONQUESTION; if (Style == WARNING) STYLE = MB_ICONWARNING; return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK)); #else fprintf(stderr, "%s\n", text); // Return no to any question (which will in general crash the emulator) return false; #endif }
// Create directory and copy contents (does not overwrite existing files) void CopyDir(const std::string &source_path, const std::string &dest_path) { if (source_path == dest_path) return; if (!File::Exists(source_path)) return; if (!File::Exists(dest_path)) File::CreateFullPath(dest_path); #ifdef _WIN32 WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(UTF8ToTStr(source_path + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return; } do { const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else struct dirent dirent, *result = NULL; DIR *dirp = opendir(source_path.c_str()); if (!dirp) return; while (!readdir_r(dirp, &dirent, &result) && result) { const std::string virtualName(result->d_name); #endif // check for "." and ".." if (virtualName == "." || virtualName == "..") continue; std::string source, dest; source = source_path + virtualName; dest = dest_path + virtualName; if (IsDirectory(source)) { source += '/'; dest += '/'; if (!File::Exists(dest)) File::CreateFullPath(dest); CopyDir(source, dest); } else if (!File::Exists(dest)) File::Copy(source, dest); #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif }
std::string GetTempFilenameForAtomicWrite(const std::string &path) { std::string abs = path; #ifdef _WIN32 TCHAR absbuf[MAX_PATH]; if (_tfullpath(absbuf, UTF8ToTStr(path).c_str(), MAX_PATH) != nullptr) abs = TStrToUTF8(absbuf); #else char absbuf[PATH_MAX]; if (realpath(path.c_str(), absbuf) != nullptr) abs = absbuf; #endif return abs + ".xxx"; }
bool RenameSync(const std::string &srcFilename, const std::string &destFilename) { if (!Rename(srcFilename, destFilename)) return false; #ifdef _WIN32 int fd = _topen(UTF8ToTStr(srcFilename).c_str(), _O_RDONLY); if (fd != -1) { _commit(fd); close(fd); } #else char *path = strdup(srcFilename.c_str()); FSyncPath(path); FSyncPath(dirname(path)); free(path); path = strdup(destFilename.c_str()); FSyncPath(dirname(path)); free(path); #endif return true; }
// Deletes a given filename, return true on success // Doesn't supports deleting a directory bool Delete(const std::string& filename) { INFO_LOG(COMMON, "Delete: file %s", filename.c_str()); const FileInfo file_info(filename); // Return true because we care about the file no // being there, not the actual delete. if (!file_info.Exists()) { WARN_LOG(COMMON, "Delete: %s does not exist", filename.c_str()); return true; } // We can't delete a directory if (file_info.IsDirectory()) { WARN_LOG(COMMON, "Delete failed: %s is a directory", filename.c_str()); return false; } #ifdef _WIN32 if (!DeleteFile(UTF8ToTStr(filename).c_str())) { WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s", filename.c_str(), GetLastErrorMsg().c_str()); return false; } #else if (unlink(filename.c_str()) == -1) { WARN_LOG(COMMON, "Delete: unlink failed on %s: %s", filename.c_str(), GetLastErrorMsg().c_str()); return false; } #endif return true; }
// 100, 100, "Dolphin Log Console" // Open console window - width and height is the size of console window // Name is the window title void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title) { #ifdef _WIN32 if (!GetConsoleWindow()) { // Open the console window and create the window handle for GetStdHandle() AllocConsole(); // Hide if (Hidden) ShowWindow(GetConsoleWindow(), SW_HIDE); // Save the window handle that AllocConsole() created hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // Set the console window title SetConsoleTitle(UTF8ToTStr(Title).c_str()); // Set letter space LetterSpace(80, 4000); //MoveWindow(GetConsoleWindow(), 200,200, 800,800, true); } else { hConsole = GetStdHandle(STD_OUTPUT_HANDLE); } #endif }
// Deletes the given directory and anything under it. Returns true on success. bool DeleteDirRecursively(const std::string &directory) { INFO_LOG(COMMON, "DeleteDirRecursively: %s", directory.c_str()); #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return false; } // windows loop do { const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else struct dirent dirent, *result = NULL; DIR *dirp = opendir(directory.c_str()); if (!dirp) return false; // non windows loop while (!readdir_r(dirp, &dirent, &result) && result) { const std::string virtualName = result->d_name; #endif // check for "." and ".." if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || ((virtualName[0] == '.') && (virtualName[1] == '.') && (virtualName[2] == '\0'))) continue; std::string newPath = directory + DIR_SEP_CHR + virtualName; if (IsDirectory(newPath)) { if (!DeleteDirRecursively(newPath)) { #ifndef _WIN32 closedir(dirp); #endif return false; } } else { if (!File::Delete(newPath)) { #ifndef _WIN32 closedir(dirp); #endif return false; } } #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif File::DeleteDir(directory); return true; }
// Scans the directory tree gets, starting from _Directory and adds the // results into parentEntry. Returns the number of files+directories found u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry) { INFO_LOG(COMMON, "ScanDirectoryTree: directory %s", directory.c_str()); // How many files + directories we found u32 foundEntries = 0; #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return foundEntries; } // windows loop do { FSTEntry entry; const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else struct dirent dirent, *result = NULL; DIR *dirp = opendir(directory.c_str()); if (!dirp) return 0; // non windows loop while (!readdir_r(dirp, &dirent, &result) && result) { FSTEntry entry; const std::string virtualName(result->d_name); #endif // check for "." and ".." if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || ((virtualName[0] == '.') && (virtualName[1] == '.') && (virtualName[2] == '\0'))) continue; entry.virtualName = virtualName; entry.physicalName = directory; entry.physicalName += DIR_SEP + entry.virtualName; if (IsDirectory(entry.physicalName.c_str())) { entry.isDirectory = true; // is a directory, lets go inside entry.size = ScanDirectoryTree(entry.physicalName, entry); foundEntries += (u32)entry.size; } else { // is a file entry.isDirectory = false; entry.size = GetSize(entry.physicalName.c_str()); } ++foundEntries; // Push into the tree parentEntry.children.push_back(entry); #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif // Return number of entries found. return foundEntries; }
// copies file srcFilename to destFilename, returns true on success bool Copy(const std::string &srcFilename, const std::string &destFilename) { INFO_LOG(COMMON, "Copy: %s --> %s", srcFilename.c_str(), destFilename.c_str()); #ifdef _WIN32 if (CopyFile(UTF8ToTStr(srcFilename).c_str(), UTF8ToTStr(destFilename).c_str(), FALSE)) return true; ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); return false; #else // buffer size #define BSIZE 1024 char buffer[BSIZE]; // Open input file FILE *input = fopen(srcFilename.c_str(), "rb"); if (!input) { ERROR_LOG(COMMON, "Copy: input failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); return false; } // open output file FILE *output = fopen(destFilename.c_str(), "wb"); if (!output) { fclose(input); ERROR_LOG(COMMON, "Copy: output failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); return false; } // copy loop while (!feof(input)) { // read input int rnum = fread(buffer, sizeof(char), BSIZE, input); if (rnum != BSIZE) { if (ferror(input) != 0) { ERROR_LOG(COMMON, "Copy: failed reading from source, %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); goto bail; } } // write output int wnum = fwrite(buffer, sizeof(char), rnum, output); if (wnum != rnum) { ERROR_LOG(COMMON, "Copy: failed writing to output, %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); goto bail; } } // close files fclose(input); fclose(output); return true; bail: if (input) fclose(input); if (output) fclose(output); return false; #endif }
void CFileSearch::FindFiles(const std::string& _searchString, const std::string& _strPath) { std::string GCMSearchPath; BuildCompleteFilename(GCMSearchPath, _strPath, _searchString); #ifdef _WIN32 WIN32_FIND_DATA findData; HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData); if (FindFirst != INVALID_HANDLE_VALUE) { bool bkeepLooping = true; while (bkeepLooping) { if (findData.cFileName[0] != '.') { std::string strFilename; BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName)); m_FileNames.push_back(strFilename); } bkeepLooping = FindNextFile(FindFirst, &findData) ? true : false; } } FindClose(FindFirst); #else // TODO: super lame/broken auto end_match(_searchString); // assuming we have a "*.blah"-like pattern if (!end_match.empty() && end_match[0] == '*') end_match.erase(0, 1); // ugly if (end_match == ".*") end_match.clear(); DIR* dir = opendir(_strPath.c_str()); if (!dir) return; while (auto const dp = readdir(dir)) { std::string found(dp->d_name); if ((found != ".") && (found != "..") && (found.size() >= end_match.size()) && std::equal(end_match.rbegin(), end_match.rend(), found.rbegin())) { std::string full_name; if (_strPath.c_str()[_strPath.size() - 1] == DIR_SEP_CHR) full_name = _strPath + found; else full_name = _strPath + DIR_SEP + found; m_FileNames.push_back(full_name); } } closedir(dir); #endif }
// copies file srcFilename to destFilename, returns true on success bool Copy(const std::string& srcFilename, const std::string& destFilename) { INFO_LOG(COMMON, "Copy: %s --> %s", srcFilename.c_str(), destFilename.c_str()); #ifdef _WIN32 if (CopyFile(UTF8ToTStr(srcFilename).c_str(), UTF8ToTStr(destFilename).c_str(), FALSE)) return true; ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg().c_str()); return false; #else // buffer size #define BSIZE 1024 char buffer[BSIZE]; // Open input file std::ifstream input; OpenFStream(input, srcFilename, std::ifstream::in | std::ifstream::binary); if (!input.is_open()) { ERROR_LOG(COMMON, "Copy: input failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg().c_str()); return false; } // open output file File::IOFile output(destFilename, "wb"); if (!output.IsOpen()) { ERROR_LOG(COMMON, "Copy: output failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg().c_str()); return false; } // copy loop while (!input.eof()) { // read input input.read(buffer, BSIZE); if (!input) { ERROR_LOG(COMMON, "Copy: failed reading from source, %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg().c_str()); return false; } // write output if (!output.WriteBytes(buffer, BSIZE)) { ERROR_LOG(COMMON, "Copy: failed writing to output, %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg().c_str()); return false; } } return true; #endif }
// Recursive or non-recursive list of files and directories under directory. FSTEntry ScanDirectoryTree(const std::string& directory, bool recursive) { INFO_LOG(COMMON, "ScanDirectoryTree: directory %s", directory.c_str()); FSTEntry parent_entry; parent_entry.physicalName = directory; parent_entry.isDirectory = true; parent_entry.size = 0; #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return parent_entry; } // Windows loop do { const std::string virtual_name(TStrToUTF8(ffd.cFileName)); #else DIR* dirp = opendir(directory.c_str()); if (!dirp) return parent_entry; // non Windows loop while (dirent* result = readdir(dirp)) { const std::string virtual_name(result->d_name); #endif if (virtual_name == "." || virtual_name == "..") continue; auto physical_name = directory + DIR_SEP + virtual_name; FSTEntry entry; const FileInfo file_info(physical_name); entry.isDirectory = file_info.IsDirectory(); if (entry.isDirectory) { if (recursive) entry = ScanDirectoryTree(physical_name, true); else entry.size = 0; parent_entry.size += entry.size; } else { entry.size = file_info.GetSize(); } entry.virtualName = virtual_name; entry.physicalName = physical_name; ++parent_entry.size; // Push into the tree parent_entry.children.push_back(entry); #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif return parent_entry; }