minilzop.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /* $MirOS: contrib/hosted/fwcf/minilzop.c,v 1.2 2007/03/09 22:25:45 tg Exp $ */
  2. /*-
  3. * Copyright (c) 2007
  4. * Thorsten Glaser <tg@mirbsd.de>
  5. *
  6. * Provided that these terms and disclaimer and all copyright notices
  7. * are retained or reproduced in an accompanying document, permission
  8. * is granted to deal in this work without restriction, including un-
  9. * limited rights to use, publicly perform, distribute, sell, modify,
  10. * merge, give away, or sublicence.
  11. *
  12. * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
  13. * the utmost extent permitted by applicable law, neither express nor
  14. * implied; without malicious intent or gross negligence. In no event
  15. * may a licensor, author or contributor be held liable for indirect,
  16. * direct, other damage, loss, or other issues arising in any way out
  17. * of dealing in the work, even if advised of the possibility of such
  18. * damage or existence of a defect, except proven that it results out
  19. * of said person's immediate fault when using the work as intended.
  20. */
  21. #include <sys/param.h>
  22. #include <err.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include "defs.h"
  28. #include "adler.h"
  29. #include "compress.h"
  30. #include "minilzop.h"
  31. #define lodsw(s) __extension__({ \
  32. const u_int8_t *lodsw_buf = (const u_int8_t *)(s);\
  33. u_int16_t lodsw_val; \
  34. \
  35. lodsw_val = lodsw_buf[0]; \
  36. lodsw_val |= lodsw_buf[1] << 8; \
  37. (lodsw_val); \
  38. })
  39. #define lodsd(s) __extension__({ \
  40. const u_int8_t *lodsd_buf = (const u_int8_t *)(s);\
  41. u_int32_t lodsd_val; \
  42. \
  43. lodsd_val = lodsd_buf[0]; \
  44. lodsd_val |= lodsd_buf[1] << 8; \
  45. lodsd_val |= lodsd_buf[2] << 16; \
  46. lodsd_val |= lodsd_buf[3] << 24; \
  47. (lodsd_val); \
  48. })
  49. #define stosw(s,w) do { \
  50. u_int8_t *stosw_buf = (u_int8_t *)(s); \
  51. u_int16_t stosw_val = (w); \
  52. \
  53. stosw_buf[0] = stosw_val & 0xFF; \
  54. stosw_buf[1] = (stosw_val >> 8) & 0xFF; \
  55. } while (0)
  56. #define stosd(s,dw) do { \
  57. u_int8_t *stosd_buf = (u_int8_t *)(s); \
  58. u_int32_t stosd_val = (dw); \
  59. \
  60. stosd_buf[0] = stosd_val & 0xFF; \
  61. stosd_buf[1] = (stosd_val >> 8) & 0xFF; \
  62. stosd_buf[2] = (stosd_val >> 16) & 0xFF; \
  63. stosd_buf[3] = (stosd_val >> 24) & 0xFF; \
  64. } while (0)
  65. void
  66. read_aszdata(int dfd, char **dbuf, size_t *dlen)
  67. {
  68. size_t len;
  69. u_int8_t hdrbuf[8];
  70. ADLER_DECL;
  71. if (read(dfd, hdrbuf, 8) != 8)
  72. err(1, "short read");
  73. *dlen = lodsd(hdrbuf + 4);
  74. if ((*dbuf = malloc(*dlen)) == NULL)
  75. err(255, "out of memory trying to allocate %zu bytes", *dlen);
  76. if ((size_t)read(dfd, *dbuf, *dlen) != *dlen)
  77. err(1, "short read");
  78. len = 4;
  79. ADLER_CALC(hdrbuf + 4);
  80. len = *dlen;
  81. ADLER_CALC(*dbuf);
  82. if ((lodsw(hdrbuf) != s1) || (lodsw(hdrbuf + 2) != s2))
  83. err(2, "checksum mismatch, size %zu,"
  84. " want 0x%02X%02X%02X%02X got 0x%04X%04X", *dlen,
  85. hdrbuf[3], hdrbuf[2], hdrbuf[1], hdrbuf[0], s2, s1);
  86. }
  87. void
  88. write_aszdata(int dfd, const char *dbuf, size_t dlen)
  89. {
  90. size_t len;
  91. u_int8_t hdrbuf[8];
  92. ADLER_DECL;
  93. stosd(hdrbuf + 4, dlen);
  94. len = 4;
  95. ADLER_CALC(hdrbuf + 4);
  96. len = dlen;
  97. ADLER_CALC(dbuf);
  98. stosw(hdrbuf, s1);
  99. stosw(hdrbuf + 2, s2);
  100. if (write(dfd, hdrbuf, 8) != 8)
  101. err(1, "short write");
  102. if ((size_t)write(dfd, dbuf, dlen) != dlen)
  103. err(1, "short write");
  104. }
  105. int
  106. minilzop(int ifd, int ofd, int compr_alg, int decompress)
  107. {
  108. size_t ilen, olen, n;
  109. char *idata, *odata;
  110. #ifndef SMALL
  111. fprintf(stderr, "minilzop: using algorithm %02X (%s)\n",
  112. compr_alg, compressor_get(compr_alg)->name);
  113. #endif
  114. if (decompress) {
  115. read_aszdata(ifd, &idata, &ilen);
  116. olen = lodsd(idata);
  117. if ((odata = malloc(olen)) == NULL)
  118. err(255, "out of memory trying to allocate %zu bytes",
  119. olen);
  120. if ((n = compressor_get(compr_alg)->decompress(odata, olen,
  121. idata + 4, ilen - 4)) != olen)
  122. errx(1, "size mismatch: decompressed %zu, want %zu",
  123. n, olen);
  124. free(idata);
  125. idata = odata; /* save for later free(3) */
  126. while (olen) {
  127. if ((n = write(ofd, odata, olen)) == (size_t)-1)
  128. err(1, "cannot write");
  129. olen -= n;
  130. odata += n;
  131. }
  132. free(idata);
  133. } else {
  134. size_t cc;
  135. n = 16384;
  136. idata = NULL;
  137. ilen = 0;
  138. slurp_file:
  139. if ((idata = realloc(idata, (n <<= 1))) == NULL)
  140. err(255, "out of memory trying to allocate %zu bytes",
  141. n);
  142. slurp_retry:
  143. if ((cc = read(ifd, idata + ilen, n - ilen)) == (size_t)-1)
  144. err(1, "cannot read");
  145. ilen += cc;
  146. if (cc > 0) {
  147. if (ilen < n)
  148. goto slurp_retry;
  149. goto slurp_file;
  150. }
  151. if ((olen = compressor_get(compr_alg)->compress(&odata, idata,
  152. ilen)) == (size_t)-1)
  153. errx(1, "%s compression failed",
  154. compressor_get(compr_alg)->name);
  155. free(idata);
  156. if ((idata = malloc(olen + 4)) == NULL)
  157. err(255, "out of memory trying to allocate %zu bytes",
  158. olen + 4);
  159. stosd(idata, ilen);
  160. memcpy(idata + 4, odata, olen);
  161. write_aszdata(ofd, idata, olen + 4);
  162. free(idata);
  163. }
  164. return (0);
  165. }