test.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. #include <zip.h>
  2. #include <assert.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/stat.h>
  7. #if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__)
  8. #define MZ_FILE_STAT_STRUCT _stat
  9. #define MZ_FILE_STAT _stat
  10. #else
  11. #define MZ_FILE_STAT_STRUCT stat
  12. #define MZ_FILE_STAT stat
  13. #endif
  14. #define ZIPNAME "test.zip\0"
  15. #define TESTDATA1 "Some test data 1...\0"
  16. #define CRC32DATA1 2220805626
  17. #define TESTDATA2 "Some test data 2...\0"
  18. #define CRC32DATA2 2532008468
  19. #define RFILE "4.txt\0"
  20. #define RMODE 0100444
  21. #define WFILE "6.txt\0"
  22. #define WMODE 0100666
  23. #define XFILE "7.txt\0"
  24. #define XMODE 0100777
  25. #define UNIXMODE 0100644
  26. #define UNUSED(x) (void)x
  27. static int total_entries = 0;
  28. static void test_write(void) {
  29. struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
  30. assert(zip != NULL);
  31. assert(0 == zip_entry_open(zip, "test/test-1.txt"));
  32. assert(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1)));
  33. assert(0 == strcmp(zip_entry_name(zip), "test/test-1.txt"));
  34. assert(total_entries == zip_entry_index(zip));
  35. assert(strlen(TESTDATA1) == zip_entry_size(zip));
  36. assert(CRC32DATA1 == zip_entry_crc32(zip));
  37. ++total_entries;
  38. assert(0 == zip_entry_close(zip));
  39. assert(0 == zip_is64(zip));
  40. zip_close(zip);
  41. }
  42. static void test_append(void) {
  43. struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'a');
  44. assert(zip != NULL);
  45. assert(0 == zip_entry_open(zip, "test\\test-2.txt"));
  46. assert(0 == strcmp(zip_entry_name(zip), "test/test-2.txt"));
  47. assert(total_entries == zip_entry_index(zip));
  48. assert(0 == zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2)));
  49. assert(strlen(TESTDATA2) == zip_entry_size(zip));
  50. assert(CRC32DATA2 == zip_entry_crc32(zip));
  51. ++total_entries;
  52. assert(0 == zip_entry_close(zip));
  53. assert(0 == zip_entry_open(zip, "test\\empty/"));
  54. assert(0 == strcmp(zip_entry_name(zip), "test/empty/"));
  55. assert(0 == zip_entry_size(zip));
  56. assert(0 == zip_entry_crc32(zip));
  57. assert(total_entries == zip_entry_index(zip));
  58. ++total_entries;
  59. assert(0 == zip_entry_close(zip));
  60. assert(0 == zip_entry_open(zip, "empty/"));
  61. assert(0 == strcmp(zip_entry_name(zip), "empty/"));
  62. assert(0 == zip_entry_size(zip));
  63. assert(0 == zip_entry_crc32(zip));
  64. assert(total_entries == zip_entry_index(zip));
  65. ++total_entries;
  66. assert(0 == zip_entry_close(zip));
  67. zip_close(zip);
  68. }
  69. static void test_read(void) {
  70. char *buf = NULL;
  71. ssize_t bufsize;
  72. size_t buftmp;
  73. struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
  74. assert(zip != NULL);
  75. assert(0 == zip_is64(zip));
  76. assert(0 == zip_entry_open(zip, "test\\test-1.txt"));
  77. assert(strlen(TESTDATA1) == zip_entry_size(zip));
  78. assert(CRC32DATA1 == zip_entry_crc32(zip));
  79. bufsize = zip_entry_read(zip, (void **)&buf, &buftmp);
  80. assert(bufsize == strlen(TESTDATA1));
  81. assert((size_t)bufsize == buftmp);
  82. assert(0 == strncmp(buf, TESTDATA1, bufsize));
  83. assert(0 == zip_entry_close(zip));
  84. free(buf);
  85. buf = NULL;
  86. bufsize = 0;
  87. assert(0 == zip_entry_open(zip, "test/test-2.txt"));
  88. assert(strlen(TESTDATA2) == zip_entry_size(zip));
  89. assert(CRC32DATA2 == zip_entry_crc32(zip));
  90. bufsize = zip_entry_read(zip, (void **)&buf, NULL);
  91. assert((size_t)bufsize == strlen(TESTDATA2));
  92. assert(0 == strncmp(buf, TESTDATA2, (size_t)bufsize));
  93. assert(0 == zip_entry_close(zip));
  94. free(buf);
  95. buf = NULL;
  96. bufsize = 0;
  97. assert(0 == zip_entry_open(zip, "test\\empty/"));
  98. assert(0 == strcmp(zip_entry_name(zip), "test/empty/"));
  99. assert(0 == zip_entry_size(zip));
  100. assert(0 == zip_entry_crc32(zip));
  101. assert(0 == zip_entry_close(zip));
  102. buftmp = strlen(TESTDATA2);
  103. buf = calloc(buftmp, sizeof(char));
  104. assert(0 == zip_entry_open(zip, "test/test-2.txt"));
  105. bufsize = zip_entry_noallocread(zip, (void *)buf, buftmp);
  106. assert(buftmp == (size_t)bufsize);
  107. assert(0 == strncmp(buf, TESTDATA2, buftmp));
  108. assert(0 == zip_entry_close(zip));
  109. free(buf);
  110. buf = NULL;
  111. bufsize = 0;
  112. buftmp = strlen(TESTDATA1);
  113. buf = calloc(buftmp, sizeof(char));
  114. assert(0 == zip_entry_open(zip, "test/test-1.txt"));
  115. bufsize = zip_entry_noallocread(zip, (void *)buf, buftmp);
  116. assert(buftmp == (size_t)bufsize);
  117. assert(0 == strncmp(buf, TESTDATA1, buftmp));
  118. assert(0 == zip_entry_close(zip));
  119. free(buf);
  120. buf = NULL;
  121. bufsize = 0;
  122. zip_close(zip);
  123. }
  124. struct buffer_t {
  125. char *data;
  126. size_t size;
  127. };
  128. static size_t on_extract(void *arg, unsigned long long offset, const void *data,
  129. size_t size) {
  130. UNUSED(offset);
  131. struct buffer_t *buf = (struct buffer_t *)arg;
  132. buf->data = realloc(buf->data, buf->size + size + 1);
  133. assert(NULL != buf->data);
  134. memcpy(&(buf->data[buf->size]), data, size);
  135. buf->size += size;
  136. buf->data[buf->size] = 0;
  137. return size;
  138. }
  139. static void test_extract(void) {
  140. struct buffer_t buf;
  141. struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
  142. assert(zip != NULL);
  143. memset((void *)&buf, 0, sizeof(struct buffer_t));
  144. assert(0 == zip_entry_open(zip, "test/test-1.txt"));
  145. assert(0 == zip_entry_extract(zip, on_extract, &buf));
  146. assert(buf.size == strlen(TESTDATA1));
  147. assert(0 == strncmp(buf.data, TESTDATA1, buf.size));
  148. assert(0 == zip_entry_close(zip));
  149. free(buf.data);
  150. buf.data = NULL;
  151. buf.size = 0;
  152. zip_close(zip);
  153. }
  154. static void test_total_entries(void) {
  155. struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
  156. assert(zip != NULL);
  157. int n = zip_total_entries(zip);
  158. zip_close(zip);
  159. assert(n == total_entries);
  160. }
  161. static void test_entry_name(void) {
  162. struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
  163. assert(zip != NULL);
  164. assert(zip_entry_name(zip) == NULL);
  165. assert(0 == zip_entry_open(zip, "test\\test-1.txt"));
  166. assert(NULL != zip_entry_name(zip));
  167. assert(0 == strcmp(zip_entry_name(zip), "test/test-1.txt"));
  168. assert(strlen(TESTDATA1) == zip_entry_size(zip));
  169. assert(CRC32DATA1 == zip_entry_crc32(zip));
  170. assert(0 == zip_entry_index(zip));
  171. assert(0 == zip_entry_close(zip));
  172. assert(0 == zip_entry_open(zip, "test/test-2.txt"));
  173. assert(NULL != zip_entry_name(zip));
  174. assert(0 == strcmp(zip_entry_name(zip), "test/test-2.txt"));
  175. assert(strlen(TESTDATA2) == zip_entry_size(zip));
  176. assert(CRC32DATA2 == zip_entry_crc32(zip));
  177. assert(1 == zip_entry_index(zip));
  178. assert(0 == zip_entry_close(zip));
  179. zip_close(zip);
  180. }
  181. static void test_entry_index(void) {
  182. struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
  183. assert(zip != NULL);
  184. assert(0 == zip_entry_open(zip, "test\\test-1.txt"));
  185. assert(0 == zip_entry_index(zip));
  186. assert(0 == strcmp(zip_entry_name(zip), "test/test-1.txt"));
  187. assert(strlen(TESTDATA1) == zip_entry_size(zip));
  188. assert(CRC32DATA1 == zip_entry_crc32(zip));
  189. assert(0 == zip_entry_close(zip));
  190. assert(0 == zip_entry_open(zip, "test/test-2.txt"));
  191. assert(1 == zip_entry_index(zip));
  192. assert(0 == strcmp(zip_entry_name(zip), "test/test-2.txt"));
  193. assert(strlen(TESTDATA2) == zip_entry_size(zip));
  194. assert(CRC32DATA2 == zip_entry_crc32(zip));
  195. assert(0 == zip_entry_close(zip));
  196. zip_close(zip);
  197. }
  198. static void test_entry_openbyindex(void) {
  199. struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
  200. assert(zip != NULL);
  201. assert(0 == zip_entry_openbyindex(zip, 1));
  202. assert(1 == zip_entry_index(zip));
  203. assert(strlen(TESTDATA2) == zip_entry_size(zip));
  204. assert(CRC32DATA2 == zip_entry_crc32(zip));
  205. assert(0 == strcmp(zip_entry_name(zip), "test/test-2.txt"));
  206. assert(0 == zip_entry_close(zip));
  207. assert(0 == zip_entry_openbyindex(zip, 0));
  208. assert(0 == zip_entry_index(zip));
  209. assert(strlen(TESTDATA1) == zip_entry_size(zip));
  210. assert(CRC32DATA1 == zip_entry_crc32(zip));
  211. assert(0 == strcmp(zip_entry_name(zip), "test/test-1.txt"));
  212. assert(0 == zip_entry_close(zip));
  213. zip_close(zip);
  214. }
  215. static void test_list_entries(void) {
  216. struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
  217. assert(zip != NULL);
  218. int i = 0, n = zip_total_entries(zip);
  219. for (; i < n; ++i) {
  220. assert(0 == zip_entry_openbyindex(zip, i));
  221. fprintf(stdout, "[%d]: %s", i, zip_entry_name(zip));
  222. if (zip_entry_isdir(zip)) {
  223. fprintf(stdout, " (DIR)");
  224. }
  225. fprintf(stdout, "\n");
  226. assert(0 == zip_entry_close(zip));
  227. }
  228. zip_close(zip);
  229. }
  230. static void test_fwrite(void) {
  231. const char *filename = WFILE;
  232. FILE *stream = NULL;
  233. struct zip_t *zip = NULL;
  234. #if defined(_MSC_VER)
  235. if (0 != fopen_s(&stream, filename, "w+"))
  236. #else
  237. if (!(stream = fopen(filename, "w+")))
  238. #endif
  239. {
  240. // Cannot open filename
  241. fprintf(stdout, "Cannot open filename\n");
  242. assert(0 == -1);
  243. }
  244. fwrite(TESTDATA1, sizeof(char), strlen(TESTDATA1), stream);
  245. assert(0 == fclose(stream));
  246. zip = zip_open(ZIPNAME, 9, 'w');
  247. assert(zip != NULL);
  248. assert(0 == zip_entry_open(zip, WFILE));
  249. assert(0 == zip_entry_fwrite(zip, WFILE));
  250. assert(0 == zip_entry_close(zip));
  251. assert(0 == zip_is64(zip));
  252. zip_close(zip);
  253. remove(WFILE);
  254. remove(ZIPNAME);
  255. }
  256. static void test_exe_permissions(void) {
  257. #if defined(_WIN32) || defined(__WIN32__)
  258. #else
  259. struct MZ_FILE_STAT_STRUCT file_stats;
  260. const char *filenames[] = {XFILE};
  261. FILE *f = fopen(XFILE, "w");
  262. fclose(f);
  263. chmod(XFILE, XMODE);
  264. remove(ZIPNAME);
  265. assert(0 == zip_create(ZIPNAME, filenames, 1));
  266. remove(XFILE);
  267. assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));
  268. assert(0 == MZ_FILE_STAT(XFILE, &file_stats));
  269. assert(XMODE == file_stats.st_mode);
  270. remove(XFILE);
  271. remove(ZIPNAME);
  272. #endif
  273. }
  274. static void test_read_permissions(void) {
  275. #if defined(_MSC_VER)
  276. #else
  277. struct MZ_FILE_STAT_STRUCT file_stats;
  278. const char *filenames[] = {RFILE};
  279. FILE *f = fopen(RFILE, "w");
  280. fclose(f);
  281. chmod(RFILE, RMODE);
  282. remove(ZIPNAME);
  283. assert(0 == zip_create(ZIPNAME, filenames, 1));
  284. // chmod from 444 to 666 to be able delete the file on windows
  285. chmod(RFILE, WMODE);
  286. remove(RFILE);
  287. assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));
  288. assert(0 == MZ_FILE_STAT(RFILE, &file_stats));
  289. assert(RMODE == file_stats.st_mode);
  290. chmod(RFILE, WMODE);
  291. remove(RFILE);
  292. remove(ZIPNAME);
  293. #endif
  294. }
  295. static void test_write_permissions(void) {
  296. #if defined(_MSC_VER)
  297. #else
  298. struct MZ_FILE_STAT_STRUCT file_stats;
  299. const char *filenames[] = {WFILE};
  300. FILE *f = fopen(WFILE, "w");
  301. fclose(f);
  302. chmod(WFILE, WMODE);
  303. remove(ZIPNAME);
  304. assert(0 == zip_create(ZIPNAME, filenames, 1));
  305. remove(WFILE);
  306. assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));
  307. assert(0 == MZ_FILE_STAT(WFILE, &file_stats));
  308. assert(WMODE == file_stats.st_mode);
  309. remove(WFILE);
  310. remove(ZIPNAME);
  311. #endif
  312. }
  313. static void test_mtime(void) {
  314. struct MZ_FILE_STAT_STRUCT file_stat1, file_stat2;
  315. const char *filename = WFILE;
  316. FILE *stream = NULL;
  317. struct zip_t *zip = NULL;
  318. #if defined(_MSC_VER)
  319. if (0 != fopen_s(&stream, filename, "w+"))
  320. #else
  321. if (!(stream = fopen(filename, "w+")))
  322. #endif
  323. {
  324. // Cannot open filename
  325. fprintf(stdout, "Cannot open filename\n");
  326. assert(0 == -1);
  327. }
  328. fwrite(TESTDATA1, sizeof(char), strlen(TESTDATA1), stream);
  329. assert(0 == fclose(stream));
  330. memset(&file_stat1, 0, sizeof(file_stat1));
  331. memset(&file_stat2, 0, sizeof(file_stat2));
  332. zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
  333. assert(zip != NULL);
  334. assert(0 == zip_entry_open(zip, filename));
  335. assert(0 == zip_entry_fwrite(zip, filename));
  336. assert(0 == zip_entry_close(zip));
  337. zip_close(zip);
  338. assert(0 == MZ_FILE_STAT(filename, &file_stat1));
  339. remove(filename);
  340. assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));
  341. assert(0 == MZ_FILE_STAT(filename, &file_stat2));
  342. fprintf(stdout, "file_stat1.st_mtime: %lu\n", file_stat1.st_mtime);
  343. fprintf(stdout, "file_stat2.st_mtime: %lu\n", file_stat2.st_mtime);
  344. assert(labs(file_stat1.st_mtime - file_stat2.st_mtime) <= 1);
  345. remove(filename);
  346. remove(ZIPNAME);
  347. }
  348. static void test_unix_permissions(void) {
  349. #if defined(_WIN64) || defined(_WIN32) || defined(__WIN32__)
  350. #else
  351. // UNIX or APPLE
  352. struct MZ_FILE_STAT_STRUCT file_stats;
  353. remove(ZIPNAME);
  354. struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
  355. assert(zip != NULL);
  356. assert(0 == zip_entry_open(zip, RFILE));
  357. assert(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1)));
  358. assert(0 == zip_entry_close(zip));
  359. zip_close(zip);
  360. remove(RFILE);
  361. assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));
  362. assert(0 == MZ_FILE_STAT(RFILE, &file_stats));
  363. assert(UNIXMODE == file_stats.st_mode);
  364. remove(RFILE);
  365. remove(ZIPNAME);
  366. #endif
  367. }
  368. int main(int argc, char *argv[]) {
  369. UNUSED(argc);
  370. UNUSED(argv);
  371. remove(ZIPNAME);
  372. test_write();
  373. test_append();
  374. test_read();
  375. test_extract();
  376. test_total_entries();
  377. test_entry_name();
  378. test_entry_index();
  379. test_entry_openbyindex();
  380. test_list_entries();
  381. test_fwrite();
  382. test_read_permissions();
  383. test_write_permissions();
  384. test_exe_permissions();
  385. test_mtime();
  386. test_unix_permissions();
  387. remove(ZIPNAME);
  388. return 0;
  389. }