buffer.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * Copyright (c) 2018 Markus Hennecke <markus-hennecke@markus-hennecke.de>
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <endian.h>
  17. #include <err.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <unistd.h>
  21. #include <zlib.h>
  22. #include "buffer.h"
  23. #define DEFLATE_BUF_SIZE 0x4000
  24. #define GZIP_ENCODING 16
  25. #define OS_CODE 0x03
  26. #define ORIG_NAME 0x08
  27. struct buffer *
  28. buffer_new(const char *_data)
  29. {
  30. size_t data_len = strlen(_data);
  31. struct buffer *buf = malloc(sizeof(struct buffer) + data_len);
  32. if (buf == NULL)
  33. err(1, NULL);
  34. buf->size = data_len;
  35. memcpy(buf->data, _data, data_len);
  36. return buf;
  37. }
  38. struct buffer *
  39. buffer_bin_new(const void *_data, size_t _size)
  40. {
  41. struct buffer *buf = malloc(sizeof(struct buffer) + _size);
  42. if (buf == NULL)
  43. err(1, NULL);
  44. buf->size = _size;
  45. memcpy(buf->data, _data, _size);
  46. return buf;
  47. }
  48. struct buffer *
  49. buffer_empty_new(size_t _size)
  50. {
  51. struct buffer *buf = malloc(sizeof(struct buffer) + _size);
  52. if (buf == NULL)
  53. err(1, NULL);
  54. buf->size = _size;
  55. return buf;
  56. }
  57. struct buffer_list *
  58. buffer_list_new(void)
  59. {
  60. struct buffer_list *bl = malloc(sizeof(struct buffer_list));
  61. if (bl == NULL)
  62. err(1, NULL);
  63. TAILQ_INIT(&bl->buffers);
  64. bl->size = 0;
  65. return bl;
  66. }
  67. void
  68. buffer_list_free(struct buffer_list *_bl)
  69. {
  70. if (_bl) {
  71. struct buffer *b;
  72. while ((b = buffer_list_rem_head(_bl)))
  73. free(b);
  74. }
  75. }
  76. ssize_t
  77. buffer_write(struct buffer *_buf, int _fd)
  78. {
  79. size_t off;
  80. ssize_t nw;
  81. for (off = 0; off < _buf->size; off += nw) {
  82. if ((nw = write(_fd, _buf->data + off, _buf->size - off)) == 0
  83. || nw == -1) {
  84. warn("write");
  85. return -1;
  86. }
  87. }
  88. return _buf->size;
  89. }
  90. char *
  91. buffer_list_concat_string(struct buffer_list *_bl)
  92. {
  93. struct buffer *buf;
  94. char *out_string = malloc(_bl->size + 1);
  95. if (out_string == NULL)
  96. err(1, NULL);
  97. char *next_out = out_string;
  98. TAILQ_FOREACH(buf, &_bl->buffers, entries) {
  99. memcpy(next_out, buf->data, buf->size);
  100. next_out += buf->size;
  101. }
  102. *next_out = '\0';
  103. return out_string;
  104. }
  105. char *
  106. buffer_list_concat(struct buffer_list *_bl)
  107. {
  108. struct buffer *buf;
  109. char *out = malloc(_bl->size);
  110. if (out == NULL)
  111. err(1, NULL);
  112. char *next_out = out;
  113. TAILQ_FOREACH(buf, &_bl->buffers, entries) {
  114. memcpy(next_out, buf->data, buf->size);
  115. next_out += buf->size;
  116. }
  117. return out;
  118. }
  119. void
  120. buffer_list_add_string(struct buffer_list *_bl, const char *_s)
  121. {
  122. struct buffer *buf = buffer_new(_s);
  123. TAILQ_INSERT_TAIL(&_bl->buffers, buf, entries);
  124. _bl->size += buf->size;
  125. }
  126. void
  127. buffer_list_add_stringn(struct buffer_list *_bl, const char *_s, size_t _len)
  128. {
  129. struct buffer *buf = buffer_empty_new(_len);
  130. memcpy(buf->data, _s, _len);
  131. TAILQ_INSERT_TAIL(&_bl->buffers, buf, entries);
  132. _bl->size += _len;
  133. }
  134. void
  135. buffer_list_add(struct buffer_list *_bl, const void *_data, size_t _size)
  136. {
  137. struct buffer *buf = buffer_bin_new(_data, _size);
  138. TAILQ_INSERT_TAIL(&_bl->buffers, buf, entries);
  139. _bl->size += buf->size;
  140. }
  141. void
  142. buffer_list_add_buffer(struct buffer_list *_bl, struct buffer *_buf)
  143. {
  144. TAILQ_INSERT_TAIL(&_bl->buffers, _buf, entries);
  145. _bl->size += _buf->size;
  146. }
  147. void
  148. buffer_list_add_list(struct buffer_list *_bl, struct buffer_list *_add)
  149. {
  150. struct buffer *b;
  151. while (_add && (b = buffer_list_rem_head(_add)))
  152. buffer_list_add_buffer(_bl, b);
  153. }
  154. struct buffer *
  155. buffer_list_rem_head(struct buffer_list *_bl)
  156. {
  157. if (! TAILQ_EMPTY(&_bl->buffers)) {
  158. struct buffer *b = TAILQ_FIRST(&_bl->buffers);
  159. _bl->size -= b->size;
  160. TAILQ_REMOVE(&_bl->buffers, b, entries);
  161. return b;
  162. }
  163. return NULL;
  164. }
  165. struct buffer *
  166. buffer_list_rem_tail(struct buffer_list *_bl)
  167. {
  168. if (! TAILQ_EMPTY(&_bl->buffers)) {
  169. struct buffer *b = TAILQ_LAST(&_bl->buffers, buffer_list_head);
  170. _bl->size -= b->size;
  171. TAILQ_REMOVE(&_bl->buffers, b, entries);
  172. return b;
  173. }
  174. return NULL;
  175. }
  176. struct buffer *
  177. buffer_list_rem(struct buffer_list *_bl, struct buffer *_buf)
  178. {
  179. struct buffer *b;
  180. TAILQ_FOREACH(b, &_bl->buffers, entries) {
  181. if (b == _buf) {
  182. _bl->size -= _buf->size;
  183. TAILQ_REMOVE(&_bl->buffers, b, entries);
  184. return b;
  185. }
  186. }
  187. return _buf;
  188. }
  189. struct buffer_list *
  190. buffer_list_gzip(struct buffer_list *_in, const char *_name, uint32_t _mtime)
  191. {
  192. z_stream strm = { 0 };
  193. strm.zalloc = Z_NULL;
  194. strm.zfree = Z_NULL;
  195. strm.opaque = Z_NULL;
  196. u_int32_t crc = crc32(0L, Z_NULL, 0);
  197. int rc;
  198. if ((rc = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED,
  199. -MAX_WBITS, 9,
  200. Z_DEFAULT_STRATEGY)) != Z_OK)
  201. errx(1, "deflateInit2: %s", zError(rc));
  202. struct buffer *input, *output;
  203. struct buffer_list *out = buffer_list_new();
  204. unsigned char gzip_header[10];
  205. gzip_header[0] = 0x1f;
  206. gzip_header[1] = 0x8b;
  207. gzip_header[2] = Z_DEFLATED;
  208. gzip_header[3] = (_name) ? ORIG_NAME : 0;
  209. gzip_header[4] = _mtime & 0xff;
  210. gzip_header[5] = _mtime >> 8;
  211. gzip_header[6] = _mtime >> 16;
  212. gzip_header[7] = _mtime >> 24;
  213. gzip_header[8] = 2;
  214. gzip_header[9] = OS_CODE;
  215. buffer_list_add(out, gzip_header, sizeof(gzip_header));
  216. if (_name)
  217. buffer_list_add(out, _name, strlen(_name) + 1);
  218. output = buffer_empty_new(DEFLATE_BUF_SIZE);
  219. strm.total_in = _in->size;
  220. strm.next_out = output->data;
  221. strm.avail_out = DEFLATE_BUF_SIZE;
  222. TAILQ_FOREACH(input, &_in->buffers, entries) {
  223. strm.avail_in = input->size;
  224. strm.next_in = input->data;
  225. while (strm.avail_in) {
  226. if ((rc = deflate(&strm, Z_NO_FLUSH)) != Z_OK)
  227. errx(1, "deflate: %s", zError(rc));
  228. if (strm.avail_out == 0) {
  229. buffer_list_add_buffer(out, output);
  230. output = buffer_empty_new(DEFLATE_BUF_SIZE);
  231. strm.next_out = output->data;
  232. strm.avail_out = DEFLATE_BUF_SIZE;
  233. }
  234. }
  235. crc = crc32(crc, input->data, input->size);
  236. }
  237. if ((rc = deflate(&strm, Z_FINISH)) != Z_STREAM_END)
  238. errx(1, "deflate: %s", zError(rc));
  239. if ((rc = deflateEnd(&strm)) != Z_OK)
  240. errx(1, "deflateEnd: %s", zError(rc));
  241. size_t last_buf_size = DEFLATE_BUF_SIZE - strm.avail_out;
  242. if (last_buf_size != 0) {
  243. buffer_list_add(out, output->data, last_buf_size);
  244. u_int32_t y = htole32(crc);
  245. buffer_list_add(out, &y, sizeof(u_int32_t));
  246. u_int32_t s = htole32(_in->size & 0xffffffff);
  247. buffer_list_add(out, &s, sizeof(u_int32_t));
  248. }
  249. free(output);
  250. return out;
  251. }