Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
5.9 KiB

  1. // files.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #ifndef CRYPTOPP_IMPORTS
  4. #include "files.h"
  5. #include <limits>
  6. NAMESPACE_BEGIN(CryptoPP)
  7. #if !defined(NDEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
  8. void Files_TestInstantiations()
  9. {
  10. FileStore f0;
  11. FileSource f1;
  12. FileSink f2;
  13. }
  14. #endif
  15. void FileStore::StoreInitialize(const NameValuePairs &parameters)
  16. {
  17. m_waiting = false;
  18. m_stream = NULL;
  19. m_file.release();
  20. const char *fileName = NULL;
  21. #if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
  22. const wchar_t *fileNameWide = NULL;
  23. if (!parameters.GetValue(Name::InputFileNameWide(), fileNameWide))
  24. #endif
  25. if (!parameters.GetValue(Name::InputFileName(), fileName))
  26. {
  27. parameters.GetValue(Name::InputStreamPointer(), m_stream);
  28. return;
  29. }
  30. std::ios::openmode binary = parameters.GetValueWithDefault(Name::InputBinaryMode(), true) ? std::ios::binary : std::ios::openmode(0);
  31. m_file.reset(new std::ifstream);
  32. #ifdef CRYPTOPP_UNIX_AVAILABLE
  33. std::string narrowed;
  34. if (fileNameWide)
  35. fileName = (narrowed = StringNarrow(fileNameWide)).c_str();
  36. #endif
  37. #if _MSC_VER >= 1400
  38. if (fileNameWide)
  39. {
  40. m_file->open(fileNameWide, std::ios::in | binary);
  41. if (!*m_file)
  42. throw OpenErr(StringNarrow(fileNameWide, false));
  43. }
  44. #endif
  45. if (fileName)
  46. {
  47. m_file->open(fileName, std::ios::in | binary);
  48. if (!*m_file)
  49. throw OpenErr(fileName);
  50. }
  51. m_stream = m_file.get();
  52. }
  53. lword FileStore::MaxRetrievable() const
  54. {
  55. if (!m_stream)
  56. return 0;
  57. std::streampos current = m_stream->tellg();
  58. std::streampos end = m_stream->seekg(0, std::ios::end).tellg();
  59. m_stream->seekg(current);
  60. return end-current;
  61. }
  62. size_t FileStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
  63. {
  64. if (!m_stream)
  65. {
  66. transferBytes = 0;
  67. return 0;
  68. }
  69. lword size=transferBytes;
  70. transferBytes = 0;
  71. if (m_waiting)
  72. goto output;
  73. while (size && m_stream->good())
  74. {
  75. {
  76. size_t spaceSize = 1024;
  77. m_space = HelpCreatePutSpace(target, channel, 1, UnsignedMin(size_t(SIZE_MAX), size), spaceSize);
  78. m_stream->read((char *)m_space, (unsigned int)STDMIN(size, (lword)spaceSize));
  79. }
  80. m_len = (size_t)m_stream->gcount();
  81. size_t blockedBytes;
  82. output:
  83. blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking);
  84. m_waiting = blockedBytes > 0;
  85. if (m_waiting)
  86. return blockedBytes;
  87. size -= m_len;
  88. transferBytes += m_len;
  89. }
  90. if (!m_stream->good() && !m_stream->eof())
  91. throw ReadErr();
  92. return 0;
  93. }
  94. size_t FileStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
  95. {
  96. if (!m_stream)
  97. return 0;
  98. if (begin == 0 && end == 1)
  99. {
  100. int result = m_stream->peek();
  101. if (result == std::char_traits<char>::eof())
  102. return 0;
  103. else
  104. {
  105. size_t blockedBytes = target.ChannelPut(channel, byte(result), blocking);
  106. begin += 1-blockedBytes;
  107. return blockedBytes;
  108. }
  109. }
  110. // TODO: figure out what happens on cin
  111. std::streampos current = m_stream->tellg();
  112. std::streampos endPosition = m_stream->seekg(0, std::ios::end).tellg();
  113. std::streampos newPosition = current + static_cast<std::streamoff>(begin);
  114. if (newPosition >= endPosition)
  115. {
  116. m_stream->seekg(current);
  117. return 0; // don't try to seek beyond the end of file
  118. }
  119. m_stream->seekg(newPosition);
  120. try
  121. {
  122. assert(!m_waiting);
  123. lword copyMax = end-begin;
  124. size_t blockedBytes = const_cast<FileStore *>(this)->TransferTo2(target, copyMax, channel, blocking);
  125. begin += copyMax;
  126. if (blockedBytes)
  127. {
  128. const_cast<FileStore *>(this)->m_waiting = false;
  129. return blockedBytes;
  130. }
  131. }
  132. catch(...)
  133. {
  134. m_stream->clear();
  135. m_stream->seekg(current);
  136. throw;
  137. }
  138. m_stream->clear();
  139. m_stream->seekg(current);
  140. return 0;
  141. }
  142. lword FileStore::Skip(lword skipMax)
  143. {
  144. if (!m_stream)
  145. return 0;
  146. lword oldPos = m_stream->tellg();
  147. std::istream::off_type offset;
  148. if (!SafeConvert(skipMax, offset))
  149. throw InvalidArgument("FileStore: maximum seek offset exceeded");
  150. m_stream->seekg(offset, std::ios::cur);
  151. return (lword)m_stream->tellg() - oldPos;
  152. }
  153. void FileSink::IsolatedInitialize(const NameValuePairs &parameters)
  154. {
  155. m_stream = NULL;
  156. m_file.release();
  157. const char *fileName = NULL;
  158. #if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
  159. const wchar_t *fileNameWide = NULL;
  160. if (!parameters.GetValue(Name::OutputFileNameWide(), fileNameWide))
  161. #endif
  162. if (!parameters.GetValue(Name::OutputFileName(), fileName))
  163. {
  164. parameters.GetValue(Name::OutputStreamPointer(), m_stream);
  165. return;
  166. }
  167. std::ios::openmode binary = parameters.GetValueWithDefault(Name::OutputBinaryMode(), true) ? std::ios::binary : std::ios::openmode(0);
  168. m_file.reset(new std::ofstream);
  169. #ifdef CRYPTOPP_UNIX_AVAILABLE
  170. std::string narrowed;
  171. if (fileNameWide)
  172. fileName = (narrowed = StringNarrow(fileNameWide)).c_str();
  173. #elif (CRYPTOPP_MSC_VERSION >= 1400)
  174. if (fileNameWide)
  175. {
  176. m_file->open(fileNameWide, std::ios::out | std::ios::trunc | binary);
  177. if (!*m_file)
  178. throw OpenErr(StringNarrow(fileNameWide, false));
  179. }
  180. #endif
  181. if (fileName)
  182. {
  183. m_file->open(fileName, std::ios::out | std::ios::trunc | binary);
  184. if (!*m_file)
  185. throw OpenErr(fileName);
  186. }
  187. m_stream = m_file.get();
  188. }
  189. bool FileSink::IsolatedFlush(bool hardFlush, bool blocking)
  190. {
  191. CRYPTOPP_UNUSED(hardFlush), CRYPTOPP_UNUSED(blocking);
  192. if (!m_stream)
  193. throw Err("FileSink: output stream not opened");
  194. m_stream->flush();
  195. if (!m_stream->good())
  196. throw WriteErr();
  197. return false;
  198. }
  199. size_t FileSink::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
  200. {
  201. CRYPTOPP_UNUSED(blocking);
  202. if (!m_stream)
  203. throw Err("FileSink: output stream not opened");
  204. while (length > 0)
  205. {
  206. std::streamsize size;
  207. if (!SafeConvert(length, size))
  208. size = ((std::numeric_limits<std::streamsize>::max)());
  209. m_stream->write((const char *)inString, size);
  210. inString += size;
  211. length -= (size_t)size;
  212. }
  213. if (messageEnd)
  214. m_stream->flush();
  215. if (!m_stream->good())
  216. throw WriteErr();
  217. return 0;
  218. }
  219. NAMESPACE_END
  220. #endif