static FILE * fopen_utf8(const char * path, const char * mode) { wchar_t * pathW = utf8_to_widechar(path); wchar_t * modeW = utf8_to_widechar(mode); FILE * file = _wfopen(pathW, modeW); free(pathW); free(modeW); return file; }
int platform_enumerate_directories_begin(const utf8 *directory) { enumerate_file_info *enumFileInfo; wchar_t *wpattern = utf8_to_widechar(directory); int length = min(utf8_length(directory), MAX_PATH); char *npattern = malloc(length+1); int converted; converted = wcstombs(npattern, wpattern, length); npattern[length - 1] = '\0'; if (converted == MAX_PATH) { log_warning("truncated string %s", npattern); } log_verbose("begin directory listing, path: %s", npattern); // TODO: add some checking for stringness and directoryness int cnt; for (int i = 0; i < countof(_enumerateFileInfoList); i++) { enumFileInfo = &_enumerateFileInfoList[i]; if (!enumFileInfo->active) { safe_strcpy(enumFileInfo->pattern, npattern, length); cnt = scandir(npattern, &enumFileInfo->fileListTemp, dirfilter, alphasort); if (cnt < 0) { break; } log_verbose("found %d files in dir '%s'", cnt, npattern); enumFileInfo->cnt = cnt; enumFileInfo->paths = malloc(cnt * sizeof(char *)); char **paths = enumFileInfo->paths; // 256 is size of dirent.d_name const int buf_len = min(MAX_PATH, 256); const int dir_name_len = strnlen(npattern, MAX_PATH); char separator[] = {platform_get_path_separator(), 0}; for (int idx = 0; idx < cnt; idx++) { struct dirent *d = enumFileInfo->fileListTemp[idx]; const int entry_len = strnlen(d->d_name, MAX_PATH); // 1 for separator, 1 for trailing null size_t path_len = sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2); paths[idx] = malloc(path_len); paths[idx][0] = '\0'; log_verbose("dir_name: %s", npattern); strncat(paths[idx], npattern, path_len - 2); strncat(paths[idx], separator, path_len - strnlen(paths[idx], path_len) - 1); strncat(paths[idx], d->d_name, path_len - strnlen(paths[idx], path_len) - 1); log_verbose("paths[%d] = %s", idx, paths[idx]); } enumFileInfo->handle = 0; enumFileInfo->active = 1; free(wpattern); free(npattern); return i; } } free(wpattern); free(npattern); return -1; }
FileStream(const utf8 * path, sint32 fileMode) { const char * mode; switch (fileMode) { case FILE_MODE_OPEN: mode = "rb"; _canRead = true; _canWrite = false; break; case FILE_MODE_WRITE: mode = "w+b"; _canRead = true; _canWrite = true; break; case FILE_MODE_APPEND: mode = "a"; _canRead = false; _canWrite = true; break; default: throw; } #ifdef _WIN32 wchar_t * pathW = utf8_to_widechar(path); wchar_t * modeW = utf8_to_widechar(mode); _file = _wfopen(pathW, modeW); free(pathW); free(modeW); #else _file = fopen(path, mode); #endif if (_file == nullptr) { throw IOException(String::StdFormat("Unable to open '%s'", path)); } Seek(0, STREAM_SEEK_END); _fileSize = GetPosition(); Seek(0, STREAM_SEEK_BEGIN); _ownsFilePtr = true; }
static std::wstring GetDumpDirectory() { char userDirectory[MAX_PATH]; platform_get_user_directory(userDirectory, NULL, sizeof(userDirectory)); wchar_t * userDirectoryW = utf8_to_widechar(userDirectory); auto result = std::wstring(userDirectoryW); free(userDirectoryW); return result; }
bool platform_file_exists(const utf8 *path) { wchar_t *wPath = utf8_to_widechar(path); int len = min(MAX_PATH, utf8_length(path)); char buffer[MAX_PATH]; wcstombs(buffer, wPath, len); buffer[len] = '\0'; free(wPath); bool exists = access(buffer, F_OK) != -1; log_warning("file '%s' exists = %i", buffer, exists); return exists; }
bool platform_original_game_data_exists(const utf8 *path) { wchar_t *wPath = utf8_to_widechar(path); int len = min(MAX_PATH, utf8_length(path)); char buffer[MAX_PATH]; wcstombs(buffer, wPath, len); buffer[len] = '\0'; free(wPath); char checkPath[MAX_PATH]; sprintf(checkPath, "%s%c%s%c%s", buffer, platform_get_path_separator(), "Data", platform_get_path_separator(), "g1.dat"); return platform_file_exists(checkPath); }
bool platform_ensure_directory_exists(const utf8 *path) { mode_t mask = getumask(); wchar_t *wPath = utf8_to_widechar(path); int len = min(MAX_PATH, utf8_length(path)); char buffer[MAX_PATH]; wcstombs(buffer, wPath, len); buffer[len - 1] = '\0'; free(wPath); log_verbose("%s", buffer); const int result = mkdir(buffer, mask); if (result == 0 || (result == -1 && errno == EEXIST)) return true; return false; }
static size_t platform_utf8_to_multibyte(const utf8 *path, char *buffer, size_t buffer_size) { wchar_t *wpath = utf8_to_widechar(path); setlocale(LC_CTYPE, "UTF-8"); size_t len = wcstombs(NULL, wpath, 0); bool truncated = false; if (len > buffer_size - 1) { truncated = true; len = buffer_size - 1; } wcstombs(buffer, wpath, len); buffer[len] = '\0'; if (truncated) log_warning("truncated string %s", buffer); free(wpath); return len; }
bool platform_directory_exists(const utf8 *path) { wchar_t *wPath = utf8_to_widechar(path); int len = min(MAX_PATH, utf8_length(path)); char buffer[MAX_PATH]; wcstombs(buffer, wPath, len); buffer[len] = '\0'; free(wPath); struct stat dirinfo; int result = stat(buffer, &dirinfo); log_verbose("checking dir %s, result = %d, is_dir = %d", buffer, result, S_ISDIR(dirinfo.st_mode)); if ((result != 0) || !S_ISDIR(dirinfo.st_mode)) { return false; } return true; }
int platform_enumerate_files_begin(const utf8 *pattern) { enumerate_file_info *enumFileInfo; wchar_t *wpattern = utf8_to_widechar(pattern); int length = min(utf8_length(pattern), MAX_PATH); char *npattern = malloc(length); int converted; converted = wcstombs(npattern, wpattern, length); npattern[length - 1] = '\0'; if (converted == MAX_PATH) { log_warning("truncated string %s", npattern); } log_warning("begin file search, pattern: %s", npattern); char *file_name = strrchr(npattern, platform_get_path_separator()); char *dir_name; if (file_name != NULL) { dir_name = strndup(npattern, file_name - npattern); file_name = &file_name[1]; } else { file_name = npattern; dir_name = strdup("."); } char *smatch = strchr(file_name, '*'); if ((smatch != file_name) && (smatch != NULL)) { log_error("Sorry, can only match '*' at start of filename."); return -1; } else { // '*' found if (smatch != NULL) { // some boundary checking needed // skip the '*' smatch = &smatch[1]; char *match2 = strchr(&smatch[1], '*'); if (match2 != NULL) { log_error("Sorry, can only match one '*' wildcard."); return -1; } } else { // '*' not found smatch = file_name; } } char *qmatch = strchr(file_name, '?'); if ((qmatch != &npattern[length - 1]) && (qmatch != NULL)) { log_error("Sorry, can only match '?' at end of filename."); return -1; } else { qmatch = &npattern[length]; } int pattern_length = qmatch - smatch; g_file_pattern = strndup(smatch, pattern_length); for (int j = 0; j < pattern_length; j++) { g_file_pattern[j] = (char)toupper(g_file_pattern[j]); } log_warning("looking for file matching %s", g_file_pattern); int cnt; for (int i = 0; i < countof(_enumerateFileInfoList); i++) { enumFileInfo = &_enumerateFileInfoList[i]; if (!enumFileInfo->active) { safe_strncpy(enumFileInfo->pattern, npattern, length); cnt = scandir(dir_name, &enumFileInfo->fileListTemp, winfilter, alphasort); if (cnt < 0) { break; } log_warning("found %d files matching in dir '%s'", cnt, dir_name); enumFileInfo->cnt = cnt; enumFileInfo->paths = malloc(cnt * sizeof(char *)); char **paths = enumFileInfo->paths; // 256 is size of dirent.d_name const int buf_len = min(MAX_PATH, 256); const int dir_name_len = strnlen(dir_name, MAX_PATH); char separator[] = {platform_get_path_separator(), 0}; for (int idx = 0; idx < cnt; idx++) { struct dirent *d = enumFileInfo->fileListTemp[idx]; const int entry_len = strnlen(d->d_name, MAX_PATH); // 1 for separator, 1 for trailing null paths[idx] = malloc(sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2)); paths[idx][0] = '\0'; log_verbose("dir_name: %s", dir_name); strncat(paths[idx], dir_name, MAX_PATH); strncat(paths[idx], separator, MAX_PATH); strncat(paths[idx], d->d_name, MAX_PATH); log_verbose("paths[%d] = %s", idx, paths[idx]); } enumFileInfo->handle = 0; enumFileInfo->active = 1; free(dir_name); free(g_file_pattern); g_file_pattern = NULL; free(wpattern); free(npattern); return i; } } free(dir_name); free(g_file_pattern); g_file_pattern = NULL; free(wpattern); free(npattern); return -1; }
int platform_enumerate_files_begin(const utf8 *pattern) { enumerate_file_info *enumFileInfo; wchar_t *wpattern = utf8_to_widechar(pattern); int length = min(utf8_length(pattern), MAX_PATH); char *npattern = malloc(length+1); int converted; converted = wcstombs(npattern, wpattern, length); npattern[length] = '\0'; if (converted == MAX_PATH) { log_warning("truncated string %s", npattern); } log_verbose("begin file search, pattern: %s", npattern); char *file_name = strrchr(npattern, platform_get_path_separator()); char *dir_name; if (file_name != NULL) { dir_name = strndup(npattern, file_name - npattern); file_name = &file_name[1]; } else { file_name = npattern; dir_name = strdup("."); } int pattern_length = strlen(file_name); g_file_pattern = strndup(file_name, pattern_length); for (int j = 0; j < pattern_length; j++) { g_file_pattern[j] = (char)toupper(g_file_pattern[j]); } log_verbose("looking for file matching %s", g_file_pattern); int cnt; for (int i = 0; i < countof(_enumerateFileInfoList); i++) { enumFileInfo = &_enumerateFileInfoList[i]; if (!enumFileInfo->active) { safe_strcpy(enumFileInfo->pattern, npattern, sizeof(enumFileInfo->pattern)); cnt = scandir(dir_name, &enumFileInfo->fileListTemp, winfilter, alphasort); if (cnt < 0) { break; } log_verbose("found %d files matching in dir '%s'", cnt, dir_name); enumFileInfo->cnt = cnt; enumFileInfo->paths = malloc(cnt * sizeof(char *)); char **paths = enumFileInfo->paths; // 256 is size of dirent.d_name const int buf_len = min(MAX_PATH, 256); const int dir_name_len = strnlen(dir_name, MAX_PATH); char separator[] = {platform_get_path_separator(), 0}; for (int idx = 0; idx < cnt; idx++) { struct dirent *d = enumFileInfo->fileListTemp[idx]; const int entry_len = strnlen(d->d_name, MAX_PATH); // 1 for separator, 1 for trailing null size_t path_len = sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2); paths[idx] = malloc(path_len); paths[idx][0] = '\0'; log_verbose("dir_name: %s", dir_name); strncat(paths[idx], dir_name, path_len - 2); strncat(paths[idx], separator, path_len - strnlen(paths[idx], path_len) - 1); strncat(paths[idx], d->d_name, path_len - strnlen(paths[idx], path_len) - 1); log_verbose("paths[%d] = %s", idx, paths[idx]); } enumFileInfo->handle = 0; enumFileInfo->active = 1; free(dir_name); free(g_file_pattern); g_file_pattern = NULL; free(wpattern); free(npattern); return i; } } free(dir_name); free(g_file_pattern); g_file_pattern = NULL; free(wpattern); free(npattern); return -1; }