// static std::string File::readToString(const char *filename) { // Binary mode is required on Windows to be able to determine a size // that can be passed to fread(). File file(filename, "rb"); FILE *fp = file.handle(); if (std::fseek(fp, 0L, SEEK_END) != 0) { GMX_THROW_WITH_ERRNO(FileIOError("Seeking to end of file failed"), "fseek", errno); } long len = std::ftell(fp); if (len == -1) { GMX_THROW_WITH_ERRNO(FileIOError("Reading file length failed"), "ftell", errno); } if (std::fseek(fp, 0L, SEEK_SET) != 0) { GMX_THROW_WITH_ERRNO(FileIOError("Seeking to start of file failed"), "fseek", errno); } std::vector<char> data(len); file.readBytes(&data[0], len); file.close(); std::string result(&data[0], len); // The below is necessary on Windows to make newlines stay as '\n' on a // roundtrip. result = replaceAll(result, "\r\n", "\n"); return result; }
/*! \brief Get the path to the main folder storing OpenCL kernels. * * By default, this function constructs the full path to the OpenCL from * the known location of the binary that is running, so that we handle * both in-source and installed builds. The user can override this * behavior by defining GMX_OCL_FILE_PATH environment variable. * * \return OS-normalized path string to the main folder storing OpenCL kernels * * \throws std::bad_alloc if out of memory. * FileIOError if GMX_OCL_FILE_PATH does not specify a readable path */ static std::string getKernelRootPath() { std::string kernelRootPath; /* Use GMX_OCL_FILE_PATH if the user has defined it */ const char *gmxOclFilePath = getenv("GMX_OCL_FILE_PATH"); if (gmxOclFilePath == nullptr) { /* Normal way of getting ocl_root_dir. First get the right root path from the path to the binary that is running. */ InstallationPrefixInfo info = getProgramContext().installationPrefix(); std::string dataPathSuffix = (info.bSourceLayout ? "src/gromacs/mdlib/nbnxn_ocl" : OCL_INSTALL_DIR); kernelRootPath = Path::join(info.path, dataPathSuffix); } else { if (!Directory::exists(gmxOclFilePath)) { GMX_THROW(FileIOError(formatString("GMX_OCL_FILE_PATH must point to the directory where OpenCL" "kernels are found, but '%s' does not exist", gmxOclFilePath))); } kernelRootPath = gmxOclFilePath; } // Make sure we return an OS-correct path format return Path::normalize(kernelRootPath); }
bool File::readLine(std::string *line) { line->clear(); const size_t bufsize = 256; std::string result; char buf[bufsize]; buf[0] = '\0'; FILE *fp = handle(); while (fgets(buf, bufsize, fp) != NULL) { size_t length = std::strlen(buf); result.append(buf, length); if (length < bufsize - 1 || buf[length - 1] == '\n') { break; } } if (ferror(fp)) { GMX_THROW_WITH_ERRNO(FileIOError("Error while reading file"), "fgets", errno); } *line = result; return !result.empty() || !feof(fp); }
EnergyFrameReaderPtr openEnergyFileToReadFields(const std::string &filename, const std::vector<std::string> &namesOfRequiredEnergyFields) { ener_file_ptr energyFile(open_enx(filename.c_str(), "r")); if (!energyFile) { GMX_THROW(FileIOError("Could not open energy file " + filename + " for reading")); } /* Read in the names of energy fields used in this file. The * resulting data structure would leak if an exception was thrown, * so transfer the contents that we actually need to a map we can * keep. * * TODO Technically, the insertions into the map could throw * std::bad_alloc and we could leak memory allocated by * do_enxnms(), but there's nothing we can do about this right * now. */ std::map<std::string, int> indicesOfEnergyFields; { int numEnergyTerms; gmx_enxnm_t *energyNames = nullptr; do_enxnms(energyFile.get(), &numEnergyTerms, &energyNames); for (int i = 0; i != numEnergyTerms; ++i) { const char *name = energyNames[i].name; auto requiredEnergy = std::find_if(std::begin(namesOfRequiredEnergyFields), std::end(namesOfRequiredEnergyFields), [name](const std::string &n){ return 0 == n.compare(name); }); if (requiredEnergy != namesOfRequiredEnergyFields.end()) { indicesOfEnergyFields[name] = i; } } // Clean up old data structures free_enxnms(numEnergyTerms, energyNames); } // Throw if we failed to find the fields we need if (indicesOfEnergyFields.size() != namesOfRequiredEnergyFields.size()) { std::string requiredEnergiesNotFound = "Did not find the following required energies in mdrun output:\n"; for (auto &name : namesOfRequiredEnergyFields) { auto possibleIndex = indicesOfEnergyFields.find(name); if (possibleIndex == indicesOfEnergyFields.end()) { requiredEnergiesNotFound += name + "\n"; } } GMX_THROW(APIError(requiredEnergiesNotFound)); } return EnergyFrameReaderPtr(new EnergyFrameReader(indicesOfEnergyFields, energyFile.release())); }
void File::writeString(const char *str) { if (fprintf(handle(), "%s", str) < 0) { GMX_THROW_WITH_ERRNO(FileIOError("Writing to file failed"), "fprintf", errno); } }
void File::throwOnError(const NotFoundInfo &info) { if (info.wasError) { const std::string message = formatString("Failed to access file '%s'.\n%s", info.filename, info.message); GMX_THROW_WITH_ERRNO(FileIOError(message), info.call, info.err); } }
std::vector<DataFileInfo> DataFileFinder::enumerateFiles(const DataFileOptions &options) const { // TODO: Consider if not being able to list one of the directories should // really be a fatal error. Or alternatively, check somewhere else that // paths in GMXLIB are valid. std::vector<DataFileInfo> result; std::vector<std::string>::const_iterator i; if (options.bCurrentDir_) { std::vector<std::string> files = DirectoryEnumerator::enumerateFilesWithExtension( ".", options.filename_, false); for (i = files.begin(); i != files.end(); ++i) { result.emplace_back(".", *i, false); } } if (impl_ != nullptr) { std::vector<std::string>::const_iterator j; for (j = impl_->searchPath_.begin(); j != impl_->searchPath_.end(); ++j) { std::vector<std::string> files = DirectoryEnumerator::enumerateFilesWithExtension( j->c_str(), options.filename_, false); for (i = files.begin(); i != files.end(); ++i) { result.emplace_back(*j, *i, false); } } } const std::string &defaultPath = Impl::getDefaultPath(); if (!defaultPath.empty()) { std::vector<std::string> files = DirectoryEnumerator::enumerateFilesWithExtension( defaultPath.c_str(), options.filename_, false); for (i = files.begin(); i != files.end(); ++i) { result.emplace_back(defaultPath, *i, true); } } if (result.empty() && options.bThrow_) { // TODO: Print the search path as is done in findFile(). std::string message( formatString("Could not find any files ending on '%s' in the " "current directory or the GROMACS library search path", options.filename_)); GMX_THROW(FileIOError(message)); } return result; }
// static FILE *File::openRawHandle(const char *filename, const char *mode) { FILE *fp = fopen(filename, mode); if (fp == NULL) { GMX_THROW_WITH_ERRNO( FileIOError(formatString("Could not open file '%s'", filename)), "fopen", errno); } return fp; }
void IntegrationTestFixture::redirectStringToStdin(const char* theString) { std::string fakeStdin("fake-stdin"); gmx::File::writeFileFromString(fakeStdin, theString); if (NULL == std::freopen(fakeStdin.c_str(), "r", stdin)) { GMX_THROW_WITH_ERRNO(FileIOError("Failed to redirect a string to stdin"), "freopen", errno); } }
void File::open(const char *filename, const char *mode) { GMX_RELEASE_ASSERT(impl_->fp_ == NULL, "Attempted to open the same file object twice"); // TODO: Port all necessary functionality from ffopen() here. impl_->fp_ = fopen(filename, mode); if (impl_->fp_ == NULL) { GMX_THROW_WITH_ERRNO( FileIOError(formatString("Could not open file '%s'", filename)), "fopen", errno); } }
void File::close() { GMX_RELEASE_ASSERT(impl_->fp_ != NULL, "Attempted to close a file object that is not open"); GMX_RELEASE_ASSERT(impl_->bClose_, "Attempted to close a file object that should not be"); bool bOk = (fclose(impl_->fp_) == 0); impl_->fp_ = NULL; if (!bOk) { GMX_THROW_WITH_ERRNO( FileIOError("Error while closing file"), "fclose", errno); } }
void File::readBytes(void *buffer, size_t bytes) { errno = 0; FILE *fp = handle(); // TODO: Retry based on errno or something else? size_t bytesRead = std::fread(buffer, 1, bytes, fp); if (bytesRead != bytes) { if (feof(fp)) { GMX_THROW(FileIOError( formatString("Premature end of file\n" "Attempted to read: %d bytes\n" "Successfully read: %d bytes", static_cast<int>(bytes), static_cast<int>(bytesRead)))); } else { GMX_THROW_WITH_ERRNO(FileIOError("Error while reading file"), "fread", errno); } } }
void HttpClient::loadResponse() { if (request == null) { throw FileIOError(THISLOCATION, 1, "Can't read response without request"); } if (!request->isOutputClosed()) request->closeOutput(); if (response == null) { createResponse(true); } else { response->readHeaders(); } while (response->canContinue()) { response->waitAfterContinue(HttpResponse::readHeadersNow); } request = null; }
bool TrajectoryFrameReader::readNextFrame() { if (haveProbedForNextFrame_) { if (nextFrameExists_) { GMX_THROW(APIError("This frame has already been probed for, it should be used before probing again.")); } else { GMX_THROW(APIError("This frame has already been probed for, it doesn't exist, so there should not be subsequent attempts to probe for it.")); } } haveProbedForNextFrame_ = true; // If there's a next frame, read it into trxframe_, and report the result. if (!haveReadFirstFrame_) { t_trxstatus *trajectoryFile; int flags = TRX_READ_X | TRX_READ_V | TRX_READ_F; nextFrameExists_ = read_first_frame(oenvGuard_.get(), &trajectoryFile, filename_.c_str(), trxframeGuard_.get(), flags); if (!trajectoryFile) { GMX_THROW(FileIOError("Could not open trajectory file " + filename_ + " for reading")); } trajectoryFileGuard_.reset(trajectoryFile); haveReadFirstFrame_ = true; } else { nextFrameExists_ = read_next_frame(oenvGuard_.get(), trajectoryFileGuard_.get(), trxframeGuard_.get()); } return nextFrameExists_; }
cl_program compileProgram(FILE *fplog, const std::string &kernelBaseFilename, const std::string &extraDefines, cl_context context, cl_device_id deviceId, ocl_vendor_id_t deviceVendorId) { cl_int cl_error; std::string kernelRootPath = getKernelRootPath(); GMX_RELEASE_ASSERT(fplog != nullptr, "Need a valid log file for building OpenCL programs"); /* Load OpenCL source files */ std::string kernelFilename = Path::join(kernelRootPath, kernelBaseFilename); /* Make the build options */ std::string preprocessorOptions = makePreprocessorOptions(kernelRootPath, getWarpSize(context, deviceId), deviceVendorId, extraDefines); bool buildCacheWasRead = false; std::string cacheFilename; if (useBuildCache) { cacheFilename = makeBinaryCacheFilename(kernelBaseFilename, deviceId); } /* Create OpenCL program */ cl_program program = nullptr; if (useBuildCache) { if (File::exists(cacheFilename, File::returnFalseOnError)) { /* Check if there's a valid cache available */ try { program = makeProgramFromCache(cacheFilename, context, deviceId); buildCacheWasRead = true; } catch (FileIOError &e) { // Failing to read from the cache is not a critical error formatExceptionMessageToFile(fplog, e); } } else { fprintf(fplog, "No OpenCL binary cache file was present, so will compile kernels normally.\n"); } } if (program == nullptr) { // Compile OpenCL program from source std::string kernelSource = TextReader::readFileToString(kernelFilename); if (kernelSource.empty()) { GMX_THROW(FileIOError("Error loading OpenCL code " + kernelFilename)); } const char *kernelSourcePtr = kernelSource.c_str(); size_t kernelSourceSize = kernelSource.size(); /* Create program from source code */ program = clCreateProgramWithSource(context, 1, &kernelSourcePtr, &kernelSourceSize, &cl_error); if (cl_error != CL_SUCCESS) { GMX_THROW(InternalError("Could not create OpenCL program, error was " + ocl_get_error_string(cl_error))); } } /* Build the OpenCL program, keeping the status to potentially write to the simulation log file. */ cl_int buildStatus = clBuildProgram(program, 0, NULL, preprocessorOptions.c_str(), NULL, NULL); /* Write log first, and then throw exception that the user know what is the issue even if the build fails. */ writeOclBuildLog(fplog, program, deviceId, kernelFilename, preprocessorOptions, buildStatus != CL_SUCCESS); if (buildStatus != CL_SUCCESS) { GMX_THROW(InternalError("Could not build OpenCL program, error was " + ocl_get_error_string(buildStatus))); } if (useBuildCache) { if (!buildCacheWasRead) { /* If OpenCL caching is ON, but the current cache is not valid => update it */ try { writeBinaryToCache(program, cacheFilename); } catch (GromacsException &e) { // Failing to write the cache is not a critical error formatExceptionMessageToFile(fplog, e); } } } if ((OCL_VENDOR_NVIDIA == deviceVendorId) && getenv("GMX_OCL_DUMP_INTERM_FILES")) { /* If dumping intermediate files has been requested and this is an NVIDIA card => write PTX to file */ char buffer[STRLEN]; cl_error = clGetDeviceInfo(deviceId, CL_DEVICE_NAME, sizeof(buffer), buffer, NULL); if (cl_error != CL_SUCCESS) { GMX_THROW(InternalError("Could not get OpenCL device info, error was " + ocl_get_error_string(cl_error))); } std::string ptxFilename = buffer; ptxFilename += ".ptx"; try { writeBinaryToCache(program, ptxFilename); } catch (GromacsException &e) { // Failing to write the cache is not a critical error formatExceptionMessageToFile(fplog, e); } } return program; }
void TrajectoryAnalysisRunnerCommon::Impl::initFirstFrame() { // Return if we have already initialized the trajectory. if (fr != NULL) { return; } time_unit_t time_unit = static_cast<time_unit_t>(settings_.timeUnit() + 1); output_env_init(&oenv_, getProgramContext(), time_unit, FALSE, exvgNONE, 0); int frflags = settings_.frflags(); frflags |= TRX_NEED_X; snew(fr, 1); if (hasTrajectory()) { if (!read_first_frame(oenv_, &status_, trjfile_.c_str(), fr, frflags)) { GMX_THROW(FileIOError("Could not read coordinates from trajectory")); } bTrajOpen_ = true; if (topInfo_.hasTopology()) { const int topologyAtomCount = topInfo_.topology()->atoms.nr; if (fr->natoms > topologyAtomCount) { const std::string message = formatString("Trajectory (%d atoms) does not match topology (%d atoms)", fr->natoms, topologyAtomCount); GMX_THROW(InconsistentInputError(message)); } } } else { // Prepare a frame from topology information. // TODO: Initialize more of the fields. if (frflags & (TRX_NEED_V)) { GMX_THROW(NotImplementedError("Velocity reading from a topology not implemented")); } if (frflags & (TRX_NEED_F)) { GMX_THROW(InvalidInputError("Forces cannot be read from a topology")); } fr->natoms = topInfo_.topology()->atoms.nr; fr->bX = TRUE; snew(fr->x, fr->natoms); memcpy(fr->x, topInfo_.xtop_, sizeof(*fr->x) * fr->natoms); fr->bBox = TRUE; copy_mat(topInfo_.boxtop_, fr->box); } set_trxframe_ePBC(fr, topInfo_.ePBC()); if (topInfo_.hasTopology() && settings_.hasRmPBC()) { gpbc_ = gmx_rmpbc_init(&topInfo_.topology()->idef, topInfo_.ePBC(), fr->natoms); } }
void TrajectoryAnalysisRunnerCommon::initFirstFrame() { // Return if we have already initialized the trajectory. if (impl_->fr) { return; } time_unit_t time_unit = static_cast<time_unit_t>(impl_->settings_.timeUnit() + 1); output_env_init(&impl_->oenv_, 0, NULL, time_unit, FALSE, exvgNONE, 0, 0); int frflags = impl_->settings_.frflags(); frflags |= TRX_NEED_X; snew(impl_->fr, 1); const TopologyInformation &top = impl_->topInfo_; if (hasTrajectory()) { if (!read_first_frame(impl_->oenv_, &impl_->status_, impl_->trjfile_.c_str(), impl_->fr, frflags)) { GMX_THROW(FileIOError("Could not read coordinates from trajectory")); } impl_->bTrajOpen_ = true; if (top.hasTopology() && impl_->fr->natoms > top.topology()->atoms.nr) { GMX_THROW(InconsistentInputError(formatString( "Trajectory (%d atoms) does not match topology (%d atoms)", impl_->fr->natoms, top.topology()->atoms.nr))); } // Check index groups if they have been initialized based on the topology. /* if (top) { for (int i = 0; i < impl_->sel->nr(); ++i) { gmx_ana_index_check(impl_->sel->sel(i)->indexGroup(), impl_->fr->natoms); } } */ } else { // Prepare a frame from topology information. // TODO: Initialize more of the fields. if (frflags & (TRX_NEED_V)) { GMX_THROW(NotImplementedError("Velocity reading from a topology not implemented")); } if (frflags & (TRX_NEED_F)) { GMX_THROW(InvalidInputError("Forces cannot be read from a topology")); } impl_->fr->flags = frflags; impl_->fr->natoms = top.topology()->atoms.nr; impl_->fr->bX = TRUE; snew(impl_->fr->x, impl_->fr->natoms); memcpy(impl_->fr->x, top.xtop_, sizeof(*impl_->fr->x) * impl_->fr->natoms); impl_->fr->bBox = TRUE; copy_mat(const_cast<rvec *>(top.boxtop_), impl_->fr->box); } set_trxframe_ePBC(impl_->fr, top.ePBC()); if (top.hasTopology() && impl_->settings_.hasRmPBC()) { impl_->gpbc_ = gmx_rmpbc_init(&top.topology()->idef, top.ePBC(), impl_->fr->natoms, impl_->fr->box); } }
bool Path::isEquivalent(const std::string &path1, const std::string &path2) { //based on boost_1_56_0/libs/filesystem/src/operations.cpp under BSL #ifdef GMX_NATIVE_WINDOWS // Note well: Physical location on external media is part of the // equivalence criteria. If there are no open handles, physical location // can change due to defragmentation or other relocations. Thus handles // must be held open until location information for both paths has // been retrieved. // p2 is done first, so any error reported is for p1 // FixME: #1635 handle_wrapper h2( CreateFile( path2.c_str(), 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); handle_wrapper h1( CreateFile( path1.c_str(), 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); if (h1.handle == INVALID_HANDLE_VALUE || h2.handle == INVALID_HANDLE_VALUE) { // if one is invalid and the other isn't, then they aren't equivalent, // but if both are invalid then it is an error if (h1.handle == INVALID_HANDLE_VALUE && h2.handle == INVALID_HANDLE_VALUE) { GMX_THROW(FileIOError("Path::isEquivalent called with two invalid files")); } return false; } // at this point, both handles are known to be valid BY_HANDLE_FILE_INFORMATION info1, info2; if (!GetFileInformationByHandle(h1.handle, &info1)) { GMX_THROW(FileIOError("Path::isEquivalent: GetFileInformationByHandle failed")); } if (!GetFileInformationByHandle(h2.handle, &info2)) { GMX_THROW(FileIOError("Path::isEquivalent: GetFileInformationByHandle failed")); } // In theory, volume serial numbers are sufficient to distinguish between // devices, but in practice VSN's are sometimes duplicated, so last write // time and file size are also checked. return info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber && info1.nFileIndexHigh == info2.nFileIndexHigh && info1.nFileIndexLow == info2.nFileIndexLow && info1.nFileSizeHigh == info2.nFileSizeHigh && info1.nFileSizeLow == info2.nFileSizeLow && info1.ftLastWriteTime.dwLowDateTime == info2.ftLastWriteTime.dwLowDateTime && info1.ftLastWriteTime.dwHighDateTime == info2.ftLastWriteTime.dwHighDateTime; #else struct stat s1, s2; int e2 = stat(path2.c_str(), &s2); int e1 = stat(path1.c_str(), &s1); if (e1 != 0 || e2 != 0) { // if one is invalid and the other isn't then they aren't equivalent, // but if both are invalid then it is an error. if (e1 != 0 && e2 != 0) { GMX_THROW_WITH_ERRNO( FileIOError("Path::isEquivalent called with two invalid files"), "stat", errno); } return false; } // both stats now known to be valid return s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino // According to the POSIX stat specs, "The st_ino and st_dev fields // taken together uniquely identify the file within the system." // Just to be sure, size and mod time are also checked. && s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime; #endif }
std::string DataFileFinder::findFile(const DataFileOptions &options) const { if (options.bCurrentDir_ && Path::exists(options.filename_)) { return options.filename_; } if (impl_ != nullptr) { std::vector<std::string>::const_iterator i; for (i = impl_->searchPath_.begin(); i != impl_->searchPath_.end(); ++i) { // TODO: Deal with an empty search path entry more reasonably. std::string testPath = Path::join(*i, options.filename_); // TODO: Consider skipping directories. if (Path::exists(testPath)) { return testPath; } } } const std::string &defaultPath = Impl::getDefaultPath(); if (!defaultPath.empty()) { std::string testPath = Path::join(defaultPath, options.filename_); if (Path::exists(testPath)) { return testPath; } } if (options.bThrow_) { const char *const envName = (impl_ != nullptr ? impl_->envName_ : nullptr); const bool bEnvIsSet = (impl_ != nullptr ? impl_->bEnvIsSet_ : false); std::string message( formatString("Library file '%s' not found", options.filename_)); if (options.bCurrentDir_) { message.append(" in current dir nor"); } if (bEnvIsSet) { message.append(formatString(" in your %s path nor", envName)); } message.append(" in the default directories.\nThe following paths were searched:"); if (options.bCurrentDir_) { message.append("\n "); message.append(Path::getWorkingDirectory()); message.append(" (current dir)"); } if (impl_ != nullptr) { std::vector<std::string>::const_iterator i; for (i = impl_->searchPath_.begin(); i != impl_->searchPath_.end(); ++i) { message.append("\n "); message.append(*i); } } if (!defaultPath.empty()) { message.append("\n "); message.append(defaultPath); message.append(" (default)"); } if (!bEnvIsSet && envName != nullptr) { message.append( formatString("\nYou can set additional directories to search " "with the %s path variable.", envName)); } GMX_THROW(FileIOError(message)); } return std::string(); }