serialise.cc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #include "serialise.hh"
  2. #include "util.hh"
  3. #include <cstring>
  4. #include <cerrno>
  5. namespace nix {
  6. BufferedSink::~BufferedSink()
  7. {
  8. /* We can't call flush() here, because C++ for some insane reason
  9. doesn't allow you to call virtual methods from a destructor. */
  10. assert(!bufPos);
  11. delete[] buffer;
  12. }
  13. void BufferedSink::operator () (const unsigned char * data, size_t len)
  14. {
  15. if (!buffer) buffer = new unsigned char[bufSize];
  16. while (len) {
  17. /* Optimisation: bypass the buffer if the data exceeds the
  18. buffer size. */
  19. if (bufPos + len >= bufSize) {
  20. flush();
  21. write(data, len);
  22. break;
  23. }
  24. /* Otherwise, copy the bytes to the buffer. Flush the buffer
  25. when it's full. */
  26. size_t n = bufPos + len > bufSize ? bufSize - bufPos : len;
  27. memcpy(buffer + bufPos, data, n);
  28. data += n; bufPos += n; len -= n;
  29. if (bufPos == bufSize) flush();
  30. }
  31. }
  32. void BufferedSink::flush()
  33. {
  34. if (bufPos == 0) return;
  35. size_t n = bufPos;
  36. bufPos = 0; // don't trigger the assert() in ~BufferedSink()
  37. write(buffer, n);
  38. }
  39. FdSink::~FdSink()
  40. {
  41. try { flush(); } catch (...) { ignoreException(); }
  42. }
  43. size_t threshold = 256 * 1024 * 1024;
  44. static void warnLargeDump()
  45. {
  46. printMsg(lvlError, "warning: dumping very large path (> 256 MiB); this may run out of memory");
  47. }
  48. void FdSink::write(const unsigned char * data, size_t len)
  49. {
  50. static bool warned = false;
  51. if (warn && !warned) {
  52. written += len;
  53. if (written > threshold) {
  54. warnLargeDump();
  55. warned = true;
  56. }
  57. }
  58. writeFull(fd, data, len);
  59. }
  60. void Source::operator () (unsigned char * data, size_t len)
  61. {
  62. while (len) {
  63. size_t n = read(data, len);
  64. data += n; len -= n;
  65. }
  66. }
  67. BufferedSource::~BufferedSource()
  68. {
  69. delete[] buffer;
  70. }
  71. size_t BufferedSource::read(unsigned char * data, size_t len)
  72. {
  73. if (!buffer) buffer = new unsigned char[bufSize];
  74. if (!bufPosIn) bufPosIn = readUnbuffered(buffer, bufSize);
  75. /* Copy out the data in the buffer. */
  76. size_t n = len > bufPosIn - bufPosOut ? bufPosIn - bufPosOut : len;
  77. memcpy(data, buffer + bufPosOut, n);
  78. bufPosOut += n;
  79. if (bufPosIn == bufPosOut) bufPosIn = bufPosOut = 0;
  80. return n;
  81. }
  82. bool BufferedSource::hasData()
  83. {
  84. return bufPosOut < bufPosIn;
  85. }
  86. size_t FdSource::readUnbuffered(unsigned char * data, size_t len)
  87. {
  88. ssize_t n;
  89. do {
  90. checkInterrupt();
  91. n = ::read(fd, (char *) data, bufSize);
  92. } while (n == -1 && errno == EINTR);
  93. if (n == -1) throw SysError("reading from file");
  94. if (n == 0) throw EndOfFile("unexpected end-of-file");
  95. return n;
  96. }
  97. size_t StringSource::read(unsigned char * data, size_t len)
  98. {
  99. if (pos == s.size()) throw EndOfFile("end of string reached");
  100. size_t n = s.copy((char *) data, len, pos);
  101. pos += n;
  102. return n;
  103. }
  104. void writePadding(size_t len, Sink & sink)
  105. {
  106. if (len % 8) {
  107. unsigned char zero[8];
  108. memset(zero, 0, sizeof(zero));
  109. sink(zero, 8 - (len % 8));
  110. }
  111. }
  112. void writeInt(unsigned int n, Sink & sink)
  113. {
  114. unsigned char buf[8];
  115. memset(buf, 0, sizeof(buf));
  116. buf[0] = n & 0xff;
  117. buf[1] = (n >> 8) & 0xff;
  118. buf[2] = (n >> 16) & 0xff;
  119. buf[3] = (n >> 24) & 0xff;
  120. sink(buf, sizeof(buf));
  121. }
  122. void writeLongLong(unsigned long long n, Sink & sink)
  123. {
  124. unsigned char buf[8];
  125. buf[0] = n & 0xff;
  126. buf[1] = (n >> 8) & 0xff;
  127. buf[2] = (n >> 16) & 0xff;
  128. buf[3] = (n >> 24) & 0xff;
  129. buf[4] = (n >> 32) & 0xff;
  130. buf[5] = (n >> 40) & 0xff;
  131. buf[6] = (n >> 48) & 0xff;
  132. buf[7] = (n >> 56) & 0xff;
  133. sink(buf, sizeof(buf));
  134. }
  135. void writeString(const unsigned char * buf, size_t len, Sink & sink)
  136. {
  137. writeInt(len, sink);
  138. sink(buf, len);
  139. writePadding(len, sink);
  140. }
  141. void writeString(const string & s, Sink & sink)
  142. {
  143. writeString((const unsigned char *) s.data(), s.size(), sink);
  144. }
  145. template<class T> void writeStrings(const T & ss, Sink & sink)
  146. {
  147. writeInt(ss.size(), sink);
  148. foreach (typename T::const_iterator, i, ss)
  149. writeString(*i, sink);
  150. }
  151. template void writeStrings(const Paths & ss, Sink & sink);
  152. template void writeStrings(const PathSet & ss, Sink & sink);
  153. void readPadding(size_t len, Source & source)
  154. {
  155. if (len % 8) {
  156. unsigned char zero[8];
  157. size_t n = 8 - (len % 8);
  158. source(zero, n);
  159. for (unsigned int i = 0; i < n; i++)
  160. if (zero[i]) throw SerialisationError("non-zero padding");
  161. }
  162. }
  163. unsigned int readInt(Source & source)
  164. {
  165. unsigned char buf[8];
  166. source(buf, sizeof(buf));
  167. if (buf[4] || buf[5] || buf[6] || buf[7])
  168. throw SerialisationError("implementation cannot deal with > 32-bit integers");
  169. return
  170. buf[0] |
  171. (buf[1] << 8) |
  172. (buf[2] << 16) |
  173. (buf[3] << 24);
  174. }
  175. unsigned long long readLongLong(Source & source)
  176. {
  177. unsigned char buf[8];
  178. source(buf, sizeof(buf));
  179. return
  180. ((unsigned long long) buf[0]) |
  181. ((unsigned long long) buf[1] << 8) |
  182. ((unsigned long long) buf[2] << 16) |
  183. ((unsigned long long) buf[3] << 24) |
  184. ((unsigned long long) buf[4] << 32) |
  185. ((unsigned long long) buf[5] << 40) |
  186. ((unsigned long long) buf[6] << 48) |
  187. ((unsigned long long) buf[7] << 56);
  188. }
  189. size_t readString(unsigned char * buf, size_t max, Source & source)
  190. {
  191. size_t len = readInt(source);
  192. if (len > max) throw Error("string is too long");
  193. source(buf, len);
  194. readPadding(len, source);
  195. return len;
  196. }
  197. string readString(Source & source)
  198. {
  199. size_t len = readInt(source);
  200. unsigned char * buf = new unsigned char[len];
  201. AutoDeleteArray<unsigned char> d(buf);
  202. source(buf, len);
  203. readPadding(len, source);
  204. return string((char *) buf, len);
  205. }
  206. template<class T> T readStrings(Source & source)
  207. {
  208. unsigned int count = readInt(source);
  209. T ss;
  210. while (count--)
  211. ss.insert(ss.end(), readString(source));
  212. return ss;
  213. }
  214. template Paths readStrings(Source & source);
  215. template PathSet readStrings(Source & source);
  216. void StringSink::operator () (const unsigned char * data, size_t len)
  217. {
  218. static bool warned = false;
  219. if (!warned && s.size() > threshold) {
  220. warnLargeDump();
  221. warned = true;
  222. }
  223. s.append((const char *) data, len);
  224. }
  225. }