minishared.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <time.h>
  6. #include <errno.h>
  7. #include <fcntl.h>
  8. #include "zlib.h"
  9. #include "ioapi.h"
  10. #ifdef _WIN32
  11. # include <direct.h>
  12. # include <io.h>
  13. #else
  14. # include <unistd.h>
  15. # include <utime.h>
  16. # include <sys/types.h>
  17. # include <sys/stat.h>
  18. #endif
  19. #include "minishared.h"
  20. #ifdef _WIN32
  21. # define USEWIN32IOAPI
  22. # include "iowin32.h"
  23. #endif
  24. uint32_t get_file_date(const char *path, uint32_t *dos_date)
  25. {
  26. int ret = 0;
  27. #ifdef _WIN32
  28. FILETIME ftm_local;
  29. HANDLE find = NULL;
  30. WIN32_FIND_DATAA ff32;
  31. find = FindFirstFileA(path, &ff32);
  32. if (find != INVALID_HANDLE_VALUE)
  33. {
  34. FileTimeToLocalFileTime(&(ff32.ftLastWriteTime), &ftm_local);
  35. FileTimeToDosDateTime(&ftm_local, ((LPWORD)dos_date) + 1, ((LPWORD)dos_date) + 0);
  36. FindClose(find);
  37. ret = 1;
  38. }
  39. #else
  40. struct stat s;
  41. struct tm *filedate = NULL;
  42. time_t tm_t = 0;
  43. memset(&s, 0, sizeof(s));
  44. if (strcmp(path, "-") != 0)
  45. {
  46. size_t len = strlen(path);
  47. char *name = (char *)malloc(len + 1);
  48. strncpy(name, path, len + 1);
  49. name[len] = 0;
  50. if (name[len - 1] == '/')
  51. name[len - 1] = 0;
  52. /* Not all systems allow stat'ing a file with / appended */
  53. if (stat(name, &s) == 0)
  54. {
  55. tm_t = s.st_mtime;
  56. ret = 1;
  57. }
  58. free(name);
  59. }
  60. filedate = localtime(&tm_t);
  61. *dos_date = tm_to_dosdate(filedate);
  62. #endif
  63. return ret;
  64. }
  65. void change_file_date(const char *path, uint32_t dos_date)
  66. {
  67. #ifdef _WIN32
  68. HANDLE handle = NULL;
  69. FILETIME ftm, ftm_local, ftm_create, ftm_access, ftm_modified;
  70. handle = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  71. if (handle != INVALID_HANDLE_VALUE)
  72. {
  73. GetFileTime(handle, &ftm_create, &ftm_access, &ftm_modified);
  74. DosDateTimeToFileTime((WORD)(dos_date >> 16), (WORD)dos_date, &ftm_local);
  75. LocalFileTimeToFileTime(&ftm_local, &ftm);
  76. SetFileTime(handle, &ftm, &ftm_access, &ftm);
  77. CloseHandle(handle);
  78. }
  79. #else
  80. struct utimbuf ut;
  81. ut.actime = ut.modtime = dosdate_to_time_t(dos_date);
  82. utime(path, &ut);
  83. #endif
  84. }
  85. int invalid_date(const struct tm *ptm)
  86. {
  87. #define datevalue_in_range(min, max, value) ((min) <= (value) && (value) <= (max))
  88. return (!datevalue_in_range(0, 207, ptm->tm_year) ||
  89. !datevalue_in_range(0, 11, ptm->tm_mon) ||
  90. !datevalue_in_range(1, 31, ptm->tm_mday) ||
  91. !datevalue_in_range(0, 23, ptm->tm_hour) ||
  92. !datevalue_in_range(0, 59, ptm->tm_min) ||
  93. !datevalue_in_range(0, 59, ptm->tm_sec));
  94. #undef datevalue_in_range
  95. }
  96. // Conversion without validation
  97. void dosdate_to_raw_tm(uint64_t dos_date, struct tm *ptm)
  98. {
  99. uint64_t date = (uint64_t)(dos_date >> 16);
  100. ptm->tm_mday = (uint16_t)(date & 0x1f);
  101. ptm->tm_mon = (uint16_t)(((date & 0x1E0) / 0x20) - 1);
  102. ptm->tm_year = (uint16_t)(((date & 0x0FE00) / 0x0200) + 80);
  103. ptm->tm_hour = (uint16_t)((dos_date & 0xF800) / 0x800);
  104. ptm->tm_min = (uint16_t)((dos_date & 0x7E0) / 0x20);
  105. ptm->tm_sec = (uint16_t)(2 * (dos_date & 0x1f));
  106. ptm->tm_isdst = -1;
  107. }
  108. int dosdate_to_tm(uint64_t dos_date, struct tm *ptm)
  109. {
  110. dosdate_to_raw_tm(dos_date, ptm);
  111. if (invalid_date(ptm))
  112. {
  113. // Invalid date stored, so don't return it.
  114. memset(ptm, 0, sizeof(struct tm));
  115. return -1;
  116. }
  117. return 0;
  118. }
  119. time_t dosdate_to_time_t(uint64_t dos_date)
  120. {
  121. struct tm ptm;
  122. dosdate_to_raw_tm(dos_date, &ptm);
  123. return mktime(&ptm);
  124. }
  125. uint32_t tm_to_dosdate(const struct tm *ptm)
  126. {
  127. struct tm fixed_tm;
  128. /* Years supported:
  129. * [00, 79] (assumed to be between 2000 and 2079)
  130. * [80, 207] (assumed to be between 1980 and 2107, typical output of old
  131. software that does 'year-1900' to get a double digit year)
  132. * [1980, 2107] (due to the date format limitations, only years between 1980 and 2107 can be stored.)
  133. */
  134. memcpy(&fixed_tm, ptm, sizeof(struct tm));
  135. if (fixed_tm.tm_year >= 1980) /* range [1980, 2107] */
  136. fixed_tm.tm_year -= 1980;
  137. else if (fixed_tm.tm_year >= 80) /* range [80, 99] */
  138. fixed_tm.tm_year -= 80;
  139. else /* range [00, 79] */
  140. fixed_tm.tm_year += 20;
  141. if (invalid_date(ptm))
  142. return 0;
  143. return (uint32_t)(((fixed_tm.tm_mday) + (32 * (fixed_tm.tm_mon + 1)) + (512 * fixed_tm.tm_year)) << 16) |
  144. ((fixed_tm.tm_sec / 2) + (32 * fixed_tm.tm_min) + (2048 * (uint32_t)fixed_tm.tm_hour));
  145. }
  146. int makedir(const char *newdir)
  147. {
  148. char *buffer = NULL;
  149. char *p = NULL;
  150. int len = (int)strlen(newdir);
  151. if (len <= 0)
  152. return 0;
  153. buffer = (char*)malloc(len + 1);
  154. if (buffer == NULL)
  155. {
  156. printf("Error allocating memory\n");
  157. return -1;
  158. }
  159. strcpy(buffer, newdir);
  160. if (buffer[len - 1] == '/')
  161. buffer[len - 1] = 0;
  162. if (MKDIR(buffer) == 0)
  163. {
  164. free(buffer);
  165. return 1;
  166. }
  167. p = buffer + 1;
  168. while (1)
  169. {
  170. char hold;
  171. while (*p && *p != '\\' && *p != '/')
  172. p++;
  173. hold = *p;
  174. *p = 0;
  175. if ((MKDIR(buffer) == -1) && (errno == ENOENT))
  176. {
  177. printf("couldn't create directory %s (%d)\n", buffer, errno);
  178. free(buffer);
  179. return 0;
  180. }
  181. if (hold == 0)
  182. break;
  183. *p++ = hold;
  184. }
  185. free(buffer);
  186. return 1;
  187. }
  188. FILE *get_file_handle(const char *path)
  189. {
  190. FILE *handle = NULL;
  191. #if defined(WIN32)
  192. wchar_t *pathWide = NULL;
  193. int pathLength = 0;
  194. pathLength = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0) + 1;
  195. pathWide = (wchar_t*)calloc(pathLength, sizeof(wchar_t));
  196. MultiByteToWideChar(CP_UTF8, 0, path, -1, pathWide, pathLength);
  197. handle = _wfopen((const wchar_t*)pathWide, L"rb");
  198. free(pathWide);
  199. #else
  200. handle = fopen64(path, "rb");
  201. #endif
  202. return handle;
  203. }
  204. int check_file_exists(const char *path)
  205. {
  206. FILE *handle = get_file_handle(path);
  207. if (handle == NULL)
  208. return 0;
  209. fclose(handle);
  210. return 1;
  211. }
  212. int is_large_file(const char *path)
  213. {
  214. FILE* handle = NULL;
  215. uint64_t pos = 0;
  216. handle = get_file_handle(path);
  217. if (handle == NULL)
  218. return 0;
  219. fseeko64(handle, 0, SEEK_END);
  220. pos = ftello64(handle);
  221. fclose(handle);
  222. printf("file : %s is %lld bytes\n", path, pos);
  223. return (pos >= UINT32_MAX);
  224. }
  225. void display_zpos64(uint64_t n, int size_char)
  226. {
  227. /* To avoid compatibility problem we do here the conversion */
  228. char number[21] = { 0 };
  229. int offset = 19;
  230. int pos_string = 19;
  231. int size_display_string = 19;
  232. while (1)
  233. {
  234. number[offset] = (char)((n % 10) + '0');
  235. if (number[offset] != '0')
  236. pos_string = offset;
  237. n /= 10;
  238. if (offset == 0)
  239. break;
  240. offset--;
  241. }
  242. size_display_string -= pos_string;
  243. while (size_char-- > size_display_string)
  244. printf(" ");
  245. printf("%s", &number[pos_string]);
  246. }