18 # include <sys/types.h>
19 # include <sys/stat.h>
22 #include "minishared.h"
25 # define USEWIN32IOAPI
29 uint32_t get_file_date(const char *path, uint32_t *dos_date)
35 WIN32_FIND_DATAA ff32;
37 find = FindFirstFileA(path, &ff32);
38 if (find != INVALID_HANDLE_VALUE)
40 FileTimeToLocalFileTime(&(ff32.ftLastWriteTime), &ftm_local);
41 FileTimeToDosDateTime(&ftm_local, ((LPWORD)dos_date) + 1, ((LPWORD)dos_date) + 0);
47 struct tm *filedate = NULL;
50 memset(&s, 0, sizeof(s));
52 if (strcmp(path, "-") != 0)
54 size_t len = strlen(path);
55 char *name = (char *)malloc(len + 1);
56 strncpy(name, path, len + 1);
58 if (name[len - 1] == '/')
61 /* Not all systems allow stat'ing a file with / appended */
62 if (stat(name, &s) == 0)
70 filedate = localtime(&tm_t);
71 *dos_date = tm_to_dosdate(filedate);
76 void change_file_date(const char *path, uint32_t dos_date)
80 FILETIME ftm, ftm_local, ftm_create, ftm_access, ftm_modified;
82 handle = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
83 if (handle != INVALID_HANDLE_VALUE)
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);
93 ut.actime = ut.modtime = dosdate_to_time_t(dos_date);
98 int invalid_date(const struct tm *ptm)
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
110 // Conversion without validation
111 void dosdate_to_raw_tm(uint64_t dos_date, struct tm *ptm)
113 uint64_t date = (uint64_t)(dos_date >> 16);
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));
124 int dosdate_to_tm(uint64_t dos_date, struct tm *ptm)
126 dosdate_to_raw_tm(dos_date, ptm);
128 if (invalid_date(ptm))
130 // Invalid date stored, so don't return it.
131 memset(ptm, 0, sizeof(struct tm));
137 time_t dosdate_to_time_t(uint64_t dos_date)
140 dosdate_to_raw_tm(dos_date, &ptm);
144 uint32_t tm_to_dosdate(const struct tm *ptm)
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.)
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;
163 if (invalid_date(ptm))
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));
170 int makedir(const char *newdir)
174 int len = (int)strlen(newdir);
179 buffer = (char*)malloc(len + 1);
182 printf("Error allocating memory\n");
186 strcpy(buffer, newdir);
188 if (buffer[len - 1] == '/')
191 if (MKDIR(buffer) == 0)
201 while (*p && *p != '\\' && *p != '/')
206 if ((MKDIR(buffer) == -1) && (errno == ENOENT))
208 printf("couldn't create directory %s (%d)\n", buffer, errno);
223 FILE *get_file_handle(const char *path)
227 wchar_t *pathWide = NULL;
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");
236 handle = fopen64(path, "rb");
242 int check_file_exists(const char *path)
244 FILE *handle = get_file_handle(path);
251 int is_large_file(const char *path)
256 handle = get_file_handle(path);
260 fseeko64(handle, 0, SEEK_END);
261 pos = ftello64(handle);
264 printf("file : %s is %lld bytes\n", path, pos);
266 return (pos >= UINT32_MAX);
269 void display_zpos64(uint64_t n, int size_char)
271 /* To avoid compatibility problem we do here the conversion */
272 char number[21] = { 0 };
275 int size_display_string = 19;
279 number[offset] = (char)((n % 10) + '0');
280 if (number[offset] != '0')
288 size_display_string -= pos_string;
289 while (size_char-- > size_display_string)
291 printf("%s", &number[pos_string]);