// 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; }
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); }
void File::throwOnNotFound(const NotFoundInfo &info) { throwOnError(info); const std::string message = formatString("File '%s' does not exist or is not accessible.\n%s", info.filename, info.message); GMX_THROW_WITH_ERRNO(InvalidInputError(message), info.call, info.err); }
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); } }
// 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); } } }
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 }