osd_file::error osd_file::open(std::string const &orig_path, UINT32 openflags, ptr &file, std::uint64_t &filesize) { std::string path; try { osd_subst_env(path, orig_path); } catch (...) { return error::OUT_OF_MEMORY; } if (win_check_socket_path(path)) return win_open_socket(path, openflags, file, filesize); else if (win_check_ptty_path(path)) return win_open_ptty(path, openflags, file, filesize); // convert path to TCHAR TCHAR *t_path = tstring_from_utf8(path.c_str()); osd_disposer<TCHAR> t_path_disposer(t_path); if (!t_path) return error::OUT_OF_MEMORY; // convert the path into something Windows compatible for (TCHAR *src = t_path; *src != 0; src++) *src = /* ('/' == *src) ? '\\' : */ *src; // select the file open modes DWORD disposition, access, sharemode; if (openflags & OPEN_FLAG_WRITE) { disposition = (!is_path_to_physical_drive(path.c_str()) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING; access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE; sharemode = FILE_SHARE_READ; } else if (openflags & OPEN_FLAG_READ) { disposition = OPEN_EXISTING; access = GENERIC_READ; sharemode = FILE_SHARE_READ; } else { return error::INVALID_ACCESS; } // attempt to open the file HANDLE h = CreateFile(t_path, access, sharemode, nullptr, disposition, 0, nullptr); if (INVALID_HANDLE_VALUE == h) { DWORD err = GetLastError(); // create the path if necessary if ((ERROR_PATH_NOT_FOUND == err) && (openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS)) { TCHAR *pathsep = _tcsrchr(t_path, '\\'); if (pathsep != nullptr) { // create the path up to the file *pathsep = 0; err = create_path_recursive(t_path); *pathsep = '\\'; // attempt to reopen the file if (err == NO_ERROR) { h = CreateFile(t_path, access, sharemode, nullptr, disposition, 0, nullptr); err = GetLastError(); } } } // if we still failed, clean up and free if (INVALID_HANDLE_VALUE == h) return win_error_to_file_error(err); } // get the file size DWORD upper, lower; lower = GetFileSize(h, &upper); if (INVALID_FILE_SIZE == lower) { DWORD const err = GetLastError(); if (NO_ERROR != err) { CloseHandle(h); return win_error_to_file_error(err); } } try { file = std::make_unique<win_osd_file>(h); filesize = (std::uint64_t(upper) << 32) | lower; return error::NONE; } catch (...) { CloseHandle(h); return error::OUT_OF_MEMORY; } }
osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize) { std::string path; try { osd_subst_env(path, orig_path); } catch (...) { return error::OUT_OF_MEMORY; } if (win_check_socket_path(path)) return win_open_socket(path, openflags, file, filesize); else if (win_check_ptty_path(path)) return win_open_ptty(path, openflags, file, filesize); // convert path to TCHAR osd::text::tstring t_path = osd::text::to_tstring(path); // convert the path into something Windows compatible (the actual interesting part appears // to have been commented out???) for (auto iter = t_path.begin(); iter != t_path.end(); iter++) *iter = /* ('/' == *iter) ? '\\' : */ *iter; // select the file open modes DWORD disposition, access, sharemode; if (openflags & OPEN_FLAG_WRITE) { disposition = (!is_path_to_physical_drive(path.c_str()) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING; access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE; sharemode = FILE_SHARE_READ; } else if (openflags & OPEN_FLAG_READ) { disposition = OPEN_EXISTING; access = GENERIC_READ; sharemode = FILE_SHARE_READ; } else { return error::INVALID_ACCESS; } // attempt to open the file HANDLE h = CreateFile(t_path.c_str(), access, sharemode, nullptr, disposition, 0, nullptr); if (INVALID_HANDLE_VALUE == h) { DWORD err = GetLastError(); // create the path if necessary if ((ERROR_PATH_NOT_FOUND == err) && (openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS)) { auto pathsep = t_path.rfind('\\'); if (pathsep != decltype(t_path)::npos) { // create the path up to the file t_path[pathsep] = 0; err = create_path_recursive(&t_path[0]); t_path[pathsep] = '\\'; // attempt to reopen the file if (err == NO_ERROR) { h = CreateFile(t_path.c_str(), access, sharemode, nullptr, disposition, 0, nullptr); err = GetLastError(); } } } // if we still failed, clean up and free if (INVALID_HANDLE_VALUE == h) return win_error_to_file_error(err); } // get the file size DWORD upper, lower; lower = GetFileSize(h, &upper); if (INVALID_FILE_SIZE == lower) { DWORD const err = GetLastError(); if (NO_ERROR != err) { CloseHandle(h); return win_error_to_file_error(err); } } try { file = std::make_unique<win_osd_file>(h); filesize = (std::uint64_t(upper) << 32) | lower; return error::NONE; } catch (...) { CloseHandle(h); return error::OUT_OF_MEMORY; } }