archive_write_set_compression_xz.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. /*-
  2. * Copyright (c) 2009 Michihiro NAKAJIMA
  3. * Copyright (c) 2003-2007 Tim Kientzle
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "archive_platform.h"
  27. __FBSDID("$FreeBSD$");
  28. #ifdef HAVE_ERRNO_H
  29. #include <errno.h>
  30. #endif
  31. #ifdef HAVE_STDLIB_H
  32. #include <stdlib.h>
  33. #endif
  34. #ifdef HAVE_STRING_H
  35. #include <string.h>
  36. #endif
  37. #include <time.h>
  38. #ifdef HAVE_LZMA_H
  39. #include <lzma.h>
  40. #endif
  41. #include "archive.h"
  42. #include "archive_private.h"
  43. #include "archive_write_private.h"
  44. #ifndef HAVE_LZMA_H
  45. int
  46. archive_write_set_compression_xz(struct archive *a)
  47. {
  48. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  49. "xz compression not supported on this platform");
  50. return (ARCHIVE_FATAL);
  51. }
  52. int
  53. archive_write_set_compression_lzma(struct archive *a)
  54. {
  55. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  56. "lzma compression not supported on this platform");
  57. return (ARCHIVE_FATAL);
  58. }
  59. #else
  60. /* Don't compile this if we don't have liblzma. */
  61. struct private_data {
  62. lzma_stream stream;
  63. lzma_filter lzmafilters[2];
  64. lzma_options_lzma lzma_opt;
  65. int64_t total_in;
  66. unsigned char *compressed;
  67. size_t compressed_buffer_size;
  68. };
  69. struct private_config {
  70. int compression_level;
  71. };
  72. static int archive_compressor_xz_init(struct archive_write *);
  73. static int archive_compressor_xz_options(struct archive_write *,
  74. const char *, const char *);
  75. static int archive_compressor_xz_finish(struct archive_write *);
  76. static int archive_compressor_xz_write(struct archive_write *,
  77. const void *, size_t);
  78. static int drive_compressor(struct archive_write *, struct private_data *,
  79. int finishing);
  80. /*
  81. * Allocate, initialize and return a archive object.
  82. */
  83. int
  84. archive_write_set_compression_xz(struct archive *_a)
  85. {
  86. struct private_config *config;
  87. struct archive_write *a = (struct archive_write *)_a;
  88. __archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
  89. ARCHIVE_STATE_NEW, "archive_write_set_compression_xz");
  90. config = calloc(1, sizeof(*config));
  91. if (config == NULL) {
  92. archive_set_error(&a->archive, ENOMEM, "Out of memory");
  93. return (ARCHIVE_FATAL);
  94. }
  95. a->compressor.config = config;
  96. a->compressor.finish = archive_compressor_xz_finish;
  97. config->compression_level = LZMA_PRESET_DEFAULT;
  98. a->compressor.init = &archive_compressor_xz_init;
  99. a->compressor.options = &archive_compressor_xz_options;
  100. a->archive.compression_code = ARCHIVE_COMPRESSION_XZ;
  101. a->archive.compression_name = "xz";
  102. return (ARCHIVE_OK);
  103. }
  104. /* LZMA is handled identically, we just need a different compression
  105. * code set. (The liblzma setup looks at the code to determine
  106. * the one place that XZ and LZMA require different handling.) */
  107. int
  108. archive_write_set_compression_lzma(struct archive *_a)
  109. {
  110. struct archive_write *a = (struct archive_write *)_a;
  111. int r = archive_write_set_compression_xz(_a);
  112. if (r != ARCHIVE_OK)
  113. return (r);
  114. a->archive.compression_code = ARCHIVE_COMPRESSION_LZMA;
  115. a->archive.compression_name = "lzma";
  116. return (ARCHIVE_OK);
  117. }
  118. static int
  119. archive_compressor_xz_init_stream(struct archive_write *a,
  120. struct private_data *state)
  121. {
  122. int ret;
  123. state->stream = (lzma_stream)LZMA_STREAM_INIT;
  124. state->stream.next_out = state->compressed;
  125. state->stream.avail_out = state->compressed_buffer_size;
  126. if (a->archive.compression_code == ARCHIVE_COMPRESSION_XZ)
  127. ret = lzma_stream_encoder(&(state->stream),
  128. state->lzmafilters, LZMA_CHECK_CRC64);
  129. else
  130. ret = lzma_alone_encoder(&(state->stream), &state->lzma_opt);
  131. if (ret == LZMA_OK)
  132. return (ARCHIVE_OK);
  133. switch (ret) {
  134. case LZMA_MEM_ERROR:
  135. archive_set_error(&a->archive, ENOMEM,
  136. "Internal error initializing compression library: "
  137. "Cannot allocate memory");
  138. break;
  139. default:
  140. archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
  141. "Internal error initializing compression library: "
  142. "It's a bug in liblzma");
  143. break;
  144. }
  145. return (ARCHIVE_FATAL);
  146. }
  147. /*
  148. * Setup callback.
  149. */
  150. static int
  151. archive_compressor_xz_init(struct archive_write *a)
  152. {
  153. int ret;
  154. struct private_data *state;
  155. struct private_config *config;
  156. if (a->client_opener != NULL) {
  157. ret = (a->client_opener)(&a->archive, a->client_data);
  158. if (ret != ARCHIVE_OK)
  159. return (ret);
  160. }
  161. state = (struct private_data *)malloc(sizeof(*state));
  162. if (state == NULL) {
  163. archive_set_error(&a->archive, ENOMEM,
  164. "Can't allocate data for compression");
  165. return (ARCHIVE_FATAL);
  166. }
  167. memset(state, 0, sizeof(*state));
  168. config = a->compressor.config;
  169. /*
  170. * See comment above. We should set compressed_buffer_size to
  171. * max(bytes_per_block, 65536), but the code can't handle that yet.
  172. */
  173. state->compressed_buffer_size = a->bytes_per_block;
  174. state->compressed = (unsigned char *)malloc(state->compressed_buffer_size);
  175. if (state->compressed == NULL) {
  176. archive_set_error(&a->archive, ENOMEM,
  177. "Can't allocate data for compression buffer");
  178. free(state);
  179. return (ARCHIVE_FATAL);
  180. }
  181. a->compressor.write = archive_compressor_xz_write;
  182. /* Initialize compression library. */
  183. if (lzma_lzma_preset(&state->lzma_opt, config->compression_level)) {
  184. archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
  185. "Internal error initializing compression library");
  186. free(state->compressed);
  187. free(state);
  188. }
  189. state->lzmafilters[0].id = LZMA_FILTER_LZMA2;
  190. state->lzmafilters[0].options = &state->lzma_opt;
  191. state->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
  192. ret = archive_compressor_xz_init_stream(a, state);
  193. if (ret == LZMA_OK) {
  194. a->compressor.data = state;
  195. return (0);
  196. }
  197. /* Library setup failed: clean up. */
  198. free(state->compressed);
  199. free(state);
  200. return (ARCHIVE_FATAL);
  201. }
  202. /*
  203. * Set write options.
  204. */
  205. static int
  206. archive_compressor_xz_options(struct archive_write *a, const char *key,
  207. const char *value)
  208. {
  209. struct private_config *config;
  210. config = (struct private_config *)a->compressor.config;
  211. if (strcmp(key, "compression-level") == 0) {
  212. if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
  213. value[1] != '\0')
  214. return (ARCHIVE_WARN);
  215. config->compression_level = value[0] - '0';
  216. if (config->compression_level > 6)
  217. config->compression_level = 6;
  218. return (ARCHIVE_OK);
  219. }
  220. return (ARCHIVE_WARN);
  221. }
  222. /*
  223. * Write data to the compressed stream.
  224. */
  225. static int
  226. archive_compressor_xz_write(struct archive_write *a, const void *buff,
  227. size_t length)
  228. {
  229. struct private_data *state;
  230. int ret;
  231. state = (struct private_data *)a->compressor.data;
  232. if (a->client_writer == NULL) {
  233. archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
  234. "No write callback is registered? "
  235. "This is probably an internal programming error.");
  236. return (ARCHIVE_FATAL);
  237. }
  238. /* Update statistics */
  239. state->total_in += length;
  240. /* Compress input data to output buffer */
  241. state->stream.next_in = buff;
  242. state->stream.avail_in = length;
  243. if ((ret = drive_compressor(a, state, 0)) != ARCHIVE_OK)
  244. return (ret);
  245. a->archive.file_position += length;
  246. return (ARCHIVE_OK);
  247. }
  248. /*
  249. * Finish the compression...
  250. */
  251. static int
  252. archive_compressor_xz_finish(struct archive_write *a)
  253. {
  254. ssize_t block_length, target_block_length, bytes_written;
  255. int ret;
  256. struct private_data *state;
  257. unsigned tocopy;
  258. ret = ARCHIVE_OK;
  259. state = (struct private_data *)a->compressor.data;
  260. if (state != NULL) {
  261. if (a->client_writer == NULL) {
  262. archive_set_error(&a->archive,
  263. ARCHIVE_ERRNO_PROGRAMMER,
  264. "No write callback is registered? "
  265. "This is probably an internal programming error.");
  266. ret = ARCHIVE_FATAL;
  267. goto cleanup;
  268. }
  269. /* By default, always pad the uncompressed data. */
  270. if (a->pad_uncompressed) {
  271. tocopy = a->bytes_per_block -
  272. (state->total_in % a->bytes_per_block);
  273. while (tocopy > 0 && tocopy < (unsigned)a->bytes_per_block) {
  274. state->stream.next_in = a->nulls;
  275. state->stream.avail_in = tocopy < a->null_length ?
  276. tocopy : a->null_length;
  277. state->total_in += state->stream.avail_in;
  278. tocopy -= state->stream.avail_in;
  279. ret = drive_compressor(a, state, 0);
  280. if (ret != ARCHIVE_OK)
  281. goto cleanup;
  282. }
  283. }
  284. /* Finish compression cycle */
  285. if (((ret = drive_compressor(a, state, 1))) != ARCHIVE_OK)
  286. goto cleanup;
  287. /* Optionally, pad the final compressed block. */
  288. block_length = state->stream.next_out - state->compressed;
  289. /* Tricky calculation to determine size of last block. */
  290. target_block_length = block_length;
  291. if (a->bytes_in_last_block <= 0)
  292. /* Default or Zero: pad to full block */
  293. target_block_length = a->bytes_per_block;
  294. else
  295. /* Round length to next multiple of bytes_in_last_block. */
  296. target_block_length = a->bytes_in_last_block *
  297. ( (block_length + a->bytes_in_last_block - 1) /
  298. a->bytes_in_last_block);
  299. if (target_block_length > a->bytes_per_block)
  300. target_block_length = a->bytes_per_block;
  301. if (block_length < target_block_length) {
  302. memset(state->stream.next_out, 0,
  303. target_block_length - block_length);
  304. block_length = target_block_length;
  305. }
  306. /* Write the last block */
  307. bytes_written = (a->client_writer)(&a->archive, a->client_data,
  308. state->compressed, block_length);
  309. if (bytes_written <= 0) {
  310. ret = ARCHIVE_FATAL;
  311. goto cleanup;
  312. }
  313. a->archive.raw_position += bytes_written;
  314. /* Cleanup: shut down compressor, release memory, etc. */
  315. cleanup:
  316. lzma_end(&(state->stream));
  317. free(state->compressed);
  318. free(state);
  319. }
  320. free(a->compressor.config);
  321. a->compressor.config = NULL;
  322. return (ret);
  323. }
  324. /*
  325. * Utility function to push input data through compressor,
  326. * writing full output blocks as necessary.
  327. *
  328. * Note that this handles both the regular write case (finishing ==
  329. * false) and the end-of-archive case (finishing == true).
  330. */
  331. static int
  332. drive_compressor(struct archive_write *a, struct private_data *state, int finishing)
  333. {
  334. ssize_t bytes_written;
  335. int ret;
  336. for (;;) {
  337. if (state->stream.avail_out == 0) {
  338. bytes_written = (a->client_writer)(&a->archive,
  339. a->client_data, state->compressed,
  340. state->compressed_buffer_size);
  341. if (bytes_written <= 0) {
  342. /* TODO: Handle this write failure */
  343. return (ARCHIVE_FATAL);
  344. } else if ((size_t)bytes_written < state->compressed_buffer_size) {
  345. /* Short write: Move remaining to
  346. * front of block and keep filling */
  347. memmove(state->compressed,
  348. state->compressed + bytes_written,
  349. state->compressed_buffer_size - bytes_written);
  350. }
  351. a->archive.raw_position += bytes_written;
  352. state->stream.next_out
  353. = state->compressed +
  354. state->compressed_buffer_size - bytes_written;
  355. state->stream.avail_out = bytes_written;
  356. }
  357. /* If there's nothing to do, we're done. */
  358. if (!finishing && state->stream.avail_in == 0)
  359. return (ARCHIVE_OK);
  360. ret = lzma_code(&(state->stream),
  361. finishing ? LZMA_FINISH : LZMA_RUN );
  362. switch (ret) {
  363. case LZMA_OK:
  364. /* In non-finishing case, check if compressor
  365. * consumed everything */
  366. if (!finishing && state->stream.avail_in == 0)
  367. return (ARCHIVE_OK);
  368. /* In finishing case, this return always means
  369. * there's more work */
  370. break;
  371. case LZMA_STREAM_END:
  372. /* This return can only occur in finishing case. */
  373. if (finishing)
  374. return (ARCHIVE_OK);
  375. archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
  376. "lzma compression data error");
  377. return (ARCHIVE_FATAL);
  378. case LZMA_MEMLIMIT_ERROR:
  379. archive_set_error(&a->archive, ENOMEM,
  380. "lzma compression error: "
  381. "%ju MiB would have been needed",
  382. (lzma_memusage(&(state->stream)) + 1024 * 1024 -1)
  383. / (1024 * 1024));
  384. return (ARCHIVE_FATAL);
  385. default:
  386. /* Any other return value indicates an error. */
  387. archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
  388. "lzma compression failed:"
  389. " lzma_code() call returned status %d",
  390. ret);
  391. return (ARCHIVE_FATAL);
  392. }
  393. }
  394. }
  395. #endif /* HAVE_LZMA_H */