win32.c 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488
  1. /*
  2. win32/win32.c - Zip 3
  3. Copyright (c) 1990-2008 Info-ZIP. All rights reserved.
  4. See the accompanying file LICENSE, version 2007-Mar-4 or later
  5. (the contents of which are also included in zip.h) for terms of use.
  6. If, for some reason, all these files are missing, the Info-ZIP license
  7. also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
  8. */
  9. /*
  10. * WIN32 specific functions for ZIP.
  11. *
  12. * The WIN32 version of ZIP heavily relies on the MSDOS and OS2 versions,
  13. * since we have to do similar things to switch between NTFS, HPFS and FAT.
  14. */
  15. #include "../zip.h"
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <limits.h>
  19. #include <time.h>
  20. #include <ctype.h>
  21. #define WIN32_LEAN_AND_MEAN
  22. #include <windows.h>
  23. /* for LARGE_FILE_SUPPORT but may not be needed */
  24. #include <io.h>
  25. #ifdef __RSXNT__
  26. # include <alloca.h>
  27. # include "../win32/rsxntwin.h"
  28. #endif
  29. #include "../win32/win32zip.h"
  30. #define A_RONLY 0x01
  31. #define A_HIDDEN 0x02
  32. #define A_SYSTEM 0x04
  33. #define A_LABEL 0x08
  34. #define A_DIR 0x10
  35. #define A_ARCHIVE 0x20
  36. #define EAID 0x0009
  37. #if (defined(__MINGW32__) && !defined(USE_MINGW_GLOBBING))
  38. int _CRT_glob = 0; /* suppress command line globbing by C RTL */
  39. #endif
  40. #ifndef UTIL
  41. extern int noisy;
  42. #ifdef NT_TZBUG_WORKAROUND
  43. local int FSusesLocalTime(const char *path);
  44. #ifdef UNICODE_SUPPORt
  45. local int FSusesLocalTimeW(const wchar_t *path);
  46. #endif
  47. #endif
  48. #if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND))
  49. local int FileTime2utime(FILETIME *pft, time_t *ut);
  50. #endif
  51. #if (defined(NT_TZBUG_WORKAROUND) && defined(W32_STAT_BANDAID))
  52. local int VFatFileTime2utime(const FILETIME *pft, time_t *ut);
  53. #endif
  54. /* FAT / HPFS detection */
  55. int IsFileSystemOldFAT(char *dir)
  56. {
  57. static char lastDrive = '\0'; /* cached drive of last GetVolumeInformation call */
  58. static int lastDriveOldFAT = 0; /* cached OldFAT value of last GetVolumeInformation call */
  59. char root[4];
  60. DWORD vfnsize;
  61. DWORD vfsflags;
  62. /*
  63. * We separate FAT and HPFS+other file systems here.
  64. * I consider other systems to be similar to HPFS/NTFS, i.e.
  65. * support for long file names and being case sensitive to some extent.
  66. */
  67. strncpy(root, dir, 3);
  68. if ( isalpha((uch)root[0]) && (root[1] == ':') ) {
  69. root[0] = to_up(dir[0]);
  70. root[2] = '\\';
  71. root[3] = 0;
  72. }
  73. else {
  74. root[0] = '\\';
  75. root[1] = 0;
  76. }
  77. if (lastDrive == root[0]) {
  78. return lastDriveOldFAT;
  79. }
  80. if ( !GetVolumeInformation(root, NULL, 0,
  81. NULL, &vfnsize, &vfsflags,
  82. NULL, 0)) {
  83. fprintf(mesg, "zip diagnostic: GetVolumeInformation failed\n");
  84. return(FALSE);
  85. }
  86. lastDrive = root[0];
  87. lastDriveOldFAT = vfnsize <= 12;
  88. return lastDriveOldFAT;
  89. }
  90. #ifdef UNICODE_SUPPORT
  91. int IsFileSystemOldFATW(wchar_t *dir)
  92. {
  93. static wchar_t lastDrive = (wchar_t)'\0'; /* cached drive of last GetVolumeInformation call */
  94. static int lastDriveOldFAT = 0; /* cached OldFAT value of last GetVolumeInformation call */
  95. wchar_t root[4];
  96. DWORD vfnsize;
  97. DWORD vfsflags;
  98. /*
  99. * We separate FAT and HPFS+other file systems here.
  100. * I consider other systems to be similar to HPFS/NTFS, i.e.
  101. * support for long file names and being case sensitive to some extent.
  102. */
  103. wcsncpy(root, dir, 3);
  104. if ( iswalpha(root[0]) && (root[1] == (wchar_t)':') ) {
  105. root[0] = towupper(dir[0]);
  106. root[2] = (wchar_t)'\\';
  107. root[3] = 0;
  108. }
  109. else {
  110. root[0] = (wchar_t)'\\';
  111. root[1] = 0;
  112. }
  113. if (lastDrive == root[0]) {
  114. return lastDriveOldFAT;
  115. }
  116. if ( !GetVolumeInformationW(root, NULL, 0,
  117. NULL, &vfnsize, &vfsflags,
  118. NULL, 0)) {
  119. fprintf(mesg, "zip diagnostic: GetVolumeInformation failed\n");
  120. return(FALSE);
  121. }
  122. lastDrive = root[0];
  123. lastDriveOldFAT = vfnsize <= 12;
  124. return lastDriveOldFAT;
  125. }
  126. #endif
  127. /* access mode bits and time stamp */
  128. int GetFileMode(char *name)
  129. {
  130. DWORD dwAttr;
  131. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  132. char *ansi_name = (char *)alloca(strlen(name) + 1);
  133. OemToAnsi(name, ansi_name);
  134. name = ansi_name;
  135. #endif
  136. dwAttr = GetFileAttributes(name);
  137. if ( dwAttr == 0xFFFFFFFF ) {
  138. zipwarn("reading file attributes failed: ", name);
  139. /*
  140. fprintf(mesg, "zip diagnostic: GetFileAttributes failed");
  141. fflush();
  142. */
  143. return(0x20); /* the most likely, though why the error? security? */
  144. }
  145. return(
  146. (dwAttr&FILE_ATTRIBUTE_READONLY ? A_RONLY :0)
  147. | (dwAttr&FILE_ATTRIBUTE_HIDDEN ? A_HIDDEN :0)
  148. | (dwAttr&FILE_ATTRIBUTE_SYSTEM ? A_SYSTEM :0)
  149. | (dwAttr&FILE_ATTRIBUTE_DIRECTORY ? A_DIR :0)
  150. | (dwAttr&FILE_ATTRIBUTE_ARCHIVE ? A_ARCHIVE :0));
  151. }
  152. #ifdef UNICODE_SUPPORT
  153. int GetFileModeW(wchar_t *namew)
  154. {
  155. DWORD dwAttr;
  156. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  157. wchar_t *ansi_namew = (wchar_t *)alloca((wcslen(namew) + 1) * sizeof(wchar_t));
  158. CharToAnsiW(namew, ansi_namew);
  159. namew = ansi_namew;
  160. #endif
  161. dwAttr = GetFileAttributesW(namew);
  162. if ( dwAttr == 0xFFFFFFFF ) {
  163. char *name = wchar_to_local_string(namew);
  164. zipwarn("reading file attributes failed: ", name);
  165. free(name);
  166. return(0x20); /* the most likely, though why the error? security? */
  167. }
  168. return(
  169. (dwAttr&FILE_ATTRIBUTE_READONLY ? A_RONLY :0)
  170. | (dwAttr&FILE_ATTRIBUTE_HIDDEN ? A_HIDDEN :0)
  171. | (dwAttr&FILE_ATTRIBUTE_SYSTEM ? A_SYSTEM :0)
  172. | (dwAttr&FILE_ATTRIBUTE_DIRECTORY ? A_DIR :0)
  173. | (dwAttr&FILE_ATTRIBUTE_ARCHIVE ? A_ARCHIVE :0));
  174. }
  175. #endif
  176. int ClearArchiveBitW(wchar_t *namew)
  177. {
  178. DWORD dwAttr;
  179. dwAttr = GetFileAttributesW(namew);
  180. if ( dwAttr == 0xFFFFFFFF ) {
  181. fprintf(mesg, "zip diagnostic: GetFileAttributes failed\n");
  182. return(0);
  183. }
  184. if (!SetFileAttributesW(namew, (DWORD)(dwAttr & ~FILE_ATTRIBUTE_ARCHIVE))) {
  185. fprintf(mesg, "zip diagnostic: SetFileAttributes failed\n");
  186. perror("SetFileAttributes");
  187. return(0);
  188. }
  189. return(1);
  190. }
  191. int ClearArchiveBit(char *name)
  192. {
  193. DWORD dwAttr;
  194. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  195. char *ansi_name = (char *)alloca(strlen(name) + 1);
  196. OemToAnsi(name, ansi_name);
  197. name = ansi_name;
  198. #endif
  199. dwAttr = GetFileAttributes(name);
  200. if ( dwAttr == 0xFFFFFFFF ) {
  201. fprintf(mesg, "zip diagnostic: GetFileAttributes failed\n");
  202. return(0);
  203. }
  204. if (!SetFileAttributes(name, (DWORD)(dwAttr & ~FILE_ATTRIBUTE_ARCHIVE))) {
  205. fprintf(mesg, "zip diagnostic: SetFileAttributes failed\n");
  206. perror("SetFileAttributes");
  207. return(0);
  208. }
  209. return(1);
  210. }
  211. #ifdef NT_TZBUG_WORKAROUND
  212. local int FSusesLocalTime(const char *path)
  213. {
  214. char *tmp0;
  215. char rootPathName[4];
  216. char tmp1[MAX_PATH], tmp2[MAX_PATH];
  217. DWORD volSerNo, maxCompLen, fileSysFlags;
  218. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  219. char *ansi_path = (char *)alloca(strlen(path) + 1);
  220. OemToAnsi(path, ansi_path);
  221. path = ansi_path;
  222. #endif
  223. if (isalpha((uch)path[0]) && (path[1] == ':'))
  224. tmp0 = (char *)path;
  225. else
  226. {
  227. GetFullPathName(path, MAX_PATH, tmp1, &tmp0);
  228. tmp0 = &tmp1[0];
  229. }
  230. strncpy(rootPathName, tmp0, 3); /* Build the root path name, */
  231. rootPathName[3] = '\0'; /* e.g. "A:/" */
  232. GetVolumeInformation((LPCTSTR)rootPathName, (LPTSTR)tmp1, (DWORD)MAX_PATH,
  233. &volSerNo, &maxCompLen, &fileSysFlags,
  234. (LPTSTR)tmp2, (DWORD)MAX_PATH);
  235. /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in
  236. * local time!
  237. */
  238. return !strncmp(strupr(tmp2), "FAT", 3) ||
  239. !strncmp(tmp2, "VFAT", 4) ||
  240. !strncmp(tmp2, "HPFS", 4);
  241. } /* end function FSusesLocalTime() */
  242. # ifdef UNICODE_SUPPORT
  243. local int FSusesLocalTimeW(const wchar_t *path)
  244. {
  245. wchar_t *tmp0;
  246. wchar_t rootPathName[4];
  247. wchar_t tmp1[MAX_PATH], tmp2[MAX_PATH];
  248. DWORD volSerNo, maxCompLen, fileSysFlags;
  249. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  250. wchar_t *ansi_path = (wchar_t *)alloca((wcslen(path) + 1) * sizeof(wchar_t));
  251. CharToAnsiW(path, ansi_path);
  252. path = ansi_path;
  253. #endif
  254. if (iswalpha(path[0]) && (path[1] == (wchar_t)':'))
  255. tmp0 = (wchar_t *)path;
  256. else
  257. {
  258. GetFullPathNameW(path, MAX_PATH, tmp1, &tmp0);
  259. tmp0 = &tmp1[0];
  260. }
  261. wcsncpy(rootPathName, tmp0, 3); /* Build the root path name, */
  262. rootPathName[3] = (wchar_t)'\0'; /* e.g. "A:/" */
  263. GetVolumeInformationW(rootPathName, tmp1, (DWORD)MAX_PATH,
  264. &volSerNo, &maxCompLen, &fileSysFlags,
  265. tmp2, (DWORD)MAX_PATH);
  266. /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in
  267. * local time!
  268. */
  269. return !wcsncmp(_wcsupr(tmp2), L"FAT", 3) ||
  270. !wcsncmp(tmp2, L"VFAT", 4) ||
  271. !wcsncmp(tmp2, L"HPFS", 4);
  272. } /* end function FSusesLocalTimeW() */
  273. # endif
  274. #endif /* NT_TZBUG_WORKAROUND */
  275. #if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND))
  276. #if (defined(__GNUC__) || defined(ULONG_LONG_MAX))
  277. typedef long long LLONG64;
  278. typedef unsigned long long ULLNG64;
  279. #elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100))
  280. typedef __int64 LLONG64;
  281. typedef unsigned __int64 ULLNG64;
  282. #elif (defined(_MSC_VER) && (_MSC_VER >= 1100))
  283. typedef __int64 LLONG64;
  284. typedef unsigned __int64 ULLNG64;
  285. #elif (defined(__IBMC__) && (__IBMC__ >= 350))
  286. typedef __int64 LLONG64;
  287. typedef unsigned __int64 ULLNG64;
  288. #else
  289. # define NO_INT64
  290. #endif
  291. # define UNIX_TIME_ZERO_HI 0x019DB1DEUL
  292. # define UNIX_TIME_ZERO_LO 0xD53E8000UL
  293. # define NT_QUANTA_PER_UNIX 10000000L
  294. # define FTQUANTA_PER_UT_L (NT_QUANTA_PER_UNIX & 0xFFFF)
  295. # define FTQUANTA_PER_UT_H (NT_QUANTA_PER_UNIX >> 16)
  296. # define UNIX_TIME_UMAX_HI 0x0236485EUL
  297. # define UNIX_TIME_UMAX_LO 0xD4A5E980UL
  298. # define UNIX_TIME_SMIN_HI 0x0151669EUL
  299. # define UNIX_TIME_SMIN_LO 0xD53E8000UL
  300. # define UNIX_TIME_SMAX_HI 0x01E9FD1EUL
  301. # define UNIX_TIME_SMAX_LO 0xD4A5E980UL
  302. local int FileTime2utime(FILETIME *pft, time_t *ut)
  303. {
  304. #ifndef NO_INT64
  305. ULLNG64 NTtime;
  306. NTtime = ((ULLNG64)pft->dwLowDateTime +
  307. ((ULLNG64)pft->dwHighDateTime << 32));
  308. /* underflow and overflow handling */
  309. #ifdef CHECK_UTIME_SIGNED_UNSIGNED
  310. if ((time_t)0x80000000L < (time_t)0L)
  311. {
  312. if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO +
  313. ((ULLNG64)UNIX_TIME_SMIN_HI << 32))) {
  314. *ut = (time_t)LONG_MIN;
  315. return FALSE;
  316. }
  317. if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO +
  318. ((ULLNG64)UNIX_TIME_SMAX_HI << 32))) {
  319. *ut = (time_t)LONG_MAX;
  320. return FALSE;
  321. }
  322. }
  323. else
  324. #endif /* CHECK_UTIME_SIGNED_UNSIGNED */
  325. {
  326. if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO +
  327. ((ULLNG64)UNIX_TIME_ZERO_HI << 32))) {
  328. *ut = (time_t)0;
  329. return FALSE;
  330. }
  331. if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO +
  332. ((ULLNG64)UNIX_TIME_UMAX_HI << 32))) {
  333. *ut = (time_t)ULONG_MAX;
  334. return FALSE;
  335. }
  336. }
  337. NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO +
  338. ((ULLNG64)UNIX_TIME_ZERO_HI << 32));
  339. *ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX);
  340. return TRUE;
  341. #else /* NO_INT64 (64-bit integer arithmetics may not be supported) */
  342. /* nonzero if `y' is a leap year, else zero */
  343. # define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0)
  344. /* number of leap years from 1970 to `y' (not including `y' itself) */
  345. # define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400)
  346. /* daycount at the end of month[m-1] */
  347. static ZCONST ush ydays[] =
  348. { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
  349. time_t days;
  350. SYSTEMTIME w32tm;
  351. /* underflow and overflow handling */
  352. #ifdef CHECK_UTIME_SIGNED_UNSIGNED
  353. if ((time_t)0x80000000L < (time_t)0L)
  354. {
  355. if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
  356. ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
  357. (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
  358. *ut = (time_t)LONG_MIN;
  359. return FALSE;
  360. if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
  361. ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
  362. (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
  363. *ut = (time_t)LONG_MAX;
  364. return FALSE;
  365. }
  366. }
  367. else
  368. #endif /* CHECK_UTIME_SIGNED_UNSIGNED */
  369. {
  370. if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
  371. ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
  372. (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
  373. *ut = (time_t)0;
  374. return FALSE;
  375. }
  376. if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
  377. ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
  378. (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
  379. *ut = (time_t)ULONG_MAX;
  380. return FALSE;
  381. }
  382. }
  383. FileTimeToSystemTime(pft, &w32tm);
  384. /* set `days' to the number of days into the year */
  385. days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] +
  386. (w32tm.wMonth > 2 && leap (w32tm.wYear));
  387. /* now set `days' to the number of days since 1 Jan 1970 */
  388. days += 365 * (time_t)(w32tm.wYear - 1970) +
  389. (time_t)(nleap(w32tm.wYear));
  390. *ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour +
  391. (time_t)(60 * w32tm.wMinute + w32tm.wSecond));
  392. return TRUE;
  393. #endif /* ?NO_INT64 */
  394. } /* end function FileTime2utime() */
  395. #endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND */
  396. #if (defined(NT_TZBUG_WORKAROUND) && defined(W32_STAT_BANDAID))
  397. local int VFatFileTime2utime(const FILETIME *pft, time_t *ut)
  398. {
  399. FILETIME lft;
  400. SYSTEMTIME w32tm;
  401. struct tm ltm;
  402. FileTimeToLocalFileTime(pft, &lft);
  403. FileTimeToSystemTime(&lft, &w32tm);
  404. /* underflow and overflow handling */
  405. /* TODO: The range checks are not accurate, the actual limits may
  406. * be off by one daylight-saving-time shift (typically 1 hour),
  407. * depending on the current state of "is_dst".
  408. */
  409. #ifdef CHECK_UTIME_SIGNED_UNSIGNED
  410. if ((time_t)0x80000000L < (time_t)0L)
  411. {
  412. if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
  413. ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
  414. (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
  415. *ut = (time_t)LONG_MIN;
  416. return FALSE;
  417. if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
  418. ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
  419. (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
  420. *ut = (time_t)LONG_MAX;
  421. return FALSE;
  422. }
  423. }
  424. else
  425. #endif /* CHECK_UTIME_SIGNED_UNSIGNED */
  426. {
  427. if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
  428. ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
  429. (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
  430. *ut = (time_t)0;
  431. return FALSE;
  432. }
  433. if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
  434. ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
  435. (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
  436. *ut = (time_t)ULONG_MAX;
  437. return FALSE;
  438. }
  439. }
  440. ltm.tm_year = w32tm.wYear - 1900;
  441. ltm.tm_mon = w32tm.wMonth - 1;
  442. ltm.tm_mday = w32tm.wDay;
  443. ltm.tm_hour = w32tm.wHour;
  444. ltm.tm_min = w32tm.wMinute;
  445. ltm.tm_sec = w32tm.wSecond;
  446. ltm.tm_isdst = -1; /* let mktime determine if DST is in effect */
  447. *ut = mktime(&ltm);
  448. /* a cheap error check: mktime returns "(time_t)-1L" on conversion errors.
  449. * Normally, we would have to apply a consistency check because "-1"
  450. * could also be a valid time. But, it is quite unlikely to read back odd
  451. * time numbers from file systems that store time stamps in DOS format.
  452. * (The only known exception is creation time on VFAT partitions.)
  453. */
  454. return (*ut != (time_t)-1L);
  455. } /* end function VFatFileTime2utime() */
  456. #endif /* NT_TZBUG_WORKAROUND && W32_STAT_BANDAID */
  457. #if 0 /* Currently, this is not used at all */
  458. long GetTheFileTime(char *name, iztimes *z_ut)
  459. {
  460. HANDLE h;
  461. FILETIME Modft, Accft, Creft, lft;
  462. WORD dh, dl;
  463. #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
  464. char *ansi_name = (char *)alloca(strlen(name) + 1);
  465. OemToAnsi(name, ansi_name);
  466. name = ansi_name;
  467. #endif
  468. h = CreateFile(name, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
  469. NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
  470. if ( h != INVALID_HANDLE_VALUE ) {
  471. BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);
  472. CloseHandle(h);
  473. #ifdef USE_EF_UT_TIME
  474. if (ftOK && (z_ut != NULL)) {
  475. FileTime2utime(&Modft, &(z_ut->mtime));
  476. if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
  477. FileTime2utime(&Accft, &(z_ut->atime));
  478. else
  479. z_ut->atime = z_ut->mtime;
  480. if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
  481. FileTime2utime(&Creft, &(z_ut->ctime));
  482. else
  483. z_ut->ctime = z_ut->mtime;
  484. }
  485. #endif
  486. FileTimeToLocalFileTime(&ft, &lft);
  487. FileTimeToDosDateTime(&lft, &dh, &dl);
  488. return(dh<<16) | dl;
  489. }
  490. else
  491. return 0L;
  492. }
  493. #endif /* never */
  494. void ChangeNameForFAT(char *name)
  495. {
  496. char *src, *dst, *next, *ptr, *dot, *start;
  497. static char invalid[] = ":;,=+\"[]<>| \t";
  498. if ( isalpha((uch)name[0]) && (name[1] == ':') )
  499. start = name + 2;
  500. else
  501. start = name;
  502. src = dst = start;
  503. if ( (*src == '/') || (*src == '\\') )
  504. src++, dst++;
  505. while ( *src )
  506. {
  507. for ( next = src; *next && (*next != '/') && (*next != '\\'); next++ );
  508. for ( ptr = src, dot = NULL; ptr < next; ptr++ )
  509. if ( *ptr == '.' )
  510. {
  511. dot = ptr; /* remember last dot */
  512. *ptr = '_';
  513. }
  514. if ( dot == NULL )
  515. for ( ptr = src; ptr < next; ptr++ )
  516. if ( *ptr == '_' )
  517. dot = ptr; /* remember last _ as if it were a dot */
  518. if ( dot && (dot > src) &&
  519. ((next - dot <= 4) ||
  520. ((next - src > 8) && (dot - src > 3))) )
  521. {
  522. if ( dot )
  523. *dot = '.';
  524. for ( ptr = src; (ptr < dot) && ((ptr - src) < 8); ptr++ )
  525. *dst++ = *ptr;
  526. for ( ptr = dot; (ptr < next) && ((ptr - dot) < 4); ptr++ )
  527. *dst++ = *ptr;
  528. }
  529. else
  530. {
  531. if ( dot && (next - src == 1) )
  532. *dot = '.'; /* special case: "." as a path component */
  533. for ( ptr = src; (ptr < next) && ((ptr - src) < 8); ptr++ )
  534. *dst++ = *ptr;
  535. }
  536. *dst++ = *next; /* either '/' or 0 */
  537. if ( *next )
  538. {
  539. src = next + 1;
  540. if ( *src == 0 ) /* handle trailing '/' on dirs ! */
  541. *dst = 0;
  542. }
  543. else
  544. break;
  545. }
  546. for ( src = start; *src != 0; ++src )
  547. if ( (strchr(invalid, *src) != NULL) || (*src == ' ') )
  548. *src = '_';
  549. }
  550. char *GetLongPathEA(char *name)
  551. {
  552. return(NULL); /* volunteers ? */
  553. }
  554. #ifdef UNICODE_SUPPORT
  555. wchar_t *GetLongPathEAW(wchar_t *name)
  556. {
  557. return(NULL); /* volunteers ? */
  558. }
  559. #endif
  560. int IsFileNameValid(x)
  561. char *x;
  562. {
  563. WIN32_FIND_DATA fd;
  564. HANDLE h;
  565. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  566. char *ansi_name = (char *)alloca(strlen(x) + 1);
  567. OemToAnsi(x, ansi_name);
  568. x = ansi_name;
  569. #endif
  570. if ((h = FindFirstFile(x, &fd)) == INVALID_HANDLE_VALUE)
  571. return FALSE;
  572. FindClose(h);
  573. return TRUE;
  574. }
  575. char *getVolumeLabel(drive, vtime, vmode, vutim)
  576. int drive; /* drive name: 'A' .. 'Z' or '\0' for current drive */
  577. ulg *vtime; /* volume label creation time (DOS format) */
  578. ulg *vmode; /* volume label file mode */
  579. time_t *vutim;/* volume label creationtime (UNIX format) */
  580. /* If a volume label exists for the given drive, return its name and
  581. pretend to set its time and mode. The returned name is static data. */
  582. {
  583. char rootpath[4];
  584. static char vol[14];
  585. DWORD fnlen, flags;
  586. *vmode = A_ARCHIVE | A_LABEL; /* this is what msdos returns */
  587. *vtime = dostime(1980, 1, 1, 0, 0, 0); /* no true date info available */
  588. *vutim = dos2unixtime(*vtime);
  589. strcpy(rootpath, "x:\\");
  590. rootpath[0] = (char)drive;
  591. if (GetVolumeInformation(drive ? rootpath : NULL, vol, 13, NULL,
  592. &fnlen, &flags, NULL, 0))
  593. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  594. return (AnsiToOem(vol, vol), vol);
  595. #else
  596. return vol;
  597. #endif
  598. else
  599. return NULL;
  600. }
  601. #endif /* !UTIL */
  602. int ZipIsWinNT(void) /* returns TRUE if real NT, FALSE if Win95 or Win32s */
  603. {
  604. static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */
  605. if (g_PlatformId == 0xFFFFFFFF) {
  606. /* note: GetVersionEx() doesn't exist on WinNT 3.1 */
  607. if (GetVersion() < 0x80000000)
  608. g_PlatformId = TRUE;
  609. else
  610. g_PlatformId = FALSE;
  611. }
  612. return (int)g_PlatformId;
  613. }
  614. #ifndef UTIL
  615. #ifdef __WATCOMC__
  616. # include <io.h>
  617. # define _get_osfhandle _os_handle
  618. /* gaah -- Watcom's docs claim that _get_osfhandle exists, but it doesn't. */
  619. #endif
  620. #ifdef HAVE_FSEEKABLE
  621. /*
  622. * return TRUE if file is seekable
  623. */
  624. int fseekable(fp)
  625. FILE *fp;
  626. {
  627. return GetFileType((HANDLE)_get_osfhandle(fileno(fp))) == FILE_TYPE_DISK;
  628. }
  629. #endif /* HAVE_FSEEKABLE */
  630. #endif /* !UTIL */
  631. #if 0 /* seems to be never used; try it out... */
  632. char *StringLower(char *szArg)
  633. {
  634. char *szPtr;
  635. /* unsigned char *szPtr; */
  636. for ( szPtr = szArg; *szPtr; szPtr++ )
  637. *szPtr = lower[*szPtr];
  638. return szArg;
  639. }
  640. #endif /* never */
  641. #ifdef W32_STAT_BANDAID
  642. /* All currently known variants of WIN32 operating systems (Windows 95/98,
  643. * WinNT 3.x, 4.0, 5.0) have a nasty bug in the OS kernel concerning
  644. * conversions between UTC and local time: In the time conversion functions
  645. * of the Win32 API, the timezone offset (including seasonal daylight saving
  646. * shift) between UTC and local time evaluation is erratically based on the
  647. * current system time. The correct evaluation must determine the offset
  648. * value as it {was/is/will be} for the actual time to be converted.
  649. *
  650. * The C runtime lib's stat() returns utc time-stamps so that
  651. * localtime(timestamp) corresponds to the (potentially false) local
  652. * time shown by the OS' system programs (Explorer, command shell dir, etc.)
  653. *
  654. * For the NTFS file system (and other filesystems that store time-stamps
  655. * as UTC values), this results in st_mtime (, st_{c|a}time) fields which
  656. * are not stable but vary according to the seasonal change of "daylight
  657. * saving time in effect / not in effect".
  658. *
  659. * To achieve timestamp consistency of UTC (UT extra field) values in
  660. * Zip archives, the Info-ZIP programs require work-around code for
  661. * proper time handling in stat() (and other time handling routines).
  662. */
  663. /* stat() functions under Windows95 tend to fail for root directories. *
  664. * Watcom and Borland, at least, are affected by this bug. Watcom made *
  665. * a partial fix for 11.0 but still missed some cases. This substitute *
  666. * detects the case and fills in reasonable values. Otherwise we get *
  667. * effects like failure to extract to a root dir because it's not found. */
  668. #ifdef LARGE_FILE_SUPPORT /* E. Gordon 9/12/03 */
  669. int zstat_zipwin32(const char *path, z_stat *buf)
  670. #else
  671. int zstat_zipwin32(const char *path, struct stat *buf)
  672. #endif
  673. {
  674. # ifdef LARGE_FILE_SUPPORT /* E. Gordon 9/12/03 */
  675. if (!zstat(path, buf))
  676. # else
  677. if (!stat(path, buf))
  678. # endif
  679. {
  680. #ifdef NT_TZBUG_WORKAROUND
  681. /* stat was successful, now redo the time-stamp fetches */
  682. int fs_uses_loctime = FSusesLocalTime(path);
  683. HANDLE h;
  684. FILETIME Modft, Accft, Creft;
  685. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  686. char *ansi_path = (char *)alloca(strlen(path) + 1);
  687. OemToAnsi(path, ansi_path);
  688. # define Ansi_Path ansi_path
  689. #else
  690. # define Ansi_Path path
  691. #endif
  692. Trace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime));
  693. h = CreateFile(Ansi_Path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
  694. NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
  695. if (h != INVALID_HANDLE_VALUE) {
  696. BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);
  697. CloseHandle(h);
  698. if (ftOK) {
  699. if (!fs_uses_loctime) {
  700. /* On a filesystem that stores UTC timestamps, we refill
  701. * the time fields of the struct stat buffer by directly
  702. * using the UTC values as returned by the Win32
  703. * GetFileTime() API call.
  704. */
  705. FileTime2utime(&Modft, &(buf->st_mtime));
  706. if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
  707. FileTime2utime(&Accft, &(buf->st_atime));
  708. else
  709. buf->st_atime = buf->st_mtime;
  710. if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
  711. FileTime2utime(&Creft, &(buf->st_ctime));
  712. else
  713. buf->st_ctime = buf->st_mtime;
  714. Tracev((stdout,"NTFS, recalculated modtime %08lx\n",
  715. buf->st_mtime));
  716. } else {
  717. /* On VFAT and FAT-like filesystems, the FILETIME values
  718. * are converted back to the stable local time before
  719. * converting them to UTC unix time-stamps.
  720. */
  721. VFatFileTime2utime(&Modft, &(buf->st_mtime));
  722. if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
  723. VFatFileTime2utime(&Accft, &(buf->st_atime));
  724. else
  725. buf->st_atime = buf->st_mtime;
  726. if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
  727. VFatFileTime2utime(&Creft, &(buf->st_ctime));
  728. else
  729. buf->st_ctime = buf->st_mtime;
  730. Tracev((stdout, "VFAT, recalculated modtime %08lx\n",
  731. buf->st_mtime));
  732. }
  733. }
  734. }
  735. # undef Ansi_Path
  736. #endif /* NT_TZBUG_WORKAROUND */
  737. return 0;
  738. }
  739. #ifdef W32_STATROOT_FIX
  740. else
  741. {
  742. DWORD flags;
  743. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  744. char *ansi_path = (char *)alloca(strlen(path) + 1);
  745. OemToAnsi(path, ansi_path);
  746. # define Ansi_Path ansi_path
  747. #else
  748. # define Ansi_Path path
  749. #endif
  750. flags = GetFileAttributes(Ansi_Path);
  751. if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {
  752. Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n",
  753. path));
  754. #ifdef LARGE_FILE_SUPPORT /* E. Gordon 9/12/03 */
  755. memset(buf, 0, sizeof(z_stat));
  756. #else
  757. memset(buf, 0, sizeof(struct stat));
  758. #endif
  759. buf->st_atime = buf->st_ctime = buf->st_mtime =
  760. dos2unixtime(DOSTIME_MINIMUM);
  761. /* !!! you MUST NOT add a cast to the type of "st_mode" here;
  762. * !!! different compilers do not agree on the "st_mode" size!
  763. * !!! (And, some compiler may not declare the "mode_t" type
  764. * !!! identifier, so you cannot use it, either.)
  765. */
  766. buf->st_mode = S_IFDIR | S_IREAD |
  767. ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);
  768. return 0;
  769. } /* assumes: stat() won't fail on non-dirs without good reason */
  770. # undef Ansi_Path
  771. }
  772. #endif /* W32_STATROOT_FIX */
  773. return -1;
  774. }
  775. # ifdef UNICODE_SUPPORT
  776. int zstat_zipwin32w(const wchar_t *pathw, zw_stat *buf)
  777. {
  778. if (!zwstat(pathw, buf))
  779. {
  780. #ifdef NT_TZBUG_WORKAROUND
  781. /* stat was successful, now redo the time-stamp fetches */
  782. int fs_uses_loctime = FSusesLocalTimeW(pathw);
  783. HANDLE h;
  784. FILETIME Modft, Accft, Creft;
  785. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  786. char *ansi_path = (char *)alloca(strlen(pathw) + 1);
  787. OemToAnsi(path, ansi_path);
  788. # define Ansi_Path ansi_path
  789. #else
  790. # define Ansi_Path pathw
  791. #endif
  792. Trace((stdout, "stat(%s) finds modtime %08lx\n", pathw, buf->st_mtime));
  793. h = CreateFileW(Ansi_Path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
  794. NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
  795. if (h != INVALID_HANDLE_VALUE) {
  796. BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);
  797. CloseHandle(h);
  798. if (ftOK) {
  799. if (!fs_uses_loctime) {
  800. /* On a filesystem that stores UTC timestamps, we refill
  801. * the time fields of the struct stat buffer by directly
  802. * using the UTC values as returned by the Win32
  803. * GetFileTime() API call.
  804. */
  805. FileTime2utime(&Modft, &(buf->st_mtime));
  806. if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
  807. FileTime2utime(&Accft, &(buf->st_atime));
  808. else
  809. buf->st_atime = buf->st_mtime;
  810. if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
  811. FileTime2utime(&Creft, &(buf->st_ctime));
  812. else
  813. buf->st_ctime = buf->st_mtime;
  814. Tracev((stdout,"NTFS, recalculated modtime %08lx\n",
  815. buf->st_mtime));
  816. } else {
  817. /* On VFAT and FAT-like filesystems, the FILETIME values
  818. * are converted back to the stable local time before
  819. * converting them to UTC unix time-stamps.
  820. */
  821. VFatFileTime2utime(&Modft, &(buf->st_mtime));
  822. if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
  823. VFatFileTime2utime(&Accft, &(buf->st_atime));
  824. else
  825. buf->st_atime = buf->st_mtime;
  826. if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
  827. VFatFileTime2utime(&Creft, &(buf->st_ctime));
  828. else
  829. buf->st_ctime = buf->st_mtime;
  830. Tracev((stdout, "VFAT, recalculated modtime %08lx\n",
  831. buf->st_mtime));
  832. }
  833. }
  834. }
  835. # undef Ansi_Path
  836. #endif /* NT_TZBUG_WORKAROUND */
  837. return 0;
  838. }
  839. #ifdef W32_STATROOT_FIX
  840. else
  841. {
  842. DWORD flags;
  843. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  844. char *ansi_path = (char *)alloca(strlen(pathw) + 1);
  845. OemToAnsi(path, ansi_path);
  846. # define Ansi_Path ansi_path
  847. #else
  848. # define Ansi_Path pathw
  849. #endif
  850. flags = GetFileAttributesW(Ansi_Path);
  851. if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {
  852. Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n",
  853. pathw));
  854. #ifdef LARGE_FILE_SUPPORT /* E. Gordon 9/12/03 */
  855. memset(buf, 0, sizeof(z_stat));
  856. #else
  857. memset(buf, 0, sizeof(struct stat));
  858. #endif
  859. buf->st_atime = buf->st_ctime = buf->st_mtime =
  860. dos2unixtime(DOSTIME_MINIMUM);
  861. /* !!! you MUST NOT add a cast to the type of "st_mode" here;
  862. * !!! different compilers do not agree on the "st_mode" size!
  863. * !!! (And, some compiler may not declare the "mode_t" type
  864. * !!! identifier, so you cannot use it, either.)
  865. */
  866. buf->st_mode = S_IFDIR | S_IREAD |
  867. ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);
  868. return 0;
  869. } /* assumes: stat() won't fail on non-dirs without good reason */
  870. # undef Ansi_Path
  871. }
  872. #endif /* W32_STATROOT_FIX */
  873. return -1;
  874. }
  875. # endif
  876. #endif /* W32_STAT_BANDAID */
  877. #ifdef W32_USE_IZ_TIMEZONE
  878. #include "timezone.h"
  879. #define SECSPERMIN 60
  880. #define MINSPERHOUR 60
  881. #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
  882. static void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule);
  883. static void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule)
  884. {
  885. if (lpw32tm->wYear != 0) {
  886. ptrule->r_type = JULIAN_DAY;
  887. ptrule->r_day = ydays[lpw32tm->wMonth - 1] + lpw32tm->wDay;
  888. } else {
  889. ptrule->r_type = MONTH_NTH_DAY_OF_WEEK;
  890. ptrule->r_mon = lpw32tm->wMonth;
  891. ptrule->r_day = lpw32tm->wDayOfWeek;
  892. ptrule->r_week = lpw32tm->wDay;
  893. }
  894. ptrule->r_time = (long)lpw32tm->wHour * SECSPERHOUR +
  895. (long)(lpw32tm->wMinute * SECSPERMIN) +
  896. (long)lpw32tm->wSecond;
  897. }
  898. int GetPlatformLocalTimezone(register struct state * ZCONST sp,
  899. void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,
  900. ZCONST struct rule * ZCONST start,
  901. ZCONST struct rule * ZCONST end))
  902. {
  903. TIME_ZONE_INFORMATION tzinfo;
  904. DWORD res;
  905. /* read current timezone settings from registry if TZ envvar missing */
  906. res = GetTimeZoneInformation(&tzinfo);
  907. if (res != TIME_ZONE_ID_INVALID)
  908. {
  909. struct rule startrule, stoprule;
  910. conv_to_rule(&(tzinfo.StandardDate), &stoprule);
  911. conv_to_rule(&(tzinfo.DaylightDate), &startrule);
  912. sp->timecnt = 0;
  913. sp->ttis[0].tt_abbrind = 0;
  914. if ((sp->charcnt =
  915. WideCharToMultiByte(CP_ACP, 0, tzinfo.StandardName, -1,
  916. sp->chars, sizeof(sp->chars), NULL, NULL))
  917. == 0)
  918. sp->chars[sp->charcnt++] = '\0';
  919. sp->ttis[1].tt_abbrind = sp->charcnt;
  920. sp->charcnt +=
  921. WideCharToMultiByte(CP_ACP, 0, tzinfo.DaylightName, -1,
  922. sp->chars + sp->charcnt,
  923. sizeof(sp->chars) - sp->charcnt, NULL, NULL);
  924. if ((sp->charcnt - sp->ttis[1].tt_abbrind) == 0)
  925. sp->chars[sp->charcnt++] = '\0';
  926. sp->ttis[0].tt_gmtoff = - (tzinfo.Bias + tzinfo.StandardBias)
  927. * MINSPERHOUR;
  928. sp->ttis[1].tt_gmtoff = - (tzinfo.Bias + tzinfo.DaylightBias)
  929. * MINSPERHOUR;
  930. sp->ttis[0].tt_isdst = 0;
  931. sp->ttis[1].tt_isdst = 1;
  932. sp->typecnt = (startrule.r_mon == 0 && stoprule.r_mon == 0) ? 1 : 2;
  933. if (sp->typecnt > 1)
  934. (*fill_tzstate_from_rules)(sp, &startrule, &stoprule);
  935. return TRUE;
  936. }
  937. return FALSE;
  938. }
  939. #endif /* W32_USE_IZ_TIMEZONE */
  940. #ifndef WINDLL
  941. /* This replacement getch() function was originally created for Watcom C
  942. * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32
  943. * ports apply this replacement rather that their supplied getch() (or
  944. * alike) function. There are problems with unabsorbed LF characters left
  945. * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed.
  946. * (Under Win95, ENTER returns two(!!) characters: CR-LF.) This problem
  947. * does not appear when run on a WinNT console prompt!
  948. */
  949. /* Watcom 10.6's getch() does not handle Alt+<digit><digit><digit>. */
  950. /* Note that if PASSWD_FROM_STDIN is defined, the file containing */
  951. /* the password must have a carriage return after the word, not a */
  952. /* Unix-style newline (linefeed only). This discards linefeeds. */
  953. int getch_win32(void)
  954. {
  955. HANDLE stin;
  956. DWORD rc;
  957. unsigned char buf[2];
  958. int ret = -1;
  959. DWORD odemode = ~(DWORD)0;
  960. # ifdef PASSWD_FROM_STDIN
  961. stin = GetStdHandle(STD_INPUT_HANDLE);
  962. # else
  963. stin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
  964. FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  965. if (stin == INVALID_HANDLE_VALUE)
  966. return -1;
  967. # endif
  968. if (GetConsoleMode(stin, &odemode))
  969. SetConsoleMode(stin, ENABLE_PROCESSED_INPUT); /* raw except ^C noticed */
  970. if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
  971. ret = buf[0];
  972. /* when the user hits return we get CR LF. We discard the LF, not the CR,
  973. * because when we call this for the first time after a previous input
  974. * such as the one for "replace foo? [y]es, ..." the LF may still be in
  975. * the input stream before whatever the user types at our prompt. */
  976. if (ret == '\n')
  977. if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
  978. ret = buf[0];
  979. if (odemode != ~(DWORD)0)
  980. SetConsoleMode(stin, odemode);
  981. # ifndef PASSWD_FROM_STDIN
  982. CloseHandle(stin);
  983. # endif
  984. return ret;
  985. }
  986. /******************************/
  987. /* Function version_local() */
  988. /******************************/
  989. void version_local()
  990. {
  991. static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s.\n\n";
  992. #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__))
  993. char buf[80];
  994. #if (defined(_MSC_VER) && (_MSC_VER > 900))
  995. char buf2[80];
  996. #endif
  997. #endif
  998. /* Define the compiler name and version strings */
  999. #if defined(_MSC_VER) /* MSC == MSVC++, including the SDK compiler */
  1000. sprintf(buf, "Microsoft C %d.%02d ", _MSC_VER/100, _MSC_VER%100);
  1001. # define COMPILER_NAME1 buf
  1002. # if (_MSC_VER == 800)
  1003. # define COMPILER_NAME2 "(Visual C++ v1.1)"
  1004. # elif (_MSC_VER == 850)
  1005. # define COMPILER_NAME2 "(Windows NT v3.5 SDK)"
  1006. # elif (_MSC_VER == 900)
  1007. # define COMPILER_NAME2 "(Visual C++ v2.x)"
  1008. # elif (_MSC_VER > 900)
  1009. sprintf(buf2, "(Visual C++ v%d.%d)", _MSC_VER/100 - 6, _MSC_VER%100/10);
  1010. # define COMPILER_NAME2 buf2
  1011. # else
  1012. # define COMPILER_NAME2 "(bad version)"
  1013. # endif
  1014. #elif defined(__WATCOMC__)
  1015. # if (__WATCOMC__ % 10 > 0)
  1016. /* We do this silly test because __WATCOMC__ gives two digits for the */
  1017. /* minor version, but Watcom packaging prefers to show only one digit. */
  1018. sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100,
  1019. __WATCOMC__ % 100);
  1020. # else
  1021. sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100,
  1022. (__WATCOMC__ % 100) / 10);
  1023. # endif /* __WATCOMC__ % 10 > 0 */
  1024. # define COMPILER_NAME1 buf
  1025. # define COMPILER_NAME2 ""
  1026. #elif defined(__TURBOC__)
  1027. # ifdef __BORLANDC__
  1028. # define COMPILER_NAME1 "Borland C++"
  1029. # if (__BORLANDC__ == 0x0452) /* __BCPLUSPLUS__ = 0x0320 */
  1030. # define COMPILER_NAME2 " 4.0 or 4.02"
  1031. # elif (__BORLANDC__ == 0x0460) /* __BCPLUSPLUS__ = 0x0340 */
  1032. # define COMPILER_NAME2 " 4.5"
  1033. # elif (__BORLANDC__ == 0x0500) /* __TURBOC__ = 0x0500 */
  1034. # define COMPILER_NAME2 " 5.0"
  1035. # elif (__BORLANDC__ == 0x0520) /* __TURBOC__ = 0x0520 */
  1036. # define COMPILER_NAME2 " 5.2 (C++ Builder 1.0)"
  1037. # elif (__BORLANDC__ == 0x0530) /* __BCPLUSPLUS__ = 0x0530 */
  1038. # define COMPILER_NAME2 " 5.3 (C++ Builder 3.0)"
  1039. # elif (__BORLANDC__ == 0x0540) /* __BCPLUSPLUS__ = 0x0540 */
  1040. # define COMPILER_NAME2 " 5.4 (C++ Builder 4.0)"
  1041. # elif (__BORLANDC__ == 0x0550) /* __BCPLUSPLUS__ = 0x0550 */
  1042. # define COMPILER_NAME2 " 5.5 (C++ Builder 5.0)"
  1043. # elif (__BORLANDC__ == 0x0551) /* __BCPLUSPLUS__ = 0x0551 */
  1044. # define COMPILER_NAME2 " 5.5.1 (C++ Builder 5.0.1)"
  1045. # elif (__BORLANDC__ == 0x0560) /* __BCPLUSPLUS__ = 0x0560 */
  1046. # define COMPILER_NAME2 " 5.6 (C++ Builder 6)"
  1047. # else
  1048. # define COMPILER_NAME2 " later than 5.6"
  1049. # endif
  1050. # else /* !__BORLANDC__ */
  1051. # define COMPILER_NAME1 "Turbo C"
  1052. # if (__TURBOC__ >= 0x0400) /* Kevin: 3.0 -> 0x0401 */
  1053. # define COMPILER_NAME2 "++ 3.0 or later"
  1054. # elif (__TURBOC__ == 0x0295) /* [661] vfy'd by Kevin */
  1055. # define COMPILER_NAME2 "++ 1.0"
  1056. # endif
  1057. # endif /* __BORLANDC__ */
  1058. #elif defined(__GNUC__)
  1059. # ifdef __RSXNT__
  1060. # if (defined(__DJGPP__) && !defined(__EMX__))
  1061. sprintf(buf, "rsxnt(djgpp v%d.%02d) / gcc ",
  1062. __DJGPP__, __DJGPP_MINOR__);
  1063. # define COMPILER_NAME1 buf
  1064. # elif defined(__DJGPP__)
  1065. sprintf(buf, "rsxnt(emx+djgpp v%d.%02d) / gcc ",
  1066. __DJGPP__, __DJGPP_MINOR__);
  1067. # define COMPILER_NAME1 buf
  1068. # elif (defined(__GO32__) && !defined(__EMX__))
  1069. # define COMPILER_NAME1 "rsxnt(djgpp v1.x) / gcc "
  1070. # elif defined(__GO32__)
  1071. # define COMPILER_NAME1 "rsxnt(emx + djgpp v1.x) / gcc "
  1072. # elif defined(__EMX__)
  1073. # define COMPILER_NAME1 "rsxnt(emx)+gcc "
  1074. # else
  1075. # define COMPILER_NAME1 "rsxnt(unknown) / gcc "
  1076. # endif
  1077. # elif defined(__CYGWIN__)
  1078. # define COMPILER_NAME1 "Cygnus win32 / gcc "
  1079. # elif defined(__MINGW32__)
  1080. # define COMPILER_NAME1 "mingw32 / gcc "
  1081. # else
  1082. # define COMPILER_NAME1 "gcc "
  1083. # endif
  1084. # define COMPILER_NAME2 __VERSION__
  1085. #elif defined(__LCC__)
  1086. # define COMPILER_NAME1 "LCC-Win32"
  1087. # define COMPILER_NAME2 ""
  1088. #else
  1089. # define COMPILER_NAME1 "unknown compiler (SDK?)"
  1090. # define COMPILER_NAME2 ""
  1091. #endif
  1092. /* Define the compile date string */
  1093. #ifdef __DATE__
  1094. # define COMPILE_DATE " on " __DATE__
  1095. #else
  1096. # define COMPILE_DATE ""
  1097. #endif
  1098. printf(CompiledWith, COMPILER_NAME1, COMPILER_NAME2,
  1099. "\nWindows 9x / Windows NT", " (32-bit)", COMPILE_DATE);
  1100. return;
  1101. } /* end function version_local() */
  1102. #endif /* !WINDLL */
  1103. /* --------------------------------------------------- */
  1104. /* Large File Support
  1105. *
  1106. * Moved to Win32i64.c to avoid conflicts in same name functions
  1107. * in WiZ using UnZip and Zip libraries.
  1108. * 9/25/2003
  1109. */
  1110. /* --------------------------------------------------- */
  1111. /* Unicode Support for Win32
  1112. *
  1113. */
  1114. #ifdef UNICODE_SUPPORT
  1115. # if 0
  1116. /* get the wide command line and convert to argvw */
  1117. /* windows ignores argv and gets argvw separately */
  1118. zchar **get_wide_argv(argv)
  1119. char **argv;
  1120. {
  1121. int i;
  1122. int argc;
  1123. int size;
  1124. zchar **argvw = NULL;
  1125. zchar *commandline = NULL;
  1126. zchar **a = NULL;
  1127. commandline = GetCommandLineW();
  1128. a = CommandLineToArgvW(commandline, &argc);
  1129. if (a == NULL) {
  1130. /* failed */
  1131. ZIPERR(ZE_COMPERR, "get_wide_argv");
  1132. }
  1133. /* copy args so can use free_args() */
  1134. if ((argvw = (zchar **)malloc((argc + 1) * sizeof(zchar *))) == NULL) {
  1135. ZIPERR(ZE_MEM, "get_wide_argv");
  1136. }
  1137. for (i = 0; i < argc; i++) {
  1138. size = zstrlen(a[i]) + 1;
  1139. if ((argvw[i] = (zchar *)malloc(size * sizeof(zchar))) == NULL) {
  1140. ZIPERR(ZE_MEM, "get_wide_argv");
  1141. }
  1142. if ((argvw[i] = copy_zstring(a[i])) == NULL) {
  1143. ZIPERR(ZE_MEM, "get_wide_argv");
  1144. }
  1145. }
  1146. argvw[argc] = L'\0';
  1147. /* free original argvw */
  1148. LocalFree(a);
  1149. return argvw;
  1150. }
  1151. # endif
  1152. /* convert wide character string to multi-byte character string */
  1153. /* win32 version */
  1154. char *wide_to_local_string(wide_string)
  1155. zwchar *wide_string;
  1156. {
  1157. int i;
  1158. wchar_t wc;
  1159. int bytes_char;
  1160. int default_used;
  1161. int wsize = 0;
  1162. int max_bytes = 9;
  1163. char buf[9];
  1164. char *buffer = NULL;
  1165. char *local_string = NULL;
  1166. if (wide_string == NULL)
  1167. return NULL;
  1168. for (wsize = 0; wide_string[wsize]; wsize++) ;
  1169. if (max_bytes < MB_CUR_MAX)
  1170. max_bytes = MB_CUR_MAX;
  1171. if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) {
  1172. ZIPERR(ZE_MEM, "wide_to_local_string");
  1173. }
  1174. /* convert it */
  1175. buffer[0] = '\0';
  1176. for (i = 0; i < wsize; i++) {
  1177. if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) {
  1178. /* wchar_t probably 2 bytes */
  1179. /* could do surrogates if state_dependent and wctomb can do */
  1180. wc = zwchar_to_wchar_t_default_char;
  1181. } else {
  1182. wc = (wchar_t)wide_string[i];
  1183. }
  1184. /* Unter some vendor's C-RTL, the Wide-to-MultiByte conversion functions
  1185. * (like wctomb() et. al.) do not use the same codepage as the other
  1186. * string arguments I/O functions (fopen, mkdir, rmdir etc.).
  1187. * Therefore, we have to fall back to the underlying Win32-API call to
  1188. * achieve a consistent behaviour for all supported compiler environments.
  1189. * Failing RTLs are for example:
  1190. * Borland (locale uses OEM-CP as default, but I/O functions expect ANSI
  1191. * names)
  1192. * Watcom (only "C" locale, wctomb() always uses OEM CP)
  1193. * (in other words: all supported environments except the Microsoft RTLs)
  1194. */
  1195. bytes_char = WideCharToMultiByte(
  1196. CP_ACP, WC_COMPOSITECHECK,
  1197. &wc, 1,
  1198. (LPSTR)buf, sizeof(buf),
  1199. NULL, &default_used);
  1200. if (default_used)
  1201. bytes_char = -1;
  1202. if (unicode_escape_all) {
  1203. if (bytes_char == 1 && (uch)buf[0] <= 0x7f) {
  1204. /* ASCII */
  1205. strncat(buffer, buf, 1);
  1206. } else {
  1207. /* use escape for wide character */
  1208. char *e = wide_char_to_escape_string(wide_string[i]);
  1209. strcat(buffer, e);
  1210. free(e);
  1211. }
  1212. } else if (bytes_char > 0) {
  1213. /* multi-byte char */
  1214. strncat(buffer, buf, bytes_char);
  1215. } else {
  1216. /* no MB for this wide */
  1217. if (use_wide_to_mb_default) {
  1218. /* default character */
  1219. strcat(buffer, wide_to_mb_default_string);
  1220. } else {
  1221. /* use escape for wide character */
  1222. char *e = wide_char_to_escape_string(wide_string[i]);
  1223. strcat(buffer, e);
  1224. free(e);
  1225. }
  1226. }
  1227. }
  1228. if ((local_string = (char *)realloc(buffer, strlen(buffer) + 1)) == NULL) {
  1229. free(buffer);
  1230. ZIPERR(ZE_MEM, "wide_to_local_string");
  1231. }
  1232. return local_string;
  1233. }
  1234. /* convert multi-byte character string to wide character string */
  1235. /* win32 version */
  1236. zwchar *local_to_wide_string(local_string)
  1237. char *local_string;
  1238. {
  1239. int wsize;
  1240. wchar_t *wc_string;
  1241. zwchar *wide_string;
  1242. /* for now try to convert as string - fails if a bad char in string */
  1243. wsize = MultiByteToWideChar(CP_ACP, 0,
  1244. local_string, -1, NULL, 0);
  1245. if (wsize == (size_t)-1) {
  1246. /* could not convert */
  1247. return NULL;
  1248. }
  1249. /* convert it */
  1250. if ((wc_string = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t))) == NULL) {
  1251. ZIPERR(ZE_MEM, "local_to_wide_string");
  1252. }
  1253. wsize = MultiByteToWideChar(CP_ACP, 0,
  1254. local_string, -1,
  1255. wc_string, wsize + 1);
  1256. wc_string[wsize] = (wchar_t) 0;
  1257. /* in case wchar_t is not zwchar */
  1258. if ((wide_string = (zwchar *)malloc((wsize + 1) * sizeof(zwchar))) == NULL) {
  1259. free(wc_string);
  1260. ZIPERR(ZE_MEM, "local_to_wide_string");
  1261. }
  1262. for (wsize = 0; (wide_string[wsize] = (zwchar)wc_string[wsize]); wsize++) ;
  1263. wide_string[wsize] = (zwchar)0;
  1264. free(wc_string);
  1265. return wide_string;
  1266. }
  1267. #endif /* UNICODE_SUPPORT */
  1268. /*
  1269. # if defined(UNICODE_SUPPORT) || defined(WIN32_OEM)
  1270. */
  1271. /* convert oem to ansi character string */
  1272. char *oem_to_local_string(local_string, oem_string)
  1273. char *local_string;
  1274. char *oem_string;
  1275. {
  1276. /* convert OEM to ANSI character set */
  1277. OemToChar(oem_string, local_string);
  1278. return local_string;
  1279. }
  1280. /*
  1281. # endif
  1282. */
  1283. /*
  1284. #if defined(UNICODE_SUPPORT) || defined(WIN32_OEM)
  1285. */
  1286. /* convert local to oem character string */
  1287. char *local_to_oem_string(oem_string, local_string)
  1288. char *oem_string;
  1289. char *local_string;
  1290. {
  1291. /* convert to OEM display character set */
  1292. CharToOem(local_string, oem_string);
  1293. return oem_string;
  1294. }
  1295. /*
  1296. #endif
  1297. */