mz_strm.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /* mz_strm.c -- Stream interface
  2. Version 2.9.2, February 12, 2020
  3. part of the MiniZip project
  4. Copyright (C) 2010-2020 Nathan Moinvaziri
  5. https://github.com/nmoinvaz/minizip
  6. This program is distributed under the terms of the same license as zlib.
  7. See the accompanying LICENSE file for the full text of the license.
  8. */
  9. #include "mz.h"
  10. #include "mz_strm.h"
  11. /***************************************************************************/
  12. #define MZ_STREAM_FIND_SIZE (1024)
  13. /***************************************************************************/
  14. int32_t mz_stream_open(void *stream, const char *path, int32_t mode)
  15. {
  16. mz_stream *strm = (mz_stream *)stream;
  17. if (strm == NULL || strm->vtbl == NULL || strm->vtbl->open == NULL)
  18. return MZ_STREAM_ERROR;
  19. return strm->vtbl->open(strm, path, mode);
  20. }
  21. int32_t mz_stream_is_open(void *stream)
  22. {
  23. mz_stream *strm = (mz_stream *)stream;
  24. if (strm == NULL || strm->vtbl == NULL || strm->vtbl->is_open == NULL)
  25. return MZ_STREAM_ERROR;
  26. return strm->vtbl->is_open(strm);
  27. }
  28. int32_t mz_stream_read(void *stream, void *buf, int32_t size)
  29. {
  30. mz_stream *strm = (mz_stream *)stream;
  31. if (strm == NULL || strm->vtbl == NULL || strm->vtbl->read == NULL)
  32. return MZ_PARAM_ERROR;
  33. if (mz_stream_is_open(stream) != MZ_OK)
  34. return MZ_STREAM_ERROR;
  35. return strm->vtbl->read(strm, buf, size);
  36. }
  37. static int32_t mz_stream_read_value(void *stream, uint64_t *value, int32_t len)
  38. {
  39. uint8_t buf[8];
  40. int32_t n = 0;
  41. int32_t i = 0;
  42. *value = 0;
  43. if (mz_stream_read(stream, buf, len) == len)
  44. {
  45. for (n = 0; n < len; n += 1, i += 8)
  46. *value += ((uint64_t)buf[n]) << i;
  47. }
  48. else if (mz_stream_error(stream))
  49. return MZ_STREAM_ERROR;
  50. else
  51. return MZ_END_OF_STREAM;
  52. return MZ_OK;
  53. }
  54. int32_t mz_stream_read_uint8(void *stream, uint8_t *value)
  55. {
  56. int32_t err = MZ_OK;
  57. uint64_t value64 = 0;
  58. *value = 0;
  59. err = mz_stream_read_value(stream, &value64, sizeof(uint8_t));
  60. if (err == MZ_OK)
  61. *value = (uint8_t)value64;
  62. return err;
  63. }
  64. int32_t mz_stream_read_uint16(void *stream, uint16_t *value)
  65. {
  66. int32_t err = MZ_OK;
  67. uint64_t value64 = 0;
  68. *value = 0;
  69. err = mz_stream_read_value(stream, &value64, sizeof(uint16_t));
  70. if (err == MZ_OK)
  71. *value = (uint16_t)value64;
  72. return err;
  73. }
  74. int32_t mz_stream_read_uint32(void *stream, uint32_t *value)
  75. {
  76. int32_t err = MZ_OK;
  77. uint64_t value64 = 0;
  78. *value = 0;
  79. err = mz_stream_read_value(stream, &value64, sizeof(uint32_t));
  80. if (err == MZ_OK)
  81. *value = (uint32_t)value64;
  82. return err;
  83. }
  84. int32_t mz_stream_read_int64(void *stream, int64_t *value)
  85. {
  86. return mz_stream_read_value(stream, (uint64_t *)value, sizeof(uint64_t));
  87. }
  88. int32_t mz_stream_read_uint64(void *stream, uint64_t *value)
  89. {
  90. return mz_stream_read_value(stream, value, sizeof(uint64_t));
  91. }
  92. int32_t mz_stream_write(void *stream, const void *buf, int32_t size)
  93. {
  94. mz_stream *strm = (mz_stream *)stream;
  95. if (size == 0)
  96. return size;
  97. if (strm == NULL || strm->vtbl == NULL || strm->vtbl->write == NULL)
  98. return MZ_PARAM_ERROR;
  99. if (mz_stream_is_open(stream) != MZ_OK)
  100. return MZ_STREAM_ERROR;
  101. return strm->vtbl->write(strm, buf, size);
  102. }
  103. static int32_t mz_stream_write_value(void *stream, uint64_t value, int32_t len)
  104. {
  105. uint8_t buf[8];
  106. int32_t n = 0;
  107. for (n = 0; n < len; n += 1)
  108. {
  109. buf[n] = (uint8_t)(value & 0xff);
  110. value >>= 8;
  111. }
  112. if (value != 0)
  113. {
  114. /* Data overflow - hack for ZIP64 (X Roche) */
  115. for (n = 0; n < len; n += 1)
  116. buf[n] = 0xff;
  117. }
  118. if (mz_stream_write(stream, buf, len) != len)
  119. return MZ_STREAM_ERROR;
  120. return MZ_OK;
  121. }
  122. int32_t mz_stream_write_uint8(void *stream, uint8_t value)
  123. {
  124. return mz_stream_write_value(stream, value, sizeof(uint8_t));
  125. }
  126. int32_t mz_stream_write_uint16(void *stream, uint16_t value)
  127. {
  128. return mz_stream_write_value(stream, value, sizeof(uint16_t));
  129. }
  130. int32_t mz_stream_write_uint32(void *stream, uint32_t value)
  131. {
  132. return mz_stream_write_value(stream, value, sizeof(uint32_t));
  133. }
  134. int32_t mz_stream_write_int64(void *stream, int64_t value)
  135. {
  136. return mz_stream_write_value(stream, (uint64_t)value, sizeof(uint64_t));
  137. }
  138. int32_t mz_stream_write_uint64(void *stream, uint64_t value)
  139. {
  140. return mz_stream_write_value(stream, value, sizeof(uint64_t));
  141. }
  142. int32_t mz_stream_copy(void *target, void *source, int32_t len)
  143. {
  144. return mz_stream_copy_stream(target, NULL, source, NULL, len);
  145. }
  146. int32_t mz_stream_copy_to_end(void *target, void *source)
  147. {
  148. return mz_stream_copy_stream_to_end(target, NULL, source, NULL);
  149. }
  150. int32_t mz_stream_copy_stream(void *target, mz_stream_write_cb write_cb, void *source,
  151. mz_stream_read_cb read_cb, int32_t len)
  152. {
  153. uint8_t buf[16384];
  154. int32_t bytes_to_copy = 0;
  155. int32_t read = 0;
  156. int32_t written = 0;
  157. if (write_cb == NULL)
  158. write_cb = mz_stream_write;
  159. if (read_cb == NULL)
  160. read_cb = mz_stream_read;
  161. while (len > 0)
  162. {
  163. bytes_to_copy = len;
  164. if (bytes_to_copy > (int32_t)sizeof(buf))
  165. bytes_to_copy = sizeof(buf);
  166. read = read_cb(source, buf, bytes_to_copy);
  167. if (read <= 0)
  168. return MZ_STREAM_ERROR;
  169. written = write_cb(target, buf, read);
  170. if (written != read)
  171. return MZ_STREAM_ERROR;
  172. len -= read;
  173. }
  174. return MZ_OK;
  175. }
  176. int32_t mz_stream_copy_stream_to_end(void *target, mz_stream_write_cb write_cb, void *source,
  177. mz_stream_read_cb read_cb)
  178. {
  179. uint8_t buf[16384];
  180. int32_t read = 0;
  181. int32_t written = 0;
  182. if (write_cb == NULL)
  183. write_cb = mz_stream_write;
  184. if (read_cb == NULL)
  185. read_cb = mz_stream_read;
  186. read = read_cb(source, buf, sizeof(buf));
  187. while (read > 0)
  188. {
  189. written = write_cb(target, buf, read);
  190. if (written != read)
  191. return MZ_STREAM_ERROR;
  192. read = read_cb(source, buf, sizeof(buf));
  193. }
  194. if (read < 0)
  195. return MZ_STREAM_ERROR;
  196. return MZ_OK;
  197. }
  198. int64_t mz_stream_tell(void *stream)
  199. {
  200. mz_stream *strm = (mz_stream *)stream;
  201. if (strm == NULL || strm->vtbl == NULL || strm->vtbl->tell == NULL)
  202. return MZ_PARAM_ERROR;
  203. if (mz_stream_is_open(stream) != MZ_OK)
  204. return MZ_STREAM_ERROR;
  205. return strm->vtbl->tell(strm);
  206. }
  207. int32_t mz_stream_seek(void *stream, int64_t offset, int32_t origin)
  208. {
  209. mz_stream *strm = (mz_stream *)stream;
  210. if (strm == NULL || strm->vtbl == NULL || strm->vtbl->seek == NULL)
  211. return MZ_PARAM_ERROR;
  212. if (mz_stream_is_open(stream) != MZ_OK)
  213. return MZ_STREAM_ERROR;
  214. if (origin == MZ_SEEK_SET && offset < 0)
  215. return MZ_SEEK_ERROR;
  216. return strm->vtbl->seek(strm, offset, origin);
  217. }
  218. int32_t mz_stream_find(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position)
  219. {
  220. uint8_t buf[MZ_STREAM_FIND_SIZE];
  221. int32_t buf_pos = 0;
  222. int32_t read_size = sizeof(buf);
  223. int32_t read = 0;
  224. int64_t read_pos = 0;
  225. int64_t start_pos = 0;
  226. int64_t disk_pos = 0;
  227. int32_t i = 0;
  228. uint8_t first = 1;
  229. int32_t err = MZ_OK;
  230. if (stream == NULL || find == NULL || position == NULL)
  231. return MZ_PARAM_ERROR;
  232. if (find_size < 0 || find_size >= (int32_t)sizeof(buf))
  233. return MZ_PARAM_ERROR;
  234. *position = -1;
  235. start_pos = mz_stream_tell(stream);
  236. while (read_pos < max_seek)
  237. {
  238. if (read_size > (int32_t)(max_seek - read_pos - buf_pos) && (max_seek - read_pos - buf_pos) < (int64_t)sizeof(buf))
  239. read_size = (int32_t)(max_seek - read_pos - buf_pos);
  240. read = mz_stream_read(stream, buf + buf_pos, read_size);
  241. if ((read <= 0) || (read + buf_pos < find_size))
  242. break;
  243. for (i = 0; i <= read + buf_pos - find_size; i += 1)
  244. {
  245. if (memcmp(&buf[i], find, find_size) != 0)
  246. continue;
  247. disk_pos = mz_stream_tell(stream);
  248. /* Seek to position on disk where the data was found */
  249. err = mz_stream_seek(stream, disk_pos - ((int64_t)read + buf_pos - i), MZ_SEEK_SET);
  250. if (err != MZ_OK)
  251. return MZ_EXIST_ERROR;
  252. *position = start_pos + read_pos + i;
  253. return MZ_OK;
  254. }
  255. if (first)
  256. {
  257. read -= find_size;
  258. read_size -= find_size;
  259. buf_pos = find_size;
  260. first = 0;
  261. }
  262. memmove(buf, buf + read, find_size);
  263. read_pos += read;
  264. }
  265. return MZ_EXIST_ERROR;
  266. }
  267. int32_t mz_stream_find_reverse(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position)
  268. {
  269. uint8_t buf[MZ_STREAM_FIND_SIZE];
  270. int32_t buf_pos = 0;
  271. int32_t read_size = MZ_STREAM_FIND_SIZE;
  272. int64_t read_pos = 0;
  273. int32_t read = 0;
  274. int64_t start_pos = 0;
  275. int64_t disk_pos = 0;
  276. uint8_t first = 1;
  277. int32_t i = 0;
  278. int32_t err = MZ_OK;
  279. if (stream == NULL || find == NULL || position == NULL)
  280. return MZ_PARAM_ERROR;
  281. if (find_size < 0 || find_size >= (int32_t)sizeof(buf))
  282. return MZ_PARAM_ERROR;
  283. *position = -1;
  284. start_pos = mz_stream_tell(stream);
  285. while (read_pos < max_seek)
  286. {
  287. if (read_size > (int32_t)(max_seek - read_pos) && (max_seek - read_pos) < (int64_t)sizeof(buf))
  288. read_size = (int32_t)(max_seek - read_pos);
  289. if (mz_stream_seek(stream, start_pos - (read_pos + read_size), MZ_SEEK_SET) != MZ_OK)
  290. break;
  291. read = mz_stream_read(stream, buf, read_size);
  292. if ((read <= 0) || (read + buf_pos < find_size))
  293. break;
  294. if (read + buf_pos < MZ_STREAM_FIND_SIZE)
  295. memmove(buf + MZ_STREAM_FIND_SIZE - (read + buf_pos), buf, read);
  296. for (i = find_size; i <= (read + buf_pos); i += 1)
  297. {
  298. if (memcmp(&buf[MZ_STREAM_FIND_SIZE - i], find, find_size) != 0)
  299. continue;
  300. disk_pos = mz_stream_tell(stream);
  301. /* Seek to position on disk where the data was found */
  302. err = mz_stream_seek(stream, disk_pos + buf_pos - i, MZ_SEEK_SET);
  303. if (err != MZ_OK)
  304. return MZ_EXIST_ERROR;
  305. *position = start_pos - (read_pos - buf_pos + i);
  306. return MZ_OK;
  307. }
  308. if (first)
  309. {
  310. read -= find_size;
  311. read_size -= find_size;
  312. buf_pos = find_size;
  313. first = 0;
  314. }
  315. if (read == 0)
  316. break;
  317. memmove(buf + read_size, buf, find_size);
  318. read_pos += read;
  319. }
  320. return MZ_EXIST_ERROR;
  321. }
  322. int32_t mz_stream_close(void *stream)
  323. {
  324. mz_stream *strm = (mz_stream *)stream;
  325. if (strm == NULL || strm->vtbl == NULL || strm->vtbl->close == NULL)
  326. return MZ_PARAM_ERROR;
  327. if (mz_stream_is_open(stream) != MZ_OK)
  328. return MZ_STREAM_ERROR;
  329. return strm->vtbl->close(strm);
  330. }
  331. int32_t mz_stream_error(void *stream)
  332. {
  333. mz_stream *strm = (mz_stream *)stream;
  334. if (strm == NULL || strm->vtbl == NULL || strm->vtbl->error == NULL)
  335. return MZ_PARAM_ERROR;
  336. return strm->vtbl->error(strm);
  337. }
  338. int32_t mz_stream_set_base(void *stream, void *base)
  339. {
  340. mz_stream *strm = (mz_stream *)stream;
  341. strm->base = (mz_stream *)base;
  342. return MZ_OK;
  343. }
  344. void* mz_stream_get_interface(void *stream)
  345. {
  346. mz_stream *strm = (mz_stream *)stream;
  347. if (strm == NULL || strm->vtbl == NULL)
  348. return NULL;
  349. return (void *)strm->vtbl;
  350. }
  351. int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value)
  352. {
  353. mz_stream *strm = (mz_stream *)stream;
  354. if (strm == NULL || strm->vtbl == NULL || strm->vtbl->get_prop_int64 == NULL)
  355. return MZ_PARAM_ERROR;
  356. return strm->vtbl->get_prop_int64(stream, prop, value);
  357. }
  358. int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value)
  359. {
  360. mz_stream *strm = (mz_stream *)stream;
  361. if (strm == NULL || strm->vtbl == NULL || strm->vtbl->set_prop_int64 == NULL)
  362. return MZ_PARAM_ERROR;
  363. return strm->vtbl->set_prop_int64(stream, prop, value);
  364. }
  365. void *mz_stream_create(void **stream, mz_stream_vtbl *vtbl)
  366. {
  367. if (stream == NULL)
  368. return NULL;
  369. if (vtbl == NULL || vtbl->create == NULL)
  370. return NULL;
  371. return vtbl->create(stream);
  372. }
  373. void mz_stream_delete(void **stream)
  374. {
  375. mz_stream *strm = NULL;
  376. if (stream == NULL)
  377. return;
  378. strm = (mz_stream *)*stream;
  379. if (strm != NULL && strm->vtbl != NULL && strm->vtbl->destroy != NULL)
  380. strm->vtbl->destroy(stream);
  381. *stream = NULL;
  382. }
  383. /***************************************************************************/
  384. typedef struct mz_stream_raw_s {
  385. mz_stream stream;
  386. int64_t total_in;
  387. int64_t total_out;
  388. int64_t max_total_in;
  389. } mz_stream_raw;
  390. /***************************************************************************/
  391. int32_t mz_stream_raw_open(void *stream, const char *path, int32_t mode)
  392. {
  393. MZ_UNUSED(stream);
  394. MZ_UNUSED(path);
  395. MZ_UNUSED(mode);
  396. return MZ_OK;
  397. }
  398. int32_t mz_stream_raw_is_open(void *stream)
  399. {
  400. mz_stream_raw *raw = (mz_stream_raw *)stream;
  401. return mz_stream_is_open(raw->stream.base);
  402. }
  403. int32_t mz_stream_raw_read(void *stream, void *buf, int32_t size)
  404. {
  405. mz_stream_raw *raw = (mz_stream_raw *)stream;
  406. int32_t bytes_to_read = size;
  407. int32_t read = 0;
  408. if (raw->max_total_in > 0)
  409. {
  410. if ((int64_t)bytes_to_read > (raw->max_total_in - raw->total_in))
  411. bytes_to_read = (int32_t)(raw->max_total_in - raw->total_in);
  412. }
  413. read = mz_stream_read(raw->stream.base, buf, bytes_to_read);
  414. if (read > 0)
  415. {
  416. raw->total_in += read;
  417. raw->total_out += read;
  418. }
  419. return read;
  420. }
  421. int32_t mz_stream_raw_write(void *stream, const void *buf, int32_t size)
  422. {
  423. mz_stream_raw *raw = (mz_stream_raw *)stream;
  424. int32_t written = 0;
  425. written = mz_stream_write(raw->stream.base, buf, size);
  426. if (written > 0)
  427. {
  428. raw->total_out += written;
  429. raw->total_in += written;
  430. }
  431. return written;
  432. }
  433. int64_t mz_stream_raw_tell(void *stream)
  434. {
  435. mz_stream_raw *raw = (mz_stream_raw *)stream;
  436. return mz_stream_tell(raw->stream.base);
  437. }
  438. int32_t mz_stream_raw_seek(void *stream, int64_t offset, int32_t origin)
  439. {
  440. mz_stream_raw *raw = (mz_stream_raw *)stream;
  441. return mz_stream_seek(raw->stream.base, offset, origin);
  442. }
  443. int32_t mz_stream_raw_close(void *stream)
  444. {
  445. MZ_UNUSED(stream);
  446. return MZ_OK;
  447. }
  448. int32_t mz_stream_raw_error(void *stream)
  449. {
  450. mz_stream_raw *raw = (mz_stream_raw *)stream;
  451. return mz_stream_error(raw->stream.base);
  452. }
  453. int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value)
  454. {
  455. mz_stream_raw *raw = (mz_stream_raw *)stream;
  456. switch (prop)
  457. {
  458. case MZ_STREAM_PROP_TOTAL_IN:
  459. *value = raw->total_in;
  460. return MZ_OK;
  461. case MZ_STREAM_PROP_TOTAL_OUT:
  462. *value = raw->total_out;
  463. return MZ_OK;
  464. }
  465. return MZ_EXIST_ERROR;
  466. }
  467. int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value)
  468. {
  469. mz_stream_raw *raw = (mz_stream_raw *)stream;
  470. switch (prop)
  471. {
  472. case MZ_STREAM_PROP_TOTAL_IN_MAX:
  473. raw->max_total_in = value;
  474. return MZ_OK;
  475. }
  476. return MZ_EXIST_ERROR;
  477. }
  478. /***************************************************************************/
  479. static mz_stream_vtbl mz_stream_raw_vtbl = {
  480. mz_stream_raw_open,
  481. mz_stream_raw_is_open,
  482. mz_stream_raw_read,
  483. mz_stream_raw_write,
  484. mz_stream_raw_tell,
  485. mz_stream_raw_seek,
  486. mz_stream_raw_close,
  487. mz_stream_raw_error,
  488. mz_stream_raw_create,
  489. mz_stream_raw_delete,
  490. mz_stream_raw_get_prop_int64,
  491. mz_stream_raw_set_prop_int64
  492. };
  493. /***************************************************************************/
  494. void *mz_stream_raw_create(void **stream)
  495. {
  496. mz_stream_raw *raw = NULL;
  497. raw = (mz_stream_raw *)MZ_ALLOC(sizeof(mz_stream_raw));
  498. if (raw != NULL)
  499. {
  500. memset(raw, 0, sizeof(mz_stream_raw));
  501. raw->stream.vtbl = &mz_stream_raw_vtbl;
  502. }
  503. if (stream != NULL)
  504. *stream = raw;
  505. return raw;
  506. }
  507. void mz_stream_raw_delete(void **stream)
  508. {
  509. mz_stream_raw *raw = NULL;
  510. if (stream == NULL)
  511. return;
  512. raw = (mz_stream_raw *)*stream;
  513. if (raw != NULL)
  514. MZ_FREE(raw);
  515. *stream = NULL;
  516. }