static std::string absolute_path(const std::string &path) { std::wstring wpath = transcode_utf8_to_utf16(path); wchar_t buf[MAX_PATH+1]; DWORD len = GetFullPathNameW(wpath.c_str(), MAX_PATH, buf, 0); buf[len] = L'\0'; return transcode_utf16_to_utf8(buf, len); }
// Call MessageBox with warning icon void Warning(const char *format, ...) { char buf[1024]; va_list ap; va_start(ap, format); vsnprintf(buf, sizeof(buf), format, ap); va_end(ap); fprintf(stderr, "Warning: %s\n", buf); MessageBoxW(0, transcode_utf8_to_utf16(buf, strlen(buf)).c_str(), L"Warning", MB_ICONWARNING|MB_OK); }
void RedirectStdio() { std::string stdout_path = FileSystem::JoinPath(FileSystem::GetUserDir(), "stdout.txt"); std::string stderr_path = FileSystem::JoinPath(FileSystem::GetUserDir(), "stderr.txt"); std::wstring wstdout_path = transcode_utf8_to_utf16(stdout_path); std::wstring wstderr_path = transcode_utf8_to_utf16(stderr_path); FILE *f; f = _wfreopen(wstdout_path.c_str(), L"w", stdout); if (!f) { fprintf(stderr, "ERROR: Couldn't redirect stdout to '%s': %s\n", stdout_path.c_str(), strerror(errno)); } else { setvbuf(f, 0, _IOLBF, BUFSIZ); } f = _wfreopen(wstderr_path.c_str(), L"w", stderr); if (!f) { fprintf(stderr, "ERROR: Couldn't redirect stderr to '%s': %s\n", stderr_path.c_str(), strerror(errno)); } else { setvbuf(f, 0, _IOLBF, BUFSIZ); } }
RefCountedPtr<FileData> FileSourceFS::ReadFile(const std::string &path) { const std::string fullpath = JoinPathBelow(GetRoot(), path); const std::wstring wfullpath = transcode_utf8_to_utf16(fullpath); HANDLE filehandle = CreateFileW(wfullpath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (filehandle == INVALID_HANDLE_VALUE) return RefCountedPtr<FileData>(0); else { const Time::DateTime modtime = file_modtime_for_handle(filehandle); LARGE_INTEGER large_size; if (!GetFileSizeEx(filehandle, &large_size)) { Output("failed to get file size for '%s'\n", fullpath.c_str()); CloseHandle(filehandle); abort(); } size_t size = size_t(large_size.QuadPart); char *data = static_cast<char*>(std::malloc(size)); if (!data) { // XXX handling memory allocation failure gracefully is too hard right now Output("failed when allocating buffer for '%s'\n", fullpath.c_str()); CloseHandle(filehandle); abort(); } if (size > 0x7FFFFFFFull) { Output("file '%s' is too large (can't currently cope with files > 2GB)\n", fullpath.c_str()); CloseHandle(filehandle); abort(); } DWORD read_size; BOOL ret = ::ReadFile(filehandle, static_cast<LPVOID>(data), (DWORD)size, &read_size, 0); if (!ret) { Output("error while reading file '%s'\n", fullpath.c_str()); CloseHandle(filehandle); abort(); } if (size_t(read_size) != size) { Output("file '%s' truncated\n", fullpath.c_str()); memset(data + read_size, 0xee, size - read_size); } CloseHandle(filehandle); return RefCountedPtr<FileData>(new FileDataMalloc(MakeFileInfo(path, FileInfo::FT_FILE, modtime), size, data)); } }
// Call MessageBox with error icon and abort void Error(const char *format, ...) { char buf[1024]; va_list ap; va_start(ap, format); vsnprintf(buf, sizeof(buf), format, ap); va_end(ap); fprintf(stderr, "Error: %s\n", buf); MessageBoxW(0, transcode_utf8_to_utf16(buf, strlen(buf)).c_str(), L"Error", MB_ICONERROR|MB_OK); #ifndef NDEBUG abort(); #else exit(-1); #endif }
FileInfo FileSourceFS::Lookup(const std::string &path) { const std::string fullpath = JoinPathBelow(GetRoot(), path); const std::wstring wfullpath = transcode_utf8_to_utf16(fullpath); DWORD attrs = GetFileAttributesW(wfullpath.c_str()); const FileInfo::FileType ty = file_type_for_attributes(attrs); Time::DateTime modtime; if (ty == FileInfo::FT_FILE || ty == FileInfo::FT_DIR) { HANDLE hfile = CreateFileW(wfullpath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hfile != INVALID_HANDLE_VALUE) { modtime = file_modtime_for_handle(hfile); CloseHandle(hfile); } } return MakeFileInfo(path, ty, modtime); }
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; }
static FILE* open_file_raw(const std::string &fullpath, const wchar_t *mode) { const std::wstring wfullpath = transcode_utf8_to_utf16(fullpath); return _wfopen(wfullpath.c_str(), mode); }
bool FileSourceFS::MakeDirectory(const std::string &path) { const std::string fullpath = JoinPathBelow(GetRoot(), path); const std::wstring wfullpath = transcode_utf8_to_utf16(fullpath); return make_directory_raw(wfullpath); }