// 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; } ERROR_LOG(COMMON, "Rename: MoveFile failed on %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorString().c_str()); #else if (rename(srcFilename.c_str(), destFilename.c_str()) == 0) return true; ERROR_LOG(COMMON, "Rename: rename failed on %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), LastStrerrorString().c_str()); #endif return false; }
// 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; }
// Overloaded GetSize, accepts FILE* u64 GetSize(FILE* f) { // can't use off_t here because it can be 32-bit u64 pos = ftello(f); if (fseeko(f, 0, SEEK_END) != 0) { ERROR_LOG(COMMON, "GetSize: seek failed %p: %s", f, LastStrerrorString().c_str()); return 0; } u64 size = ftello(f); if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) { ERROR_LOG(COMMON, "GetSize: seek failed %p: %s", f, LastStrerrorString().c_str()); return 0; } return size; }
// Returns the current directory std::string GetCurrentDir() { // Get the current working directory (getcwd uses malloc) char* dir = __getcwd(nullptr, 0); if (!dir) { ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s", LastStrerrorString().c_str()); return nullptr; } std::string strDir = dir; free(dir); return strDir; }
// creates an empty file filename, returns true on success bool CreateEmptyFile(const std::string& filename) { INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str()); if (!File::IOFile(filename, "wb")) { ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s", filename.c_str(), LastStrerrorString().c_str()); return false; } 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(), GetLastErrorString().c_str()); return false; } #else if (unlink(filename.c_str()) == -1) { WARN_LOG(COMMON, "Delete: unlink failed on %s: %s", filename.c_str(), LastStrerrorString().c_str()); return false; } #endif return true; }
u8* MemArena::FindMemoryBase() { #if _ARCH_32 const size_t memory_size = 0x31000000; #else const size_t memory_size = 0x400000000; #endif #ifdef _WIN32 u8* base = static_cast<u8*>(VirtualAlloc(nullptr, memory_size, MEM_RESERVE, PAGE_READWRITE)); if (!base) { PanicAlert("Failed to map enough memory space: %s", GetLastErrorString().c_str()); return nullptr; } VirtualFree(base, 0, MEM_RELEASE); return base; #else #ifdef ANDROID // Android 4.3 changed how mmap works. // if we map it private and then munmap it, we can't use the base returned. // This may be due to changes in them support a full SELinux implementation. const int flags = MAP_ANON | MAP_SHARED; #else const int flags = MAP_ANON | MAP_PRIVATE; #endif void* base = mmap(nullptr, memory_size, PROT_NONE, flags, -1, 0); if (base == MAP_FAILED) { PanicAlert("Failed to map enough memory space: %s", LastStrerrorString().c_str()); return nullptr; } munmap(base, memory_size); return static_cast<u8*>(base); #endif }
bool SDCardCreate(u64 disk_size /*in MB*/, const std::string& filename) { u32 sectors_per_fat; u32 sectors_per_disk; // Convert MB to bytes disk_size *= 1024 * 1024; if (disk_size < 0x800000 || disk_size > 0x800000000ULL) { ERROR_LOG(COMMON, "Trying to create SD Card image of size %" PRIu64 "MB is out of range (8MB-32GB)", disk_size / (1024 * 1024)); return false; } // Pretty unlikely to overflow. sectors_per_disk = (u32)(disk_size / 512); sectors_per_fat = get_sectors_per_fat(disk_size, get_sectors_per_cluster(disk_size)); boot_sector_init(s_boot_sector, s_fsinfo_sector, disk_size, nullptr); fat_init(s_fat_head); File::IOFile file(filename, "wb"); FILE* const f = file.GetHandle(); if (!f) { ERROR_LOG(COMMON, "Could not create file '%s', aborting...", filename.c_str()); return false; } /* Here's the layout: * * boot_sector * fsinfo_sector * empty * backup boot sector * backup fsinfo sector * RESERVED_SECTORS - 4 empty sectors (if backup sectors), or RESERVED_SECTORS - 2 (if no backup) * first fat * second fat * zero sectors */ if (write_sector(f, s_boot_sector)) goto FailWrite; if (write_sector(f, s_fsinfo_sector)) goto FailWrite; if (BACKUP_BOOT_SECTOR > 0) { if (write_empty(f, BACKUP_BOOT_SECTOR - 2)) goto FailWrite; if (write_sector(f, s_boot_sector)) goto FailWrite; if (write_sector(f, s_fsinfo_sector)) goto FailWrite; if (write_empty(f, RESERVED_SECTORS - 2 - BACKUP_BOOT_SECTOR)) goto FailWrite; } else { if (write_empty(f, RESERVED_SECTORS - 2)) goto FailWrite; } if (write_sector(f, s_fat_head)) goto FailWrite; if (write_empty(f, sectors_per_fat - 1)) goto FailWrite; if (write_sector(f, s_fat_head)) goto FailWrite; if (write_empty(f, sectors_per_fat - 1)) goto FailWrite; if (write_empty(f, sectors_per_disk - RESERVED_SECTORS - 2 * sectors_per_fat)) goto FailWrite; return true; FailWrite: ERROR_LOG(COMMON, "Could not write to '%s', aborting...", filename.c_str()); if (unlink(filename.c_str()) < 0) ERROR_LOG(COMMON, "unlink(%s) failed: %s", filename.c_str(), LastStrerrorString().c_str()); return false; }