ioapi.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /* ioapi.c -- IO base function header for compress/uncompress .zip
  2. part of the MiniZip project
  3. Copyright (C) 1998-2010 Gilles Vollant
  4. http://www.winimage.com/zLibDll/minizip.html
  5. Modifications for Zip64 support
  6. Copyright (C) 2009-2010 Mathias Svensson
  7. http://result42.com
  8. This program is distributed under the terms of the same license as zlib.
  9. See the accompanying LICENSE file for the full text of the license.
  10. */
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #if defined unix || defined __APPLE__
  14. #include <sys/types.h>
  15. #include <unistd.h>
  16. #endif
  17. #include "ioapi.h"
  18. #ifdef _WIN32
  19. # define snprintf _snprintf
  20. #ifdef _MSC_VER
  21. # pragma warning(push)
  22. # pragma warning(disable : 4131 4100)
  23. #endif
  24. # ifdef __clang__
  25. # pragma clang diagnostic push
  26. # pragma clang diagnostic ignored "-Wunused-parameter"
  27. # endif
  28. #endif // _WIN32
  29. voidpf call_zopen64(const zlib_filefunc64_32_def *pfilefunc, const void *filename, int mode)
  30. {
  31. if (pfilefunc->zfile_func64.zopen64_file != NULL)
  32. return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque, filename, mode);
  33. return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque, (const char*)filename, mode);
  34. }
  35. voidpf call_zopendisk64(const zlib_filefunc64_32_def *pfilefunc, voidpf filestream, uint32_t number_disk, int mode)
  36. {
  37. if (pfilefunc->zfile_func64.zopendisk64_file != NULL)
  38. return (*(pfilefunc->zfile_func64.zopendisk64_file)) (pfilefunc->zfile_func64.opaque, filestream, number_disk, mode);
  39. return (*(pfilefunc->zopendisk32_file))(pfilefunc->zfile_func64.opaque, filestream, number_disk, mode);
  40. }
  41. long call_zseek64(const zlib_filefunc64_32_def *pfilefunc, voidpf filestream, uint64_t offset, int origin)
  42. {
  43. uint32_t offset_truncated = 0;
  44. if (pfilefunc->zfile_func64.zseek64_file != NULL)
  45. return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
  46. offset_truncated = (uint32_t)offset;
  47. if (offset_truncated != offset)
  48. return -1;
  49. return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream, offset_truncated, origin);
  50. }
  51. uint64_t call_ztell64(const zlib_filefunc64_32_def *pfilefunc, voidpf filestream)
  52. {
  53. uint64_t position;
  54. if (pfilefunc->zfile_func64.zseek64_file != NULL)
  55. return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque, filestream);
  56. position = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque, filestream);
  57. if ((position) == UINT32_MAX)
  58. return (uint64_t)-1;
  59. return position;
  60. }
  61. void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def *p_filefunc64_32, const zlib_filefunc_def *p_filefunc32)
  62. {
  63. p_filefunc64_32->zfile_func64.zopen64_file = NULL;
  64. p_filefunc64_32->zfile_func64.zopendisk64_file = NULL;
  65. p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
  66. p_filefunc64_32->zopendisk32_file = p_filefunc32->zopendisk_file;
  67. p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
  68. p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
  69. p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
  70. p_filefunc64_32->zfile_func64.ztell64_file = NULL;
  71. p_filefunc64_32->zfile_func64.zseek64_file = NULL;
  72. p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
  73. p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
  74. p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
  75. p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
  76. p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
  77. }
  78. static voidpf ZCALLBACK fopen_file_func(voidpf opaque, const char *filename, int mode);
  79. static uint32_t ZCALLBACK fread_file_func(voidpf opaque, voidpf stream, void* buf, uint32_t size);
  80. static uint32_t ZCALLBACK fwrite_file_func(voidpf opaque, voidpf stream, const void *buf, uint32_t size);
  81. static uint64_t ZCALLBACK ftell64_file_func(voidpf opaque, voidpf stream);
  82. static long ZCALLBACK fseek64_file_func(voidpf opaque, voidpf stream, uint64_t offset, int origin);
  83. static int ZCALLBACK fclose_file_func(voidpf opaque, voidpf stream);
  84. static int ZCALLBACK ferror_file_func(voidpf opaque, voidpf stream);
  85. typedef struct
  86. {
  87. FILE *file;
  88. int filenameLength;
  89. void *filename;
  90. } FILE_IOPOSIX;
  91. static voidpf file_build_ioposix(FILE *file, const char *filename)
  92. {
  93. FILE_IOPOSIX *ioposix = NULL;
  94. if (file == NULL)
  95. return NULL;
  96. ioposix = (FILE_IOPOSIX*)malloc(sizeof(FILE_IOPOSIX));
  97. ioposix->file = file;
  98. ioposix->filenameLength = (int)strlen(filename) + 1;
  99. ioposix->filename = (char*)malloc(ioposix->filenameLength * sizeof(char));
  100. memcpy((char*)ioposix->filename, filename, ioposix->filenameLength);
  101. return (voidpf)ioposix;
  102. }
  103. static voidpf ZCALLBACK fopen_file_func(voidpf opaque, const char *filename, int mode)
  104. {
  105. FILE* file = NULL;
  106. const char *mode_fopen = NULL;
  107. if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
  108. mode_fopen = "rb";
  109. else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
  110. mode_fopen = "r+b";
  111. else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
  112. mode_fopen = "wb";
  113. if ((filename != NULL) && (mode_fopen != NULL))
  114. {
  115. file = fopen(filename, mode_fopen);
  116. return file_build_ioposix(file, filename);
  117. }
  118. return file;
  119. }
  120. static voidpf ZCALLBACK fopen64_file_func(voidpf opaque, const void *filename, int mode)
  121. {
  122. FILE* file = NULL;
  123. const char *mode_fopen = NULL;
  124. if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
  125. mode_fopen = "rb";
  126. else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
  127. mode_fopen = "r+b";
  128. else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
  129. mode_fopen = "wb";
  130. if ((filename != NULL) && (mode_fopen != NULL))
  131. {
  132. file = fopen64((const char*)filename, mode_fopen);
  133. return file_build_ioposix(file, (const char*)filename);
  134. }
  135. return file;
  136. }
  137. static voidpf ZCALLBACK fopendisk64_file_func(voidpf opaque, voidpf stream, uint32_t number_disk, int mode)
  138. {
  139. FILE_IOPOSIX *ioposix = NULL;
  140. char *diskFilename = NULL;
  141. voidpf ret = NULL;
  142. int i = 0;
  143. if (stream == NULL)
  144. return NULL;
  145. ioposix = (FILE_IOPOSIX*)stream;
  146. diskFilename = (char*)malloc(ioposix->filenameLength * sizeof(char));
  147. strncpy(diskFilename, (const char*)ioposix->filename, ioposix->filenameLength);
  148. for (i = ioposix->filenameLength - 1; i >= 0; i -= 1)
  149. {
  150. if (diskFilename[i] != '.')
  151. continue;
  152. snprintf(&diskFilename[i], ioposix->filenameLength - i, ".z%02u", number_disk + 1);
  153. break;
  154. }
  155. if (i >= 0)
  156. ret = fopen64_file_func(opaque, diskFilename, mode);
  157. free(diskFilename);
  158. return ret;
  159. }
  160. static voidpf ZCALLBACK fopendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_disk, int mode)
  161. {
  162. FILE_IOPOSIX *ioposix = NULL;
  163. char *diskFilename = NULL;
  164. voidpf ret = NULL;
  165. int i = 0;
  166. if (stream == NULL)
  167. return NULL;
  168. ioposix = (FILE_IOPOSIX*)stream;
  169. diskFilename = (char*)malloc(ioposix->filenameLength * sizeof(char));
  170. strncpy(diskFilename, (const char*)ioposix->filename, ioposix->filenameLength);
  171. for (i = ioposix->filenameLength - 1; i >= 0; i -= 1)
  172. {
  173. if (diskFilename[i] != '.')
  174. continue;
  175. snprintf(&diskFilename[i], ioposix->filenameLength - i, ".z%02u", number_disk + 1);
  176. break;
  177. }
  178. if (i >= 0)
  179. ret = fopen_file_func(opaque, diskFilename, mode);
  180. free(diskFilename);
  181. return ret;
  182. }
  183. static uint32_t ZCALLBACK fread_file_func(voidpf opaque, voidpf stream, void* buf, uint32_t size)
  184. {
  185. FILE_IOPOSIX *ioposix = NULL;
  186. uint32_t read = (uint32_t)-1;
  187. if (stream == NULL)
  188. return read;
  189. ioposix = (FILE_IOPOSIX*)stream;
  190. read = (uint32_t)fread(buf, 1, (size_t)size, ioposix->file);
  191. return read;
  192. }
  193. static uint32_t ZCALLBACK fwrite_file_func(voidpf opaque, voidpf stream, const void *buf, uint32_t size)
  194. {
  195. FILE_IOPOSIX *ioposix = NULL;
  196. uint32_t written = (uint32_t)-1;
  197. if (stream == NULL)
  198. return written;
  199. ioposix = (FILE_IOPOSIX*)stream;
  200. written = (uint32_t)fwrite(buf, 1, (size_t)size, ioposix->file);
  201. return written;
  202. }
  203. static long ZCALLBACK ftell_file_func(voidpf opaque, voidpf stream)
  204. {
  205. FILE_IOPOSIX *ioposix = NULL;
  206. long ret = -1;
  207. if (stream == NULL)
  208. return ret;
  209. ioposix = (FILE_IOPOSIX*)stream;
  210. ret = ftell(ioposix->file);
  211. return ret;
  212. }
  213. static uint64_t ZCALLBACK ftell64_file_func(voidpf opaque, voidpf stream)
  214. {
  215. FILE_IOPOSIX *ioposix = NULL;
  216. uint64_t ret = (uint64_t)-1;
  217. if (stream == NULL)
  218. return ret;
  219. ioposix = (FILE_IOPOSIX*)stream;
  220. ret = ftello64(ioposix->file);
  221. return ret;
  222. }
  223. static long ZCALLBACK fseek_file_func(voidpf opaque, voidpf stream, uint32_t offset, int origin)
  224. {
  225. FILE_IOPOSIX *ioposix = NULL;
  226. int fseek_origin = 0;
  227. long ret = 0;
  228. if (stream == NULL)
  229. return -1;
  230. ioposix = (FILE_IOPOSIX*)stream;
  231. switch (origin)
  232. {
  233. case ZLIB_FILEFUNC_SEEK_CUR:
  234. fseek_origin = SEEK_CUR;
  235. break;
  236. case ZLIB_FILEFUNC_SEEK_END:
  237. fseek_origin = SEEK_END;
  238. break;
  239. case ZLIB_FILEFUNC_SEEK_SET:
  240. fseek_origin = SEEK_SET;
  241. break;
  242. default:
  243. return -1;
  244. }
  245. if (fseek(ioposix->file, offset, fseek_origin) != 0)
  246. ret = -1;
  247. return ret;
  248. }
  249. static long ZCALLBACK fseek64_file_func(voidpf opaque, voidpf stream, uint64_t offset, int origin)
  250. {
  251. FILE_IOPOSIX *ioposix = NULL;
  252. int fseek_origin = 0;
  253. long ret = 0;
  254. if (stream == NULL)
  255. return -1;
  256. ioposix = (FILE_IOPOSIX*)stream;
  257. switch (origin)
  258. {
  259. case ZLIB_FILEFUNC_SEEK_CUR:
  260. fseek_origin = SEEK_CUR;
  261. break;
  262. case ZLIB_FILEFUNC_SEEK_END:
  263. fseek_origin = SEEK_END;
  264. break;
  265. case ZLIB_FILEFUNC_SEEK_SET:
  266. fseek_origin = SEEK_SET;
  267. break;
  268. default:
  269. return -1;
  270. }
  271. if (fseeko64(ioposix->file, offset, fseek_origin) != 0)
  272. ret = -1;
  273. return ret;
  274. }
  275. static int ZCALLBACK fclose_file_func(voidpf opaque, voidpf stream)
  276. {
  277. FILE_IOPOSIX *ioposix = NULL;
  278. int ret = -1;
  279. if (stream == NULL)
  280. return ret;
  281. ioposix = (FILE_IOPOSIX*)stream;
  282. if (ioposix->filename != NULL)
  283. free(ioposix->filename);
  284. ret = fclose(ioposix->file);
  285. free(ioposix);
  286. return ret;
  287. }
  288. static int ZCALLBACK ferror_file_func(voidpf opaque, voidpf stream)
  289. {
  290. FILE_IOPOSIX *ioposix = NULL;
  291. int ret = -1;
  292. if (stream == NULL)
  293. return ret;
  294. ioposix = (FILE_IOPOSIX*)stream;
  295. ret = ferror(ioposix->file);
  296. return ret;
  297. }
  298. void fill_fopen_filefunc(zlib_filefunc_def *pzlib_filefunc_def)
  299. {
  300. pzlib_filefunc_def->zopen_file = fopen_file_func;
  301. pzlib_filefunc_def->zopendisk_file = fopendisk_file_func;
  302. pzlib_filefunc_def->zread_file = fread_file_func;
  303. pzlib_filefunc_def->zwrite_file = fwrite_file_func;
  304. pzlib_filefunc_def->ztell_file = ftell_file_func;
  305. pzlib_filefunc_def->zseek_file = fseek_file_func;
  306. pzlib_filefunc_def->zclose_file = fclose_file_func;
  307. pzlib_filefunc_def->zerror_file = ferror_file_func;
  308. pzlib_filefunc_def->opaque = NULL;
  309. }
  310. void fill_fopen64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def)
  311. {
  312. pzlib_filefunc_def->zopen64_file = fopen64_file_func;
  313. pzlib_filefunc_def->zopendisk64_file = fopendisk64_file_func;
  314. pzlib_filefunc_def->zread_file = fread_file_func;
  315. pzlib_filefunc_def->zwrite_file = fwrite_file_func;
  316. pzlib_filefunc_def->ztell64_file = ftell64_file_func;
  317. pzlib_filefunc_def->zseek64_file = fseek64_file_func;
  318. pzlib_filefunc_def->zclose_file = fclose_file_func;
  319. pzlib_filefunc_def->zerror_file = ferror_file_func;
  320. pzlib_filefunc_def->opaque = NULL;
  321. }
  322. #ifdef _MSC_VER
  323. # pragma warning(pop)
  324. # ifdef __clang__
  325. # pragma clang diagnostic pop
  326. # endif
  327. #endif // _MSC_VER