ioapi.cpp 12 KB

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