win32zip.c 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980
  1. /*
  2. win32/win32zip.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. #ifndef UTIL /* this file contains nothing used by UTIL */
  10. #include "../zip.h"
  11. #include <ctype.h>
  12. #if !defined(__EMX__) && !defined(__CYGWIN__)
  13. #include <direct.h> /* for rmdir() */
  14. #endif
  15. #include <time.h>
  16. #ifndef __BORLANDC__
  17. #include <sys/utime.h>
  18. #else
  19. #include <utime.h>
  20. #endif
  21. #define WIN32_LEAN_AND_MEAN
  22. #include <windows.h> /* for findfirst/findnext stuff */
  23. #ifdef __RSXNT__
  24. # include "../win32/rsxntwin.h"
  25. #endif
  26. #include <io.h>
  27. #define PAD 0
  28. #define PATH_END '/'
  29. #define HIDD_SYS_BITS (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)
  30. #ifdef UNICODE_SUPPORT
  31. typedef struct zdirscanw {
  32. HANDLE d_hFindFile;
  33. int d_first;
  34. WIN32_FIND_DATAW d_fdw;
  35. } zDIRSCANW;
  36. #endif
  37. typedef struct zdirscan {
  38. HANDLE d_hFindFile;
  39. int d_first;
  40. WIN32_FIND_DATA d_fd;
  41. } zDIRSCAN;
  42. #define INVALID_WIN32_FILE_ATTRIBS ~0
  43. #ifdef UNICODE_SUPPORT
  44. #define GetDirAttribsW(d) ((d)->d_fdw.dwFileAttributes)
  45. #endif
  46. #define GetDirAttribs(d) ((d)->d_fd.dwFileAttributes)
  47. #include "../win32/win32zip.h"
  48. #include "../win32/nt.h"
  49. /* Local functions */
  50. local zDIRSCAN * OpenDirScan OF((ZCONST char *n));
  51. local struct zdirscan * GetNextDirEntry OF((zDIRSCAN *d));
  52. local void CloseDirScan OF((zDIRSCAN *d));
  53. #ifdef UNICODE_SUPPORT
  54. local zDIRSCANW * OpenDirScanW OF((ZCONST wchar_t *wn));
  55. local struct zdirscanw * GetNextDirEntryW OF((zDIRSCANW *dw));
  56. local void CloseDirScanW OF((zDIRSCANW *dw));
  57. #endif
  58. local char *readd OF((zDIRSCAN *));
  59. #ifdef UNICODE_SUPPORT
  60. local wchar_t *readdw OF((zDIRSCANW *));
  61. #endif
  62. local int wild_recurse OF((char *, char *));
  63. #ifdef UNICODE_SUPPORT
  64. local int wild_recursew OF((wchar_t *, wchar_t *));
  65. #endif
  66. #ifdef NTSD_EAS
  67. local void GetSD OF((char *path, char **bufptr, ush *size,
  68. char **cbufptr, ush *csize));
  69. #endif
  70. #ifdef USE_EF_UT_TIME
  71. local int GetExtraTime OF((struct zlist far *z, iztimes *z_utim));
  72. #endif
  73. local int procname_win32 OF((char *n, int caseflag, DWORD attribs));
  74. #ifdef UNICODE_SUPPORT
  75. local int procname_win32w OF((wchar_t *n, int caseflag, DWORD attribs));
  76. #endif
  77. /* Module level variables */
  78. extern char *label /* = NULL */ ; /* defined in fileio.c */
  79. local ulg label_time = 0;
  80. local ulg label_mode = 0;
  81. local time_t label_utim = 0;
  82. /* Module level constants */
  83. local ZCONST char wild_match_all[] = "*.*";
  84. #ifdef UNICODE_SUPPORT
  85. local zDIRSCANW *OpenDirScanW(nw)
  86. ZCONST wchar_t *nw; /* directory to open */
  87. /* Start searching for files in the MSDOS directory n */
  88. {
  89. zDIRSCANW *dw; /* malloc'd return value */
  90. wchar_t *pw; /* malloc'd temporary string */
  91. wchar_t *qw;
  92. size_t i;
  93. if ((dw = (zDIRSCANW *)malloc(sizeof(zDIRSCANW))) == NULL) {
  94. return NULL;
  95. }
  96. if ((pw = (wchar_t *)malloc(wcslen(nw) * sizeof(wchar_t) +
  97. (2 + sizeof(wild_match_all)) * sizeof(wchar_t))) == NULL) {
  98. if (dw != NULL) free((zvoid *)dw);
  99. return NULL;
  100. }
  101. wcscpy(pw, nw);
  102. qw = pw + wcslen(pw);
  103. if ((qw - pw) > 0 && wcschr(pw, (wchar_t)':') == (qw - 1))
  104. *qw++ = (wchar_t)'.';
  105. if ((qw - pw) > 0 && wcschr(pw, (wchar_t)'/') != (qw - 1))
  106. *qw++ = (wchar_t)'/';
  107. for (i = 0; i < strlen(wild_match_all); i++) {
  108. qw[i] = (wchar_t)wild_match_all[i];
  109. }
  110. qw[i] = (wchar_t)'\0';
  111. dw->d_hFindFile = FindFirstFileW(pw, &dw->d_fdw);
  112. free((zvoid *)pw);
  113. if (dw->d_hFindFile == INVALID_HANDLE_VALUE)
  114. {
  115. free((zvoid *)dw);
  116. return NULL;
  117. }
  118. dw->d_first = 1;
  119. return dw;
  120. }
  121. #endif
  122. local zDIRSCAN *OpenDirScan(n)
  123. ZCONST char *n; /* directory to open */
  124. /* Start searching for files in the MSDOS directory n */
  125. {
  126. zDIRSCAN *d; /* malloc'd return value */
  127. char *p; /* malloc'd temporary string */
  128. char *q;
  129. if ((d = (zDIRSCAN *)malloc(sizeof(zDIRSCAN))) == NULL ||
  130. (p = malloc(strlen(n) + (2 + sizeof(wild_match_all)))) == NULL) {
  131. if (d != NULL) free((zvoid *)d);
  132. return NULL;
  133. }
  134. strcpy(p, n);
  135. q = p + strlen(p);
  136. if ((q - p) > 0 && MBSRCHR(p, ':') == (q - 1))
  137. *q++ = '.';
  138. if ((q - p) > 0 && MBSRCHR(p, '/') != (q - 1))
  139. *q++ = '/';
  140. strcpy(q, wild_match_all);
  141. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  142. OemToAnsi(p, p);
  143. #endif
  144. d->d_hFindFile = FindFirstFile(p, &d->d_fd);
  145. free((zvoid *)p);
  146. if (d->d_hFindFile == INVALID_HANDLE_VALUE)
  147. {
  148. free((zvoid *)d);
  149. return NULL;
  150. }
  151. d->d_first = 1;
  152. return d;
  153. }
  154. #ifdef UNICODE_SUPPORT
  155. local struct zdirscanw *GetNextDirEntryW(dw)
  156. zDIRSCANW *dw; /* directory stream to read from */
  157. /* Return pointer to first or next directory entry, or NULL if end. */
  158. {
  159. if (dw->d_first)
  160. dw->d_first = 0;
  161. else
  162. {
  163. if (!FindNextFileW(dw->d_hFindFile, &dw->d_fdw))
  164. return NULL;
  165. }
  166. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  167. CharToOemW(dw->d_fdw.cFileName, dw->d_fdw.cFileName);
  168. #endif
  169. return (struct zdirscanw *)dw;
  170. }
  171. #endif
  172. local struct zdirscan *GetNextDirEntry(d)
  173. zDIRSCAN *d; /* directory stream to read from */
  174. /* Return pointer to first or next directory entry, or NULL if end. */
  175. {
  176. if (d->d_first)
  177. d->d_first = 0;
  178. else
  179. {
  180. if (!FindNextFile(d->d_hFindFile, &d->d_fd))
  181. return NULL;
  182. }
  183. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  184. AnsiToOem(d->d_fd.cFileName, d->d_fd.cFileName);
  185. #endif
  186. return (struct zdirscan *)d;
  187. }
  188. local void CloseDirScan(d)
  189. zDIRSCAN *d; /* directory stream to close */
  190. {
  191. FindClose(d->d_hFindFile);
  192. free((zvoid *)d);
  193. }
  194. #ifdef UNICODE_SUPPORT
  195. local void CloseDirScanW(dw)
  196. zDIRSCANW *dw; /* directory stream to close */
  197. {
  198. FindClose(dw->d_hFindFile);
  199. free((zvoid *)dw);
  200. }
  201. #endif
  202. #ifdef UNICODE_SUPPORT
  203. local wchar_t *readdw(dw)
  204. zDIRSCANW *dw; /* directory stream to read from */
  205. /* Return a pointer to the next name in the directory stream dw, or NULL if
  206. no more entries or an error occurs. */
  207. {
  208. struct zdirscanw *ew;
  209. do
  210. ew = GetNextDirEntryW(dw);
  211. while (ew &&
  212. ((!hidden_files && ew->d_fdw.dwFileAttributes & HIDD_SYS_BITS) ||
  213. (only_archive_set &&
  214. !(ew->d_fdw.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) &&
  215. !(ew->d_fdw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))));
  216. if (ew == NULL)
  217. return (wchar_t *) NULL;
  218. return ew->d_fdw.cFileName;
  219. }
  220. #endif
  221. local char *readd(d)
  222. zDIRSCAN *d; /* directory stream to read from */
  223. /* Return a pointer to the next name in the directory stream d, or NULL if
  224. no more entries or an error occurs. */
  225. {
  226. struct zdirscan *e;
  227. do
  228. e = GetNextDirEntry(d);
  229. while (e &&
  230. ((!hidden_files && e->d_fd.dwFileAttributes & HIDD_SYS_BITS) ||
  231. (only_archive_set &&
  232. !(e->d_fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) &&
  233. !(e->d_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))));
  234. /* When a wide character that is not supported by the current character
  235. set is found, FindFirstFile and FindNextFile return a "?" in that spot.
  236. A question mark is illegal in file names, so this flags that something
  237. needs to be done. It seems the fix is to use the 8.3 name in
  238. this case, as that allows directory scans to continue.
  239. */
  240. if (e == NULL)
  241. return (char *) NULL;
  242. if (strchr(e->d_fd.cFileName, '?') && e->d_fd.cAlternateFileName) {
  243. /* Have '?' in name, assume wide character we can't handle is in
  244. the name and use short name if there is one.
  245. */
  246. return e->d_fd.cAlternateFileName;
  247. }
  248. return e->d_fd.cFileName;
  249. }
  250. #if 0
  251. /* scan for the file in p and return Windows long name */
  252. char *get_win32_longpath(p, n)
  253. char *p; /* path to get short name path for */
  254. char **n; /* pointer to name in returned path */
  255. {
  256. char *q; /* return string */
  257. char *c;
  258. int is_dir = 0;
  259. char *f;
  260. char *fp;
  261. int nr;
  262. int fplen;
  263. int fplen2;
  264. HANDLE d_hFindFile;
  265. WIN32_FIND_DATA d_fd;
  266. int slashes = 0;
  267. int returnslashes = 0;
  268. if (p == NULL)
  269. return NULL;
  270. /* count path components */
  271. for (f = p; *f; f++) {
  272. if (*f == '/' || *f == '\\') {
  273. slashes++;
  274. }
  275. }
  276. /* Ignore trailing slash */
  277. if (*p && (*(f - 1) == '/' || *(f - 1) == '\\'))
  278. slashes--;
  279. /* get the length of the full path */
  280. fplen = GetFullPathName(p, 0, NULL, NULL);
  281. if ((fp = malloc(fplen + 1)) == NULL) {
  282. return NULL;
  283. }
  284. /* get full path */
  285. fplen2 = GetFullPathName(p, fplen, fp, &f);
  286. if (fplen2 > fplen) {
  287. /* something changed */
  288. free(fp);
  289. return NULL;
  290. }
  291. c = fp + strlen(fp) - 1;
  292. if (*c == '\\' || *c == '/') {
  293. is_dir = 1;
  294. *c = '\0';
  295. }
  296. d_hFindFile = FindFirstFile(fp, &d_fd);
  297. free(fp);
  298. if (d_hFindFile == INVALID_HANDLE_VALUE)
  299. {
  300. return NULL;
  301. }
  302. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  303. AnsiToOem(d->d_fd.cFileName, d->d_fd.cFileName);
  304. #endif
  305. FindClose(d_hFindFile);
  306. if (d_fd.cFileName == NULL) {
  307. return NULL;
  308. }
  309. /* get the length of the full path */
  310. fplen = GetFullPathName(d_fd.cFileName, 0, NULL, NULL);
  311. if ((fp = malloc(fplen + 1)) == NULL) {
  312. return NULL;
  313. }
  314. /* get full path */
  315. fplen2 = GetFullPathName(d_fd.cFileName, fplen, fp, &f);
  316. if (fplen2 > fplen) {
  317. /* something changed */
  318. free(fp);
  319. return NULL;
  320. }
  321. /* characters from end to start of last component */
  322. nr = 0;
  323. /* find start of relative path we came in with */
  324. for (f = fp + strlen(fp); f != fp; f--) {
  325. if (*f == ':')
  326. break;
  327. if (*f == '/' || *f == '\\') {
  328. returnslashes++;
  329. /* convert \ to / */
  330. *f = '/';
  331. if (nr == 0)
  332. /* first slash from end */
  333. nr = strlen(fp) - (f - fp);
  334. if (returnslashes > slashes)
  335. break;
  336. }
  337. if (*f == '\\' && *(f + 1) == '\\')
  338. break;
  339. }
  340. if (f != fp)
  341. /* on slash in middle */
  342. f++;
  343. if ((q = malloc(strlen(f) + 2)) == NULL) {
  344. return NULL;
  345. }
  346. strcpy(q, f);
  347. *n = q + (strlen(q) - nr + 1);
  348. if (is_dir) {
  349. strcat(q, "/");
  350. }
  351. free(fp);
  352. return q;
  353. }
  354. #endif
  355. #if 0
  356. /* scan for the file in p and return Windows UTF-8 name */
  357. char *get_win32_utf8path(p)
  358. char *p; /* path to get utf-8 name for */
  359. {
  360. char *q; /* return string */
  361. char *r = NULL;
  362. int is_dir = 0;
  363. char *f;
  364. char *fcp;
  365. char *fp;
  366. wchar_t *qw;
  367. char *lastc = '\0';
  368. int fplen;
  369. int fplen2;
  370. int ulen;
  371. int ulenw;
  372. HANDLE d_hFindFile;
  373. WIN32_FIND_DATAW d_fd;
  374. int pathslashes = 0;
  375. int componentslashes = 0;
  376. int slashes = 0;
  377. if (p == NULL)
  378. return NULL;
  379. /* count path components */
  380. for (f = p; *f; PREINCSTR(f)) {
  381. if (*f == '/' || *f == '\\') {
  382. slashes++;
  383. }
  384. lastc = f;
  385. }
  386. /* do not count trailing / */
  387. if (*lastc == '/' || *lastc == '\\') {
  388. is_dir = 1;
  389. slashes--;
  390. }
  391. /* Get the short path (as a bad long path could cause FindFirstFile to fail) */
  392. /* get the length of the short path */
  393. fplen = GetShortPathName(p, NULL, 0);
  394. if ((fp = malloc(fplen + 1)) == NULL) {
  395. return NULL;
  396. }
  397. /* get short path */
  398. fplen2 = GetShortPathName(p, fp, fplen);
  399. if (fplen2 > fplen) {
  400. /* something changed */
  401. free(fp);
  402. return NULL;
  403. }
  404. for (pathslashes = 0; pathslashes <= slashes; pathslashes++)
  405. {
  406. /* get component path */
  407. if ((fcp = malloc(fplen + 1)) == NULL) {
  408. return NULL;
  409. }
  410. strcpy(fcp, fp);
  411. componentslashes = 0;
  412. for (f = fcp; *f; PREINCSTR(f)) {
  413. if (*f == '/' || *f == '\\') {
  414. componentslashes++;
  415. if (componentslashes > pathslashes)
  416. break;
  417. }
  418. lastc = f;
  419. }
  420. *f = '\0';
  421. /* Get information for the file, including wide path */
  422. /* get length */
  423. ulenw = MultiByteToWideChar(
  424. CP_ACP, /* ANSI code page */
  425. 0, /* flags for character-type options */
  426. fcp, /* string to convert */
  427. -1, /* string length (-1 = NULL terminated) */
  428. NULL, /* buffer */
  429. 0 ); /* buffer length (0 = return length) */
  430. if (ulenw == 0) {
  431. /* failed */
  432. free(fcp);
  433. free(fp);
  434. return NULL;
  435. }
  436. ulenw++;
  437. /* get length in bytes */
  438. ulen = sizeof(wchar_t) * (ulenw + 1);
  439. if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) {
  440. free(fcp);
  441. free(fp);
  442. return NULL;
  443. }
  444. /* convert multibyte to wide */
  445. ulen = MultiByteToWideChar(
  446. CP_ACP, /* ANSI code page */
  447. 0, /* flags for character-type options */
  448. fcp, /* string to convert */
  449. -1, /* string length (-1 = NULL terminated) */
  450. qw, /* buffer */
  451. ulenw); /* buffer length (0 = return length) */
  452. if (ulen == 0) {
  453. /* failed */
  454. free(qw);
  455. free(fcp);
  456. free(fp);
  457. return 0;
  458. }
  459. d_hFindFile = FindFirstFileW(qw, &d_fd);
  460. /* If this Win32 platform does not support Unicode wide paths
  461. this returns INVALID_HANDLE_VALUE and the OS error is
  462. "No such file or directory". We return NULL and go with
  463. the UTF-8 version of z->iname in f->uname.
  464. */
  465. free(qw);
  466. free(fcp);
  467. FindClose(d_hFindFile);
  468. if (d_hFindFile == INVALID_HANDLE_VALUE)
  469. {
  470. return NULL;
  471. }
  472. /* Get buffer length */
  473. ulen = WideCharToMultiByte(
  474. CP_UTF8, /* UTF-8 code page */
  475. 0, /* flags */
  476. d_fd.cFileName, /* string to convert */
  477. -1, /* input chars (-1 = NULL terminated) */
  478. NULL, /* buffer */
  479. 0, /* size of buffer (0 = return needed size) */
  480. NULL, /* default char */
  481. NULL); /* used default char */
  482. if (ulen == 0) {
  483. /* failed */
  484. return NULL;
  485. }
  486. ulen += 2;
  487. if ((q = malloc(ulen + 1)) == NULL) {
  488. return NULL;
  489. }
  490. /* Convert the Unicode string to UTF-8 */
  491. if ((ulen = WideCharToMultiByte(
  492. CP_UTF8, /* UTF-8 code page */
  493. 0, /* flags */
  494. d_fd.cFileName, /* string to convert */
  495. -1, /* input chars (-1 = NULL terminated) */
  496. q, /* buffer */
  497. ulen, /* size of buffer (0 = return needed size) */
  498. NULL, /* default char */
  499. NULL)) == 0) /* used default char */
  500. {
  501. free(fp);
  502. free(q);
  503. return NULL;
  504. }
  505. if (r == NULL) {
  506. /* first one */
  507. r = q;
  508. } else {
  509. if ((r = realloc(r, strlen(r) + strlen(q) + 3)) == NULL) {
  510. free(fp);
  511. free(q);
  512. return NULL;
  513. }
  514. strcat(r, "/");
  515. strcat(r, q);
  516. free(q);
  517. }
  518. }
  519. free(fp);
  520. if (is_dir) {
  521. strcat(r, "/");
  522. }
  523. return r;
  524. }
  525. #endif
  526. #define ONENAMELEN 255
  527. /* whole is a pathname with wildcards, wildtail points somewhere in the */
  528. /* middle of it. All wildcards to be expanded must come AFTER wildtail. */
  529. #ifdef UNICODE_SUPPORT
  530. wchar_t *local_to_wchar_string(local_string)
  531. char *local_string; /* path to get utf-8 name for */
  532. {
  533. wchar_t *qw;
  534. int ulen;
  535. int ulenw;
  536. if (local_string == NULL)
  537. return NULL;
  538. /* get length */
  539. ulenw = MultiByteToWideChar(
  540. CP_ACP, /* ANSI code page */
  541. 0, /* flags for character-type options */
  542. local_string, /* string to convert */
  543. -1, /* string length (-1 = NULL terminated) */
  544. NULL, /* buffer */
  545. 0 ); /* buffer length (0 = return length) */
  546. if (ulenw == 0) {
  547. /* failed */
  548. return NULL;
  549. }
  550. ulenw++;
  551. /* get length in bytes */
  552. ulen = sizeof(wchar_t) * (ulenw + 1);
  553. if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) {
  554. return NULL;
  555. }
  556. /* convert multibyte to wide */
  557. ulen = MultiByteToWideChar(
  558. CP_ACP, /* ANSI code page */
  559. 0, /* flags for character-type options */
  560. local_string, /* string to convert */
  561. -1, /* string length (-1 = NULL terminated) */
  562. qw, /* buffer */
  563. ulenw); /* buffer length (0 = return length) */
  564. if (ulen == 0) {
  565. /* failed */
  566. free(qw);
  567. return NULL;
  568. }
  569. return qw;
  570. }
  571. wchar_t *utf8_to_wchar_string(utf8_string)
  572. char *utf8_string; /* path to get utf-8 name for */
  573. {
  574. wchar_t *qw;
  575. int ulen;
  576. int ulenw;
  577. if (utf8_string == NULL)
  578. return NULL;
  579. /* get length */
  580. ulenw = MultiByteToWideChar(
  581. CP_UTF8, /* UTF-8 code page */
  582. 0, /* flags for character-type options */
  583. utf8_string, /* string to convert */
  584. -1, /* string length (-1 = NULL terminated) */
  585. NULL, /* buffer */
  586. 0 ); /* buffer length (0 = return length) */
  587. if (ulenw == 0) {
  588. /* failed */
  589. return NULL;
  590. }
  591. ulenw++;
  592. /* get length in bytes */
  593. ulen = sizeof(wchar_t) * (ulenw + 1);
  594. if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) {
  595. return NULL;
  596. }
  597. /* convert multibyte to wide */
  598. ulen = MultiByteToWideChar(
  599. CP_UTF8, /* UTF-8 code page */
  600. 0, /* flags for character-type options */
  601. utf8_string, /* string to convert */
  602. -1, /* string length (-1 = NULL terminated) */
  603. qw, /* buffer */
  604. ulenw); /* buffer length (0 = return length) */
  605. if (ulen == 0) {
  606. /* failed */
  607. free(qw);
  608. return NULL;
  609. }
  610. return qw;
  611. }
  612. /* Convert wchar_t string to utf8 using Windows calls
  613. so any characters needing more than one wchar_t are
  614. are handled by Windows */
  615. char *wchar_to_utf8_string(wstring)
  616. wchar_t *wstring;
  617. {
  618. char *q; /* return string */
  619. int ulen;
  620. if (wstring == NULL)
  621. return NULL;
  622. /* Get buffer length */
  623. ulen = WideCharToMultiByte(
  624. CP_UTF8, /* UTF-8 code page */
  625. 0, /* flags */
  626. wstring, /* string to convert */
  627. -1, /* input chars (-1 = NULL terminated) */
  628. NULL, /* buffer */
  629. 0, /* size of buffer (0 = return needed size) */
  630. NULL, /* default char */
  631. NULL); /* used default char */
  632. if (ulen == 0) {
  633. /* failed */
  634. return NULL;
  635. }
  636. ulen += 2;
  637. if ((q = malloc(ulen + 1)) == NULL) {
  638. return NULL;
  639. }
  640. /* Convert the Unicode string to UTF-8 */
  641. if ((ulen = WideCharToMultiByte(
  642. CP_UTF8, /* UTF-8 code page */
  643. 0, /* flags */
  644. wstring, /* string to convert */
  645. -1, /* input chars (-1 = NULL terminated) */
  646. q, /* buffer */
  647. ulen, /* size of buffer (0 = return needed size) */
  648. NULL, /* default char */
  649. NULL)) == 0) /* used default char */
  650. {
  651. free(q);
  652. return NULL;
  653. }
  654. return q;
  655. }
  656. local int wild_recursew(whole, wildtail)
  657. wchar_t *whole;
  658. wchar_t *wildtail;
  659. {
  660. zDIRSCANW *dirw;
  661. wchar_t *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;
  662. extent newlen;
  663. int amatch = 0, e = ZE_MISS;
  664. if (!isshexpw(wildtail)) {
  665. if (GetFileAttributesW(whole) != 0xFFFFFFFF) { /* file exists? */
  666. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  667. CharToOemW(whole, whole);
  668. #endif
  669. return procnamew(whole, 0);
  670. }
  671. else
  672. return ZE_MISS; /* woops, no wildcards! */
  673. }
  674. /* back up thru path components till existing dir found */
  675. do {
  676. name = wildtail + wcslen(wildtail) - 1;
  677. for (;;)
  678. if (name-- <= wildtail || *name == PATH_END) {
  679. subwild = name + 1;
  680. plug2 = *subwild;
  681. *subwild = 0;
  682. break;
  683. }
  684. if (glue)
  685. *glue = plug;
  686. glue = subwild;
  687. plug = plug2;
  688. dirw = OpenDirScanW(whole);
  689. } while (!dirw && subwild > wildtail);
  690. wildtail = subwild; /* skip past non-wild components */
  691. if ((subwild = wcschr(wildtail + 1, PATH_END)) != NULL) {
  692. /* this "+ 1" dodges the ^^^ hole left by *glue == 0 */
  693. *(subwild++) = 0; /* wildtail = one component pattern */
  694. newlen = wcslen(whole) + wcslen(subwild) + (ONENAMELEN + 2);
  695. } else
  696. newlen = wcslen(whole) + (ONENAMELEN + 1);
  697. if (!dirw || ((newwhole = malloc(newlen * sizeof(wchar_t))) == NULL)) {
  698. if (glue)
  699. *glue = plug;
  700. e = dirw ? ZE_MEM : ZE_MISS;
  701. goto ohforgetit;
  702. }
  703. wcscpy(newwhole, whole);
  704. newlen = wcslen(newwhole);
  705. if (glue)
  706. *glue = plug; /* repair damage to whole */
  707. if (!isshexpw(wildtail)) {
  708. e = ZE_MISS; /* non-wild name not found */
  709. goto ohforgetit;
  710. }
  711. while ((name = readdw(dirw)) != NULL) {
  712. if (wcscmp(name, L".") && wcscmp(name, L"..") &&
  713. MATCHW(wildtail, name, 0)) {
  714. wcscpy(newwhole + newlen, name);
  715. if (subwild) {
  716. name = newwhole + wcslen(newwhole);
  717. *(name++) = (wchar_t)PATH_END;
  718. wcscpy(name, subwild);
  719. e = wild_recursew(newwhole, name);
  720. } else
  721. e = procname_win32w(newwhole, 0, GetDirAttribsW(dirw));
  722. newwhole[newlen] = 0;
  723. if (e == ZE_OK)
  724. amatch = 1;
  725. else if (e != ZE_MISS)
  726. break;
  727. }
  728. }
  729. ohforgetit:
  730. if (dirw) CloseDirScanW(dirw);
  731. if (subwild) *--subwild = PATH_END;
  732. if (newwhole) free(newwhole);
  733. if (e == ZE_MISS && amatch)
  734. e = ZE_OK;
  735. return e;
  736. }
  737. #endif
  738. local int wild_recurse(whole, wildtail)
  739. char *whole;
  740. char *wildtail;
  741. {
  742. zDIRSCAN *dir;
  743. char *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;
  744. extent newlen;
  745. int amatch = 0, e = ZE_MISS;
  746. if (!isshexp(wildtail)) {
  747. if (GetFileAttributes(whole) != 0xFFFFFFFF) { /* file exists? */
  748. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  749. AnsiToOem(whole, whole);
  750. #endif
  751. return procname(whole, 0);
  752. }
  753. else
  754. return ZE_MISS; /* woops, no wildcards! */
  755. }
  756. /* back up thru path components till existing dir found */
  757. do {
  758. name = wildtail + strlen(wildtail) - 1;
  759. for (;;)
  760. if (name-- <= wildtail || *name == PATH_END) {
  761. subwild = name + 1;
  762. plug2 = *subwild;
  763. *subwild = 0;
  764. break;
  765. }
  766. if (glue)
  767. *glue = plug;
  768. glue = subwild;
  769. plug = plug2;
  770. dir = OpenDirScan(whole);
  771. } while (!dir && subwild > wildtail);
  772. wildtail = subwild; /* skip past non-wild components */
  773. if ((subwild = MBSCHR(wildtail + 1, PATH_END)) != NULL) {
  774. /* this "+ 1" dodges the ^^^ hole left by *glue == 0 */
  775. *(subwild++) = 0; /* wildtail = one component pattern */
  776. newlen = strlen(whole) + strlen(subwild) + (ONENAMELEN + 2);
  777. } else
  778. newlen = strlen(whole) + (ONENAMELEN + 1);
  779. if (!dir || ((newwhole = malloc(newlen)) == NULL)) {
  780. if (glue)
  781. *glue = plug;
  782. e = dir ? ZE_MEM : ZE_MISS;
  783. goto ohforgetit;
  784. }
  785. strcpy(newwhole, whole);
  786. newlen = strlen(newwhole);
  787. if (glue)
  788. *glue = plug; /* repair damage to whole */
  789. if (!isshexp(wildtail)) {
  790. e = ZE_MISS; /* non-wild name not found */
  791. goto ohforgetit;
  792. }
  793. while ((name = readd(dir)) != NULL) {
  794. if (strcmp(name, ".") && strcmp(name, "..") &&
  795. MATCH(wildtail, name, 0)) {
  796. strcpy(newwhole + newlen, name);
  797. if (subwild) {
  798. name = newwhole + strlen(newwhole);
  799. *(name++) = PATH_END;
  800. strcpy(name, subwild);
  801. e = wild_recurse(newwhole, name);
  802. } else
  803. e = procname_win32(newwhole, 0, GetDirAttribs(dir));
  804. newwhole[newlen] = 0;
  805. if (e == ZE_OK)
  806. amatch = 1;
  807. else if (e != ZE_MISS)
  808. break;
  809. }
  810. }
  811. ohforgetit:
  812. if (dir) CloseDirScan(dir);
  813. if (subwild) *--subwild = PATH_END;
  814. if (newwhole) free(newwhole);
  815. if (e == ZE_MISS && amatch)
  816. e = ZE_OK;
  817. return e;
  818. }
  819. #ifdef UNICODE_SUPPORT
  820. int has_win32_wide() {
  821. DWORD r;
  822. /* test if we have wide function support */
  823. /* check if already set */
  824. if (no_win32_wide != -1)
  825. return !no_win32_wide;
  826. /* assume we don't */
  827. no_win32_wide = 1;
  828. /* get attributes for this directory */
  829. r = GetFileAttributes(".");
  830. /* r should be 16 = FILE_ATTRIBUTE_DIRECTORY */
  831. if (r == FILE_ATTRIBUTE_DIRECTORY) {
  832. /* now see if it works for the wide version */
  833. r = GetFileAttributesW(L".");
  834. /* if this fails then we probably don't have wide functions */
  835. if (r == 0xFFFFFFFF) {
  836. /* error is probably "This function is only valid in Win32 mode." */
  837. } else if (r == FILE_ATTRIBUTE_DIRECTORY) {
  838. /* worked, so assume we have wide support */
  839. no_win32_wide = 0;
  840. }
  841. }
  842. return !no_win32_wide;
  843. }
  844. #endif
  845. int wild(w)
  846. char *w; /* path/pattern to match */
  847. /* If not in exclude mode, expand the pattern based on the contents of the
  848. file system. Return an error code in the ZE_ class. */
  849. {
  850. char *p; /* path */
  851. char *q; /* diskless path */
  852. int e; /* result */
  853. #ifdef UNICODE_SUPPORT
  854. wchar_t *pw; /* wide path */
  855. wchar_t *qw; /* wide diskless path */
  856. #endif
  857. if (volume_label == 1) {
  858. volume_label = 2;
  859. label = getVolumeLabel((w != NULL && isascii((uch)w[0]) && w[1] == ':')
  860. ? to_up(w[0]) : '\0',
  861. &label_time, &label_mode, &label_utim);
  862. if (label != NULL)
  863. (void)newname(label, 0, 0);
  864. if (w == NULL || (isascii((uch)w[0]) && w[1] == ':' && w[2] == '\0'))
  865. return ZE_OK;
  866. /* "zip -$ foo a:" can be used to force drive name */
  867. }
  868. /* special handling of stdin request */
  869. if (strcmp(w, "-") == 0) /* if compressing stdin */
  870. return newname(w, 0, 0);
  871. /* Allocate and copy pattern, leaving room to add "." if needed */
  872. if ((p = malloc(strlen(w) + 2)) == NULL)
  873. return ZE_MEM;
  874. strcpy(p, w);
  875. /* Normalize path delimiter as '/' */
  876. for (q = p; *q; INCSTR(q)) /* use / consistently */
  877. if (*q == '\\')
  878. *q = '/';
  879. #ifdef UNICODE_SUPPORT
  880. if (!no_win32_wide) {
  881. /* wide char version */
  882. pw = local_to_wchar_string(p);
  883. /* Separate the disk part of the path */
  884. if ((qw = wcschr(pw, ':')) != NULL) {
  885. if (wcschr(++qw, ':')) /* sanity check for safety of wild_recurse */
  886. return ZE_MISS;
  887. } else
  888. qw = pw;
  889. /* Normalize bare disk names */
  890. if (qw > pw && !*qw)
  891. wcscpy(qw, L".");
  892. } else {
  893. /* multibyte version */
  894. /* Separate the disk part of the path */
  895. if ((q = MBSCHR(p, ':')) != NULL) {
  896. if (MBSCHR(++q, ':')) /* sanity check for safety of wild_recurse */
  897. return ZE_MISS;
  898. } else
  899. q = p;
  900. /* Normalize bare disk names */
  901. if (q > p && !*q)
  902. strcpy(q, ".");
  903. }
  904. #else
  905. /* multibyte version */
  906. /* Separate the disk part of the path */
  907. if ((q = MBSCHR(p, ':')) != NULL) {
  908. if (MBSCHR(++q, ':')) /* sanity check for safety of wild_recurse */
  909. return ZE_MISS;
  910. } else
  911. q = p;
  912. /* Normalize bare disk names */
  913. if (q > p && !*q)
  914. strcpy(q, ".");
  915. #endif
  916. /* Here we go */
  917. #ifdef UNICODE_SUPPORT
  918. if (!no_win32_wide) {
  919. /* use wide Unicode directory scan */
  920. e = wild_recursew(pw, qw);
  921. free(pw);
  922. } else {
  923. /* use multibyte directory scan */
  924. e = wild_recurse(p, q);
  925. }
  926. #else
  927. e = wild_recurse(p, q);
  928. #endif
  929. free((zvoid *)p);
  930. return e;
  931. }
  932. local int procname_win32(n, caseflag, attribs)
  933. char *n; /* name to process */
  934. int caseflag; /* true to force case-sensitive match */
  935. DWORD attribs;
  936. /* Process a name or sh expression to operate on (or exclude). Return
  937. an error code in the ZE_ class. */
  938. {
  939. char *a; /* path and name for recursion */
  940. zDIRSCAN *d; /* directory stream from OpenDirScan() */
  941. char *e; /* pointer to name from readd() */
  942. int m; /* matched flag */
  943. char *p; /* path for recursion */
  944. z_stat s; /* result of stat() */
  945. struct zlist far *z; /* steps through zfiles list */
  946. if (strcmp(n, "-") == 0) /* if compressing stdin */
  947. return newname(n, 0, caseflag);
  948. else if (attribs != INVALID_WIN32_FILE_ATTRIBS)
  949. {
  950. /* Avoid calling stat() for performance reasons when it is already known
  951. (from a previous directory scan) that the passed name corresponds to
  952. a "real existing" file. The only information needed further down in
  953. this function is the distinction between directory entries and other
  954. (typically normal file) entries. This distinction can be derived from
  955. the file's attributes that the directory lookup has already provided
  956. "for free".
  957. */
  958. s.st_mode = ((attribs & FILE_ATTRIBUTE_DIRECTORY) ? S_IFDIR : S_IFREG);
  959. }
  960. else if (LSSTAT(n, &s)
  961. #ifdef __TURBOC__
  962. /* For this compiler, stat() succeeds on wild card names! */
  963. /* Unfortunately, this causes failure on names containing */
  964. /* square bracket characters, which are legal in win32. */
  965. || isshexp(n)
  966. #endif
  967. )
  968. {
  969. #ifdef UNICODE_SUPPORT
  970. char *uname = NULL;
  971. #endif
  972. /* Not a file or directory--search for shell expression in zip file */
  973. p = ex2in(n, 0, (int *)NULL); /* shouldn't affect matching chars */
  974. m = 1;
  975. for (z = zfiles; z != NULL; z = z->nxt) {
  976. if (MATCH(p, z->iname, caseflag))
  977. {
  978. z->mark = pcount ? filter(z->zname, caseflag) : 1;
  979. if (verbose)
  980. fprintf(mesg, "zip diagnostic: %scluding %s\n",
  981. z->mark ? "in" : "ex", z->oname);
  982. m = 0;
  983. }
  984. }
  985. #ifdef UNICODE_SUPPORT
  986. /* also check escaped Unicode names */
  987. for (z = zfiles; z != NULL; z = z->nxt) {
  988. if (z->zuname) {
  989. #ifdef WIN32
  990. /* It seems something is lost in going from a listed
  991. name from zip -su in a console window to using that
  992. name in a command line. This kluge may fix it
  993. and just takes zuname, converts to oem (i.e.ouname),
  994. then converts it back which ends up not the same as
  995. started with.
  996. */
  997. uname = z->wuname;
  998. #else
  999. uname = z->zuname;
  1000. #endif
  1001. if (MATCH(p, uname, caseflag))
  1002. {
  1003. z->mark = pcount ? filter(uname, caseflag) : 1;
  1004. if (verbose) {
  1005. fprintf(mesg, "zip diagnostic: %scluding %s\n",
  1006. z->mark ? "in" : "ex", z->oname);
  1007. fprintf(mesg, " Escaped Unicode: %s\n",
  1008. z->ouname);
  1009. }
  1010. m = 0;
  1011. }
  1012. }
  1013. }
  1014. #endif
  1015. free((zvoid *)p);
  1016. return m ? ZE_MISS : ZE_OK;
  1017. }
  1018. /* Live name--use if file, recurse if directory */
  1019. for (p = n; *p; INCSTR(p)) /* use / consistently */
  1020. if (*p == '\\')
  1021. *p = '/';
  1022. if ((s.st_mode & S_IFDIR) == 0)
  1023. {
  1024. /* add exclusions in directory recurse but ignored for single file */
  1025. DWORD dwAttr;
  1026. dwAttr = GetFileMode(n);
  1027. if ((hidden_files ||
  1028. !(dwAttr & FILE_ATTRIBUTE_HIDDEN || dwAttr & FILE_ATTRIBUTE_SYSTEM)) &&
  1029. (!only_archive_set || (dwAttr & FILE_ATTRIBUTE_ARCHIVE)))
  1030. {
  1031. /* add or remove name of file */
  1032. if ((m = newname(n, 0, caseflag)) != ZE_OK)
  1033. return m;
  1034. }
  1035. } else {
  1036. /* Add trailing / to the directory name */
  1037. if ((p = (char *) malloc(strlen(n)+2)) == NULL)
  1038. return ZE_MEM;
  1039. if (strcmp(n, ".") == 0 || strcmp(n, "/.") == 0) {
  1040. *p = '\0'; /* avoid "./" prefix and do not create zip entry */
  1041. } else {
  1042. strcpy(p, n);
  1043. a = p + strlen(p);
  1044. if (lastchar(p) != '/')
  1045. strcpy(a, "/");
  1046. if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
  1047. free((zvoid *)p);
  1048. return m;
  1049. }
  1050. }
  1051. /* recurse into directory */
  1052. if (recurse && (d = OpenDirScan(n)) != NULL)
  1053. {
  1054. while ((e = readd(d)) != NULL) {
  1055. if (strcmp(e, ".") && strcmp(e, ".."))
  1056. {
  1057. if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
  1058. {
  1059. CloseDirScan(d);
  1060. free((zvoid *)p);
  1061. return ZE_MEM;
  1062. }
  1063. strcat(strcpy(a, p), e);
  1064. if ((m = procname_win32(a, caseflag, GetDirAttribs(d)))
  1065. != ZE_OK) /* recurse on name */
  1066. {
  1067. if (m == ZE_MISS)
  1068. zipwarn("name not matched: ", a);
  1069. else
  1070. ziperr(m, a);
  1071. }
  1072. free((zvoid *)a);
  1073. }
  1074. }
  1075. CloseDirScan(d);
  1076. }
  1077. free((zvoid *)p);
  1078. } /* (s.st_mode & S_IFDIR) == 0) */
  1079. return ZE_OK;
  1080. }
  1081. #ifdef UNICODE_SUPPORT
  1082. local int procname_win32w(nw, caseflag, attribs)
  1083. wchar_t *nw; /* name to process */
  1084. int caseflag; /* true to force case-sensitive match */
  1085. DWORD attribs;
  1086. /* Process a name or sh expression to operate on (or exclude). Return
  1087. an error code in the ZE_ class. */
  1088. {
  1089. wchar_t *aw; /* path and name for recursion */
  1090. zDIRSCANW *dw; /* directory stream from OpenDirScan() */
  1091. wchar_t *ew; /* pointer to name from readd() */
  1092. int m; /* matched flag */
  1093. wchar_t *pw; /* path for recursion */
  1094. zw_stat s; /* result of stat() */
  1095. struct zlist far *z; /* steps through zfiles list */
  1096. if (wcscmp(nw, L"-") == 0) /* if compressing stdin */
  1097. return newnamew(nw, 0, caseflag);
  1098. else if (attribs != INVALID_WIN32_FILE_ATTRIBS)
  1099. {
  1100. /* Avoid calling stat() for performance reasons when it is already known
  1101. (from a previous directory scan) that the passed name corresponds to
  1102. a "real existing" file. The only information needed further down in
  1103. this function is the distinction between directory entries and other
  1104. (typically normal file) entries. This distinction can be derived from
  1105. the file's attributes that the directory lookup has already provided
  1106. "for free".
  1107. */
  1108. s.st_mode = ((attribs & FILE_ATTRIBUTE_DIRECTORY) ? S_IFDIR : S_IFREG);
  1109. }
  1110. else if (LSSTATW(nw, &s)
  1111. #ifdef __TURBOC__
  1112. /* For this compiler, stat() succeeds on wild card names! */
  1113. /* Unfortunately, this causes failure on names containing */
  1114. /* square bracket characters, which are legal in win32. */
  1115. || isshexpw(nw)
  1116. #endif
  1117. )
  1118. {
  1119. wchar_t *unamew = NULL;
  1120. /* Not a file or directory--search for shell expression in zip file */
  1121. pw = ex2inw(nw, 0, (int *)NULL); /* shouldn't affect matching chars */
  1122. m = 1;
  1123. for (z = zfiles; z != NULL; z = z->nxt) {
  1124. if (MATCHW(pw, z->znamew, caseflag))
  1125. {
  1126. z->mark = pcount ? filter(z->zname, caseflag) : 1;
  1127. if (verbose)
  1128. fprintf(mesg, "zip diagnostic: %scluding %s\n",
  1129. z->mark ? "in" : "ex", z->oname);
  1130. m = 0;
  1131. }
  1132. }
  1133. /* also check escaped Unicode names */
  1134. for (z = zfiles; z != NULL; z = z->nxt) {
  1135. if (z->zuname) {
  1136. unamew = z->znamew;
  1137. if (MATCHW(pw, unamew, caseflag))
  1138. {
  1139. z->mark = pcount ? filter(z->iname, caseflag) : 1;
  1140. if (verbose) {
  1141. fprintf(mesg, "zip diagnostic: %scluding %s\n",
  1142. z->mark ? "in" : "ex", z->oname);
  1143. fprintf(mesg, " Escaped Unicode: %s\n",
  1144. z->ouname);
  1145. }
  1146. m = 0;
  1147. }
  1148. }
  1149. }
  1150. free((zvoid *)pw);
  1151. return m ? ZE_MISS : ZE_OK;
  1152. }
  1153. /* Live name--use if file, recurse if directory */
  1154. for (pw = nw; *pw; pw++) /* use / consistently */
  1155. if (*pw == (wchar_t)'\\')
  1156. *pw = (wchar_t)'/';
  1157. if ((s.st_mode & S_IFDIR) == 0)
  1158. {
  1159. /* add exclusions in directory recurse but ignored for single file */
  1160. DWORD dwAttr;
  1161. dwAttr = GetFileModeW(nw);
  1162. if ((hidden_files ||
  1163. !(dwAttr & FILE_ATTRIBUTE_HIDDEN || dwAttr & FILE_ATTRIBUTE_SYSTEM)) &&
  1164. (!only_archive_set || (dwAttr & FILE_ATTRIBUTE_ARCHIVE)))
  1165. {
  1166. /* add or remove name of file */
  1167. if ((m = newnamew(nw, 0, caseflag)) != ZE_OK)
  1168. return m;
  1169. }
  1170. } else {
  1171. /* Add trailing / to the directory name */
  1172. pw = (wchar_t *)malloc( (wcslen(nw)+2) * sizeof(wchar_t) );
  1173. if (pw == NULL)
  1174. return ZE_MEM;
  1175. if (wcscmp(nw, L".") == 0 || wcscmp(nw, L"/.") == 0) {
  1176. *pw = (wchar_t)'\0'; /* avoid "./" prefix and do not create zip entry */
  1177. } else {
  1178. wcscpy(pw, nw);
  1179. aw = pw + wcslen(pw);
  1180. if (pw[wcslen(pw) - 1] != (wchar_t)'/')
  1181. wcscpy(aw, L"/");
  1182. if (dirnames && (m = newnamew(pw, 1, caseflag)) != ZE_OK) {
  1183. free((zvoid *)pw);
  1184. return m;
  1185. }
  1186. }
  1187. /* recurse into directory */
  1188. if (recurse && (dw = OpenDirScanW(nw)) != NULL)
  1189. {
  1190. while ((ew = readdw(dw)) != NULL) {
  1191. if (wcscmp(ew, L".") && wcscmp(ew, L".."))
  1192. {
  1193. if ((aw = malloc((wcslen(pw) + wcslen(ew) + 1) * sizeof(wchar_t))) == NULL)
  1194. {
  1195. CloseDirScanW(dw);
  1196. free((zvoid *)pw);
  1197. return ZE_MEM;
  1198. }
  1199. wcscat(wcscpy(aw, pw), ew);
  1200. if ((m = procname_win32w(aw, caseflag, GetDirAttribsW(dw)))
  1201. != ZE_OK) /* recurse on name */
  1202. {
  1203. char *a;
  1204. char *ad;
  1205. a = wchar_to_local_string(aw);
  1206. ad = local_to_display_string(a);
  1207. if (m == ZE_MISS)
  1208. zipwarn("name not matched: ", ad);
  1209. else
  1210. ziperr(m, a);
  1211. free(ad);
  1212. free(a);
  1213. }
  1214. free((zvoid *)aw);
  1215. }
  1216. }
  1217. CloseDirScanW(dw);
  1218. }
  1219. free((zvoid *)pw);
  1220. } /* (s.st_mode & S_IFDIR) == 0) */
  1221. return ZE_OK;
  1222. }
  1223. #endif
  1224. #ifdef UNICODE_SUPPORT
  1225. int procnamew(nw, caseflag)
  1226. wchar_t *nw; /* name to process */
  1227. int caseflag; /* true to force case-sensitive match */
  1228. {
  1229. return procname_win32w(nw, caseflag, INVALID_WIN32_FILE_ATTRIBS);
  1230. }
  1231. #endif
  1232. int procname(n, caseflag)
  1233. char *n; /* name to process */
  1234. int caseflag; /* true to force case-sensitive match */
  1235. {
  1236. return procname_win32(n, caseflag, INVALID_WIN32_FILE_ATTRIBS);
  1237. }
  1238. char *ex2in(x, isdir, pdosflag)
  1239. char *x; /* external file name */
  1240. int isdir; /* input: x is a directory */
  1241. int *pdosflag; /* output: force MSDOS file attributes? */
  1242. /* Convert the external file name to a zip file name, returning the malloc'ed
  1243. string or NULL if not enough memory. */
  1244. {
  1245. char *n; /* internal file name (malloc'ed) */
  1246. char *t; /* shortened name */
  1247. int dosflag;
  1248. dosflag = dosify || IsFileSystemOldFAT(x);
  1249. if (!dosify && use_longname_ea && (t = GetLongPathEA(x)) != NULL)
  1250. {
  1251. x = t;
  1252. dosflag = 0;
  1253. }
  1254. /* Find starting point in name before doing malloc */
  1255. /* Strip drive specification */
  1256. t = *x && isascii((uch)*x) && *(x + 1) == ':' ? x + 2 : x;
  1257. /* Strip "//host/share/" part of a UNC name */
  1258. if ((!strncmp(x,"//",2) || !strncmp(x,"\\\\",2)) &&
  1259. (x[2] != '\0' && x[2] != '/' && x[2] != '\\')) {
  1260. n = x + 2;
  1261. while (*n != '\0' && *n != '/' && *n != '\\')
  1262. INCSTR(n); /* strip host name */
  1263. if (*n != '\0') {
  1264. INCSTR(n);
  1265. while (*n != '\0' && *n != '/' && *n != '\\')
  1266. INCSTR(n); /* strip `share' name */
  1267. }
  1268. if (*n != '\0')
  1269. t = n + MB_CLEN(n);
  1270. }
  1271. /* Strip leading "/" to convert an absolute path into a relative path */
  1272. while (*t == '/' || *t == '\\')
  1273. t++;
  1274. /* Strip leading "./" as well as drive letter */
  1275. while (*t == '.' && (t[1] == '/' || t[1] == '\\'))
  1276. t += 2;
  1277. /* Make changes, if any, to the copied name (leave original intact) */
  1278. for (n = t; *n; INCSTR(n))
  1279. if (*n == '\\')
  1280. *n = '/';
  1281. if (!pathput)
  1282. t = last(t, PATH_END);
  1283. /* Malloc space for internal name and copy it */
  1284. if ((n = malloc(strlen(t) + 1)) == NULL)
  1285. return NULL;
  1286. strcpy(n, t);
  1287. if (dosify)
  1288. msname(n);
  1289. /* Returned malloc'ed name */
  1290. if (pdosflag)
  1291. *pdosflag = dosflag;
  1292. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  1293. OemToAnsi(n, n);
  1294. #endif
  1295. return n;
  1296. }
  1297. #ifdef UNICODE_SUPPORT
  1298. wchar_t *ex2inw(xw, isdir, pdosflag)
  1299. wchar_t *xw; /* external file name */
  1300. int isdir; /* input: x is a directory */
  1301. int *pdosflag; /* output: force MSDOS file attributes? */
  1302. /* Convert the external file name to a zip file name, returning the malloc'ed
  1303. string or NULL if not enough memory. */
  1304. {
  1305. wchar_t *nw; /* internal file name (malloc'ed) */
  1306. wchar_t *tw; /* shortened name */
  1307. int dosflag;
  1308. dosflag = dosify || IsFileSystemOldFATW(xw);
  1309. if (!dosify && use_longname_ea && (tw = GetLongPathEAW(xw)) != NULL)
  1310. {
  1311. xw = tw;
  1312. dosflag = 0;
  1313. }
  1314. /* Find starting point in name before doing malloc */
  1315. /* Strip drive specification */
  1316. tw = *xw && iswascii(*xw) && *(xw + 1) == (wchar_t)':' ? xw + 2 : xw;
  1317. /* Strip "//host/share/" part of a UNC name */
  1318. if ((!wcsncmp(xw,L"//",2) || !wcsncmp(xw,L"\\\\",2)) &&
  1319. (xw[2] != (wchar_t)'\0' && xw[2] != (wchar_t)'/' && xw[2] != (wchar_t)'\\')) {
  1320. nw = xw + 2;
  1321. while (*nw != (wchar_t)'\0' && *nw != (wchar_t)'/' && *nw != (wchar_t)'\\')
  1322. nw++; /* strip host name */
  1323. if (*nw != (wchar_t)'\0') {
  1324. nw++;
  1325. while (*nw != (wchar_t)'\0' && *nw != (wchar_t)'/' && *nw != (wchar_t)'\\')
  1326. nw++; /* strip `share' name */
  1327. }
  1328. if (*nw != (wchar_t)'\0')
  1329. tw = nw++;
  1330. }
  1331. /* Strip leading "/" to convert an absolute path into a relative path */
  1332. while (*tw == (wchar_t)'/' || *tw == (wchar_t)'\\')
  1333. tw++;
  1334. /* Strip leading "./" as well as drive letter */
  1335. while (*tw == (wchar_t)'.' && (tw[1] == (wchar_t)'/' || tw[1] == (wchar_t)'\\'))
  1336. tw += 2;
  1337. /* Make changes, if any, to the copied name (leave original intact) */
  1338. for (nw = tw; *nw; nw++)
  1339. if (*nw == '\\')
  1340. *nw = '/';
  1341. if (!pathput)
  1342. tw = lastw(tw, PATH_END);
  1343. /* Malloc space for internal name and copy it */
  1344. if ((nw = malloc((wcslen(tw) + 1) * sizeof(wchar_t))) == NULL)
  1345. return NULL;
  1346. wcscpy(nw, tw);
  1347. if (dosify)
  1348. msnamew(nw);
  1349. /* Returned malloc'ed name */
  1350. if (pdosflag)
  1351. *pdosflag = dosflag;
  1352. #if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  1353. CharToAnsiW(nw, nw);
  1354. #endif
  1355. return nw;
  1356. }
  1357. #endif
  1358. char *in2ex(n)
  1359. char *n; /* internal file name */
  1360. /* Convert the zip file name to an external file name, returning the malloc'ed
  1361. string or NULL if not enough memory. */
  1362. {
  1363. char *x; /* external file name */
  1364. if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
  1365. return NULL;
  1366. strcpy(x, n);
  1367. # if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  1368. AnsiToOem(x, x);
  1369. # endif
  1370. return x;
  1371. }
  1372. #ifdef UNICODE_SUPPORT
  1373. wchar_t *in2exw(nw)
  1374. wchar_t *nw; /* internal file name */
  1375. /* Convert the zip file name to an external file name, returning the malloc'ed
  1376. string or NULL if not enough memory. */
  1377. {
  1378. wchar_t *xw; /* external file name */
  1379. if ((xw = malloc((wcslen(nw) + 1 + PAD) * sizeof(wchar_t))) == NULL)
  1380. return NULL;
  1381. wcscpy(xw, nw);
  1382. # if defined(__RSXNT__) /* RSXNT/EMX C rtl uses OEM charset */
  1383. CharToOemW(xw, xw);
  1384. # endif
  1385. return xw;
  1386. }
  1387. #endif
  1388. void stamp(f, d)
  1389. char *f; /* name of file to change */
  1390. ulg d; /* dos-style time to change it to */
  1391. /* Set last updated and accessed time of file f to the DOS time d. */
  1392. {
  1393. #if defined(__TURBOC__) && !defined(__BORLANDC__)
  1394. int h; /* file handle */
  1395. if ((h = open(f, 0)) != -1)
  1396. {
  1397. setftime(h, (struct ftime *)&d);
  1398. close(h);
  1399. }
  1400. #else /* !__TURBOC__ */
  1401. struct utimbuf u; /* argument for utime() */
  1402. /* Convert DOS time to time_t format in u.actime and u.modtime */
  1403. u.actime = u.modtime = dos2unixtime(d);
  1404. /* Set updated and accessed times of f */
  1405. utime(f, &u);
  1406. #endif /* ?__TURBOC__ */
  1407. }
  1408. ulg filetime(f, a, n, t)
  1409. char *f; /* name of file to get info on */
  1410. ulg *a; /* return value: file attributes */
  1411. zoff_t *n; /* return value: file size */
  1412. iztimes *t; /* return value: access, modific. and creation times */
  1413. /* If file *f does not exist, return 0. Else, return the file's last
  1414. modified date and time as an MSDOS date and time. The date and
  1415. time is returned in a long with the date most significant to allow
  1416. unsigned integer comparison of absolute times. Also, if a is not
  1417. a NULL pointer, store the file attributes there, with the high two
  1418. bytes being the Unix attributes, and the low byte being a mapping
  1419. of that to DOS attributes. If n is not NULL, store the file size
  1420. there. If t is not NULL, the file's access, modification and creation
  1421. times are stored there as UNIX time_t values.
  1422. If f is "-", use standard input as the file. If f is a device, return
  1423. a file size of -1 */
  1424. {
  1425. z_stat s; /* results of zstat() */
  1426. /* converted to malloc instead of using FNMAX - 11/8/04 EG */
  1427. char *name;
  1428. unsigned int len = strlen(f);
  1429. int isstdin = !strcmp(f, "-");
  1430. if (f == label) {
  1431. if (a != NULL)
  1432. *a = label_mode;
  1433. if (n != NULL)
  1434. *n = -2L; /* convention for a label name */
  1435. if (t != NULL)
  1436. t->atime = t->mtime = t->ctime = label_utim;
  1437. return label_time;
  1438. }
  1439. if ((name = malloc(len + 1)) == NULL) {
  1440. ZIPERR(ZE_MEM, "filetime");
  1441. }
  1442. strcpy(name, f);
  1443. if (MBSRCHR(name, '/') == (name + len - 1))
  1444. name[len - 1] = '\0';
  1445. /* not all systems allow stat'ing a file with / appended */
  1446. /* zip64 support 08/31/2003 R.Nausedat */
  1447. if (isstdin) {
  1448. if (zfstat(fileno(stdin), &s) != 0) {
  1449. free(name);
  1450. error("fstat(stdin)");
  1451. }
  1452. time((time_t *)&s.st_mtime); /* some fstat()s return time zero */
  1453. } else if (LSSTAT(name, &s) != 0) {
  1454. /* Accept about any file kind including directories
  1455. * (stored with trailing / with -r option)
  1456. */
  1457. free(name);
  1458. return 0;
  1459. }
  1460. if (a != NULL) {
  1461. #ifdef WIN32_OEM
  1462. /* When creating DOS-like archives with OEM-charset names, only the
  1463. standard FAT attributes should be used.
  1464. (Note: On a Win32 system, the UNIX style attributes from stat()
  1465. do not contain any additional information...)
  1466. */
  1467. *a = (isstdin ? 0L : (ulg)GetFileMode(name));
  1468. #else
  1469. *a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)GetFileMode(name));
  1470. #endif
  1471. }
  1472. if (n != NULL)
  1473. /* device return -1 */
  1474. *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
  1475. if (t != NULL) {
  1476. t->atime = s.st_atime;
  1477. t->mtime = s.st_mtime;
  1478. t->ctime = s.st_ctime;
  1479. }
  1480. free(name);
  1481. return unix2dostime((time_t *)&s.st_mtime);
  1482. }
  1483. #ifdef UNICODE_SUPPORT
  1484. ulg filetimew(fw, a, n, t)
  1485. wchar_t *fw; /* name of file to get info on */
  1486. ulg *a; /* return value: file attributes */
  1487. zoff_t *n; /* return value: file size */
  1488. iztimes *t; /* return value: access, modific. and creation times */
  1489. /* If file *f does not exist, return 0. Else, return the file's last
  1490. modified date and time as an MSDOS date and time. The date and
  1491. time is returned in a long with the date most significant to allow
  1492. unsigned integer comparison of absolute times. Also, if a is not
  1493. a NULL pointer, store the file attributes there, with the high two
  1494. bytes being the Unix attributes, and the low byte being a mapping
  1495. of that to DOS attributes. If n is not NULL, store the file size
  1496. there. If t is not NULL, the file's access, modification and creation
  1497. times are stored there as UNIX time_t values.
  1498. If f is "-", use standard input as the file. If f is a device, return
  1499. a file size of -1 */
  1500. {
  1501. zw_stat sw; /* results of zstat() */
  1502. /* converted to malloc instead of using FNMAX - 11/8/04 EG */
  1503. wchar_t *namew;
  1504. unsigned int len = wcslen(fw);
  1505. int isstdin = !wcscmp(fw, L"-");
  1506. wchar_t *labelw = local_to_wchar_string(label);
  1507. if (labelw && wcscmp(fw, labelw) == 0) {
  1508. if (a != NULL)
  1509. *a = label_mode;
  1510. if (n != NULL)
  1511. *n = -2L; /* convention for a label name */
  1512. if (t != NULL)
  1513. t->atime = t->mtime = t->ctime = label_utim;
  1514. return label_time;
  1515. }
  1516. if ((namew = malloc((len + 1) * sizeof(wchar_t))) == NULL) {
  1517. ZIPERR(ZE_MEM, "filetime");
  1518. }
  1519. wcscpy(namew, fw);
  1520. if (wcsrchr(namew, (wchar_t)'/') == (namew + len - 1))
  1521. namew[len - 1] = '\0';
  1522. /* not all systems allow stat'ing a file with / appended */
  1523. /* zip64 support 08/31/2003 R.Nausedat */
  1524. if (isstdin) {
  1525. if (zwfstat(fileno(stdin), &sw) != 0) {
  1526. free(namew);
  1527. error("fstat(stdin)");
  1528. }
  1529. time((time_t *)&sw.st_mtime); /* some fstat()s return time zero */
  1530. } else if (LSSTATW(namew, &sw) != 0) {
  1531. /* Accept about any file kind including directories
  1532. * (stored with trailing / with -r option)
  1533. */
  1534. free(namew);
  1535. return 0;
  1536. }
  1537. if (a != NULL) {
  1538. #ifdef WIN32_OEM
  1539. /* When creating DOS-like archives with OEM-charset names, only the
  1540. standard FAT attributes should be used.
  1541. (Note: On a Win32 system, the UNIX style attributes from stat()
  1542. do not contain any additional information...)
  1543. */
  1544. *a = (isstdin ? 0L : (ulg)GetFileModeW(namew));
  1545. #else
  1546. *a = ((ulg)sw.st_mode << 16) | (isstdin ? 0L : (ulg)GetFileModeW(namew));
  1547. #endif
  1548. }
  1549. if (n != NULL)
  1550. /* device return -1 */
  1551. *n = (sw.st_mode & S_IFMT) == S_IFREG ? sw.st_size : -1L;
  1552. if (t != NULL) {
  1553. t->atime = sw.st_atime;
  1554. t->mtime = sw.st_mtime;
  1555. t->ctime = sw.st_ctime;
  1556. }
  1557. free(namew);
  1558. return unix2dostime((time_t *)&sw.st_mtime);
  1559. }
  1560. #endif
  1561. #ifdef NTSD_EAS
  1562. /* changed size, csize from size_t to ush 3/10/2005 EG */
  1563. local void GetSD(char *path, char **bufptr, ush *size,
  1564. char **cbufptr, ush *csize)
  1565. {
  1566. unsigned char stackbuffer[NTSD_BUFFERSIZE];
  1567. unsigned long bytes = NTSD_BUFFERSIZE;
  1568. unsigned char *buffer = stackbuffer;
  1569. unsigned char *DynBuffer = NULL;
  1570. ulg cbytes;
  1571. PEF_NTSD_L_HEADER pLocalHeader;
  1572. PEF_NTSD_C_HEADER pCentralHeader;
  1573. VOLUMECAPS VolumeCaps;
  1574. /* check target volume capabilities */
  1575. if (!ZipGetVolumeCaps(path, path, &VolumeCaps) ||
  1576. !(VolumeCaps.dwFileSystemFlags & FS_PERSISTENT_ACLS)) {
  1577. return;
  1578. }
  1579. VolumeCaps.bUsePrivileges = use_privileges;
  1580. VolumeCaps.dwFileAttributes = 0;
  1581. /* should set to file attributes, if possible */
  1582. if (!SecurityGet(path, &VolumeCaps, buffer, (LPDWORD)&bytes)) {
  1583. /* try to malloc the buffer if appropriate */
  1584. if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  1585. DynBuffer = malloc(bytes);
  1586. if(DynBuffer == NULL) return;
  1587. buffer = DynBuffer; /* switch to the new buffer and try again */
  1588. if(!SecurityGet(path, &VolumeCaps, buffer, (LPDWORD)&bytes)) {
  1589. free(DynBuffer);
  1590. return;
  1591. }
  1592. } else {
  1593. return; /* bail */
  1594. }
  1595. }
  1596. /* # bytes to compress: compress type, CRC, data bytes */
  1597. cbytes = (2 + 4 + EB_DEFLAT_EXTRA) + bytes;
  1598. /* our two possible failure points. don't allow trashing of any data
  1599. if either fails - notice that *size and *csize don't get updated.
  1600. *bufptr leaks if malloc() was used and *cbufptr alloc fails - this
  1601. isn't relevant because it's probably indicative of a bigger problem. */
  1602. if(*size)
  1603. *bufptr = realloc(*bufptr, *size + EF_NTSD_L_LEN + cbytes);
  1604. else
  1605. *bufptr = malloc(EF_NTSD_L_LEN + cbytes);
  1606. if(*csize)
  1607. *cbufptr = realloc(*cbufptr, *csize + EF_NTSD_C_LEN);
  1608. else
  1609. *cbufptr = malloc(EF_NTSD_C_LEN);
  1610. if(*bufptr == NULL || *cbufptr == NULL) {
  1611. if(DynBuffer) free(DynBuffer);
  1612. return;
  1613. }
  1614. /* local header */
  1615. pLocalHeader = (PEF_NTSD_L_HEADER) (*bufptr + *size);
  1616. cbytes = memcompress(((char *)pLocalHeader + EF_NTSD_L_LEN), cbytes,
  1617. (char *)buffer, bytes);
  1618. if (cbytes > 0x7FFF) {
  1619. sprintf(errbuf, "security info too large to store (%ld bytes), %d max", bytes, 0x7FFF);
  1620. zipwarn(errbuf, "");
  1621. zipwarn("security info not stored: ", path);
  1622. if(DynBuffer) free(DynBuffer);
  1623. return;
  1624. }
  1625. *size += EF_NTSD_L_LEN + (ush)cbytes;
  1626. pLocalHeader->nID = EF_NTSD;
  1627. pLocalHeader->nSize = (USHORT)(EF_NTSD_L_LEN - EB_HEADSIZE
  1628. + cbytes);
  1629. pLocalHeader->lSize = bytes; /* uncompressed size */
  1630. pLocalHeader->Version = 0;
  1631. /* central header */
  1632. pCentralHeader = (PEF_NTSD_C_HEADER) (*cbufptr + *csize);
  1633. *csize += EF_NTSD_C_LEN;
  1634. pCentralHeader->nID = EF_NTSD;
  1635. pCentralHeader->nSize = EF_NTSD_C_LEN - EB_HEADSIZE; /* sbz */
  1636. pCentralHeader->lSize = bytes;
  1637. if (noisy) {
  1638. sprintf(errbuf, " (%ld bytes security)", bytes);
  1639. zipmessage_nl(errbuf, 0);
  1640. }
  1641. if(DynBuffer) free(DynBuffer);
  1642. }
  1643. #endif /* NTSD_EAS */
  1644. #ifdef USE_EF_UT_TIME
  1645. #define EB_L_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(3))
  1646. #define EB_C_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(1))
  1647. local int GetExtraTime(struct zlist far *z, iztimes *z_utim)
  1648. {
  1649. char *eb_l_ptr;
  1650. char *eb_c_ptr;
  1651. ulg ultime;
  1652. /* brain-dead IBM compiler defines time_t as "double", so we have to convert
  1653. * it into unsigned long integer number...
  1654. */
  1655. #ifdef IZ_CHECK_TZ
  1656. if (!zp_tz_is_valid) return ZE_OK; /* skip silently if no valid TZ info */
  1657. #endif
  1658. if(z->ext)
  1659. eb_l_ptr = realloc(z->extra, (z->ext + EB_L_UT_SIZE));
  1660. else
  1661. eb_l_ptr = malloc(EB_L_UT_SIZE);
  1662. if (eb_l_ptr == NULL)
  1663. return ZE_MEM;
  1664. if(z->cext)
  1665. eb_c_ptr = realloc(z->cextra, (z->cext + EB_C_UT_SIZE));
  1666. else
  1667. eb_c_ptr = malloc(EB_C_UT_SIZE);
  1668. if (eb_c_ptr == NULL)
  1669. return ZE_MEM;
  1670. z->extra = eb_l_ptr;
  1671. eb_l_ptr += z->ext;
  1672. z->ext += EB_L_UT_SIZE;
  1673. eb_l_ptr[0] = 'U';
  1674. eb_l_ptr[1] = 'T';
  1675. eb_l_ptr[2] = EB_UT_LEN(3); /* length of data part of e.f. */
  1676. eb_l_ptr[3] = 0;
  1677. eb_l_ptr[4] = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME;
  1678. ultime = (ulg)z_utim->mtime;
  1679. eb_l_ptr[5] = (char)(ultime);
  1680. eb_l_ptr[6] = (char)(ultime >> 8);
  1681. eb_l_ptr[7] = (char)(ultime >> 16);
  1682. eb_l_ptr[8] = (char)(ultime >> 24);
  1683. ultime = (ulg)z_utim->atime;
  1684. eb_l_ptr[9] = (char)(ultime);
  1685. eb_l_ptr[10] = (char)(ultime >> 8);
  1686. eb_l_ptr[11] = (char)(ultime >> 16);
  1687. eb_l_ptr[12] = (char)(ultime >> 24);
  1688. ultime = (ulg)z_utim->ctime;
  1689. eb_l_ptr[13] = (char)(ultime);
  1690. eb_l_ptr[14] = (char)(ultime >> 8);
  1691. eb_l_ptr[15] = (char)(ultime >> 16);
  1692. eb_l_ptr[16] = (char)(ultime >> 24);
  1693. z->cextra = eb_c_ptr;
  1694. eb_c_ptr += z->cext;
  1695. z->cext += EB_C_UT_SIZE;
  1696. memcpy(eb_c_ptr, eb_l_ptr, EB_C_UT_SIZE);
  1697. eb_c_ptr[EB_LEN] = EB_UT_LEN(1);
  1698. return ZE_OK;
  1699. }
  1700. #endif /* USE_EF_UT_TIME */
  1701. int set_extra_field(z, z_utim)
  1702. struct zlist far *z;
  1703. iztimes *z_utim;
  1704. /* create extra field and change z->att if desired */
  1705. {
  1706. #ifdef NTSD_EAS
  1707. if(ZipIsWinNT()) {
  1708. /* store SECURITY_DECRIPTOR data in local header,
  1709. and size only in central headers */
  1710. GetSD(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);
  1711. }
  1712. #endif /* NTSD_EAS */
  1713. #ifdef USE_EF_UT_TIME
  1714. /* store extended time stamps in both headers */
  1715. return GetExtraTime(z, z_utim);
  1716. #else /* !USE_EF_UT_TIME */
  1717. return ZE_OK;
  1718. #endif /* ?USE_EF_UT_TIME */
  1719. }
  1720. int deletedir(d)
  1721. char *d; /* directory to delete */
  1722. /* Delete the directory *d if it is empty, do nothing otherwise.
  1723. Return the result of rmdir(), delete(), or system().
  1724. For VMS, d must be in format [x.y]z.dir;1 (not [x.y.z]).
  1725. */
  1726. {
  1727. return rmdir(d);
  1728. }
  1729. #endif /* !UTIL */