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