mz_os_posix.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /* mz_os_posix.c -- System functions for posix
  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. #include "mz_os.h"
  12. #include <stdio.h> /* rename */
  13. #include <errno.h>
  14. #include <iconv.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #if defined(__APPLE__) || defined(__unix__) || defined(__riscos__)
  18. # include <utime.h>
  19. # include <unistd.h>
  20. #endif
  21. #if defined(__APPLE__)
  22. # include <mach/clock.h>
  23. # include <mach/mach.h>
  24. #endif
  25. /***************************************************************************/
  26. uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding)
  27. {
  28. iconv_t cd;
  29. const char *from_encoding = NULL;
  30. size_t result = 0;
  31. size_t string_length = 0;
  32. size_t string_utf8_size = 0;
  33. uint8_t *string_utf8 = NULL;
  34. uint8_t *string_utf8_ptr = NULL;
  35. if (string == NULL)
  36. return NULL;
  37. if (encoding == MZ_ENCODING_CODEPAGE_437)
  38. from_encoding = "CP437";
  39. else if (encoding == MZ_ENCODING_CODEPAGE_932)
  40. from_encoding = "CP932";
  41. else if (encoding == MZ_ENCODING_CODEPAGE_936)
  42. from_encoding = "CP936";
  43. else if (encoding == MZ_ENCODING_CODEPAGE_950)
  44. from_encoding = "CP950";
  45. else if (encoding == MZ_ENCODING_UTF8)
  46. from_encoding = "UTF-8";
  47. else
  48. return NULL;
  49. cd = iconv_open("UTF-8", from_encoding);
  50. if (cd == (iconv_t)-1)
  51. return NULL;
  52. string_length = strlen(string);
  53. string_utf8_size = string_length * 2;
  54. string_utf8 = (uint8_t *)MZ_ALLOC((int32_t)(string_utf8_size + 1));
  55. string_utf8_ptr = string_utf8;
  56. if (string_utf8)
  57. {
  58. memset(string_utf8, 0, string_utf8_size + 1);
  59. result = iconv(cd, (char **)&string, &string_length,
  60. (char **)&string_utf8_ptr, &string_utf8_size);
  61. }
  62. iconv_close(cd);
  63. if (result == (size_t)-1)
  64. {
  65. MZ_FREE(string_utf8);
  66. string_utf8 = NULL;
  67. }
  68. return string_utf8;
  69. }
  70. void mz_os_utf8_string_delete(uint8_t **string)
  71. {
  72. if (string != NULL)
  73. {
  74. MZ_FREE(*string);
  75. *string = NULL;
  76. }
  77. }
  78. /***************************************************************************/
  79. int32_t mz_os_rand(uint8_t *buf, int32_t size)
  80. {
  81. static unsigned calls = 0;
  82. int32_t i = 0;
  83. /* Ensure different random header each time */
  84. if (++calls == 1)
  85. {
  86. #define PI_SEED 3141592654UL
  87. srand((unsigned)(time(NULL) ^ PI_SEED));
  88. }
  89. while (i < size)
  90. buf[i++] = (rand() >> 7) & 0xff;
  91. return size;
  92. }
  93. int32_t mz_os_rename(const char *source_path, const char *target_path)
  94. {
  95. if (rename(source_path, target_path) == -1)
  96. return MZ_EXIST_ERROR;
  97. return MZ_OK;
  98. }
  99. int32_t mz_os_unlink(const char *path)
  100. {
  101. if (unlink(path) == -1)
  102. return MZ_EXIST_ERROR;
  103. return MZ_OK;
  104. }
  105. int32_t mz_os_file_exists(const char *path)
  106. {
  107. struct stat path_stat;
  108. memset(&path_stat, 0, sizeof(path_stat));
  109. if (stat(path, &path_stat) == 0)
  110. return MZ_OK;
  111. return MZ_EXIST_ERROR;
  112. }
  113. int64_t mz_os_get_file_size(const char *path)
  114. {
  115. struct stat path_stat;
  116. memset(&path_stat, 0, sizeof(path_stat));
  117. if (stat(path, &path_stat) == 0)
  118. {
  119. /* Stat returns size taken up by directory entry, so return 0 */
  120. if (S_ISDIR(path_stat.st_mode))
  121. return 0;
  122. return path_stat.st_size;
  123. }
  124. return 0;
  125. }
  126. int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date)
  127. {
  128. struct stat path_stat;
  129. char *name = NULL;
  130. size_t len = 0;
  131. int32_t err = MZ_INTERNAL_ERROR;
  132. memset(&path_stat, 0, sizeof(path_stat));
  133. if (strcmp(path, "-") != 0)
  134. {
  135. /* Not all systems allow stat'ing a file with / appended */
  136. len = strlen(path);
  137. name = (char *)malloc(len + 1);
  138. strncpy(name, path, len + 1);
  139. mz_path_remove_slash(name);
  140. if (stat(name, &path_stat) == 0)
  141. {
  142. if (modified_date != NULL)
  143. *modified_date = path_stat.st_mtime;
  144. if (accessed_date != NULL)
  145. *accessed_date = path_stat.st_atime;
  146. /* Creation date not supported */
  147. if (creation_date != NULL)
  148. *creation_date = 0;
  149. err = MZ_OK;
  150. }
  151. free(name);
  152. }
  153. return err;
  154. }
  155. int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date)
  156. {
  157. struct utimbuf ut;
  158. ut.actime = accessed_date;
  159. ut.modtime = modified_date;
  160. /* Creation date not supported */
  161. MZ_UNUSED(creation_date);
  162. if (utime(path, &ut) != 0)
  163. return MZ_INTERNAL_ERROR;
  164. return MZ_OK;
  165. }
  166. int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes)
  167. {
  168. struct stat path_stat;
  169. int32_t err = MZ_OK;
  170. memset(&path_stat, 0, sizeof(path_stat));
  171. if (lstat(path, &path_stat) == -1)
  172. err = MZ_INTERNAL_ERROR;
  173. *attributes = path_stat.st_mode;
  174. return err;
  175. }
  176. int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes)
  177. {
  178. int32_t err = MZ_OK;
  179. if (chmod(path, (mode_t)attributes) == -1)
  180. err = MZ_INTERNAL_ERROR;
  181. return err;
  182. }
  183. int32_t mz_os_make_dir(const char *path)
  184. {
  185. int32_t err = 0;
  186. err = mkdir(path, 0755);
  187. if (err != 0 && errno != EEXIST)
  188. return MZ_INTERNAL_ERROR;
  189. return MZ_OK;
  190. }
  191. DIR* mz_os_open_dir(const char *path)
  192. {
  193. return opendir(path);
  194. }
  195. struct dirent* mz_os_read_dir(DIR *dir)
  196. {
  197. if (dir == NULL)
  198. return NULL;
  199. return readdir(dir);
  200. }
  201. int32_t mz_os_close_dir(DIR *dir)
  202. {
  203. if (dir == NULL)
  204. return MZ_PARAM_ERROR;
  205. if (closedir(dir) == -1)
  206. return MZ_INTERNAL_ERROR;
  207. return MZ_OK;
  208. }
  209. int32_t mz_os_is_dir(const char *path)
  210. {
  211. struct stat path_stat;
  212. memset(&path_stat, 0, sizeof(path_stat));
  213. stat(path, &path_stat);
  214. if (S_ISDIR(path_stat.st_mode))
  215. return MZ_OK;
  216. return MZ_EXIST_ERROR;
  217. }
  218. int32_t mz_os_is_symlink(const char *path)
  219. {
  220. struct stat path_stat;
  221. memset(&path_stat, 0, sizeof(path_stat));
  222. lstat(path, &path_stat);
  223. if (S_ISLNK(path_stat.st_mode))
  224. return MZ_OK;
  225. return MZ_EXIST_ERROR;
  226. }
  227. int32_t mz_os_make_symlink(const char *path, const char *target_path)
  228. {
  229. if (symlink(target_path, path) != 0)
  230. return MZ_INTERNAL_ERROR;
  231. return MZ_OK;
  232. }
  233. int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path)
  234. {
  235. size_t length = 0;
  236. length = (size_t)readlink(path, target_path, max_target_path - 1);
  237. if (length == (size_t)-1)
  238. return MZ_EXIST_ERROR;
  239. target_path[length] = 0;
  240. return MZ_OK;
  241. }
  242. uint64_t mz_os_ms_time(void)
  243. {
  244. struct timespec ts;
  245. #if defined(__APPLE__)
  246. clock_serv_t cclock;
  247. mach_timespec_t mts;
  248. host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
  249. clock_get_time(cclock, &mts);
  250. mach_port_deallocate(mach_task_self(), cclock);
  251. ts.tv_sec = mts.tv_sec;
  252. ts.tv_nsec = mts.tv_nsec;
  253. #else
  254. clock_gettime(CLOCK_MONOTONIC, &ts);
  255. #endif
  256. return ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000);
  257. }