buffer.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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. strlcpy(buf->data, _data, data_len + 1);
  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. out_string[0] = '\0';
  98. TAILQ_FOREACH(buf, &_bl->buffers, entries) {
  99. strlcat(out_string, buf->data, _bl->size + 1);
  100. }
  101. return out_string;
  102. }
  103. char *
  104. buffer_list_concat(struct buffer_list *_bl)
  105. {
  106. struct buffer *buf;
  107. char *out = malloc(_bl->size);
  108. if (out == NULL)
  109. err(1, NULL);
  110. char *next_out = out;
  111. TAILQ_FOREACH(buf, &_bl->buffers, entries) {
  112. memcpy(next_out, buf->data, _bl->size);
  113. next_out += buf->size;
  114. }
  115. return out;
  116. }
  117. void
  118. buffer_list_add_string(struct buffer_list *_bl, const char *_s)
  119. {
  120. struct buffer *buf = buffer_new(_s);
  121. TAILQ_INSERT_TAIL(&_bl->buffers, buf, entries);
  122. _bl->size += buf->size;
  123. }
  124. void
  125. buffer_list_add_stringn(struct buffer_list *_bl, const char *_s, size_t _len)
  126. {
  127. struct buffer *buf = buffer_empty_new(_len + 1);
  128. strlcpy(buf->data, _s, _len);
  129. TAILQ_INSERT_TAIL(&_bl->buffers, buf, entries);
  130. _bl->size += buf->size;
  131. }
  132. void
  133. buffer_list_add(struct buffer_list *_bl, const void *_data, size_t _size)
  134. {
  135. struct buffer *buf = buffer_bin_new(_data, _size);
  136. TAILQ_INSERT_TAIL(&_bl->buffers, buf, entries);
  137. _bl->size += buf->size;
  138. }
  139. void
  140. buffer_list_add_buffer(struct buffer_list *_bl, struct buffer *_buf)
  141. {
  142. TAILQ_INSERT_TAIL(&_bl->buffers, _buf, entries);
  143. _bl->size += _buf->size;
  144. }
  145. void
  146. buffer_list_add_list(struct buffer_list *_bl, struct buffer_list *_add)
  147. {
  148. struct buffer *b;
  149. while (_add && (b = buffer_list_rem_head(_add)))
  150. buffer_list_add_buffer(_bl, b);
  151. }
  152. struct buffer *
  153. buffer_list_rem_head(struct buffer_list *_bl)
  154. {
  155. if (! TAILQ_EMPTY(&_bl->buffers)) {
  156. struct buffer *b = TAILQ_FIRST(&_bl->buffers);
  157. _bl->size -= b->size;
  158. TAILQ_REMOVE(&_bl->buffers, b, entries);
  159. return b;
  160. }
  161. return NULL;
  162. }
  163. struct buffer *
  164. buffer_list_rem_tail(struct buffer_list *_bl)
  165. {
  166. if (! TAILQ_EMPTY(&_bl->buffers)) {
  167. struct buffer *b = TAILQ_LAST(&_bl->buffers, buffer_list_head);
  168. _bl->size -= b->size;
  169. TAILQ_REMOVE(&_bl->buffers, b, entries);
  170. return b;
  171. }
  172. return NULL;
  173. }
  174. struct buffer *
  175. buffer_list_rem(struct buffer_list *_bl, struct buffer *_buf)
  176. {
  177. struct buffer *b;
  178. TAILQ_FOREACH(b, &_bl->buffers, entries) {
  179. if (b == _buf) {
  180. _bl->size -= _buf->size;
  181. TAILQ_REMOVE(&_bl->buffers, b, entries);
  182. return b;
  183. }
  184. }
  185. return _buf;
  186. }
  187. struct buffer_list *
  188. buffer_list_gzip(struct buffer_list *_in, const char *_name, uint32_t _mtime)
  189. {
  190. z_stream strm = { 0 };
  191. strm.zalloc = Z_NULL;
  192. strm.zfree = Z_NULL;
  193. strm.opaque = Z_NULL;
  194. u_int32_t crc = crc32(0L, Z_NULL, 0);
  195. int rc;
  196. if ((rc = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED,
  197. -MAX_WBITS, 9,
  198. Z_DEFAULT_STRATEGY)) != Z_OK)
  199. errx(1, "deflateInit2: %s", zError(rc));
  200. struct buffer *input, *output;
  201. struct buffer_list *out = buffer_list_new();
  202. unsigned char gzip_header[10];
  203. gzip_header[0] = 0x1f;
  204. gzip_header[1] = 0x8b;
  205. gzip_header[2] = Z_DEFLATED;
  206. gzip_header[3] = (_name) ? ORIG_NAME : 0;
  207. gzip_header[4] = _mtime & 0xff;
  208. gzip_header[5] = _mtime >> 8;
  209. gzip_header[6] = _mtime >> 16;
  210. gzip_header[7] = _mtime >> 24;
  211. gzip_header[8] = 2;
  212. gzip_header[9] = OS_CODE;
  213. buffer_list_add(out, gzip_header, sizeof(gzip_header));
  214. if (_name)
  215. buffer_list_add(out, _name, strlen(_name) + 1);
  216. output = buffer_empty_new(DEFLATE_BUF_SIZE);
  217. strm.total_in = _in->size;
  218. strm.next_out = output->data;
  219. strm.avail_out = DEFLATE_BUF_SIZE;
  220. TAILQ_FOREACH(input, &_in->buffers, entries) {
  221. strm.avail_in = input->size;
  222. strm.next_in = input->data;
  223. while (strm.avail_in) {
  224. if ((rc = deflate(&strm, Z_NO_FLUSH)) != Z_OK)
  225. errx(1, "deflate: %s", zError(rc));
  226. if (strm.avail_out == 0) {
  227. buffer_list_add_buffer(out, output);
  228. output = buffer_empty_new(DEFLATE_BUF_SIZE);
  229. strm.next_out = output->data;
  230. strm.avail_out = DEFLATE_BUF_SIZE;
  231. }
  232. }
  233. crc = crc32(crc, input->data, input->size);
  234. }
  235. if ((rc = deflate(&strm, Z_FINISH)) != Z_STREAM_END)
  236. errx(1, "deflate: %s", zError(rc));
  237. if ((rc = deflateEnd(&strm)) != Z_OK)
  238. errx(1, "deflateEnd: %s", zError(rc));
  239. size_t last_buf_size = DEFLATE_BUF_SIZE - strm.avail_out;
  240. if (last_buf_size != 0) {
  241. buffer_list_add(out, output->data, last_buf_size);
  242. u_int32_t y = htole32(crc);
  243. buffer_list_add(out, &y, sizeof(u_int32_t));
  244. u_int32_t s = htole32(_in->size & 0xffffffff);
  245. buffer_list_add(out, &s, sizeof(u_int32_t));
  246. }
  247. free(output);
  248. return out;
  249. }