unzip_stream.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /* seekable zip */
  2. #include "unzip.h"
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include "zlib/zlib.h"
  7. #define errormsg(str1,def,fname) printf("%s: " #def ": " str1 "\n", fname);
  8. /* from gzio.c . Be careful with binary compatibility */
  9. typedef struct gz_stream {
  10. z_stream stream;
  11. int z_err; /* error code for last stream operation */
  12. int z_eof; /* set if end of input file */
  13. FILE *file; /* .gz file */
  14. Byte *inbuf; /* input buffer */
  15. Byte *outbuf; /* output buffer */
  16. uLong crc; /* crc32 of uncompressed data */
  17. char *msg; /* error message */
  18. char *path; /* path name for debugging only */
  19. int transparent; /* 1 if input file is not a .gz file */
  20. char mode; /* 'w' or 'r' */
  21. z_off_t start; /* start of compressed data in file (header skipped) */
  22. z_off_t in; /* bytes into deflate or inflate */
  23. z_off_t out; /* bytes out of deflate or inflate */
  24. int back; /* one character push-back */
  25. int last; /* true if push-back is last character */
  26. } gz_stream;
  27. #ifndef Z_BUFSIZE
  28. # ifdef MAXSEG_64K
  29. # define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
  30. # else
  31. # define Z_BUFSIZE 16384
  32. # endif
  33. #endif
  34. #ifndef Z_PRINTF_BUFSIZE
  35. # define Z_PRINTF_BUFSIZE 4096
  36. #endif
  37. #define ALLOC(size) malloc(size)
  38. int destroy OF((gz_stream *s));
  39. gzFile zip2gz(ZIP* zip, struct zipent* ent)
  40. {
  41. int err;
  42. gz_stream *s;
  43. const char *path;
  44. int transparent = 0;
  45. uInt len;
  46. if (!zip || !ent)
  47. return NULL;
  48. /* zip stuff */
  49. if (ent->compression_method == 0x0000)
  50. {
  51. /* file is not compressed, simply stored */
  52. /* check if size are equal */
  53. if (ent->compressed_size != ent->uncompressed_size) {
  54. errormsg("Wrong uncompressed size in store compression", ERROR_CORRUPT,zip->zip);
  55. return NULL;
  56. }
  57. transparent = 1;
  58. }
  59. else if (ent->compression_method == 0x0008)
  60. {
  61. /* file is compressed using "Deflate" method */
  62. if (ent->version_needed_to_extract > 0x14) {
  63. errormsg("Version too new", ERROR_UNSUPPORTED,zip->zip);
  64. return NULL;
  65. }
  66. if (ent->os_needed_to_extract != 0x00) {
  67. errormsg("OS not supported", ERROR_UNSUPPORTED,zip->zip);
  68. return NULL;
  69. }
  70. if (ent->disk_number_start != zip->number_of_this_disk) {
  71. errormsg("Cannot span disks", ERROR_UNSUPPORTED,zip->zip);
  72. return NULL;
  73. }
  74. } else {
  75. errormsg("Compression method unsupported", ERROR_UNSUPPORTED, zip->zip);
  76. return NULL;
  77. }
  78. /* seek to compressed data */
  79. if (seekcompresszip(zip,ent) != 0) {
  80. return NULL;
  81. }
  82. path = zip->zip;
  83. /* normal gzip init for read */
  84. s = (gz_stream *)ALLOC(sizeof(gz_stream));
  85. if (!s) return Z_NULL;
  86. s->stream.zalloc = (alloc_func)0;
  87. s->stream.zfree = (free_func)0;
  88. s->stream.opaque = (voidpf)0;
  89. s->stream.next_in = s->inbuf = Z_NULL;
  90. s->stream.next_out = s->outbuf = Z_NULL;
  91. s->stream.avail_in = s->stream.avail_out = 0;
  92. s->file = NULL;
  93. s->z_err = Z_OK;
  94. s->z_eof = 0;
  95. s->in = 0;
  96. s->out = 0;
  97. s->back = EOF;
  98. s->crc = crc32(0L, Z_NULL, 0);
  99. s->msg = NULL;
  100. s->transparent = transparent;
  101. s->mode = 'r';
  102. s->path = (char*)ALLOC(strlen(path)+1);
  103. if (s->path == NULL) {
  104. return destroy(s), (gzFile)Z_NULL;
  105. }
  106. strcpy(s->path, path); /* do this early for debugging */
  107. s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
  108. err = inflateInit2(&(s->stream), -MAX_WBITS);
  109. /* windowBits is passed < 0 to tell that there is no zlib header.
  110. * Note that in this case inflate *requires* an extra "dummy" byte
  111. * after the compressed stream in order to complete decompression and
  112. * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
  113. * present after the compressed stream.
  114. */
  115. if (err != Z_OK || s->inbuf == Z_NULL) {
  116. return destroy(s), (gzFile)Z_NULL;
  117. }
  118. s->stream.avail_out = Z_BUFSIZE;
  119. errno = 0;
  120. s->file = zip->fp;
  121. if (s->file == NULL) {
  122. return destroy(s), (gzFile)Z_NULL;
  123. }
  124. /* check_header(s); */
  125. errno = 0;
  126. len = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
  127. if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
  128. s->stream.avail_in += len;
  129. s->stream.next_in = s->inbuf;
  130. if (s->stream.avail_in < 2) {
  131. return destroy(s), (gzFile)Z_NULL;
  132. }
  133. s->start = ftell(s->file) - s->stream.avail_in;
  134. return (gzFile)s;
  135. }
  136. int gzerror2(gzFile file)
  137. {
  138. gz_stream *s = (gz_stream*)file;
  139. if (s == NULL)
  140. return Z_STREAM_ERROR;
  141. return s->z_err;
  142. }