unz60d10_w32wide-Unicode_patch.txt 163 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102
  1. diff -ru2 unz60d10/extract.c unz60d10_w32w/extract.c
  2. --- unz60d10/extract.c Thu Dec 27 21:41:40 2007
  3. +++ unz60d10_w32w/extract.c Mon Feb 11 02:22:00 2008
  4. @@ -87,4 +87,11 @@
  5. static int store_info OF((__GPRO));
  6. #ifdef SET_DIR_ATTRIB
  7. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  8. +static int extract_or_test_entrylistw OF((__GPRO__ unsigned numchunk,
  9. + ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,
  10. + unsigned *pnum_dirs,
  11. + direntryw **pdirlistw,
  12. + int error_in_archive));
  13. +# endif
  14. static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk,
  15. ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,
  16. @@ -112,4 +119,7 @@
  17. #endif
  18. #ifdef SET_DIR_ATTRIB
  19. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  20. + static int Cdecl dircompw OF((ZCONST zvoid *a, ZCONST zvoid *b));
  21. +# endif
  22. static int Cdecl dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));
  23. #endif
  24. @@ -336,4 +346,7 @@
  25. #ifdef SET_DIR_ATTRIB
  26. unsigned num_dirs=0;
  27. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  28. + direntryw *dirlistw=(direntryw *)NULL, **sorted_dirlistw=(direntryw **)NULL;
  29. +#endif
  30. direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL;
  31. #endif
  32. @@ -356,8 +369,25 @@
  33. if (uO.exdir != (char *)NULL && G.extract_flag) {
  34. G.create_dirs = !uO.fflag;
  35. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  36. + if (G.has_win32_wide) {
  37. + wchar_t *exdirw = local_to_wchar_string(uO.exdir);
  38. + if ((error = checkdirw(exdirw, ROOT)) > MPN_INF_SKIP) {
  39. + /* out of memory, or file in way */
  40. + free(exdirw);
  41. + return (error == MPN_NOMEM ? PK_MEM : PK_ERR);
  42. + }
  43. + free(exdirw);
  44. + } else {
  45. + if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) {
  46. + /* out of memory, or file in way */
  47. + return (error == MPN_NOMEM ? PK_MEM : PK_ERR);
  48. + }
  49. + }
  50. +# else /* ! (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  51. if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) {
  52. /* out of memory, or file in way */
  53. return (error == MPN_NOMEM ? PK_MEM : PK_ERR);
  54. }
  55. +# endif /* ! (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  56. }
  57. #endif /* !SFX || SFX_EXDIR */
  58. @@ -570,5 +600,18 @@
  59. -----------------------------------------------------------------------*/
  60. - error = extract_or_test_entrylist(__G__ j,
  61. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  62. + if (G.has_win32_wide)
  63. + {
  64. + error = extract_or_test_entrylistw(__G__ j,
  65. + &filnum, &num_bad_pwd, &old_extra_bytes,
  66. +# ifdef SET_DIR_ATTRIB
  67. + &num_dirs, &dirlistw,
  68. +# endif
  69. + error_in_archive);
  70. + }
  71. + else
  72. +#endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  73. + {
  74. + error = extract_or_test_entrylist(__G__ j,
  75. &filnum, &num_bad_pwd, &old_extra_bytes,
  76. #ifdef SET_DIR_ATTRIB
  77. @@ -576,4 +619,5 @@
  78. #endif
  79. error_in_archive);
  80. + }
  81. if (error != PK_COOL) {
  82. if (error > error_in_archive)
  83. @@ -643,4 +687,55 @@
  84. #ifdef SET_DIR_ATTRIB
  85. if (num_dirs > 0) {
  86. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  87. + if (G.has_win32_wide) {
  88. + sorted_dirlistw = (direntryw **)malloc(num_dirs*sizeof(direntryw *));
  89. + if (sorted_dirlistw == (direntryw **)NULL) {
  90. + Info(slide, 0x401, ((char *)slide,
  91. + LoadFarString(DirlistSortNoMem)));
  92. + while (dirlistw != (direntryw *)NULL) {
  93. + direntryw *dw = dirlistw;
  94. +
  95. + dirlistw = dirlistw->next;
  96. + free(dw);
  97. + }
  98. + } else {
  99. + ulg ndirs_fail = 0;
  100. +
  101. + if (num_dirs == 1)
  102. + sorted_dirlistw[0] = dirlistw;
  103. + else {
  104. + for (i = 0; i < num_dirs; ++i) {
  105. + sorted_dirlistw[i] = dirlistw;
  106. + dirlistw = dirlistw->next;
  107. + }
  108. + qsort((char *)sorted_dirlistw, num_dirs, sizeof(direntryw *),
  109. + dircompw);
  110. + }
  111. +
  112. + Trace((stderr, "setting directory times/perms/attributes\n"));
  113. + for (i = 0; i < num_dirs; ++i) {
  114. + direntryw *dw = sorted_dirlistw[i];
  115. +
  116. + Trace((stderr, "dir = %s\n", dw->fn));
  117. + if ((error = set_direc_attribsw(__G__ dw)) != PK_OK) {
  118. + ndirs_fail++;
  119. + Info(slide, 0x201, ((char *)slide,
  120. + LoadFarString(DirlistSetAttrFailed), dw->fnw));
  121. + if (!error_in_archive)
  122. + error_in_archive = error;
  123. + }
  124. + free(dw);
  125. + }
  126. + free(sorted_dirlistw);
  127. + if (!uO.tflag && QCOND2) {
  128. + if (ndirs_fail > 0)
  129. + Info(slide, 0, ((char *)slide,
  130. + LoadFarString(DirlistFailAttrSum), ndirs_fail));
  131. + }
  132. + }
  133. + }
  134. + else
  135. +# endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  136. + {
  137. sorted_dirlist = (direntry **)malloc(num_dirs*sizeof(direntry *));
  138. if (sorted_dirlist == (direntry **)NULL) {
  139. @@ -688,4 +783,5 @@
  140. }
  141. }
  142. + }
  143. }
  144. #endif /* SET_DIR_ATTRIB */
  145. @@ -821,190 +917,731 @@
  146. #endif
  147. -#ifdef USE_WAVP
  148. -# define UNKN_WAVP (G.crec.compression_method!=WAVPACKED)
  149. -#else
  150. -# define UNKN_WAVP TRUE /* WavPack unknown */
  151. +#ifdef USE_WAVP
  152. +# define UNKN_WAVP (G.crec.compression_method!=WAVPACKED)
  153. +#else
  154. +# define UNKN_WAVP TRUE /* WavPack unknown */
  155. +#endif
  156. +
  157. +#ifdef USE_PPMD
  158. +# define UNKN_PPMD (G.crec.compression_method!=PPMDED)
  159. +#else
  160. +# define UNKN_PPMD TRUE /* PPMd unknown */
  161. +#endif
  162. +
  163. +#ifdef SFX
  164. +# ifdef USE_DEFLATE64
  165. +# define UNKN_COMPR \
  166. + (G.crec.compression_method!=STORED && G.crec.compression_method<DEFLATED \
  167. + && G.crec.compression_method>ENHDEFLATED \
  168. + && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
  169. +# else
  170. +# define UNKN_COMPR \
  171. + (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\
  172. + && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
  173. +# endif
  174. +#else
  175. +# ifdef COPYRIGHT_CLEAN /* no reduced files */
  176. +# define UNKN_RED (G.crec.compression_method >= REDUCED1 && \
  177. + G.crec.compression_method <= REDUCED4)
  178. +# else
  179. +# define UNKN_RED FALSE /* reducing not unknown */
  180. +# endif
  181. +# ifdef LZW_CLEAN /* no shrunk files */
  182. +# define UNKN_SHR (G.crec.compression_method == SHRUNK)
  183. +# else
  184. +# define UNKN_SHR FALSE /* unshrinking not unknown */
  185. +# endif
  186. +# ifdef USE_DEFLATE64
  187. +# define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
  188. + G.crec.compression_method==TOKENIZED || \
  189. + (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \
  190. + && UNKN_WAVP && UNKN_PPMD))
  191. +# else
  192. +# define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
  193. + G.crec.compression_method==TOKENIZED || \
  194. + (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \
  195. + && UNKN_WAVP && UNKN_PPMD))
  196. +# endif
  197. +#endif
  198. +
  199. +#if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS))
  200. + int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS);
  201. +# define UNZVERS_SUPPORT unzvers_support
  202. +#else
  203. +# define UNZVERS_SUPPORT UNZIP_VERSION
  204. +#endif
  205. +
  206. +/*---------------------------------------------------------------------------
  207. + Check central directory info for version/compatibility requirements.
  208. + ---------------------------------------------------------------------------*/
  209. +
  210. + G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1; /* bit field */
  211. + G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8; /* bit */
  212. + G.pInfo->textfile = G.crec.internal_file_attributes & 1; /* bit field */
  213. + G.pInfo->crc = G.crec.crc32;
  214. + G.pInfo->compr_size = G.crec.csize;
  215. + G.pInfo->uncompr_size = G.crec.ucsize;
  216. +
  217. + switch (uO.aflag) {
  218. + case 0:
  219. + G.pInfo->textmode = FALSE; /* bit field */
  220. + break;
  221. + case 1:
  222. + G.pInfo->textmode = G.pInfo->textfile; /* auto-convert mode */
  223. + break;
  224. + default: /* case 2: */
  225. + G.pInfo->textmode = TRUE;
  226. + break;
  227. + }
  228. +
  229. + if (G.crec.version_needed_to_extract[1] == VMS_) {
  230. + if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
  231. + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  232. + Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
  233. + FnFilter1(G.filename), "VMS",
  234. + G.crec.version_needed_to_extract[0] / 10,
  235. + G.crec.version_needed_to_extract[0] % 10,
  236. + VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));
  237. + return 0;
  238. + }
  239. +#ifndef VMS /* won't be able to use extra field, but still have data */
  240. + else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */
  241. + Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),
  242. + FnFilter1(G.filename)));
  243. + fgets(G.answerbuf, 9, stdin);
  244. + if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))
  245. + return 0;
  246. + }
  247. +#endif /* !VMS */
  248. + /* usual file type: don't need VMS to extract */
  249. + } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) {
  250. + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  251. + Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
  252. + FnFilter1(G.filename), "PK",
  253. + G.crec.version_needed_to_extract[0] / 10,
  254. + G.crec.version_needed_to_extract[0] % 10,
  255. + UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10));
  256. + return 0;
  257. + }
  258. +
  259. + if (UNKN_COMPR) {
  260. + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {
  261. +#ifndef SFX
  262. + unsigned cmpridx;
  263. +
  264. + if ((cmpridx = find_compr_idx(G.crec.compression_method))
  265. + < NUM_METHODS)
  266. + Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
  267. + FnFilter1(G.filename),
  268. + LoadFarStringSmall(ComprNames[cmpridx])));
  269. + else
  270. +#endif
  271. + Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),
  272. + FnFilter1(G.filename),
  273. + G.crec.compression_method));
  274. + }
  275. + return 0;
  276. + }
  277. +#if (!CRYPT)
  278. + if (G.pInfo->encrypted) {
  279. + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  280. + Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),
  281. + FnFilter1(G.filename)));
  282. + return 0;
  283. + }
  284. +#endif /* !CRYPT */
  285. +
  286. +#ifndef SFX
  287. + /* store a copy of the central header filename for later comparison */
  288. + if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) {
  289. + Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName),
  290. + FnFilter1(G.filename)));
  291. + } else
  292. + zfstrcpy(G.pInfo->cfilname, G.filename);
  293. +#endif /* !SFX */
  294. +
  295. + /* map whatever file attributes we have into the local format */
  296. + mapattr(__G); /* GRR: worry about return value later */
  297. +
  298. + G.pInfo->diskstart = G.crec.disk_number_start;
  299. + G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header;
  300. + return 1;
  301. +
  302. +} /* end function store_info() */
  303. +
  304. +
  305. +
  306. +
  307. +
  308. +#ifndef SFX
  309. +/*******************************/
  310. +/* Function find_compr_idx() */
  311. +/*******************************/
  312. +
  313. +unsigned find_compr_idx(compr_methodnum)
  314. + unsigned compr_methodnum;
  315. +{
  316. + unsigned i;
  317. +
  318. + for (i = 0; i < NUM_METHODS; i++) {
  319. + if (ComprIDs[i] == compr_methodnum) break;
  320. + }
  321. + return i;
  322. +}
  323. +#endif /* !SFX */
  324. +
  325. +
  326. +
  327. +
  328. +
  329. +/******************************************/
  330. +/* Function extract_or_test_entrylist() */
  331. +/******************************************/
  332. +
  333. +static int extract_or_test_entrylist(__G__ numchunk,
  334. + pfilnum, pnum_bad_pwd, pold_extra_bytes,
  335. +#ifdef SET_DIR_ATTRIB
  336. + pnum_dirs, pdirlist,
  337. +#endif
  338. + error_in_archive) /* return PK-type error code */
  339. + __GDEF
  340. + unsigned numchunk;
  341. + ulg *pfilnum;
  342. + ulg *pnum_bad_pwd;
  343. + zoff_t *pold_extra_bytes;
  344. +#ifdef SET_DIR_ATTRIB
  345. + unsigned *pnum_dirs;
  346. + direntry **pdirlist;
  347. +#endif
  348. + int error_in_archive;
  349. +{
  350. + unsigned i;
  351. + int renamed, query;
  352. + int skip_entry;
  353. + zoff_t bufstart, inbuf_offset, request;
  354. + int error, errcode;
  355. +
  356. +/* possible values for local skip_entry flag: */
  357. +#define SKIP_NO 0 /* do not skip this entry */
  358. +#define SKIP_Y_EXISTING 1 /* skip this entry, do not overwrite file */
  359. +#define SKIP_Y_NONEXIST 2 /* skip this entry, do not create new file */
  360. +
  361. + /*-----------------------------------------------------------------------
  362. + Second loop: process files in current block, extracting or testing
  363. + each one.
  364. + -----------------------------------------------------------------------*/
  365. +
  366. + for (i = 0; i < numchunk; ++i) {
  367. + (*pfilnum)++; /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */
  368. + G.pInfo = &G.info[i];
  369. +#ifdef NOVELL_BUG_FAILSAFE
  370. + G.dne = FALSE; /* assume file exists until stat() says otherwise */
  371. +#endif
  372. +
  373. + /* if the target position is not within the current input buffer
  374. + * (either haven't yet read far enough, or (maybe) skipping back-
  375. + * ward), skip to the target position and reset readbuf(). */
  376. +
  377. + /* seek_zipf(__G__ pInfo->offset); */
  378. + request = G.pInfo->offset + G.extra_bytes;
  379. + inbuf_offset = request % INBUFSIZ;
  380. + bufstart = request - inbuf_offset;
  381. +
  382. + Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n",
  383. + (long)request, (long)inbuf_offset));
  384. + Trace((stderr,
  385. + "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
  386. + (long)bufstart, (long)G.cur_zipfile_bufstart));
  387. + if (request < 0) {
  388. + Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
  389. + G.zipfn, LoadFarString(ReportMsg)));
  390. + error_in_archive = PK_ERR;
  391. + if (*pfilnum == 1 && G.extra_bytes != 0L) {
  392. + Info(slide, 0x401, ((char *)slide,
  393. + LoadFarString(AttemptRecompensate)));
  394. + *pold_extra_bytes = G.extra_bytes;
  395. + G.extra_bytes = 0L;
  396. + request = G.pInfo->offset; /* could also check if != 0 */
  397. + inbuf_offset = request % INBUFSIZ;
  398. + bufstart = request - inbuf_offset;
  399. + Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n",
  400. + (long)request, (long)inbuf_offset));
  401. + Trace((stderr,
  402. + "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
  403. + (long)bufstart, (long)G.cur_zipfile_bufstart));
  404. + /* try again */
  405. + if (request < 0) {
  406. + Trace((stderr,
  407. + "debug: recompensated request still < 0\n"));
  408. + Info(slide, 0x401, ((char *)slide,
  409. + LoadFarStringSmall(SeekMsg),
  410. + G.zipfn, LoadFarString(ReportMsg)));
  411. + error_in_archive = PK_BADERR;
  412. + continue;
  413. + }
  414. + } else {
  415. + error_in_archive = PK_BADERR;
  416. + continue; /* this one hosed; try next */
  417. + }
  418. + }
  419. +
  420. + if (bufstart != G.cur_zipfile_bufstart) {
  421. + Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n"));
  422. +#ifdef USE_STRM_INPUT
  423. + zfseeko(G.zipfd, bufstart, SEEK_SET);
  424. + G.cur_zipfile_bufstart = zftello(G.zipfd);
  425. +#else /* !USE_STRM_INPUT */
  426. + G.cur_zipfile_bufstart =
  427. + zlseek(G.zipfd, bufstart, SEEK_SET);
  428. +#endif /* ?USE_STRM_INPUT */
  429. + if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
  430. + {
  431. + Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  432. + *pfilnum, "lseek", (long)bufstart));
  433. + error_in_archive = PK_BADERR;
  434. + continue; /* can still do next file */
  435. + }
  436. + G.inptr = G.inbuf + (int)inbuf_offset;
  437. + G.incnt -= (int)inbuf_offset;
  438. + } else {
  439. + G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;
  440. + G.inptr = G.inbuf + (int)inbuf_offset;
  441. + }
  442. +
  443. + /* should be in proper position now, so check for sig */
  444. + if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */
  445. + Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  446. + *pfilnum, "EOF", (long)request));
  447. + error_in_archive = PK_BADERR;
  448. + continue; /* but can still try next one */
  449. + }
  450. + if (strncmp(G.sig, local_hdr_sig, 4)) {
  451. + Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  452. + *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request));
  453. + /*
  454. + GRRDUMP(G.sig, 4)
  455. + GRRDUMP(local_hdr_sig, 4)
  456. + */
  457. + error_in_archive = PK_ERR;
  458. + if ((*pfilnum == 1 && G.extra_bytes != 0L) ||
  459. + (G.extra_bytes == 0L && *pold_extra_bytes != 0L)) {
  460. + Info(slide, 0x401, ((char *)slide,
  461. + LoadFarString(AttemptRecompensate)));
  462. + if (G.extra_bytes) {
  463. + *pold_extra_bytes = G.extra_bytes;
  464. + G.extra_bytes = 0L;
  465. + } else
  466. + G.extra_bytes = *pold_extra_bytes; /* third attempt */
  467. + if (((error = seek_zipf(__G__ G.pInfo->offset)) != PK_OK) ||
  468. + (readbuf(__G__ G.sig, 4) == 0)) { /* bad offset */
  469. + if (error != PK_BADERR)
  470. + Info(slide, 0x401, ((char *)slide,
  471. + LoadFarString(OffsetMsg), *pfilnum, "EOF",
  472. + (long)request));
  473. + error_in_archive = PK_BADERR;
  474. + continue; /* but can still try next one */
  475. + }
  476. + if (strncmp(G.sig, local_hdr_sig, 4)) {
  477. + Info(slide, 0x401, ((char *)slide,
  478. + LoadFarString(OffsetMsg), *pfilnum,
  479. + LoadFarStringSmall(LocalHdrSig), (long)request));
  480. + error_in_archive = PK_BADERR;
  481. + continue;
  482. + }
  483. + } else
  484. + continue; /* this one hosed; try next */
  485. + }
  486. + if ((error = process_local_file_hdr(__G)) != PK_COOL) {
  487. + Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),
  488. + *pfilnum));
  489. + error_in_archive = error; /* only PK_EOF defined */
  490. + continue; /* can still try next one */
  491. + }
  492. + if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) !=
  493. + PK_COOL)
  494. + {
  495. + if (error > error_in_archive)
  496. + error_in_archive = error;
  497. + if (error > PK_WARN) {
  498. + Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
  499. + FnFilter1(G.filename), "local"));
  500. + continue; /* go on to next one */
  501. + }
  502. + }
  503. + if (G.extra_field != (uch *)NULL) {
  504. + free(G.extra_field);
  505. + G.extra_field = (uch *)NULL;
  506. + }
  507. + if ((error =
  508. + do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)
  509. + {
  510. + if (error > error_in_archive)
  511. + error_in_archive = error;
  512. + if (error > PK_WARN) {
  513. + Info(slide, 0x401, ((char *)slide,
  514. + LoadFarString(ExtFieldMsg),
  515. + FnFilter1(G.filename), "local"));
  516. + continue; /* go on */
  517. + }
  518. + }
  519. +#ifndef SFX
  520. + /* Filename consistency checks must come after reading in the local
  521. + * extra field, so that a UTF-8 entry name e.f. block has already
  522. + * been processed.
  523. + */
  524. + if (G.pInfo->cfilname != (char Far *)NULL) {
  525. + if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) {
  526. +# ifdef SMALL_MEM
  527. + char *temp_cfilnam = slide + (7 * (WSIZE>>3));
  528. +
  529. + zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname);
  530. +# define cFile_PrintBuf temp_cfilnam
  531. +# else
  532. +# define cFile_PrintBuf G.pInfo->cfilname
  533. +# endif
  534. + Info(slide, 0x401, ((char *)slide,
  535. + LoadFarStringSmall2(LvsCFNamMsg),
  536. + FnFilter2(cFile_PrintBuf), FnFilter1(G.filename)));
  537. +# undef cFile_PrintBuf
  538. + zfstrcpy(G.filename, G.pInfo->cfilname);
  539. + if (error_in_archive < PK_WARN)
  540. + error_in_archive = PK_WARN;
  541. + }
  542. + zffree(G.pInfo->cfilname);
  543. + G.pInfo->cfilname = (char Far *)NULL;
  544. + }
  545. +#endif /* !SFX */
  546. + /* Size consistency checks must come after reading in the local extra
  547. + * field, so that any Zip64 extension local e.f. block has already
  548. + * been processed.
  549. + */
  550. + if (G.lrec.compression_method == STORED) {
  551. + zusz_t csiz_decrypted = G.lrec.csize;
  552. +
  553. + if (G.pInfo->encrypted)
  554. + csiz_decrypted -= 12;
  555. + if (G.lrec.ucsize != csiz_decrypted) {
  556. + Info(slide, 0x401, ((char *)slide,
  557. + LoadFarStringSmall2(WrnStorUCSizCSizDiff),
  558. + FnFilter1(G.filename),
  559. + FmZofft(G.lrec.ucsize, NULL, "u"),
  560. + FmZofft(csiz_decrypted, NULL, "u")));
  561. + G.lrec.ucsize = csiz_decrypted;
  562. + if (error_in_archive < PK_WARN)
  563. + error_in_archive = PK_WARN;
  564. + }
  565. + }
  566. +
  567. +#if CRYPT
  568. + if (G.pInfo->encrypted &&
  569. + (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) {
  570. + if (error == PK_WARN) {
  571. + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  572. + Info(slide, 0x401, ((char *)slide,
  573. + LoadFarString(SkipIncorrectPasswd),
  574. + FnFilter1(G.filename)));
  575. + ++(*pnum_bad_pwd);
  576. + } else { /* (error > PK_WARN) */
  577. + if (error > error_in_archive)
  578. + error_in_archive = error;
  579. + Info(slide, 0x401, ((char *)slide,
  580. + LoadFarString(SkipCannotGetPasswd),
  581. + FnFilter1(G.filename)));
  582. + }
  583. + continue; /* go on to next file */
  584. + }
  585. +#endif /* CRYPT */
  586. +
  587. + /*
  588. + * just about to extract file: if extracting to disk, check if
  589. + * already exists, and if so, take appropriate action according to
  590. + * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
  591. + * loop because we don't store the possibly renamed filename[] in
  592. + * info[])
  593. + */
  594. +#ifdef DLL
  595. + if (!uO.tflag && !uO.cflag && !G.redirect_data)
  596. +#else
  597. + if (!uO.tflag && !uO.cflag)
  598. +#endif
  599. + {
  600. + renamed = FALSE; /* user hasn't renamed output file yet */
  601. +
  602. +startover:
  603. + query = FALSE;
  604. + skip_entry = SKIP_NO;
  605. + /* for files from DOS FAT, check for use of backslash instead
  606. + * of slash as directory separator (bug in some zipper(s); so
  607. + * far, not a problem in HPFS, NTFS or VFAT systems)
  608. + */
  609. +#ifndef SFX
  610. + if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) {
  611. + char *p=G.filename;
  612. +
  613. + if (*p) do {
  614. + if (*p == '\\') {
  615. + if (!G.reported_backslash) {
  616. + Info(slide, 0x21, ((char *)slide,
  617. + LoadFarString(BackslashPathSep), G.zipfn));
  618. + G.reported_backslash = TRUE;
  619. + if (!error_in_archive)
  620. + error_in_archive = PK_WARN;
  621. + }
  622. + *p = '/';
  623. + }
  624. + } while (*PREINCSTR(p));
  625. + }
  626. +#endif /* !SFX */
  627. +
  628. + if (!renamed) {
  629. + /* remove absolute path specs */
  630. + if (G.filename[0] == '/') {
  631. + Info(slide, 0x401, ((char *)slide,
  632. + LoadFarString(AbsolutePathWarning),
  633. + FnFilter1(G.filename)));
  634. + if (!error_in_archive)
  635. + error_in_archive = PK_WARN;
  636. + do {
  637. + char *p = G.filename + 1;
  638. + do {
  639. + *(p-1) = *p;
  640. + } while (*p++ != '\0');
  641. + } while (G.filename[0] == '/');
  642. + }
  643. + }
  644. +
  645. + /* mapname can create dirs if not freshening or if renamed */
  646. + error = mapname(__G__ renamed);
  647. + if ((errcode = error & ~MPN_MASK) != PK_OK &&
  648. + error_in_archive < errcode)
  649. + error_in_archive = errcode;
  650. + if ((errcode = error & MPN_MASK) > MPN_INF_TRUNC) {
  651. + if (errcode == MPN_CREATED_DIR) {
  652. +#ifdef SET_DIR_ATTRIB
  653. + direntry *d_entry;
  654. +
  655. + error = defer_dir_attribs(__G__ &d_entry);
  656. + if (d_entry == (direntry *)NULL) {
  657. + /* There may be no dir_attribs info available, or
  658. + * we have encountered a mem allocation error.
  659. + * In case of an error, report it and set program
  660. + * error state to warning level.
  661. + */
  662. + if (error) {
  663. + Info(slide, 0x401, ((char *)slide,
  664. + LoadFarString(DirlistEntryNoMem)));
  665. + if (!error_in_archive)
  666. + error_in_archive = PK_WARN;
  667. + }
  668. + } else {
  669. + d_entry->next = (*pdirlist);
  670. + (*pdirlist) = d_entry;
  671. + ++(*pnum_dirs);
  672. + }
  673. +#endif /* SET_DIR_ATTRIB */
  674. + } else if (errcode == MPN_VOL_LABEL) {
  675. +#ifdef DOS_OS2_W32
  676. + Info(slide, 0x401, ((char *)slide,
  677. + LoadFarString(SkipVolumeLabel),
  678. + FnFilter1(G.filename),
  679. + uO.volflag? "hard disk " : ""));
  680. +#else
  681. + Info(slide, 1, ((char *)slide,
  682. + LoadFarString(SkipVolumeLabel),
  683. + FnFilter1(G.filename), ""));
  684. +#endif
  685. + } else if (errcode > MPN_INF_SKIP &&
  686. + error_in_archive < PK_ERR)
  687. + error_in_archive = PK_ERR;
  688. + Trace((stderr, "mapname(%s) returns error code = %d\n",
  689. + FnFilter1(G.filename), error));
  690. + continue; /* go on to next file */
  691. + }
  692. +
  693. +#ifdef QDOS
  694. + QFilename(__G__ G.filename);
  695. +#endif
  696. + switch (check_for_newer(__G__ G.filename)) {
  697. + case DOES_NOT_EXIST:
  698. +#ifdef NOVELL_BUG_FAILSAFE
  699. + G.dne = TRUE; /* stat() says file DOES NOT EXIST */
  700. +#endif
  701. + /* freshen (no new files): skip unless just renamed */
  702. + if (uO.fflag && !renamed)
  703. + skip_entry = SKIP_Y_NONEXIST;
  704. + break;
  705. + case EXISTS_AND_OLDER:
  706. +#ifdef UNIXBACKUP
  707. + if (!uO.B_flag)
  708. +#endif
  709. + {
  710. + if (IS_OVERWRT_NONE)
  711. + /* never overwrite: skip file */
  712. + skip_entry = SKIP_Y_EXISTING;
  713. + else if (!IS_OVERWRT_ALL)
  714. + query = TRUE;
  715. + }
  716. + break;
  717. + case EXISTS_AND_NEWER: /* (or equal) */
  718. +#ifdef UNIXBACKUP
  719. + if ((!uO.B_flag && IS_OVERWRT_NONE) ||
  720. +#else
  721. + if (IS_OVERWRT_NONE ||
  722. +#endif
  723. + (uO.uflag && !renamed)) {
  724. + /* skip if update/freshen & orig name */
  725. + skip_entry = SKIP_Y_EXISTING;
  726. + } else {
  727. +#ifdef UNIXBACKUP
  728. + if (!IS_OVERWRT_ALL && !uO.B_flag)
  729. +#else
  730. + if (!IS_OVERWRT_ALL)
  731. +#endif
  732. + query = TRUE;
  733. + }
  734. + break;
  735. + }
  736. + if (query) {
  737. +#ifdef WINDLL
  738. + switch (G.lpUserFunctions->replace != NULL ?
  739. + (*G.lpUserFunctions->replace)(G.filename) :
  740. + IDM_REPLACE_NONE) {
  741. + case IDM_REPLACE_RENAME:
  742. + _ISO_INTERN(G.filename);
  743. + renamed = TRUE;
  744. + goto startover;
  745. + case IDM_REPLACE_ALL:
  746. + G.overwrite_mode = OVERWRT_ALWAYS;
  747. + /* FALL THROUGH, extract */
  748. + case IDM_REPLACE_YES:
  749. + break;
  750. + case IDM_REPLACE_NONE:
  751. + G.overwrite_mode = OVERWRT_NEVER;
  752. + /* FALL THROUGH, skip */
  753. + case IDM_REPLACE_NO:
  754. + skip_entry = SKIP_Y_EXISTING;
  755. + break;
  756. + }
  757. +#else /* !WINDLL */
  758. + extent fnlen;
  759. +reprompt:
  760. + Info(slide, 0x81, ((char *)slide,
  761. + LoadFarString(ReplaceQuery),
  762. + FnFilter1(G.filename)));
  763. + if (fgets(G.answerbuf, 9, stdin) == (char *)NULL) {
  764. + Info(slide, 1, ((char *)slide,
  765. + LoadFarString(AssumeNone)));
  766. + *G.answerbuf = 'N';
  767. + if (!error_in_archive)
  768. + error_in_archive = 1; /* not extracted: warning */
  769. + }
  770. + switch (*G.answerbuf) {
  771. + case 'r':
  772. + case 'R':
  773. + do {
  774. + Info(slide, 0x81, ((char *)slide,
  775. + LoadFarString(NewNameQuery)));
  776. + fgets(G.filename, FILNAMSIZ, stdin);
  777. + /* usually get \n here: better check for it */
  778. + fnlen = strlen(G.filename);
  779. + if (lastchar(G.filename, fnlen) == '\n')
  780. + G.filename[--fnlen] = '\0';
  781. + } while (fnlen == 0);
  782. +#ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */
  783. + _OEM_INTERN(G.filename);
  784. +#endif
  785. + renamed = TRUE;
  786. + goto startover; /* sorry for a goto */
  787. + case 'A': /* dangerous option: force caps */
  788. + G.overwrite_mode = OVERWRT_ALWAYS;
  789. + /* FALL THROUGH, extract */
  790. + case 'y':
  791. + case 'Y':
  792. + break;
  793. + case 'N':
  794. + G.overwrite_mode = OVERWRT_NEVER;
  795. + /* FALL THROUGH, skip */
  796. + case 'n':
  797. + /* skip file */
  798. + skip_entry = SKIP_Y_EXISTING;
  799. + break;
  800. + case '\n':
  801. + case '\r':
  802. + /* Improve echo of '\n' and/or '\r'
  803. + (sizeof(G.answerbuf) == 10 (see globals.h), so
  804. + there is enough space for the provided text...) */
  805. + strcpy(G.answerbuf, "{ENTER}");
  806. + /* fall through ... */
  807. + default:
  808. + Info(slide, 1, ((char *)slide,
  809. + LoadFarString(InvalidResponse), *G.answerbuf));
  810. + goto reprompt; /* yet another goto? */
  811. + } /* end switch (*answerbuf) */
  812. +#endif /* ?WINDLL */
  813. + } /* end if (query) */
  814. + if (skip_entry != SKIP_NO) {
  815. +#ifdef WINDLL
  816. + if (skip_entry == SKIP_Y_EXISTING) {
  817. + /* report skipping of an existing entry */
  818. + Info(slide, 0, ((char *)slide,
  819. + ((IS_OVERWRT_NONE || !uO.uflag || renamed) ?
  820. + "Target file exists.\nSkipping %s\n" :
  821. + "Target file newer.\nSkipping %s\n"),
  822. + FnFilter1(G.filename)));
  823. + }
  824. +#endif /* WINDLL */
  825. + continue;
  826. + }
  827. + } /* end if (extracting to disk) */
  828. +
  829. +#ifdef DLL
  830. + if ((G.statreportcb != NULL) &&
  831. + (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn,
  832. + G.filename, NULL)) {
  833. + return IZ_CTRLC; /* cancel operation by user request */
  834. + }
  835. #endif
  836. -
  837. -#ifdef USE_PPMD
  838. -# define UNKN_PPMD (G.crec.compression_method!=PPMDED)
  839. -#else
  840. -# define UNKN_PPMD TRUE /* PPMd unknown */
  841. +#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
  842. + UserStop();
  843. #endif
  844. -
  845. -#ifdef SFX
  846. -# ifdef USE_DEFLATE64
  847. -# define UNKN_COMPR \
  848. - (G.crec.compression_method!=STORED && G.crec.compression_method<DEFLATED \
  849. - && G.crec.compression_method>ENHDEFLATED \
  850. - && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
  851. -# else
  852. -# define UNKN_COMPR \
  853. - (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\
  854. - && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
  855. -# endif
  856. -#else
  857. -# ifdef COPYRIGHT_CLEAN /* no reduced files */
  858. -# define UNKN_RED (G.crec.compression_method >= REDUCED1 && \
  859. - G.crec.compression_method <= REDUCED4)
  860. -# else
  861. -# define UNKN_RED FALSE /* reducing not unknown */
  862. -# endif
  863. -# ifdef LZW_CLEAN /* no shrunk files */
  864. -# define UNKN_SHR (G.crec.compression_method == SHRUNK)
  865. -# else
  866. -# define UNKN_SHR FALSE /* unshrinking not unknown */
  867. -# endif
  868. -# ifdef USE_DEFLATE64
  869. -# define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
  870. - G.crec.compression_method==TOKENIZED || \
  871. - (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \
  872. - && UNKN_WAVP && UNKN_PPMD))
  873. -# else
  874. -# define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
  875. - G.crec.compression_method==TOKENIZED || \
  876. - (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \
  877. - && UNKN_WAVP && UNKN_PPMD))
  878. -# endif
  879. +#ifdef AMIGA
  880. + G.filenote_slot = i;
  881. #endif
  882. -
  883. -#if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS))
  884. - int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS);
  885. -# define UNZVERS_SUPPORT unzvers_support
  886. + G.disk_full = 0;
  887. + if ((error = extract_or_test_member(__G)) != PK_COOL) {
  888. + if (error > error_in_archive)
  889. + error_in_archive = error; /* ...and keep going */
  890. +#ifdef DLL
  891. + if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
  892. #else
  893. -# define UNZVERS_SUPPORT UNZIP_VERSION
  894. + if (G.disk_full > 1) {
  895. #endif
  896. -
  897. -/*---------------------------------------------------------------------------
  898. - Check central directory info for version/compatibility requirements.
  899. - ---------------------------------------------------------------------------*/
  900. -
  901. - G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1; /* bit field */
  902. - G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8; /* bit */
  903. - G.pInfo->textfile = G.crec.internal_file_attributes & 1; /* bit field */
  904. - G.pInfo->crc = G.crec.crc32;
  905. - G.pInfo->compr_size = G.crec.csize;
  906. - G.pInfo->uncompr_size = G.crec.ucsize;
  907. -
  908. - switch (uO.aflag) {
  909. - case 0:
  910. - G.pInfo->textmode = FALSE; /* bit field */
  911. - break;
  912. - case 1:
  913. - G.pInfo->textmode = G.pInfo->textfile; /* auto-convert mode */
  914. - break;
  915. - default: /* case 2: */
  916. - G.pInfo->textmode = TRUE;
  917. - break;
  918. - }
  919. -
  920. - if (G.crec.version_needed_to_extract[1] == VMS_) {
  921. - if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
  922. - if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  923. - Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
  924. - FnFilter1(G.filename), "VMS",
  925. - G.crec.version_needed_to_extract[0] / 10,
  926. - G.crec.version_needed_to_extract[0] % 10,
  927. - VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));
  928. - return 0;
  929. + return error_in_archive; /* (unless disk full) */
  930. + }
  931. }
  932. -#ifndef VMS /* won't be able to use extra field, but still have data */
  933. - else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */
  934. - Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),
  935. - FnFilter1(G.filename)));
  936. - fgets(G.answerbuf, 9, stdin);
  937. - if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))
  938. - return 0;
  939. +#ifdef DLL
  940. + if ((G.statreportcb != NULL) &&
  941. + (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
  942. + G.filename, (zvoid *)&G.lrec.ucsize)) {
  943. + return IZ_CTRLC; /* cancel operation by user request */
  944. }
  945. -#endif /* !VMS */
  946. - /* usual file type: don't need VMS to extract */
  947. - } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) {
  948. - if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  949. - Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
  950. - FnFilter1(G.filename), "PK",
  951. - G.crec.version_needed_to_extract[0] / 10,
  952. - G.crec.version_needed_to_extract[0] % 10,
  953. - UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10));
  954. - return 0;
  955. - }
  956. -
  957. - if (UNKN_COMPR) {
  958. - if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {
  959. -#ifndef SFX
  960. - unsigned cmpridx;
  961. -
  962. - if ((cmpridx = find_compr_idx(G.crec.compression_method))
  963. - < NUM_METHODS)
  964. - Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
  965. - FnFilter1(G.filename),
  966. - LoadFarStringSmall(ComprNames[cmpridx])));
  967. - else
  968. #endif
  969. - Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),
  970. - FnFilter1(G.filename),
  971. - G.crec.compression_method));
  972. - }
  973. - return 0;
  974. - }
  975. -#if (!CRYPT)
  976. - if (G.pInfo->encrypted) {
  977. - if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  978. - Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),
  979. - FnFilter1(G.filename)));
  980. - return 0;
  981. - }
  982. -#endif /* !CRYPT */
  983. -
  984. -#ifndef SFX
  985. - /* store a copy of the central header filename for later comparison */
  986. - if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) {
  987. - Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName),
  988. - FnFilter1(G.filename)));
  989. - } else
  990. - zfstrcpy(G.pInfo->cfilname, G.filename);
  991. -#endif /* !SFX */
  992. -
  993. - /* map whatever file attributes we have into the local format */
  994. - mapattr(__G); /* GRR: worry about return value later */
  995. -
  996. - G.pInfo->diskstart = G.crec.disk_number_start;
  997. - G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header;
  998. - return 1;
  999. -
  1000. -} /* end function store_info() */
  1001. -
  1002. -
  1003. -
  1004. -
  1005. -
  1006. -#ifndef SFX
  1007. -/*******************************/
  1008. -/* Function find_compr_idx() */
  1009. -/*******************************/
  1010. -
  1011. -unsigned find_compr_idx(compr_methodnum)
  1012. - unsigned compr_methodnum;
  1013. -{
  1014. - unsigned i;
  1015. -
  1016. - for (i = 0; i < NUM_METHODS; i++) {
  1017. - if (ComprIDs[i] == compr_methodnum) break;
  1018. - }
  1019. - return i;
  1020. -}
  1021. -#endif /* !SFX */
  1022. +#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
  1023. + UserStop();
  1024. +#endif
  1025. + } /* end for-loop (i: files in current block) */
  1026. + return error_in_archive;
  1027. +} /* end function extract_or_test_entrylist() */
  1028. -/******************************************/
  1029. -/* Function extract_or_test_entrylist() */
  1030. -/******************************************/
  1031. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1032. -static int extract_or_test_entrylist(__G__ numchunk,
  1033. +static int extract_or_test_entrylistw(__G__ numchunk,
  1034. pfilnum, pnum_bad_pwd, pold_extra_bytes,
  1035. #ifdef SET_DIR_ATTRIB
  1036. - pnum_dirs, pdirlist,
  1037. + pnum_dirs, pdirlistw,
  1038. #endif
  1039. error_in_archive) /* return PK-type error code */
  1040. @@ -1016,5 +1653,5 @@
  1041. #ifdef SET_DIR_ATTRIB
  1042. unsigned *pnum_dirs;
  1043. - direntry **pdirlist;
  1044. + direntryw **pdirlistw;
  1045. #endif
  1046. int error_in_archive;
  1047. @@ -1190,8 +1827,4 @@
  1048. }
  1049. #ifndef SFX
  1050. - /* Filename consistency checks must come after reading in the local
  1051. - * extra field, so that a UTF-8 entry name e.f. block has already
  1052. - * been processed.
  1053. - */
  1054. if (G.pInfo->cfilname != (char Far *)NULL) {
  1055. if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) {
  1056. @@ -1316,5 +1949,8 @@
  1057. /* mapname can create dirs if not freshening or if renamed */
  1058. - error = mapname(__G__ renamed);
  1059. + if (G.has_win32_wide)
  1060. + error = mapnamew(__G__ renamed);
  1061. + else
  1062. + error = mapname(__G__ renamed);
  1063. if ((errcode = error & ~MPN_MASK) != PK_OK &&
  1064. error_in_archive < errcode)
  1065. @@ -1323,24 +1959,24 @@
  1066. if (errcode == MPN_CREATED_DIR) {
  1067. #ifdef SET_DIR_ATTRIB
  1068. - direntry *d_entry;
  1069. + direntryw *d_entryw;
  1070. - error = defer_dir_attribs(__G__ &d_entry);
  1071. - if (d_entry == (direntry *)NULL) {
  1072. - /* There may be no dir_attribs info available, or
  1073. - * we have encountered a mem allocation error.
  1074. - * In case of an error, report it and set program
  1075. - * error state to warning level.
  1076. - */
  1077. - if (error) {
  1078. - Info(slide, 0x401, ((char *)slide,
  1079. - LoadFarString(DirlistEntryNoMem)));
  1080. - if (!error_in_archive)
  1081. - error_in_archive = PK_WARN;
  1082. - }
  1083. - } else {
  1084. - d_entry->next = (*pdirlist);
  1085. - (*pdirlist) = d_entry;
  1086. - ++(*pnum_dirs);
  1087. - }
  1088. + error = defer_dir_attribsw(__G__ &d_entryw);
  1089. + if (d_entryw == (direntryw *)NULL) {
  1090. + /* There may be no dir_attribs info available, or
  1091. + * we have encountered a mem allocation error.
  1092. + * In case of an error, report it and set program
  1093. + * error state to warning level.
  1094. + */
  1095. + if (error) {
  1096. + Info(slide, 0x401, ((char *)slide,
  1097. + LoadFarString(DirlistEntryNoMem)));
  1098. + if (!error_in_archive)
  1099. + error_in_archive = PK_WARN;
  1100. + }
  1101. + } else {
  1102. + d_entryw->next = (*pdirlistw);
  1103. + (*pdirlistw) = d_entryw;
  1104. + ++(*pnum_dirs);
  1105. + }
  1106. #endif /* SET_DIR_ATTRIB */
  1107. } else if (errcode == MPN_VOL_LABEL) {
  1108. @@ -1366,5 +2002,5 @@
  1109. QFilename(__G__ G.filename);
  1110. #endif
  1111. - switch (check_for_newer(__G__ G.filename)) {
  1112. + switch (check_for_newerw(__G__ G.unipath_widefilename)) {
  1113. case DOES_NOT_EXIST:
  1114. #ifdef NOVELL_BUG_FAILSAFE
  1115. @@ -1538,5 +2174,7 @@
  1116. return error_in_archive;
  1117. -} /* end function extract_or_test_entrylist() */
  1118. +} /* end function extract_or_test_entrylistw() */
  1119. +
  1120. +#endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  1121. @@ -2565,4 +3203,14 @@
  1122. /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */
  1123. }
  1124. +
  1125. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1126. +static int Cdecl dircompw(a, b) /* used by qsort(); swiped from Zip */
  1127. + ZCONST zvoid *a, *b;
  1128. +{
  1129. + /* order is significant: this sorts in reverse order (deepest first) */
  1130. + return wcscmp((*(direntryw **)b)->fnw, (*(direntryw **)a)->fnw);
  1131. + /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */
  1132. +}
  1133. +# endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  1134. #endif /* SET_DIR_ATTRIB */
  1135. diff -ru2 unz60d10/fileio.c unz60d10_w32w/fileio.c
  1136. --- unz60d10/fileio.c Sun Jan 27 16:39:14 2008
  1137. +++ unz60d10_w32w/fileio.c Mon Feb 11 01:09:22 2008
  1138. @@ -294,5 +294,12 @@
  1139. zlstat(G.filename, &G.statbuf) == 0)
  1140. #else
  1141. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1142. + if ((G.has_win32_wide
  1143. + ? SSTATW(G.unipath_widefilename, &G.statbuf)
  1144. + : SSTAT(G.filename, &G.statbuf)
  1145. + ) == 0)
  1146. +#else
  1147. if (SSTAT(G.filename, &G.statbuf) == 0)
  1148. +#endif
  1149. #endif /* ?SYMLINKS */
  1150. {
  1151. @@ -378,5 +385,13 @@
  1152. chmod(G.filename, 0);
  1153. #endif /* NLM */
  1154. - if (unlink(G.filename) != 0) {
  1155. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1156. + if ((G.has_win32_wide
  1157. + ? _wunlink(G.unipath_widefilename)
  1158. + : unlink(G.filename)
  1159. + ) != 0)
  1160. +#else
  1161. + if (unlink(G.filename) != 0)
  1162. +#endif
  1163. + {
  1164. Info(slide, 0x401, ((char *)slide,
  1165. LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename)));
  1166. @@ -456,5 +471,12 @@
  1167. G.outfile = zfopen(G.filename, FOPWR);
  1168. #else
  1169. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1170. + G.outfile = (G.has_win32_wide
  1171. + ? zfopenw(G.unipath_widefilename, L"wb")
  1172. + : zfopen(G.filename, FOPW)
  1173. + );
  1174. +#else /* (UNICODE_SUPPORT && WIN32_WIDE) */
  1175. G.outfile = zfopen(G.filename, FOPW);
  1176. +#endif /* ?(UNICODE_SUPPORT && WIN32_WIDE) */
  1177. #endif
  1178. #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM)
  1179. @@ -1984,4 +2006,115 @@
  1180. } /* end function check_for_newer() */
  1181. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1182. +int check_for_newerw(__G__ filenamew) /* return 1 if existing file is newer */
  1183. + __GDEF /* or equal; 0 if older; -1 if doesn't */
  1184. + wchar_t *filenamew; /* exist yet */
  1185. +{
  1186. + time_t existing, archive;
  1187. +#ifdef USE_EF_UT_TIME
  1188. + iztimes z_utime;
  1189. +#endif
  1190. +#ifdef AOS_VS
  1191. + long dyy, dmm, ddd, dhh, dmin, dss;
  1192. +
  1193. +
  1194. + dyy = (lrec.last_mod_dos_datetime >> 25) + 1980;
  1195. + dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f;
  1196. + ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f;
  1197. + dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f;
  1198. + dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f;
  1199. + dss = (lrec.last_mod_dos_datetime & 0x1f) * 2;
  1200. +
  1201. + /* under AOS/VS, file times can only be set at creation time,
  1202. + * with the info in a special DG format. Make sure we can create
  1203. + * it here - we delete it later & re-create it, whether or not
  1204. + * it exists now.
  1205. + */
  1206. + if (!zvs_create(filenamew, (((ulg)dgdate(dmm, ddd, dyy)) << 16) |
  1207. + (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1))
  1208. + return DOES_NOT_EXIST;
  1209. +#endif /* AOS_VS */
  1210. +
  1211. + Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename)));
  1212. + if (SSTATW(filenamew, &G.statbuf)) {
  1213. + Trace((stderr,
  1214. + "check_for_newer: stat(%s) returns %d: file does not exist\n",
  1215. + FnFilter1(filename), SSTAT(filename, &G.statbuf)));
  1216. +#ifdef SYMLINKS
  1217. + Trace((stderr, "check_for_newer: doing lstat(%s)\n",
  1218. + FnFilter1(filename)));
  1219. + /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
  1220. + if (zlstat(filename, &G.statbuf) == 0) {
  1221. + Trace((stderr,
  1222. + "check_for_newer: lstat(%s) returns 0: symlink does exist\n",
  1223. + FnFilter1(filename)));
  1224. + if (QCOND2 && !IS_OVERWRT_ALL)
  1225. + Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
  1226. + FnFilter1(filename), " with no real file"));
  1227. + return EXISTS_AND_OLDER; /* symlink dates are meaningless */
  1228. + }
  1229. +#endif /* SYMLINKS */
  1230. + return DOES_NOT_EXIST;
  1231. + }
  1232. + Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n",
  1233. + FnFilter1(filename)));
  1234. +
  1235. +#ifdef SYMLINKS
  1236. + /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
  1237. + if (zlstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) {
  1238. + Trace((stderr, "check_for_newer: %s is a symbolic link\n",
  1239. + FnFilter1(filename)));
  1240. + if (QCOND2 && !IS_OVERWRT_ALL)
  1241. + Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
  1242. + FnFilter1(filename), ""));
  1243. + return EXISTS_AND_OLDER; /* symlink dates are meaningless */
  1244. + }
  1245. +#endif /* SYMLINKS */
  1246. +
  1247. + NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */
  1248. +
  1249. +#ifdef USE_EF_UT_TIME
  1250. + /* The `Unix extra field mtime' should be used for comparison with the
  1251. + * time stamp of the existing file >>>ONLY<<< when the EF info is also
  1252. + * used to set the modification time of the extracted file.
  1253. + */
  1254. + if (G.extra_field &&
  1255. +#ifdef IZ_CHECK_TZ
  1256. + G.tz_is_valid &&
  1257. +#endif
  1258. + (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
  1259. + G.lrec.last_mod_dos_datetime, &z_utime, NULL)
  1260. + & EB_UT_FL_MTIME))
  1261. + {
  1262. + TTrace((stderr, "check_for_newer: using Unix extra field mtime\n"));
  1263. + existing = G.statbuf.st_mtime;
  1264. + archive = z_utime.mtime;
  1265. + } else {
  1266. + /* round up existing filetime to nearest 2 seconds for comparison,
  1267. + * but saturate in case of arithmetic overflow
  1268. + */
  1269. + existing = ((G.statbuf.st_mtime & 1) &&
  1270. + (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
  1271. + G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
  1272. + archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
  1273. + }
  1274. +#else /* !USE_EF_UT_TIME */
  1275. + /* round up existing filetime to nearest 2 seconds for comparison,
  1276. + * but saturate in case of arithmetic overflow
  1277. + */
  1278. + existing = ((G.statbuf.st_mtime & 1) &&
  1279. + (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
  1280. + G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
  1281. + archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
  1282. +#endif /* ?USE_EF_UT_TIME */
  1283. +
  1284. + TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n",
  1285. + (ulg)existing, (ulg)archive, (long)(existing-archive)));
  1286. +
  1287. + return (existing >= archive);
  1288. +
  1289. +} /* end function check_for_newerw() */
  1290. +#endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  1291. +
  1292. #endif /* !VMS && !OS2 && !CMS_MVS */
  1293. @@ -2319,4 +2452,23 @@
  1294. free(fn);
  1295. }
  1296. +# ifdef WIN32_WIDE
  1297. + G.unipath_widefilename = NULL;
  1298. + if (G.has_win32_wide) {
  1299. + if (G.unipath_filename)
  1300. + /* Get wide path from UTF-8 */
  1301. + G.unipath_widefilename = utf8_to_wchar_string(G.unipath_filename);
  1302. + else
  1303. + G.unipath_widefilename = utf8_to_wchar_string(G.filename);
  1304. +
  1305. + if (G.pInfo->lcflag) /* replace with lowercase filename */
  1306. + wcslwr(G.unipath_widefilename);
  1307. +
  1308. + if (G.pInfo->vollabel && length > 8 && G.unipath_widefilename[8] == '.') {
  1309. + wchar_t *p = G.unipath_widefilename+8;
  1310. + while (*p++)
  1311. + p[-1] = *p; /* disk label, and 8th char is dot: remove dot */
  1312. + }
  1313. + }
  1314. +# endif /* WIN32_WIDE */
  1315. }
  1316. #endif /* UNICODE_SUPPORT */
  1317. diff -ru2 unz60d10/globals.h unz60d10_w32w/globals.h
  1318. --- unz60d10/globals.h Sun Jan 27 16:31:56 2008
  1319. +++ unz60d10_w32w/globals.h Mon Feb 11 01:09:22 2008
  1320. @@ -302,4 +302,8 @@
  1321. ulg unipath_checksum; /* Unicode field checksum */
  1322. char *unipath_filename; /* UTF-8 path */
  1323. +# ifdef WIN32_WIDE
  1324. + wchar_t *unipath_widefilename; /* wide character filename */
  1325. + int has_win32_wide; /* true if Win32 W calls work */
  1326. +# endif
  1327. char *unipath_escapedfilename;
  1328. #endif /* UNICODE_SUPPORT */
  1329. diff -ru2 unz60d10/match.c unz60d10_w32w/match.c
  1330. --- unz60d10/match.c Sun Aug 14 20:00:36 2005
  1331. +++ unz60d10_w32w/match.c Sun Jan 6 18:19:46 2008
  1332. @@ -1,4 +1,4 @@
  1333. /*
  1334. - Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
  1335. + Copyright (c) 1990-2008 Info-ZIP. All rights reserved.
  1336. See the accompanying file LICENSE, version 2000-Apr-09 or later
  1337. @@ -407,5 +407,18 @@
  1338. } /* end function iswild() */
  1339. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1340. +int iswildw(pw) /* originally only used for stat()-bug workaround in */
  1341. + ZCONST wchar_t *pw; /* VAX C, Turbo/Borland C, Watcom C, Atari MiNT libs; */
  1342. +{ /* now used in process_zipfiles() as well */
  1343. + for (; *pw; pw++)
  1344. + if (*pw == '\\' && *(pw+1))
  1345. + ++pw;
  1346. + else if (*pw == '?' || *pw == '*' || *pw == '[')
  1347. + return TRUE;
  1348. +
  1349. + return FALSE;
  1350. +} /* end function iswildw() */
  1351. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  1352. diff -ru2 unz60d10/process.c unz60d10_w32w/process.c
  1353. --- unz60d10/process.c Sun Feb 3 00:03:34 2008
  1354. +++ unz60d10_w32w/process.c Mon Feb 11 01:09:22 2008
  1355. @@ -43,4 +43,7 @@
  1356. # include "crc32.h"
  1357. #endif
  1358. +#ifdef UNICODE_SUPPORT
  1359. +# include <wchar.h>
  1360. +#endif /* def UNICODE_SUPPORT */
  1361. static int do_seekable OF((__GPRO__ int lastchance));
  1362. @@ -552,5 +555,12 @@
  1363. inflate_free(__G);
  1364. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1365. + if (G.has_win32_wide)
  1366. + checkdirw(__G__ (wchar_t *)NULL, END);
  1367. + else
  1368. + checkdir(__G__ (char *)NULL, END);
  1369. +#else
  1370. checkdir(__G__ (char *)NULL, END);
  1371. +#endif
  1372. #ifdef DYNALLOC_CRCTAB
  1373. @@ -1507,26 +1517,4 @@
  1374. */
  1375. - /* This is an internal comment. Remove before the next public beta.
  1376. -
  1377. - Below check does not catch when an entry requires Zip64, as
  1378. - when the uncompressed size is larger than 4 GB, but the
  1379. - standard fields in ecrec (called EOCDR in the Zip source)
  1380. - are sufficient, as when the file compresses under the Zip64
  1381. - limit. In such cases ecrec64 (called Zip64 EOCDR in Zip)
  1382. - will exist to flag the archive as Zip64, even though none
  1383. - of the ecrec values are set to the FFFF or FFFFFFFF flag
  1384. - values.
  1385. -
  1386. - if(check_ecrec_zip64(__G)){
  1387. - need_zip64 = TRUE;
  1388. - }
  1389. -
  1390. - In fact, this check is not needed, as ecrec64 will ALWAYS
  1391. - exist for a proper Zip64 archive, as the Version Needed To Extract
  1392. - field is required to be set to 4.5 or higher.
  1393. -
  1394. - End of internal comment.
  1395. - */
  1396. -
  1397. /* The ecrec64 will ALWAYS exist for a proper Zip64 archive, as
  1398. the Version Needed To Extract field is required to be set to
  1399. @@ -1954,7 +1942,4 @@
  1400. G.unipath_filename[ULen] = '\0';
  1401. }
  1402. -# if 0
  1403. - G.unipath_escapedfilename = utf8_to_escaped_string(G.unipath_filename);
  1404. -# endif
  1405. }
  1406. @@ -2324,4 +2309,37 @@
  1407. return w;
  1408. }
  1409. +
  1410. +char *wchar_to_local_string(wchar_string, escape_all)
  1411. + wchar_t *wchar_string;
  1412. + int escape_all;
  1413. +{
  1414. + zwchar *wide_string = wchar_to_wide_string(wchar_string);
  1415. + char *local_string = wide_to_local_string(wide_string, escape_all);
  1416. +
  1417. + free(wide_string);
  1418. +
  1419. + return local_string;
  1420. +}
  1421. +
  1422. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1423. +zwchar *wchar_to_wide_string(wchar_string)
  1424. + wchar_t *wchar_string;
  1425. +{
  1426. + int i;
  1427. + int wchar_len;
  1428. + zwchar *wide_string;
  1429. +
  1430. + wchar_len = wcslen(wchar_string);
  1431. +
  1432. + if ((wide_string = malloc((wchar_len + 1) * sizeof(zwchar))) == NULL) {
  1433. + return NULL;
  1434. + }
  1435. + for (i = 0; i <= wchar_len; i++) {
  1436. + wide_string[i] = wchar_string[i];
  1437. + }
  1438. +
  1439. + return wide_string;
  1440. +}
  1441. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  1442. char *utf8_to_escaped_string(utf8_string, escape_all)
  1443. diff -ru2 unz60d10/unzpriv.h unz60d10_w32w/unzpriv.h
  1444. --- unz60d10/unzpriv.h Sun Feb 3 15:50:52 2008
  1445. +++ unz60d10_w32w/unzpriv.h Mon Feb 11 02:05:46 2008
  1446. @@ -1318,4 +1318,7 @@
  1447. # define zstat _stati64
  1448. # define zfstat _fstati64
  1449. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1450. +# define zstatw _wstati64
  1451. +# endif
  1452. /* 64-bit lseek */
  1453. @@ -1332,4 +1335,7 @@
  1454. /* 64-bit fopen */
  1455. # define zfopen fopen
  1456. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1457. +# define zfopenw _wfopen
  1458. +# endif
  1459. # define zfdopen fdopen
  1460. @@ -1904,4 +1910,11 @@
  1461. char buf[1]; /* start of system-specific internal data */
  1462. } direntry;
  1463. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1464. + typedef struct direntryw { /* head of system-specific struct holding */
  1465. + struct direntryw *next; /* defered directory attributes info */
  1466. + wchar_t *fnw; /* filename of directory */
  1467. + wchar_t buf[1]; /* start of system-specific internal data */
  1468. + } direntryw;
  1469. +# endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  1470. #endif /* SET_DIR_ATTRIB */
  1471. @@ -2225,4 +2238,7 @@
  1472. time_t dos_to_unix_time OF((ulg dos_datetime));
  1473. int check_for_newer OF((__GPRO__ char *filename)); /* os2,vmcms,vms */
  1474. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1475. +int check_for_newerw OF((__GPRO__ wchar_t *filenamew)); /* os2,vmcms,vms */
  1476. +#endif
  1477. int do_string OF((__GPRO__ unsigned int length, int option));
  1478. ush makeword OF((ZCONST uch *b));
  1479. @@ -2468,4 +2484,8 @@
  1480. int zstat_win32 OF((__W32STAT_GLOBALS__
  1481. const char *path, z_stat *buf)); /* win32.c */
  1482. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1483. + int zstat_win32w OF((__W32STAT_GLOBALS__
  1484. + const wchar_t *pathw, z_stat *buf)); /* win32.c */
  1485. +# endif
  1486. #endif
  1487. #endif
  1488. @@ -2485,4 +2505,7 @@
  1489. int ic __WDLPRO)); /* match.c */
  1490. int iswild OF((ZCONST char *p)); /* match.c */
  1491. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1492. +int iswildw OF((ZCONST wchar_t *pw)); /* match.c */
  1493. +#endif
  1494. /* declarations of public CRC-32 functions have been moved into crc32.h
  1495. @@ -2497,4 +2520,8 @@
  1496. int mapname OF((__GPRO__ int renamed)); /* local */
  1497. int checkdir OF((__GPRO__ char *pathcomp, int flag)); /* local */
  1498. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1499. + int mapnamew OF((__GPRO__ int renamed)); /* local */
  1500. + int checkdirw OF((__GPRO__ wchar_t *pathcomp, int flag)); /* local */
  1501. +#endif
  1502. char *do_wild OF((__GPRO__ ZCONST char *wildzipfn)); /* local */
  1503. char *GetLoadPath OF((__GPRO)); /* local */
  1504. @@ -2517,4 +2544,8 @@
  1505. int defer_dir_attribs OF((__GPRO__ direntry **pd)); /* local */
  1506. int set_direc_attribs OF((__GPRO__ direntry *d)); /* local */
  1507. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1508. + int defer_dir_attribsw OF((__GPRO__ direntryw **pd)); /* local */
  1509. + int set_direc_attribsw OF((__GPRO__ direntryw *d)); /* local */
  1510. +# endif
  1511. #endif
  1512. #ifdef TIMESTAMP
  1513. @@ -2980,4 +3011,8 @@
  1514. /* convert UTF-8 string to wide string */
  1515. zwchar *utf8_to_wide_string OF((char *));
  1516. +
  1517. + char *wchar_to_local_string OF((wchar_t *, int));
  1518. +
  1519. + zwchar *wchar_to_wide_string OF((wchar_t *));
  1520. /* convert wide string to multi-byte string */
  1521. diff -ru2 unz60d10/win32/nt.c unz60d10_w32w/win32/nt.c
  1522. --- unz60d10/win32/nt.c Tue Dec 25 12:34:50 2007
  1523. +++ unz60d10_w32w/win32/nt.c Mon Feb 11 02:09:20 2008
  1524. @@ -1,6 +1,6 @@
  1525. /*
  1526. - Copyright (c) 1990-2007 Info-ZIP. All rights reserved.
  1527. + Copyright (c) 1990-2008 Info-ZIP. All rights reserved.
  1528. - See the accompanying file LICENSE, version 2000-Apr-09 or later
  1529. + See the accompanying file LICENSE, version 2007-Mar-04 or later
  1530. (the contents of which are also included in unzip.h) for terms of use.
  1531. If, for some reason, all these files are missing, the Info-ZIP license
  1532. @@ -63,5 +63,10 @@
  1533. static BOOL Initialize(VOID);
  1534. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1535. +static VOID GetRemotePrivilegesSet(wchar_t *FileName,
  1536. + PDWORD dwRemotePrivileges);
  1537. +#else
  1538. static VOID GetRemotePrivilegesSet(CHAR *FileName, PDWORD dwRemotePrivileges);
  1539. +#endif
  1540. static VOID InitLocalPrivileges(VOID);
  1541. @@ -191,5 +196,10 @@
  1542. }
  1543. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1544. +static VOID GetRemotePrivilegesSet(wchar_t *FileName,
  1545. + PDWORD dwRemotePrivileges)
  1546. +#else
  1547. static VOID GetRemotePrivilegesSet(char *FileName, PDWORD dwRemotePrivileges)
  1548. +#endif
  1549. {
  1550. HANDLE hFile;
  1551. @@ -199,5 +209,9 @@
  1552. /* see if we have the SeRestorePrivilege */
  1553. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1554. + hFile = CreateFileW(
  1555. +#else
  1556. hFile = CreateFileA(
  1557. +#endif
  1558. FileName,
  1559. ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER | READ_CONTROL,
  1560. @@ -236,5 +250,9 @@
  1561. /* note we don't need this if we have SeRestorePrivilege */
  1562. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1563. + hFile = CreateFileW(
  1564. +#else
  1565. hFile = CreateFileA(
  1566. +#endif
  1567. FileName,
  1568. ACCESS_SYSTEM_SECURITY,
  1569. @@ -255,10 +273,19 @@
  1570. BOOL GetVolumeCaps(
  1571. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1572. + wchar_t *rootpath, /* filepath, or NULL */
  1573. + wchar_t *name, /* filename associated with rootpath */
  1574. +#else
  1575. char *rootpath, /* filepath, or NULL */
  1576. char *name, /* filename associated with rootpath */
  1577. +#endif
  1578. PVOLUMECAPS VolumeCaps /* result structure describing capabilities */
  1579. )
  1580. {
  1581. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1582. + wchar_t TempRootPath[MAX_PATH + 1];
  1583. +#else
  1584. char TempRootPath[MAX_PATH + 1];
  1585. +#endif
  1586. DWORD cchTempRootPath = 0;
  1587. BOOL bSuccess = TRUE; /* assume success until told otherwise */
  1588. @@ -273,5 +300,9 @@
  1589. DWORD i;
  1590. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1591. + cchTempRootPath = lstrlenW(rootpath);
  1592. +#else
  1593. cchTempRootPath = lstrlenA(rootpath);
  1594. +#endif
  1595. if(cchTempRootPath > MAX_PATH) return FALSE;
  1596. @@ -345,5 +376,9 @@
  1597. if(!g_VolumeCaps.bValid ||
  1598. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1599. + lstrcmpiW(g_VolumeCaps.RootPath, TempRootPath) != 0)
  1600. +#else
  1601. lstrcmpiA(g_VolumeCaps.RootPath, TempRootPath) != 0)
  1602. +#endif
  1603. {
  1604. @@ -357,5 +392,9 @@
  1605. LeaveCriticalSection( &VolumeCapsLock );
  1606. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1607. + bSuccess = GetVolumeInformationW(
  1608. +#else
  1609. bSuccess = GetVolumeInformationA(
  1610. +#endif
  1611. (TempRootPath[0] == '\0') ? NULL : TempRootPath,
  1612. NULL, 0,
  1613. @@ -371,5 +410,9 @@
  1614. VolumeCaps->bUsePrivileges)
  1615. {
  1616. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1617. + if(GetDriveTypeW( (TempRootPath[0] == '\0') ? NULL : TempRootPath )
  1618. +#else
  1619. if(GetDriveTypeA( (TempRootPath[0] == '\0') ? NULL : TempRootPath )
  1620. +#endif
  1621. == DRIVE_REMOTE)
  1622. {
  1623. @@ -388,5 +431,9 @@
  1624. if(bSuccess) {
  1625. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1626. + lstrcpynW(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1);
  1627. +#else
  1628. lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1);
  1629. +#endif
  1630. g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags;
  1631. g_VolumeCaps.bRemote = bRemote;
  1632. @@ -413,5 +460,9 @@
  1633. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1634. +BOOL SecuritySet(wchar_t *resource, PVOLUMECAPS VolumeCaps, uch *securitydata)
  1635. +#else
  1636. BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata)
  1637. +#endif
  1638. {
  1639. HANDLE hFile;
  1640. @@ -491,5 +542,9 @@
  1641. dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;
  1642. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1643. + hFile = CreateFileW(
  1644. +#else
  1645. hFile = CreateFileA(
  1646. +#endif
  1647. resource,
  1648. dwDesiredAccess,
  1649. diff -ru2 unz60d10/win32/nt.h unz60d10_w32w/win32/nt.h
  1650. --- unz60d10/win32/nt.h Mon Jan 24 02:46:38 2005
  1651. +++ unz60d10_w32w/win32/nt.h Mon Feb 11 02:07:20 2008
  1652. @@ -1,4 +1,4 @@
  1653. /*
  1654. - Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
  1655. + Copyright (c) 1990-2008 Info-ZIP. All rights reserved.
  1656. See the accompanying file LICENSE, version 2000-Apr-09 or later
  1657. @@ -24,9 +24,18 @@
  1658. DWORD dwRemotePrivileges; /* relevant only on remote volumes */
  1659. DWORD dwFileAttributes;
  1660. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1661. + wchar_t RootPath[MAX_PATH+1]; /* path to network / filesystem */
  1662. +#else
  1663. char RootPath[MAX_PATH+1]; /* path to network / filesystem */
  1664. +#endif
  1665. } VOLUMECAPS, *PVOLUMECAPS, *LPVOLUMECAPS;
  1666. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1667. +BOOL SecuritySet(wchar_t *resource, PVOLUMECAPS VolumeCaps, uch *securitydata);
  1668. +BOOL GetVolumeCaps(wchar_t *rootpath, wchar_t *name, PVOLUMECAPS VolumeCaps);
  1669. +#else
  1670. BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata);
  1671. BOOL GetVolumeCaps(char *rootpath, char *name, PVOLUMECAPS VolumeCaps);
  1672. +#endif
  1673. BOOL ValidateSecurity(uch *securitydata);
  1674. diff -ru2 unz60d10/win32/vc6/funzip.dsp unz60d10_w32w/win32/vc6/funzip.dsp
  1675. --- unz60d10/win32/vc6/funzip.dsp Mon Feb 11 02:55:18 2008
  1676. +++ unz60d10_w32w/win32/vc6/funzip.dsp Mon Feb 11 02:55:38 2008
  1677. @@ -45,5 +45,5 @@
  1678. # PROP Target_Dir ""
  1679. # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c
  1680. -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "FUNZIP" /D "_CONSOLE" /D "_MBCS" /FD /c
  1681. +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "FUNZIP" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /c
  1682. # ADD BASE RSC /l 0x409 /d "NDEBUG"
  1683. # ADD RSC /l 0x409 /d "NDEBUG"
  1684. @@ -69,5 +69,5 @@
  1685. # PROP Target_Dir ""
  1686. # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c
  1687. -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "FUNZIP" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
  1688. +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "FUNZIP" /D "_CONSOLE" /D "_MBCS" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /FD /GZ /c
  1689. # ADD BASE RSC /l 0x409 /d "_DEBUG"
  1690. # ADD RSC /l 0x409 /d "_DEBUG"
  1691. @@ -93,5 +93,5 @@
  1692. # PROP Target_Dir ""
  1693. # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "FUNZIP" /FD /c
  1694. -# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "FUNZIP" /D "ASM_CRC" /D "_CONSOLE" /D "_MBCS" /FD /c
  1695. +# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "FUNZIP" /D "ASM_CRC" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /c
  1696. # ADD BASE RSC /l 0x409 /d "NDEBUG"
  1697. # ADD RSC /l 0x409 /d "NDEBUG"
  1698. @@ -117,5 +117,5 @@
  1699. # PROP Target_Dir ""
  1700. # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "FUNZIP" /FD /GZ /c
  1701. -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "FUNZIP" /D "ASM_CRC" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
  1702. +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "FUNZIP" /D "ASM_CRC" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /GZ /c
  1703. # ADD BASE RSC /l 0x409 /d "_DEBUG"
  1704. # ADD RSC /l 0x409 /d "_DEBUG"
  1705. diff -ru2 unz60d10/win32/vc6/unzip.dsp unz60d10_w32w/win32/vc6/unzip.dsp
  1706. --- unz60d10/win32/vc6/unzip.dsp Sat Mar 24 19:51:24 2007
  1707. +++ unz60d10_w32w/win32/vc6/unzip.dsp Mon Feb 11 02:52:48 2008
  1708. @@ -45,5 +45,5 @@
  1709. # PROP Target_Dir ""
  1710. # ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /FD /c
  1711. -# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FD /c
  1712. +# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /c
  1713. # ADD BASE RSC /l 0x409 /d "NDEBUG"
  1714. # ADD RSC /l 0x409 /d "NDEBUG"
  1715. @@ -69,5 +69,5 @@
  1716. # PROP Target_Dir ""
  1717. # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /FD /GZ /c
  1718. -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
  1719. +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /FR /FD /GZ /c
  1720. # ADD BASE RSC /l 0x409 /d "_DEBUG"
  1721. # ADD RSC /l 0x409 /d "_DEBUG"
  1722. @@ -93,5 +93,5 @@
  1723. # PROP Target_Dir ""
  1724. # ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /FD /c
  1725. -# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "ASM_CRC" /D "_CONSOLE" /D "_MBCS" /FD /c
  1726. +# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "ASM_CRC" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /c
  1727. # ADD BASE RSC /l 0x409 /d "NDEBUG"
  1728. # ADD RSC /l 0x409 /d "NDEBUG"
  1729. @@ -118,5 +118,5 @@
  1730. # PROP Target_Dir ""
  1731. # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /FD /GZ /c
  1732. -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "ASM_CRC" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
  1733. +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "ASM_CRC" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /GZ /c
  1734. # ADD BASE RSC /l 0x409 /d "_DEBUG"
  1735. # ADD RSC /l 0x409 /d "_DEBUG"
  1736. diff -ru2 unz60d10/win32/vc6/unzipbz2.dsp unz60d10_w32w/win32/vc6/unzipbz2.dsp
  1737. --- unz60d10/win32/vc6/unzipbz2.dsp Sun Jan 6 19:14:44 2008
  1738. +++ unz60d10_w32w/win32/vc6/unzipbz2.dsp Mon Feb 11 02:52:48 2008
  1739. @@ -45,5 +45,5 @@
  1740. # PROP Target_Dir ""
  1741. # ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /FD /c
  1742. -# ADD CPP /nologo /W3 /GX /O2 /I "../../bzip2" /D "NDEBUG" /D "WIN32" /D "USE_BZIP2" /D "_CONSOLE" /D "_MBCS" /FD /c
  1743. +# ADD CPP /nologo /W3 /GX /O2 /I "../../bzip2" /D "NDEBUG" /D "WIN32" /D "USE_BZIP2" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /c
  1744. # ADD BASE RSC /l 0x409 /d "NDEBUG"
  1745. # ADD RSC /l 0x409 /d "NDEBUG"
  1746. @@ -69,5 +69,5 @@
  1747. # PROP Target_Dir ""
  1748. # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /FD /GZ /c
  1749. -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../bzip2" /D "_DEBUG" /D "WIN32" /D "USE_BZIP2" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
  1750. +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../bzip2" /D "_DEBUG" /D "WIN32" /D "USE_BZIP2" /D "_CONSOLE" /D "_MBCS" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /FD /GZ /c
  1751. # ADD BASE RSC /l 0x409 /d "_DEBUG"
  1752. # ADD RSC /l 0x409 /d "_DEBUG"
  1753. @@ -93,5 +93,5 @@
  1754. # PROP Target_Dir ""
  1755. # ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /FD /c
  1756. -# ADD CPP /nologo /W3 /GX /O2 /I "../../bzip2" /D "NDEBUG" /D "WIN32" /D "ASM_CRC" /D "USE_BZIP2" /D "_CONSOLE" /D "_MBCS" /FD /c
  1757. +# ADD CPP /nologo /W3 /GX /O2 /I "../../bzip2" /D "NDEBUG" /D "WIN32" /D "ASM_CRC" /D "USE_BZIP2" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /c
  1758. # ADD BASE RSC /l 0x409 /d "NDEBUG"
  1759. # ADD RSC /l 0x409 /d "NDEBUG"
  1760. @@ -118,5 +118,5 @@
  1761. # PROP Target_Dir ""
  1762. # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /FD /GZ /c
  1763. -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../bzip2" /D "_DEBUG" /D "WIN32" /D "ASM_CRC" /D "USE_BZIP2" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
  1764. +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../bzip2" /D "_DEBUG" /D "WIN32" /D "ASM_CRC" /D "USE_BZIP2" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /GZ /c
  1765. # ADD BASE RSC /l 0x409 /d "_DEBUG"
  1766. # ADD RSC /l 0x409 /d "_DEBUG"
  1767. diff -ru2 unz60d10/win32/vc6/unzipsfx.dsp unz60d10_w32w/win32/vc6/unzipsfx.dsp
  1768. --- unz60d10/win32/vc6/unzipsfx.dsp Sun Jan 6 19:13:46 2008
  1769. +++ unz60d10_w32w/win32/vc6/unzipsfx.dsp Mon Feb 11 02:52:48 2008
  1770. @@ -45,5 +45,5 @@
  1771. # PROP Target_Dir ""
  1772. # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c
  1773. -# ADD CPP /nologo /W3 /GX /O1 /D "WIN32" /D "SFX" /D "_CONSOLE" /D "_MBCS" /FD /c
  1774. +# ADD CPP /nologo /W3 /GX /O1 /D "WIN32" /D "SFX" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /c
  1775. # ADD BASE RSC /l 0x409 /d "NDEBUG"
  1776. # ADD RSC /l 0x409 /d "NDEBUG"
  1777. @@ -69,5 +69,5 @@
  1778. # PROP Target_Dir ""
  1779. # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c
  1780. -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "SFX" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
  1781. +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "SFX" /D "_CONSOLE" /D "_MBCS" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /FD /GZ /c
  1782. # ADD BASE RSC /l 0x409 /d "_DEBUG"
  1783. # ADD RSC /l 0x409 /d "_DEBUG"
  1784. @@ -93,5 +93,5 @@
  1785. # PROP Target_Dir ""
  1786. # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "SFX" /FD /c
  1787. -# ADD CPP /nologo /W3 /GX /O1 /D "NDEBUG" /D "WIN32" /D "SFX" /D "ASM_CRC" /D "_CONSOLE" /D "_MBCS" /FD /c
  1788. +# ADD CPP /nologo /W3 /GX /O1 /D "NDEBUG" /D "WIN32" /D "SFX" /D "ASM_CRC" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /c
  1789. # ADD BASE RSC /l 0x409 /d "NDEBUG"
  1790. # ADD RSC /l 0x409 /d "NDEBUG"
  1791. @@ -117,5 +117,5 @@
  1792. # PROP Target_Dir ""
  1793. # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "SFX" /FD /GZ /c
  1794. -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "SFX" /D "ASM_CRC" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
  1795. +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "SFX" /D "ASM_CRC" /D "_CONSOLE" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /D "_MBCS" /FD /GZ /c
  1796. # ADD BASE RSC /l 0x409 /d "_DEBUG"
  1797. # ADD RSC /l 0x409 /d "_DEBUG"
  1798. diff -ru2 unz60d10/win32/w32cfg.h unz60d10_w32w/win32/w32cfg.h
  1799. --- unz60d10/win32/w32cfg.h Thu Oct 4 02:05:42 2007
  1800. +++ unz60d10_w32w/win32/w32cfg.h Tue Jan 1 18:34:48 2008
  1801. @@ -271,15 +271,38 @@
  1802. #define STR_TO_ISO
  1803. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1804. + wchar_t *utf8_to_wchar_string OF((char *));
  1805. + wchar_t *local_to_wchar_string OF((char *));
  1806. + int has_win32_wide();
  1807. +#endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  1808. +
  1809. /* Static variables that we have to add to Uz_Globs: */
  1810. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1811. #define SYSTEM_SPECIFIC_GLOBALS \
  1812. int created_dir, renamed_fullpath, fnlen;\
  1813. unsigned nLabelDrive;\
  1814. char lastRootPath[4];\
  1815. + wchar_t lastRootPathw[4];\
  1816. int lastVolOldFAT, lastVolLocTim;\
  1817. char *rootpath, *buildpathHPFS, *buildpathFAT, *endHPFS, *endFAT;\
  1818. + wchar_t *rootpathw, *buildpathHPFSw, *buildpathFATw, *endHPFSw, *endFATw;\
  1819. ZCONST char *wildname;\
  1820. + ZCONST wchar_t *wildnamew;\
  1821. char *dirname, matchname[FILNAMSIZ];\
  1822. + wchar_t *dirnamew, matchnamew[FILNAMSIZ];\
  1823. int rootlen, have_dirname, dirnamelen, notfirstcall;\
  1824. zvoid *wild_dir;
  1825. +#else /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  1826. +#define SYSTEM_SPECIFIC_GLOBALS \
  1827. + int created_dir, renamed_fullpath, fnlen;\
  1828. + unsigned nLabelDrive;\
  1829. + char lastRootPath[4];\
  1830. + int lastVolOldFAT, lastVolLocTim;\
  1831. + char *rootpath, *buildpathHPFS, *buildpathFAT, *endHPFS, *endFAT;\
  1832. + ZCONST char *wildname;\
  1833. + char *dirname, matchname[FILNAMSIZ];\
  1834. + int rootlen, have_dirname, dirnamelen, notfirstcall;\
  1835. + zvoid *wild_dir;
  1836. +#endif /* ?(defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  1837. /* created_dir, renamed_fullpath, fnlen, and nLabelDrive are used by */
  1838. @@ -342,4 +365,13 @@
  1839. # define SSTAT(path, pbuf) zstat_win32(__W32STAT_G__ path, pbuf)
  1840. #endif
  1841. +
  1842. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1843. +# ifdef WILD_STAT_BUG
  1844. +# define SSTATW(pathw, pbuf) (iswildw(pathw) || zstat_win32w(__W32STAT_G__ pathw, pbuf))
  1845. +# else
  1846. +# define SSTATW(pathw, pbuf) zstat_win32w(__W32STAT_G__ pathw, pbuf)
  1847. +# endif
  1848. +#endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  1849. +
  1850. #ifdef __WATCOMC__
  1851. diff -ru2 unz60d10/win32/win32.c unz60d10_w32w/win32/win32.c
  1852. --- unz60d10/win32/win32.c Tue Jan 1 21:26:22 2008
  1853. +++ unz60d10_w32w/win32/win32.c Tue Jan 1 21:26:24 2008
  1854. @@ -75,4 +75,12 @@
  1855. #endif
  1856. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1857. +# if (defined(__EMX__) || defined(__CYGWIN__))
  1858. +# define MKDIRW(pathw,mode) _wmkdir(pathw,mode)
  1859. +# else
  1860. +# define MKDIRW(pathw,mode) _wmkdir(pathw)
  1861. +# endif
  1862. +#endif
  1863. +
  1864. #ifdef HAVE_WORKING_DIRENT_H
  1865. # undef HAVE_WORKING_DIRENT_H
  1866. @@ -124,4 +132,22 @@
  1867. } NTdirattr;
  1868. #define NtAtt(d) ((NTdirattr *)d) /* typecast shortcut */
  1869. +
  1870. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1871. + typedef struct NTdirattrw { /* struct for holding unix style directory */
  1872. + struct NTdirattrw *next; /* info until can be sorted and set at end */
  1873. + wchar_t *fnw; /* filename of directory */
  1874. + FILETIME Modft; /* File time type defined in NT, `last modified' time */
  1875. + FILETIME Accft; /* NT file time type, `last access' time */
  1876. + FILETIME Creft; /* NT file time type, `file creation' time */
  1877. + int gotTime;
  1878. + unsigned perms; /* same as min_info.file_attr */
  1879. +# ifdef NTSD_EAS
  1880. + unsigned SDlen; /* length of SD data in buf */
  1881. +# endif
  1882. + wchar_t buf[1]; /* buffer stub for directory SD and name */
  1883. + } NTdirattrw;
  1884. +# define NtAttw(dw) ((NTdirattrw *)dw) /* typecast shortcut */
  1885. +# endif
  1886. +
  1887. #endif /* SET_DIR_ATTRIB */
  1888. @@ -129,10 +155,15 @@
  1889. /* Function prototypes */
  1890. #ifdef NTSD_EAS
  1891. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1892. + static int SetSD(__GPRO__ wchar_t *path, unsigned fperms,
  1893. + uch *eb_ptr, unsigned eb_len);
  1894. +# else
  1895. static int SetSD(__GPRO__ char *path, unsigned fperms,
  1896. uch *eb_ptr, unsigned eb_len);
  1897. +# endif
  1898. static int FindSDExtraField(__GPRO__
  1899. uch *ef_ptr, unsigned ef_len,
  1900. uch **p_ebSD_ptr, unsigned *p_ebSD_len);
  1901. -#endif
  1902. +#endif /* NTSD_EAS */
  1903. #ifndef NO_W32TIMES_IZFIX
  1904. @@ -147,13 +178,27 @@
  1905. #endif
  1906. static int FStampIsLocTime(__GPRO__ const char *path);
  1907. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1908. + static int FStampIsLocTimeW(__GPRO__ const wchar_t *pathw);
  1909. +#endif
  1910. static int getNTfiletime (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT,
  1911. FILETIME *pCreFT);
  1912. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1913. +static int getNTfiletimeW (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT,
  1914. + FILETIME *pCreFT);
  1915. +#endif
  1916. static int isfloppy (int nDrive);
  1917. static int NTQueryVolInfo (__GPRO__ const char *name);
  1918. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1919. + static int NTQueryVolInfoW (__GPRO__ const wchar_t *namew);
  1920. +#endif
  1921. static int IsVolumeOldFAT (__GPRO__ const char *name);
  1922. static void maskDOSdevice (__GPRO__ char *pathcomp);
  1923. static void map2fat (char *pathcomp, char **pEndFAT);
  1924. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1925. + static void maskDOSdevicew (__GPRO__ wchar_t *pathcompw);
  1926. + static void map2fatw (wchar_t *pathcompw, wchar_t **pEndFATw);
  1927. +#endif
  1928. @@ -309,7 +354,13 @@
  1929. /**********************/
  1930. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1931. +static int SetSD(__G__ path, fperms, eb_ptr, eb_len)
  1932. + __GDEF
  1933. + wchar_t *path;
  1934. +#else
  1935. static int SetSD(__G__ path, fperms, eb_ptr, eb_len)
  1936. __GDEF
  1937. char *path;
  1938. +#endif
  1939. unsigned fperms;
  1940. uch *eb_ptr;
  1941. @@ -918,4 +969,12 @@
  1942. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1943. +static int FStampIsLocTimeW(__GPRO__ const wchar_t *pathw)
  1944. +{
  1945. + return (NTQueryVolInfoW(__G__ pathw) ? G.lastVolLocTim : FALSE);
  1946. +}
  1947. +#endif
  1948. +
  1949. +
  1950. #ifndef NO_W32TIMES_IZFIX
  1951. @@ -991,4 +1050,63 @@
  1952. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  1953. + static int getNTfiletimeW(__G__ pModFT, pAccFT, pCreFT)
  1954. + __GDEF
  1955. + FILETIME *pModFT;
  1956. + FILETIME *pAccFT;
  1957. + FILETIME *pCreFT;
  1958. + {
  1959. +# ifdef USE_EF_UT_TIME
  1960. + unsigned eb_izux_flg;
  1961. + iztimes z_utime; /* struct for Unix-style actime & modtime, + creatime */
  1962. +# endif
  1963. + int fs_uses_loctime = FStampIsLocTimeW(__G__ G.unipath_widefilename);
  1964. +
  1965. + /* Copy and/or convert time and date variables, if necessary;
  1966. + * return a flag indicating which time stamps are available. */
  1967. +# ifdef USE_EF_UT_TIME
  1968. + if (G.extra_field &&
  1969. +# ifdef IZ_CHECK_TZ
  1970. + G.tz_is_valid &&
  1971. +# endif
  1972. + ((eb_izux_flg = ef_scan_for_izux(G.extra_field,
  1973. + G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,
  1974. + &z_utime, NULL)) & EB_UT_FL_MTIME))
  1975. + {
  1976. + TTrace((stderr, "getNTfiletime: Unix e.f. modif. time = %lu\n",
  1977. + z_utime.mtime));
  1978. + UTIME_2_IZFILETIME(z_utime.mtime, pModFT)
  1979. + if (eb_izux_flg & EB_UT_FL_ATIME) {
  1980. + UTIME_2_IZFILETIME(z_utime.atime, pAccFT)
  1981. + }
  1982. + if (eb_izux_flg & EB_UT_FL_CTIME) {
  1983. + UTIME_2_IZFILETIME(z_utime.ctime, pCreFT)
  1984. + }
  1985. + return (int)eb_izux_flg;
  1986. + }
  1987. +# endif /* USE_EF_UT_TIME */
  1988. +# ifndef NO_W32TIMES_IZFIX
  1989. + if (!fs_uses_loctime) {
  1990. + time_t ux_modtime;
  1991. +
  1992. + ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
  1993. + utime2NtfsFileTime(ux_modtime, pModFT);
  1994. + } else
  1995. +#endif /* NO_W32TIMES_IZFIX */
  1996. + {
  1997. + FILETIME lft;
  1998. +
  1999. + DosDateTimeToFileTime((WORD)(G.lrec.last_mod_dos_datetime >> 16),
  2000. + (WORD)(G.lrec.last_mod_dos_datetime & 0xFFFFL),
  2001. + &lft);
  2002. + LocalFileTimeToFileTime(&lft, pModFT);
  2003. + }
  2004. + *pAccFT = *pModFT;
  2005. + return (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
  2006. +
  2007. + } /* end function getNTfiletime() */
  2008. +#endif /* (UNICODE_SUPPORT && WIN32_WIDE) */
  2009. +
  2010. +
  2011. @@ -1059,66 +1177,72 @@
  2012. unsigned ebSDlen;
  2013. #endif
  2014. +
  2015. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  2016. + if (!G.has_win32_wide) {
  2017. +#endif
  2018. #ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
  2019. - char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
  2020. + char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
  2021. - INTERN_TO_ISO(G.filename, ansi_name);
  2022. -# define Ansi_Fname ansi_name
  2023. + INTERN_TO_ISO(G.filename, ansi_name);
  2024. +# define Ansi_Fname ansi_name
  2025. #else
  2026. -# define Ansi_Fname G.filename
  2027. +# define Ansi_Fname G.filename
  2028. #endif
  2029. #ifndef __RSXNT__
  2030. - if (IsWinNT()) {
  2031. +# if !(defined(UNICODE_SUPPORT) && defined(WIN32_WIDE))
  2032. + if (IsWinNT()) {
  2033. /* Truncate the file to the current position.
  2034. * This is needed to remove excess allocation in case the
  2035. * extraction has failed or stopped prematurely. */
  2036. SetEndOfFile((HANDLE)_get_osfhandle(fileno(G.outfile)));
  2037. - }
  2038. + }
  2039. +# endif /* !(defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  2040. #endif
  2041. - /* Close the file and then re-open it using the Win32
  2042. - * CreateFile call, so that the file can be created
  2043. - * with GENERIC_WRITE access, otherwise the SetFileTime
  2044. - * call will fail. */
  2045. - fclose(G.outfile);
  2046. -
  2047. - /* don't set the time stamp and attributes on standard output */
  2048. - if (uO.cflag)
  2049. - return;
  2050. -
  2051. - /* skip restoring time stamps on user's request */
  2052. - if (uO.D_flag <= 1) {
  2053. - gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft);
  2054. -
  2055. - /* open a handle to the file before processing extra fields;
  2056. - we do this in case new security on file prevents us from updating
  2057. - time stamps */
  2058. - hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
  2059. - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  2060. - } else {
  2061. - gotTime = 0;
  2062. - }
  2063. -
  2064. - /* sfield@microsoft.com: set attributes before time in case we decide to
  2065. - support other filetime members later. This also allows us to apply
  2066. - attributes before the security is changed, which may prevent this
  2067. - from succeeding otherwise. Also, since most files don't have
  2068. - any interesting attributes, only change them if something other than
  2069. - FILE_ATTRIBUTE_ARCHIVE appears in the attributes. This works well
  2070. - as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the
  2071. - file anyway, when it's created new. */
  2072. - if ((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) {
  2073. - if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F))
  2074. - Info(slide, 1, ((char *)slide,
  2075. - "\nwarning (%d): could not set file attributes\n",
  2076. - (int)GetLastError()));
  2077. - }
  2078. + /* Close the file and then re-open it using the Win32
  2079. + * CreateFile call, so that the file can be created
  2080. + * with GENERIC_WRITE access, otherwise the SetFileTime
  2081. + * call will fail. */
  2082. + fclose(G.outfile);
  2083. +
  2084. + /* don't set the time stamp and attributes on standard output */
  2085. + if (uO.cflag)
  2086. + return;
  2087. +
  2088. + gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft);
  2089. +
  2090. + /* open a handle to the file before processing extra fields;
  2091. + we do this in case new security on file prevents us from updating
  2092. + time stamps */
  2093. + hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
  2094. + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  2095. +
  2096. + /* sfield@microsoft.com: set attributes before time in case we decide to
  2097. + support other filetime members later. This also allows us to apply
  2098. + attributes before the security is changed, which may prevent this
  2099. + from succeeding otherwise. Also, since most files don't have
  2100. + any interesting attributes, only change them if something other than
  2101. + FILE_ATTRIBUTE_ARCHIVE appears in the attributes. This works well
  2102. + as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the
  2103. + file anyway, when it's created new. */
  2104. + if((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) {
  2105. + if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F))
  2106. + Info(slide, 1, ((char *)slide,
  2107. + "\nwarning (%d): could not set file attributes\n",
  2108. + (int)GetLastError()));
  2109. + }
  2110. #ifdef NTSD_EAS
  2111. - /* set NTFS SD extra fields */
  2112. - if (G.extra_field && /* zipfile extra field may have extended attribs */
  2113. - FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,
  2114. - &ebSDptr, &ebSDlen))
  2115. - {
  2116. + /* set NTFS SD extra fields */
  2117. + if (G.extra_field && /* zipfile extra field may have extended attribs */
  2118. + FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,
  2119. + &ebSDptr, &ebSDlen))
  2120. + {
  2121. +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  2122. + /* no win32_wide implies "no NT SD support", so FindSDExtraField
  2123. + * will never return "success".
  2124. + */
  2125. +# else /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  2126. int err = SetSD(__G__ Ansi_Fname, G.pInfo->file_attr,
  2127. ebSDptr, ebSDlen);
  2128. @@ -1131,9 +1255,10 @@
  2129. ebSDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), uO.qflag? "\n":""));
  2130. }
  2131. - }
  2132. +# endif /* ? (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  2133. + }
  2134. #endif /* NTSD_EAS */
  2135. - /* skip restoring time stamps on user's request */
  2136. - if (uO.D_flag <= 1) {
  2137. + /* skip restoring time stamps on user's request */
  2138. + if (uO.D_flag <= 1) {
  2139. if ( hFile == INVALID_HANDLE_VALUE )
  2140. Info(slide, 1, ((char *)slide,
  2141. @@ -1152,10 +1277,101 @@
  2142. CloseHandle(hFile);
  2143. }
  2144. - }
  2145. + }
  2146. - return;
  2147. + return;
  2148. #undef Ansi_Fname
  2149. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  2150. + } else {
  2151. + /* wide version */
  2152. +
  2153. +#ifndef __RSXNT__
  2154. + if (IsWinNT()) {
  2155. + /* Truncate the file to the current position.
  2156. + * This is needed to remove excess allocation in case the
  2157. + * extraction has failed or stopped prematurely. */
  2158. + SetEndOfFile((HANDLE)_get_osfhandle(fileno(G.outfile)));
  2159. + }
  2160. +#endif
  2161. +
  2162. + /* Close the file and then re-open it using the Win32
  2163. + * CreateFile call, so that the file can be created
  2164. + * with GENERIC_WRITE access, otherwise the SetFileTime
  2165. + * call will fail. */
  2166. + fclose(G.outfile);
  2167. +
  2168. + /* don't set the time stamp and attributes on standard output */
  2169. + if (uO.cflag)
  2170. + return;
  2171. +
  2172. + gotTime = getNTfiletimeW(__G__ &Modft, &Accft, &Creft);
  2173. +
  2174. + /* open a handle to the file before processing extra fields;
  2175. + we do this in case new security on file prevents us from updating
  2176. + time stamps */
  2177. + hFile = CreateFileW(G.unipath_widefilename,
  2178. + GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
  2179. + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  2180. +
  2181. + /* sfield@microsoft.com: set attributes before time in case we decide to
  2182. + support other filetime members later. This also allows us to apply
  2183. + attributes before the security is changed, which may prevent this
  2184. + from succeeding otherwise. Also, since most files don't have
  2185. + any interesting attributes, only change them if something other than
  2186. + FILE_ATTRIBUTE_ARCHIVE appears in the attributes. This works well
  2187. + as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the
  2188. + file anyway, when it's created new. */
  2189. + if((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) {
  2190. + if (!SetFileAttributesW(G.unipath_widefilename, G.pInfo->file_attr & 0x7F))
  2191. + Info(slide, 1, ((char *)slide,
  2192. + "\nwarning (%d): could not set file attributes\n",
  2193. + (int)GetLastError()));
  2194. + }
  2195. +
  2196. +#ifdef NTSD_EAS
  2197. + /* set NTFS SD extra fields */
  2198. + if (G.extra_field && /* zipfile extra field may have extended attribs */
  2199. + FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,
  2200. + &ebSDptr, &ebSDlen))
  2201. + {
  2202. + int err = SetSD(__G__ G.unipath_widefilename, G.pInfo->file_attr,
  2203. + ebSDptr, ebSDlen);
  2204. +
  2205. + if (err == IZ_EF_TRUNC) {
  2206. + if (uO.qflag)
  2207. + Info(slide, 1, ((char *)slide, "%-22s ",
  2208. + FnFilter1(G.filename)));
  2209. + Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),
  2210. + ebSDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), uO.qflag? "\n":""));
  2211. + }
  2212. + }
  2213. +#endif /* NTSD_EAS */
  2214. +
  2215. + /* skip restoring time stamps on user's request */
  2216. + if (uO.D_flag <= 1) {
  2217. + if ( hFile == INVALID_HANDLE_VALUE )
  2218. + Info(slide, 1, ((char *)slide,
  2219. + "\nCreateFile() error %d when trying set file time\n",
  2220. + (int)GetLastError()));
  2221. + else {
  2222. + if (gotTime) {
  2223. + FILETIME *pModft = (gotTime & EB_UT_FL_MTIME) ? &Modft : NULL;
  2224. + FILETIME *pAccft = (gotTime & EB_UT_FL_ATIME) ? &Accft : NULL;
  2225. + FILETIME *pCreft = (gotTime & EB_UT_FL_CTIME) ? &Creft : NULL;
  2226. +
  2227. + if (!SetFileTime(hFile, pCreft, pAccft, pModft))
  2228. + Info(slide, 0, ((char *)slide,
  2229. + "\nSetFileTime failed: %d\n", (int)GetLastError()));
  2230. + }
  2231. + CloseHandle(hFile);
  2232. + }
  2233. + }
  2234. +
  2235. + return;
  2236. +
  2237. + }
  2238. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  2239. +
  2240. } /* end function close_outfile() */
  2241. @@ -1225,8 +1441,76 @@
  2242. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  2243. +int defer_dir_attribsw(__G__ pdw)
  2244. + __GDEF
  2245. + direntryw **pdw;
  2246. +{
  2247. + NTdirattrw *d_entryw;
  2248. +#ifdef NTSD_EAS
  2249. + uch *ebSDptr;
  2250. + unsigned ebSDlen;
  2251. +#endif
  2252. +
  2253. + /* Win9x does not support setting directory time stamps. */
  2254. + if (!IsWinNT()) {
  2255. + *pdw = (direntryw *)NULL;
  2256. + return PK_OK;
  2257. + }
  2258. +
  2259. +#ifdef NTSD_EAS
  2260. + /* set extended attributes from extra fields */
  2261. + if (G.extra_field && /* zipfile e.f. may have extended attribs */
  2262. + FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,
  2263. + &ebSDptr, &ebSDlen)) {
  2264. + /* ebSDlen contains the payload size of the e.f. block, but
  2265. + we store it including the e.b. header. */
  2266. + ebSDlen += EB_HEADSIZE;
  2267. + } else {
  2268. + /* no NTSD e.f. block -> no space needed to allocate */
  2269. + ebSDlen = 0;
  2270. + }
  2271. +#endif /* NTSD_EAS */
  2272. +
  2273. + d_entryw = (NTdirattrw *)malloc(sizeof(NTdirattrw)
  2274. +#ifdef NTSD_EAS
  2275. + + ebSDlen
  2276. +#endif
  2277. + + (wcslen(G.unipath_widefilename)
  2278. + * sizeof(wchar_t)));
  2279. + *pdw = (direntryw *)d_entryw;
  2280. + if (d_entryw == (NTdirattrw *)NULL) {
  2281. + return PK_MEM;
  2282. + }
  2283. +#ifdef NTSD_EAS
  2284. + if (ebSDlen > 0)
  2285. + memcpy(d_entryw->buf, ebSDptr, ebSDlen);
  2286. + d_entryw->SDlen = ebSDlen;
  2287. + d_entryw->fnw = d_entryw->buf + ebSDlen;
  2288. +#else
  2289. + d_entryw->fnw = d_entryw->buf;
  2290. +#endif
  2291. +
  2292. + wcscpy(d_entryw->fnw, G.unipath_widefilename);
  2293. +
  2294. + d_entryw->perms = G.pInfo->file_attr;
  2295. +
  2296. + d_entryw->gotTime = (uO.D_flag <= 0
  2297. + ? getNTfiletimeW(__G__ &(d_entryw->Modft),
  2298. + &(d_entryw->Accft),
  2299. + &(d_entryw->Creft))
  2300. + : 0);
  2301. + return PK_OK;
  2302. +} /* end function defer_dir_attribsw() */
  2303. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  2304. +
  2305. +
  2306. int set_direc_attribs(__G__ d)
  2307. __GDEF
  2308. direntry *d;
  2309. {
  2310. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  2311. + /* Win9x does not support setting directory time stamps. */
  2312. + return PK_OK;
  2313. +#else /* ! (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  2314. int errval;
  2315. HANDLE hFile = INVALID_HANDLE_VALUE; /* File handle defined in NT */
  2316. @@ -1320,6 +1604,107 @@
  2317. return errval;
  2318. +#endif /* ? (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
  2319. } /* end function set_direc_attribs() */
  2320. +
  2321. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  2322. +int set_direc_attribsw(__G__ dw)
  2323. + __GDEF
  2324. + direntryw *dw;
  2325. +{
  2326. + int errval;
  2327. + HANDLE hFile = INVALID_HANDLE_VALUE; /* File handle defined in NT */
  2328. +
  2329. + /* Win9x does not support setting directory time stamps. */
  2330. + if (!IsWinNT())
  2331. + return PK_OK;
  2332. +
  2333. + errval = PK_OK;
  2334. +
  2335. + /* Skip restoring directory time stamps on user' request. */
  2336. + if (uO.D_flag <= 0) {
  2337. + /* Open a handle to the directory before processing extra fields;
  2338. + we do this in case new security on file prevents us from updating
  2339. + time stamps.
  2340. + Although the WIN32 documentation recommends to use GENERIC_WRITE
  2341. + access flag to create the handle for SetFileTime(), this is too
  2342. + demanding for directories with the "read-only" attribute bit set.
  2343. + So we use the more specific flag FILE_WRITE_ATTRIBUTES here to
  2344. + request the minimum required access rights. (This problem is a
  2345. + Windows bug that has been silently fixed in Windows XP SP2.) */
  2346. + hFile = CreateFileW(dw->fnw, FILE_WRITE_ATTRIBUTES,
  2347. + FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
  2348. + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
  2349. + }
  2350. +
  2351. +#ifdef NTSD_EAS
  2352. + if (NtAtt(dw)->SDlen > 0) {
  2353. + int err;
  2354. +
  2355. + if (QCOND2) {
  2356. + char *fn = wchar_to_local_string(dw->fnw, G.unicode_escape_all);
  2357. + Info(slide, 1, ((char *)slide, " set attrib: %-22s ",
  2358. + FnFilter1(fn)));
  2359. + free(fn);
  2360. + }
  2361. +
  2362. + /* set NTFS SD extra fields */
  2363. + err = SetSD(__G__ dw->fnw, NtAtt(dw)->perms,
  2364. + NtAtt(dw)->buf, NtAtt(dw)->SDlen - EB_HEADSIZE);
  2365. + if (err == IZ_EF_TRUNC) {
  2366. + if (!QCOND2) {
  2367. + char *fn = wchar_to_local_string(dw->fnw, G.unicode_escape_all);
  2368. + Info(slide, 1, ((char *)slide, "%-22s ",
  2369. + FnFilter1(fn)));
  2370. + free(fn);
  2371. + }
  2372. + Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),
  2373. + NtAtt(dw)->SDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n"));
  2374. + } else if (QCOND2) {
  2375. + Info(slide, 0, ((char *)slide, "\n"));
  2376. + }
  2377. + if (errval < err)
  2378. + errval = err;
  2379. + }
  2380. +#endif /* NTSD_EAS */
  2381. +
  2382. + /* Skip restoring directory time stamps on user' request. */
  2383. + if (uO.D_flag <= 0) {
  2384. + if (hFile == INVALID_HANDLE_VALUE) {
  2385. + char *fn = wchar_to_local_string(dw->fnw, G.unicode_escape_all);
  2386. + Info(slide, 1, ((char *)slide,
  2387. + "warning: CreateFile() error %d (set file times for %s)\n",
  2388. + (int)GetLastError(), FnFilter1(fn)));
  2389. + free(fn);
  2390. + if (!errval)
  2391. + errval = PK_WARN;
  2392. + } else {
  2393. + if (NtAtt(dw)->gotTime) {
  2394. + FILETIME *pModft = (NtAtt(dw)->gotTime & EB_UT_FL_MTIME)
  2395. + ? &(NtAtt(dw)->Modft) : NULL;
  2396. + FILETIME *pAccft = (NtAtt(dw)->gotTime & EB_UT_FL_ATIME)
  2397. + ? &(NtAtt(dw)->Accft) : NULL;
  2398. + FILETIME *pCreft = (NtAtt(dw)->gotTime & EB_UT_FL_CTIME)
  2399. + ? &(NtAtt(dw)->Creft) : NULL;
  2400. +
  2401. + if (!SetFileTime(hFile, pCreft, pAccft, pModft)) {
  2402. + char *fn = wchar_to_local_string(dw->fnw,
  2403. + G.unicode_escape_all);
  2404. + Info(slide, 0, ((char *)slide,
  2405. + "warning: SetFileTime() for %s error %d\n",
  2406. + FnFilter1(fn), (int)GetLastError()));
  2407. + free(fn);
  2408. + if (!errval)
  2409. + errval = PK_WARN;
  2410. + }
  2411. + }
  2412. + CloseHandle(hFile);
  2413. + }
  2414. + }
  2415. +
  2416. + return errval;
  2417. +} /* end function set_direc_attribsw() */
  2418. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  2419. +
  2420. #endif /* SET_DIR_ATTRIB */
  2421. @@ -1419,5 +1804,5 @@
  2422. #endif
  2423. - if ((!strncmp(name, "//", 2) || !strncmp(name, "\\\\", 2)) &&
  2424. + if ((!strncmp(name, "//", 2) || !strncmp(name,"\\\\", 2)) &&
  2425. (name[2] != '\0' && name[2] != '/' && name[2] != '\\')) {
  2426. /* GetFullPathname() and GetVolumeInformation() do not work
  2427. @@ -1467,4 +1852,63 @@
  2428. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  2429. +static int NTQueryVolInfoW(__GPRO__ const wchar_t *namew)
  2430. +{
  2431. + /* static char lastRootPath[4] = ""; */
  2432. + /* static int lastVolOldFAT; */
  2433. + /* static int lastVolLocTim; */
  2434. + wchar_t *tmp0w;
  2435. + wchar_t tmp1w[MAX_PATH], tmp2w[MAX_PATH];
  2436. + DWORD volSerNo, maxCompLen, fileSysFlags;
  2437. +
  2438. + if ((!wcsncmp(namew, L"//", 2) || !wcsncmp(namew, L"\\\\", 2)) &&
  2439. + (namew[2] != '\0' && namew[2] != '/' && namew[2] != '\\')) {
  2440. + /* GetFullPathname() and GetVolumeInformation() do not work
  2441. + * on UNC names. For now, we return "error".
  2442. + * **FIXME**: check if UNC name is mapped to a drive letter
  2443. + * and use mapped drive for volume info query.
  2444. + */
  2445. + return FALSE;
  2446. + }
  2447. + if (iswalpha(namew[0]) && (namew[1] == ':'))
  2448. + tmp0w = (wchar_t *)namew;
  2449. + else
  2450. + {
  2451. + if (!GetFullPathNameW(namew, MAX_PATH, tmp1w, &tmp0w))
  2452. + return FALSE;
  2453. + tmp0w = &tmp1w[0];
  2454. + }
  2455. + if (wcsncmp(G.lastRootPathw, tmp0w, 2) != 0) {
  2456. + /* For speed, we skip repeated queries for the same device */
  2457. + wcsncpy(G.lastRootPathw, tmp0w, 2); /* Build the root path name, */
  2458. + G.lastRootPathw[2] = '/'; /* e.g. "A:/" */
  2459. + G.lastRootPathw[3] = '\0';
  2460. +
  2461. + if (!GetVolumeInformationW(G.lastRootPathw,
  2462. + tmp1w, (DWORD)MAX_PATH,
  2463. + &volSerNo, &maxCompLen, &fileSysFlags,
  2464. + tmp2w, (DWORD)MAX_PATH)) {
  2465. + G.lastRootPathw[0] = '\0';
  2466. + return FALSE;
  2467. + }
  2468. +
  2469. + /* LFNs are available if the component length is > 12 */
  2470. + G.lastVolOldFAT = (maxCompLen <= 12);
  2471. +/* G.lastVolOldFAT = !strncmp(strupr(tmp2), "FAT", 3); old version */
  2472. +
  2473. + /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in
  2474. + * local time!
  2475. + */
  2476. + G.lastVolLocTim = !wcsncmp(_wcsupr(tmp2w), L"VFAT", 4) ||
  2477. + !wcsncmp(tmp2w, L"HPFS", 4) ||
  2478. + !wcsncmp(tmp2w, L"FAT", 3);
  2479. + }
  2480. +
  2481. + return TRUE;
  2482. +
  2483. +} /* end function NTQueryVolInfoW() */
  2484. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  2485. +
  2486. +
  2487. @@ -1478,4 +1922,11 @@
  2488. }
  2489. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  2490. +static int IsVolumeOldFATw(__GPRO__ const wchar_t *namew)
  2491. +{
  2492. + return (NTQueryVolInfoW(__G__ namew) ? G.lastVolOldFAT : FALSE);
  2493. +}
  2494. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  2495. +
  2496. @@ -1931,13 +2382,253 @@
  2497. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  2498. +/* Win32 wide version */
  2499. -/****************************/
  2500. -/* Function maskDOSdevice() */
  2501. -/****************************/
  2502. -
  2503. -static void maskDOSdevice(__G__ pathcomp)
  2504. +int mapnamew(__G__ renamed)
  2505. __GDEF
  2506. - char *pathcomp;
  2507. + int renamed;
  2508. +/*
  2509. + * returns:
  2510. + * MPN_OK - no problem detected
  2511. + * MPN_INF_TRUNC - caution (truncated filename)
  2512. + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist)
  2513. + * MPN_ERR_SKIP - error -> skip entry
  2514. + * MPN_ERR_TOOLONG - error -> path is too long
  2515. + * MPN_NOMEM - error (memory allocation failed) -> skip entry
  2516. + * [also MPN_VOL_LABEL, MPN_CREATED_DIR]
  2517. + */
  2518. +{
  2519. + wchar_t pathcompw[FILNAMSIZ]; /* path-component buffer */
  2520. + wchar_t *ppw, *cpw=NULL; /* character pointers */
  2521. + wchar_t *lastsemiw = NULL; /* pointer to last semi-colon in pathcomp */
  2522. + int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */
  2523. + int error;
  2524. + register wchar_t workchw; /* hold the character being tested */
  2525. +
  2526. +
  2527. +/*---------------------------------------------------------------------------
  2528. + Initialize various pointers and counters and stuff.
  2529. + ---------------------------------------------------------------------------*/
  2530. +
  2531. + /* can create path as long as not just freshening, or if user told us */
  2532. + G.create_dirs = (!uO.fflag || renamed);
  2533. +
  2534. + G.created_dir = FALSE; /* not yet */
  2535. + G.renamed_fullpath = FALSE;
  2536. + G.fnlen = wcslen(G.unipath_widefilename);
  2537. +
  2538. + if (renamed) {
  2539. + cpw = G.unipath_widefilename; /* point to beginning of renamed name... */
  2540. + if (*cpw) do {
  2541. + if (*cpw == '\\') /* convert backslashes to forward */
  2542. + *cpw = '/';
  2543. + } while (*(++cpw));
  2544. + cpw = G.unipath_widefilename;
  2545. + /* use temporary rootpath if user gave full pathname */
  2546. + if (G.unipath_widefilename[0] == '/') {
  2547. + G.renamed_fullpath = TRUE;
  2548. + pathcompw[0] = '/'; /* copy the '/' and terminate */
  2549. + pathcompw[1] = '\0';
  2550. + ++cpw;
  2551. + } else if (iswalpha(G.unipath_widefilename[0]) && G.unipath_widefilename[1] == ':') {
  2552. + G.renamed_fullpath = TRUE;
  2553. + ppw = pathcompw;
  2554. + *ppw++ = *cpw++; /* copy the "d:" (+ '/', possibly) */
  2555. + *ppw++ = *cpw++;
  2556. + if (*cpw == '/')
  2557. + *ppw++ = *cpw++; /* otherwise add "./"? */
  2558. + *ppw = '\0';
  2559. + }
  2560. + }
  2561. +
  2562. + /* pathcomp is ignored unless renamed_fullpath is TRUE: */
  2563. + if ((error = checkdirw(__G__ pathcompw, INIT)) != 0) /* init path buffer */
  2564. + return error; /* ...unless no mem or vol label on hard disk */
  2565. +
  2566. + *pathcompw = '\0'; /* initialize translation buffer */
  2567. + ppw = pathcompw; /* point to translation buffer */
  2568. + if (!renamed) { /* cp already set if renamed */
  2569. + if (uO.jflag) /* junking directories */
  2570. + cpw = wcschr(G.unipath_widefilename, '/');
  2571. + if (cpw == NULL) /* no '/' or not junking dirs */
  2572. + cpw = G.unipath_widefilename; /* point to internal zipfile-member pathname */
  2573. + else
  2574. + ++cpw; /* point to start of last component of path */
  2575. + }
  2576. +
  2577. +/*---------------------------------------------------------------------------
  2578. + Begin main loop through characters in filename.
  2579. + ---------------------------------------------------------------------------*/
  2580. +
  2581. + for (; (workchw = *cpw) != 0; cpw++) {
  2582. +
  2583. + switch (workchw) {
  2584. + case '/': /* can assume -j flag not given */
  2585. + *ppw = '\0';
  2586. + maskDOSdevicew(__G__ pathcompw);
  2587. + if (wcscmp(pathcompw, L".") == 0) {
  2588. + /* don't botherw appending "./" to the path */
  2589. + *pathcompw = '\0';
  2590. + } else if (!uO.ddotflag && wcscmp(pathcompw, L"..") == 0) {
  2591. + /* "../" dir traversal detected, skip over it */
  2592. + *pathcompw = '\0';
  2593. + killed_ddot = TRUE; /* set "show message" flag */
  2594. + }
  2595. + /* when path component is not empty, append it now */
  2596. + if (*pathcompw != '\0' &&
  2597. + ((error = checkdirw(__G__ pathcompw, APPEND_DIR))
  2598. + & MPN_MASK) > MPN_INF_TRUNC)
  2599. + return error;
  2600. + ppw = pathcompw; /* reset conversion buffer for next piece */
  2601. + lastsemiw = (wchar_t *)NULL; /* leave direct. semi-colons alone */
  2602. + break;
  2603. +
  2604. + case ':': /* drive spec not stored, so no colon allowed */
  2605. + case '\\': /* '\\' may come as normal filename char (not */
  2606. + case '<': /* dir sep char!) from unix-like file system */
  2607. + case '>': /* no redirection symbols allowed either */
  2608. + case '|': /* no pipe signs allowed */
  2609. + case '"': /* no double quotes allowed */
  2610. + case '?': /* no wildcards allowed */
  2611. + case '*':
  2612. + *ppw++ = '_'; /* these rules apply equally to FAT and NTFS */
  2613. + break;
  2614. + case ';': /* start of VMS version? */
  2615. + lastsemiw = ppw; /* remove VMS version later... */
  2616. + *ppw++ = ';'; /* but keep semicolon for now */
  2617. + break;
  2618. +
  2619. +
  2620. + case ' ': /* keep spaces unless specifically */
  2621. + /* NT cannot create filenames with spaces on FAT volumes */
  2622. + if (uO.sflag || IsVolumeOldFATw(__G__ G.unipath_widefilename))
  2623. + *ppw++ = '_';
  2624. + else
  2625. + *ppw++ = ' ';
  2626. + break;
  2627. +
  2628. + default:
  2629. + /* allow European characters in filenames: */
  2630. + if (iswprint(workchw) || workchw >= 127)
  2631. + *ppw++ = workchw;
  2632. + } /* end switch */
  2633. +
  2634. + } /* end while loop */
  2635. +
  2636. + /* Show warning when stripping insecure "parent dir" path components */
  2637. + /* For now use standard path for output messages */
  2638. + if (killed_ddot && QCOND2) {
  2639. + Info(slide, 0, ((char *)slide,
  2640. + "warning: skipped \"../\" path component(s) in %s\n",
  2641. + FnFilter1(G.filename)));
  2642. + if (!(error & ~MPN_MASK))
  2643. + error = (error & MPN_MASK) | PK_WARN;
  2644. + }
  2645. +
  2646. +/*---------------------------------------------------------------------------
  2647. + Report if directory was created (and no file to create: filename ended
  2648. + in '/'), check name to be sure it exists, and combine path and name be-
  2649. + fore exiting.
  2650. + ---------------------------------------------------------------------------*/
  2651. +
  2652. + if (G.unipath_widefilename[wcslen(G.unipath_widefilename) - 1] == '/') {
  2653. + checkdirw(__G__ G.unipath_widefilename, GETPATH);
  2654. + if (G.created_dir) {
  2655. + if (QCOND2) {
  2656. + Info(slide, 0, ((char *)slide, " creating: %-22s\n",
  2657. + FnFilter1(G.filename)));
  2658. + }
  2659. +
  2660. + /* set file attributes:
  2661. + The default for newly created directories is "DIR attribute
  2662. + flags set", so there is no need to change attributes unless
  2663. + one of the DOS style attribute flags is set. The readonly
  2664. + attribute need not be masked, since it does not prevent
  2665. + modifications in the new directory. */
  2666. + if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {
  2667. + if (!SetFileAttributesW(G.unipath_widefilename, G.pInfo->file_attr & 0x7F))
  2668. + Info(slide, 1, ((char *)slide,
  2669. + "\nwarning (%d): could not set file attributes for %s\n",
  2670. + (int)GetLastError(), FnFilter1(G.filename)));
  2671. + }
  2672. +
  2673. + /* set dir time (note trailing '/') */
  2674. + return (error & ~MPN_MASK) | MPN_CREATED_DIR;
  2675. + } else if (IS_OVERWRT_ALL) {
  2676. + /* overwrite attributes of existing directory on user's request */
  2677. +
  2678. + /* set file attributes: */
  2679. + if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {
  2680. + if (!SetFileAttributesW(G.unipath_widefilename, G.pInfo->file_attr & 0x7F))
  2681. + Info(slide, 1, ((char *)slide,
  2682. + "\nwarning (%d): could not set file attributes for %s\n",
  2683. + (int)GetLastError(), FnFilter1(G.filename)));
  2684. + }
  2685. + }
  2686. + /* dir existed already; don't look for data to extract */
  2687. + return (error & ~MPN_MASK) | MPN_INF_SKIP;
  2688. + }
  2689. +
  2690. + *ppw = '\0'; /* done with pathcomp: terminate it */
  2691. +
  2692. + /* if not saving them, remove VMS version numbers (appended "###") */
  2693. + if (!uO.V_flag && lastsemiw) {
  2694. + ppw = lastsemiw + 1; /* semi-colon was kept: expect #'s after */
  2695. + while (iswdigit(*ppw))
  2696. + ++ppw;
  2697. + if (*ppw == '\0') /* only digits between ';' and end: nuke */
  2698. + *lastsemiw = '\0';
  2699. + }
  2700. +
  2701. + maskDOSdevicew(__G__ pathcompw);
  2702. +
  2703. + if (*pathcompw == '\0') {
  2704. + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n",
  2705. + FnFilter1(G.filename)));
  2706. + return (error & ~MPN_MASK) | MPN_ERR_SKIP;
  2707. + }
  2708. +
  2709. + checkdirw(__G__ pathcompw, APPEND_NAME); /* returns 1 if truncated: care? */
  2710. + checkdirw(__G__ G.unipath_widefilename, GETPATH);
  2711. +
  2712. + if (G.pInfo->vollabel) { /* set the volume label now */
  2713. + char drive[4];
  2714. + wchar_t drivew[4];
  2715. +
  2716. + /* Build a drive string, e.g. "b:" */
  2717. + drive[0] = (char)('a' + G.nLabelDrive - 1);
  2718. + drivew[0] = (wchar_t)('a' + G.nLabelDrive - 1);
  2719. + wcscpy(drivew + 1, L":\\");
  2720. + if (QCOND2)
  2721. + Info(slide, 0, ((char *)slide, "labelling %s %-22s\n", drive,
  2722. + FnFilter1(G.filename)));
  2723. + if (!SetVolumeLabelW(drivew, G.unipath_widefilename)) {
  2724. + Info(slide, 1, ((char *)slide,
  2725. + "mapname: error setting volume label\n"));
  2726. + return (error & ~MPN_MASK) | MPN_ERR_SKIP;
  2727. + }
  2728. + /* success: skip the "extraction" quietly */
  2729. + return (error & ~MPN_MASK) | MPN_INF_SKIP;
  2730. + }
  2731. +
  2732. + Trace((stderr, "mapname returns with filename = [%s] (error = %d)\n\n",
  2733. + FnFilter1(G.filename), error));
  2734. + return error;
  2735. +
  2736. +} /* end function mapnamew() */
  2737. +
  2738. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  2739. +
  2740. +
  2741. +
  2742. +
  2743. +/****************************/
  2744. +/* Function maskDOSdevice() */
  2745. +/****************************/
  2746. +
  2747. +static void maskDOSdevice(__G__ pathcomp)
  2748. + __GDEF
  2749. + char *pathcomp;
  2750. {
  2751. /*---------------------------------------------------------------------------
  2752. @@ -1981,4 +2672,40 @@
  2753. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  2754. +
  2755. +static void maskDOSdevicew(__G__ pathcompw)
  2756. + __GDEF
  2757. + wchar_t *pathcompw;
  2758. +{
  2759. +/*---------------------------------------------------------------------------
  2760. + Put an underscore in front of the file name if the file name is a
  2761. + DOS/WINDOWS device name like CON.*, AUX.*, PRN.*, etc. Trying to
  2762. + extract such a file would fail at best and wedge us at worst.
  2763. + ---------------------------------------------------------------------------*/
  2764. +#if !defined(S_IFCHR) && defined(_S_IFCHR)
  2765. +# define S_IFCHR _S_IFCHR
  2766. +#endif
  2767. +#if !defined(S_ISCHR)
  2768. +# if defined(_S_ISCHR)
  2769. +# define S_ISCHR(m) _S_ISCHR(m)
  2770. +# elif defined(S_IFCHR)
  2771. +# define S_ISCHR(m) ((m) & S_IFCHR)
  2772. +# endif
  2773. +#endif
  2774. +
  2775. + if (zstatw(pathcompw, &G.statbuf) == 0 && S_ISCHR(G.statbuf.st_mode)) {
  2776. + extent i;
  2777. +
  2778. + /* pathcomp contains a name of a DOS character device (builtin or
  2779. + * installed device driver).
  2780. + * Prepend a '_' to allow creation of the item in the file system.
  2781. + */
  2782. + for (i = wcslen(pathcompw) + 1; i > 0; --i)
  2783. + pathcompw[i] = pathcompw[i - 1];
  2784. + pathcompw[0] = '_';
  2785. + }
  2786. +} /* end function maskDOSdevicew() */
  2787. +
  2788. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  2789. @@ -2080,19 +2807,511 @@
  2790. *pEndFAT = pEnd; /* filename is fine; point at terminating zero */
  2791. - if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ')
  2792. - last_dot[-1] = '_'; /* NO blank in front of '.'! */
  2793. + if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ')
  2794. + last_dot[-1] = '_'; /* NO blank in front of '.'! */
  2795. + }
  2796. +} /* end function map2fat() */
  2797. +
  2798. +
  2799. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  2800. +
  2801. +static void map2fatw(pathcompw, pEndFATw)
  2802. + wchar_t *pathcompw, **pEndFATw;
  2803. +{
  2804. + wchar_t *ppcw = pathcompw; /* variable pointer to pathcomp */
  2805. + wchar_t *pEndw = *pEndFATw; /* variable pointer to buildpathFAT */
  2806. + wchar_t *pBeginw = *pEndFATw; /* constant pointer to start of this comp. */
  2807. + wchar_t *last_dotw = NULL; /* last dot not converted to underscore */
  2808. + register wchar_t workchw; /* hold the character being tested */
  2809. +
  2810. +
  2811. + /* Only need check those characters which are legal in NTFS but not
  2812. + * in FAT: to get here, must already have passed through mapname.
  2813. + * Also must truncate path component to ensure 8.3 compliance.
  2814. + */
  2815. + while ((workchw = *ppcw++) != 0) {
  2816. + switch (workchw) {
  2817. + case '[':
  2818. + case ']':
  2819. + case '+':
  2820. + case ',':
  2821. + case ';':
  2822. + case '=':
  2823. + *pEndw++ = '_'; /* convert brackets to underscores */
  2824. + break;
  2825. +
  2826. + case '.':
  2827. + if (pEndw == *pEndFATw) { /* nothing appended yet... */
  2828. + if (*ppcw == '\0') /* don't bother appending a */
  2829. + break; /* "./" component to the path */
  2830. + else if (*ppcw == '.' && ppcw[1] == '\0') { /* "../" */
  2831. + *pEndw++ = '.'; /* add first dot, */
  2832. + *pEndw++ = '.'; /* add second dot, and */
  2833. + ++ppcw; /* skip over to pathcomp's end */
  2834. + } else { /* FAT doesn't allow null filename */
  2835. + *pEndw++ = '_'; /* bodies, so map .exrc -> _exrc */
  2836. + } /* (_.exr would keep max 3 chars) */
  2837. + } else { /* found dot within path component */
  2838. + last_dotw = pEndw; /* point at last dot so far... */
  2839. + *pEndw++ = '_'; /* convert to underscore for now */
  2840. + }
  2841. + break;
  2842. +
  2843. + default:
  2844. + *pEndw++ = workchw;
  2845. +
  2846. + } /* end switch */
  2847. + } /* end while loop */
  2848. +
  2849. + *pEndw = '\0'; /* terminate buildpathFAT */
  2850. +
  2851. + /* NOTE: keep in mind that pEnd points to the end of the path
  2852. + * component, and *pEndFAT still points to the *beginning* of it...
  2853. + * Also note that the algorithm does not try to get too fancy:
  2854. + * if there are no dots already, the name either gets truncated
  2855. + * at 8 characters or the last underscore is converted to a dot
  2856. + * (only if more characters are saved that way). In no case is
  2857. + * a dot inserted between existing characters.
  2858. + */
  2859. + if (last_dotw == NULL) { /* no dots: check for underscores... */
  2860. + wchar_t *pluw = wcschr(pBeginw, '_'); /* pointer to last underscore */
  2861. +
  2862. + if ((pluw != NULL) && /* found underscore: convert to dot? */
  2863. + (MIN(pluw - pBeginw, 8) + MIN(pEndw - pluw - 1, 3) > 8)) {
  2864. + last_dotw = pluw; /* be lazy: drop through to next if-blk */
  2865. + } else if ((pEndw - *pEndFATw) > 8) {
  2866. + /* no underscore; or converting underscore to dot would save less
  2867. + chars than leaving everything in the basename */
  2868. + *pEndFATw += 8; /* truncate at 8 chars */
  2869. + **pEndFATw = '\0';
  2870. + } else
  2871. + *pEndFATw = pEndw; /* whole thing fits into 8 chars or less */
  2872. + }
  2873. +
  2874. + if (last_dotw != NULL) { /* one dot is OK: */
  2875. + *last_dotw = '.'; /* put it back in */
  2876. +
  2877. + if ((last_dotw - pBeginw) > 8) {
  2878. + wchar_t *pw, *qw;
  2879. + int i;
  2880. +
  2881. + pw = last_dotw;
  2882. + qw = last_dotw = pBeginw + 8;
  2883. + for (i = 0; (i < 4) && *pw; ++i) /* too many chars in basename: */
  2884. + *qw++ = *pw++; /* shift .ext left and trun- */
  2885. + *qw = '\0'; /* cate/terminate it */
  2886. + *pEndFATw = qw;
  2887. + } else if ((pEndw - last_dotw) > 4) { /* too many chars in extension */
  2888. + *pEndFATw = last_dotw + 4;
  2889. + **pEndFATw = '\0';
  2890. + } else
  2891. + *pEndFATw = pEndw; /* filename is fine; point at terminating zero */
  2892. +
  2893. + if ((last_dotw - pBeginw) > 0 && last_dotw[-1] == ' ')
  2894. + last_dotw[-1] = '_'; /* NO blank in front of '.'! */
  2895. + }
  2896. +} /* end function map2fatw() */
  2897. +
  2898. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  2899. +
  2900. +
  2901. +
  2902. +/***********************/ /* Borrowed from os2.c for UnZip 5.1. */
  2903. +/* Function checkdir() */ /* Difference: no EA stuff */
  2904. +/***********************/ /* HPFS stuff works on NTFS too */
  2905. +
  2906. +int checkdir(__G__ pathcomp, flag)
  2907. + __GDEF
  2908. + char *pathcomp;
  2909. + int flag;
  2910. +/*
  2911. + * returns:
  2912. + * MPN_OK - no problem detected
  2913. + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename
  2914. + * MPN_INF_SKIP - path doesn't exist, not allowed to create
  2915. + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path
  2916. + * exists and is not a directory, but is supposed to be
  2917. + * MPN_ERR_TOOLONG - path is too long
  2918. + * MPN_NOMEM - can't allocate memory for filename buffers
  2919. + */
  2920. +{
  2921. + /* static int rootlen = 0; */ /* length of rootpath */
  2922. + /* static char *rootpath; */ /* user's "extract-to" directory */
  2923. + /* static char *buildpathHPFS; */ /* full path (so far) to extracted file, */
  2924. + /* static char *buildpathFAT; */ /* both HPFS/EA (main) and FAT versions */
  2925. + /* static char *endHPFS; */ /* corresponding pointers to end of */
  2926. + /* static char *endFAT; */ /* buildpath ('\0') */
  2927. +
  2928. +# define FN_MASK 7
  2929. +# define FUNCTION (flag & FN_MASK)
  2930. +
  2931. +
  2932. +
  2933. +/*---------------------------------------------------------------------------
  2934. + APPEND_DIR: append the path component to the path being built and check
  2935. + for its existence. If doesn't exist and we are creating directories, do
  2936. + so for this one; else signal success or error as appropriate.
  2937. + ---------------------------------------------------------------------------*/
  2938. +
  2939. + if (FUNCTION == APPEND_DIR) {
  2940. + char *p = pathcomp;
  2941. + int too_long = FALSE;
  2942. +
  2943. + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp)));
  2944. + while ((*G.endHPFS = *p++) != '\0') /* copy to HPFS filename */
  2945. + ++G.endHPFS;
  2946. + if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
  2947. + p = pathcomp;
  2948. + while ((*G.endFAT = *p++) != '\0') /* copy to FAT filename, too */
  2949. + ++G.endFAT;
  2950. + } else
  2951. + map2fat(pathcomp, &G.endFAT); /* map into FAT fn, update endFAT */
  2952. +
  2953. + /* GRR: could do better check, see if overrunning buffer as we go:
  2954. + * check endHPFS-buildpathHPFS after each append, set warning variable
  2955. + * if within 20 of FILNAMSIZ; then if var set, do careful check when
  2956. + * appending. Clear variable when begin new path. */
  2957. +
  2958. + /* next check: need to append '/', at least one-char name, '\0' */
  2959. + if ((G.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3)
  2960. + too_long = TRUE; /* check if extracting dir? */
  2961. +#ifdef FIX_STAT_BUG
  2962. + /* Borland C++ 5.0 does not handle a call to stat() well if the
  2963. + * directory does not exist (it tends to crash in strange places.)
  2964. + * This is apparently a problem only when compiling for GUI rather
  2965. + * than console. The code below attempts to work around this problem.
  2966. + */
  2967. + if (access(G.buildpathFAT, 0) != 0) {
  2968. + if (!G.create_dirs) { /* told not to create (freshening) */
  2969. + free(G.buildpathHPFS);
  2970. + free(G.buildpathFAT);
  2971. + /* path doesn't exist: nothing to do */
  2972. + return MPN_INF_SKIP;
  2973. + }
  2974. + if (too_long) { /* GRR: should allow FAT extraction w/o EAs */
  2975. + Info(slide, 1, ((char *)slide,
  2976. + "checkdir error: path too long: %s\n",
  2977. + FnFilter1(G.buildpathHPFS)));
  2978. + free(G.buildpathHPFS);
  2979. + free(G.buildpathFAT);
  2980. + /* no room for filenames: fatal */
  2981. + return MPN_ERR_TOOLONG;
  2982. + }
  2983. + if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
  2984. + Info(slide, 1, ((char *)slide,
  2985. + "checkdir error: cannot create %s\n\
  2986. + unable to process %s.\n",
  2987. + FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
  2988. + free(G.buildpathHPFS);
  2989. + free(G.buildpathFAT);
  2990. + /* path didn't exist, tried to create, failed */
  2991. + return MPN_ERR_SKIP;
  2992. + }
  2993. + G.created_dir = TRUE;
  2994. + }
  2995. +#endif /* FIX_STAT_BUG */
  2996. + if (SSTAT(G.buildpathFAT, &G.statbuf)) /* path doesn't exist */
  2997. + {
  2998. + if (!G.create_dirs) { /* told not to create (freshening) */
  2999. + free(G.buildpathHPFS);
  3000. + free(G.buildpathFAT);
  3001. + /* path doesn't exist: nothing to do */
  3002. + return MPN_INF_SKIP;
  3003. + }
  3004. + if (too_long) { /* GRR: should allow FAT extraction w/o EAs */
  3005. + Info(slide, 1, ((char *)slide,
  3006. + "checkdir error: path too long: %s\n",
  3007. + FnFilter1(G.buildpathHPFS)));
  3008. + free(G.buildpathHPFS);
  3009. + free(G.buildpathFAT);
  3010. + /* no room for filenames: fatal */
  3011. + return MPN_ERR_TOOLONG;
  3012. + }
  3013. + if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
  3014. + Info(slide, 1, ((char *)slide,
  3015. + "checkdir error: cannot create %s\n\
  3016. + unable to process %s.\n",
  3017. + FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
  3018. + free(G.buildpathHPFS);
  3019. + free(G.buildpathFAT);
  3020. + /* path didn't exist, tried to create, failed */
  3021. + return MPN_ERR_SKIP;
  3022. + }
  3023. + G.created_dir = TRUE;
  3024. + } else if (!S_ISDIR(G.statbuf.st_mode)) {
  3025. + Info(slide, 1, ((char *)slide,
  3026. + "checkdir error: %s exists but is not directory\n \
  3027. + unable to process %s.\n",
  3028. + FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
  3029. + free(G.buildpathHPFS);
  3030. + free(G.buildpathFAT);
  3031. + /* path existed but wasn't dir */
  3032. + return MPN_ERR_SKIP;
  3033. + }
  3034. + if (too_long) {
  3035. + Info(slide, 1, ((char *)slide,
  3036. + "checkdir error: path too long: %s\n",
  3037. + FnFilter1(G.buildpathHPFS)));
  3038. + free(G.buildpathHPFS);
  3039. + free(G.buildpathFAT);
  3040. + /* no room for filenames: fatal */
  3041. + return MPN_ERR_TOOLONG;
  3042. + }
  3043. + *G.endHPFS++ = '/';
  3044. + *G.endFAT++ = '/';
  3045. + *G.endHPFS = *G.endFAT = '\0';
  3046. + Trace((stderr, "buildpathHPFS now = [%s]\nbuildpathFAT now = [%s]\n",
  3047. + FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
  3048. + return MPN_OK;
  3049. +
  3050. + } /* end if (FUNCTION == APPEND_DIR) */
  3051. +
  3052. +/*---------------------------------------------------------------------------
  3053. + GETPATH: copy full FAT path to the string pointed at by pathcomp (want
  3054. + filename to reflect name used on disk, not EAs; if full path is HPFS,
  3055. + buildpathFAT and buildpathHPFS will be identical). Also free both paths.
  3056. + ---------------------------------------------------------------------------*/
  3057. +
  3058. + if (FUNCTION == GETPATH) {
  3059. + Trace((stderr, "getting and freeing FAT path [%s]\n",
  3060. + FnFilter1(G.buildpathFAT)));
  3061. + Trace((stderr, "freeing HPFS path [%s]\n",
  3062. + FnFilter1(G.buildpathHPFS)));
  3063. + strcpy(pathcomp, G.buildpathFAT);
  3064. + free(G.buildpathFAT);
  3065. + free(G.buildpathHPFS);
  3066. + G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL;
  3067. + return MPN_OK;
  3068. + }
  3069. +
  3070. +/*---------------------------------------------------------------------------
  3071. + APPEND_NAME: assume the path component is the filename; append it and
  3072. + return without checking for existence.
  3073. + ---------------------------------------------------------------------------*/
  3074. +
  3075. + if (FUNCTION == APPEND_NAME) {
  3076. + char *p = pathcomp;
  3077. + int error = MPN_OK;
  3078. +
  3079. + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp)));
  3080. + /* The buildpathHPFS buffer has been allocated large enough to
  3081. + * hold the complete combined name, so there is no need to check
  3082. + * for OS filename size limit overflow within the copy loop.
  3083. + */
  3084. + while ((*G.endHPFS = *p++) != '\0') { /* copy to HPFS filename */
  3085. + ++G.endHPFS;
  3086. + }
  3087. + /* Now, check for OS filename size overflow. When detected, the
  3088. + * mapped HPFS name is truncated and a warning message is shown.
  3089. + */
  3090. + if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) {
  3091. + G.buildpathHPFS[FILNAMSIZ-1] = '\0';
  3092. + Info(slide, 1, ((char *)slide,
  3093. + "checkdir warning: path too long; truncating\n \
  3094. + %s\n -> %s\n",
  3095. + FnFilter1(G.filename), FnFilter2(G.buildpathHPFS)));
  3096. + error = MPN_INF_TRUNC; /* filename truncated */
  3097. + }
  3098. +
  3099. + /* The buildpathFAT buffer has the same allocated size as the
  3100. + * buildpathHPFS buffer, so there is no need for an overflow check
  3101. + * within the following copy loop, either.
  3102. + */
  3103. + if (G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
  3104. + /* copy to FAT filename, too */
  3105. + p = pathcomp;
  3106. + while ((*G.endFAT = *p++) != '\0')
  3107. + ++G.endFAT;
  3108. + } else
  3109. + /* map into FAT fn, update endFAT */
  3110. + map2fat(pathcomp, &G.endFAT);
  3111. +
  3112. + /* Check that the FAT path does not exceed the FILNAMSIZ limit, and
  3113. + * truncate when neccessary.
  3114. + * Note that truncation can only happen when the HPFS path (which is
  3115. + * never shorter than the FAT path) has been already truncated.
  3116. + * So, emission of the warning message and setting the error code
  3117. + * has already happened.
  3118. + */
  3119. + if ((G.endFAT-G.buildpathFAT) >= FILNAMSIZ)
  3120. + G.buildpathFAT[FILNAMSIZ-1] = '\0';
  3121. + Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n",
  3122. + FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
  3123. +
  3124. + return error; /* could check for existence, prompt for new name... */
  3125. +
  3126. + } /* end if (FUNCTION == APPEND_NAME) */
  3127. +
  3128. +/*---------------------------------------------------------------------------
  3129. + INIT: allocate and initialize buffer space for the file currently being
  3130. + extracted. If file was renamed with an absolute path, don't prepend the
  3131. + extract-to path.
  3132. + ---------------------------------------------------------------------------*/
  3133. +
  3134. + if (FUNCTION == INIT) {
  3135. + Trace((stderr, "initializing buildpathHPFS and buildpathFAT to "));
  3136. +#ifdef ACORN_FTYPE_NFS
  3137. + if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+
  3138. + (uO.acorn_nfs_ext ? 5 : 1)))
  3139. +#else
  3140. + if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1))
  3141. +#endif
  3142. + == NULL)
  3143. + return MPN_NOMEM;
  3144. +#ifdef ACORN_FTYPE_NFS
  3145. + if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+
  3146. + (uO.acorn_nfs_ext ? 5 : 1)))
  3147. +#else
  3148. + if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1))
  3149. +#endif
  3150. + == NULL) {
  3151. + free(G.buildpathHPFS);
  3152. + return MPN_NOMEM;
  3153. + }
  3154. + if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */
  3155. +/* GRR: for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */
  3156. + if (G.renamed_fullpath && pathcomp[1] == ':')
  3157. + *G.buildpathHPFS = (char)ToLower(*pathcomp);
  3158. + else if (!G.renamed_fullpath && G.rootlen > 1 &&
  3159. + G.rootpath[1] == ':')
  3160. + *G.buildpathHPFS = (char)ToLower(*G.rootpath);
  3161. + else {
  3162. + char tmpN[MAX_PATH], *tmpP;
  3163. + if (GetFullPathNameA(".", MAX_PATH, tmpN, &tmpP) > MAX_PATH)
  3164. + { /* by definition of MAX_PATH we should never get here */
  3165. + Info(slide, 1, ((char *)slide,
  3166. + "checkdir warning: current dir path too long\n"));
  3167. + return MPN_INF_TRUNC; /* can't get drive letter */
  3168. + }
  3169. + G.nLabelDrive = *tmpN - 'a' + 1;
  3170. + *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a');
  3171. + }
  3172. + G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */
  3173. + if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */
  3174. + || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */
  3175. + free(G.buildpathHPFS);
  3176. + free(G.buildpathFAT);
  3177. + return MPN_VOL_LABEL; /* skipping with message */
  3178. + }
  3179. + *G.buildpathHPFS = '\0';
  3180. + } else if (G.renamed_fullpath) /* pathcomp = valid data */
  3181. + strcpy(G.buildpathHPFS, pathcomp);
  3182. + else if (G.rootlen > 0)
  3183. + strcpy(G.buildpathHPFS, G.rootpath);
  3184. + else
  3185. + *G.buildpathHPFS = '\0';
  3186. + G.endHPFS = G.buildpathHPFS;
  3187. + G.endFAT = G.buildpathFAT;
  3188. + while ((*G.endFAT = *G.endHPFS) != '\0') {
  3189. + ++G.endFAT;
  3190. + ++G.endHPFS;
  3191. + }
  3192. + Trace((stderr, "[%s]\n", FnFilter1(G.buildpathHPFS)));
  3193. + return MPN_OK;
  3194. + }
  3195. +
  3196. +/*---------------------------------------------------------------------------
  3197. + ROOT: if appropriate, store the path in rootpath and create it if neces-
  3198. + sary; else assume it's a zipfile member and return. This path segment
  3199. + gets used in extracting all members from every zipfile specified on the
  3200. + command line. Note that under OS/2 and MS-DOS, if a candidate extract-to
  3201. + directory specification includes a drive letter (leading "x:"), it is
  3202. + treated just as if it had a trailing '/'--that is, one directory level
  3203. + will be created if the path doesn't exist, unless this is otherwise pro-
  3204. + hibited (e.g., freshening).
  3205. + ---------------------------------------------------------------------------*/
  3206. +
  3207. +#if (!defined(SFX) || defined(SFX_EXDIR))
  3208. + if (FUNCTION == ROOT) {
  3209. + Trace((stderr, "initializing root path to [%s]\n",
  3210. + FnFilter1(pathcomp)));
  3211. + if (pathcomp == NULL) {
  3212. + G.rootlen = 0;
  3213. + return MPN_OK;
  3214. + }
  3215. + if (G.rootlen > 0) /* rootpath was already set, nothing to do */
  3216. + return MPN_OK;
  3217. + if ((G.rootlen = strlen(pathcomp)) > 0) {
  3218. + int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE;
  3219. + char *tmproot;
  3220. +
  3221. + if ((tmproot = (char *)malloc(G.rootlen+3)) == (char *)NULL) {
  3222. + G.rootlen = 0;
  3223. + return MPN_NOMEM;
  3224. + }
  3225. + strcpy(tmproot, pathcomp);
  3226. + if (isalpha((uch)tmproot[0]) && tmproot[1] == ':')
  3227. + has_drive = TRUE; /* drive designator */
  3228. + if (tmproot[G.rootlen-1] == '/' || tmproot[G.rootlen-1] == '\\') {
  3229. + tmproot[--G.rootlen] = '\0';
  3230. + had_trailing_pathsep = TRUE;
  3231. + }
  3232. + if (has_drive && (G.rootlen == 2)) {
  3233. + if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */
  3234. + add_dot = TRUE; /* relative path: add '.' before '/' */
  3235. + } else if (G.rootlen > 0) { /* need not check "x:." and "x:/" */
  3236. + if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
  3237. + {
  3238. + /* path does not exist */
  3239. + if (!G.create_dirs /* || iswild(tmproot) */ ) {
  3240. + free(tmproot);
  3241. + G.rootlen = 0;
  3242. + /* treat as stored file */
  3243. + return MPN_INF_SKIP;
  3244. + }
  3245. + /* create directory (could add loop here scanning tmproot
  3246. + * to create more than one level, but really necessary?) */
  3247. + if (MKDIR(tmproot, 0777) == -1) {
  3248. + Info(slide, 1, ((char *)slide,
  3249. + "checkdir: cannot create extraction directory: %s\n",
  3250. + FnFilter1(tmproot)));
  3251. + free(tmproot);
  3252. + G.rootlen = 0;
  3253. + /* path didn't exist, tried to create, failed: */
  3254. + /* file exists, or need 2+ subdir levels */
  3255. + return MPN_ERR_SKIP;
  3256. + }
  3257. + }
  3258. + }
  3259. + if (add_dot) /* had just "x:", make "x:." */
  3260. + tmproot[G.rootlen++] = '.';
  3261. + tmproot[G.rootlen++] = '/';
  3262. + tmproot[G.rootlen] = '\0';
  3263. + if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) {
  3264. + free(tmproot);
  3265. + G.rootlen = 0;
  3266. + return MPN_NOMEM;
  3267. + }
  3268. + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath)));
  3269. + }
  3270. + return MPN_OK;
  3271. + }
  3272. +#endif /* !SFX || SFX_EXDIR */
  3273. +
  3274. +/*---------------------------------------------------------------------------
  3275. + END: free rootpath, immediately prior to program exit.
  3276. + ---------------------------------------------------------------------------*/
  3277. +
  3278. + if (FUNCTION == END) {
  3279. + Trace((stderr, "freeing rootpath\n"));
  3280. + if (G.rootlen > 0) {
  3281. + free(G.rootpath);
  3282. + G.rootlen = 0;
  3283. + }
  3284. + return MPN_OK;
  3285. }
  3286. -} /* end function map2fat() */
  3287. + return MPN_INVALID; /* should never reach */
  3288. +
  3289. +} /* end function checkdir() */
  3290. -/***********************/ /* Borrowed from os2.c for UnZip 5.1. */
  3291. -/* Function checkdir() */ /* Difference: no EA stuff */
  3292. -/***********************/ /* HPFS stuff works on NTFS too */
  3293. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  3294. -int checkdir(__G__ pathcomp, flag)
  3295. +/* WIN32 wide version */
  3296. +
  3297. +int checkdirw(__G__ pathcompw, flag)
  3298. __GDEF
  3299. - char *pathcomp;
  3300. + wchar_t *pathcompw;
  3301. int flag;
  3302. /*
  3303. @@ -2126,16 +3345,20 @@
  3304. if (FUNCTION == APPEND_DIR) {
  3305. - char *p = pathcomp;
  3306. + wchar_t *pw = pathcompw;
  3307. int too_long = FALSE;
  3308. -
  3309. - Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp)));
  3310. - while ((*G.endHPFS = *p++) != '\0') /* copy to HPFS filename */
  3311. - ++G.endHPFS;
  3312. - if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
  3313. - p = pathcomp;
  3314. - while ((*G.endFAT = *p++) != '\0') /* copy to FAT filename, too */
  3315. - ++G.endFAT;
  3316. + char *buildpathFAT = wchar_to_local_string(G.buildpathFATw, G.unicode_escape_all);
  3317. + char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);
  3318. + /* Could use G.filename from the standard path, but may
  3319. + not work well on this port */
  3320. + char *fn = wchar_to_local_string(G.unipath_widefilename, G.unicode_escape_all);
  3321. +
  3322. + while ((*G.endHPFSw = *pw++) != '\0') /* copy to HPFS filename */
  3323. + ++G.endHPFSw;
  3324. + if (!IsVolumeOldFATw(__G__ G.buildpathHPFSw)) {
  3325. + pw = pathcompw;
  3326. + while ((*G.endFATw = *pw++) != '\0') /* copy to FAT filename, too */
  3327. + ++G.endFATw;
  3328. } else
  3329. - map2fat(pathcomp, &G.endFAT); /* map into FAT fn, update endFAT */
  3330. + map2fatw(pathcompw, &G.endFATw); /* map into FAT fn, update endFAT */
  3331. /* GRR: could do better check, see if overrunning buffer as we go:
  3332. @@ -2145,5 +3368,5 @@
  3333. /* next check: need to append '/', at least one-char name, '\0' */
  3334. - if ((G.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3)
  3335. + if ((G.endHPFSw-G.buildpathHPFSw) > FILNAMSIZ-3)
  3336. too_long = TRUE; /* check if extracting dir? */
  3337. #ifdef FIX_STAT_BUG
  3338. @@ -2153,8 +3376,11 @@
  3339. * than console. The code below attempts to work around this problem.
  3340. */
  3341. - if (access(G.buildpathFAT, 0) != 0) {
  3342. + if (_waccess(G.buildpathFATw, 0) != 0) {
  3343. if (!G.create_dirs) { /* told not to create (freshening) */
  3344. - free(G.buildpathHPFS);
  3345. - free(G.buildpathFAT);
  3346. + free(buildpathHPFS);
  3347. + free(buildpathFAT);
  3348. + free(fn);
  3349. + free(G.buildpathHPFSw);
  3350. + free(G.buildpathFATw);
  3351. /* path doesn't exist: nothing to do */
  3352. return MPN_INF_SKIP;
  3353. @@ -2163,28 +3389,40 @@
  3354. Info(slide, 1, ((char *)slide,
  3355. "checkdir error: path too long: %s\n",
  3356. - FnFilter1(G.buildpathHPFS)));
  3357. - free(G.buildpathHPFS);
  3358. - free(G.buildpathFAT);
  3359. + FnFilter1(fn)));
  3360. + free(buildpathHPFS);
  3361. + free(buildpathFAT);
  3362. + free(fn);
  3363. + free(G.buildpathHPFSw);
  3364. + free(G.buildpathFATw);
  3365. /* no room for filenames: fatal */
  3366. return MPN_ERR_TOOLONG;
  3367. }
  3368. - if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
  3369. - Info(slide, 1, ((char *)slide,
  3370. - "checkdir error: cannot create %s\n\
  3371. - unable to process %s.\n",
  3372. - FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
  3373. - free(G.buildpathHPFS);
  3374. - free(G.buildpathFAT);
  3375. - /* path didn't exist, tried to create, failed */
  3376. - return MPN_ERR_SKIP;
  3377. - }
  3378. - G.created_dir = TRUE;
  3379. + {
  3380. + int i = MKDIRW(G.buildpathFATw, 0777);
  3381. + if (i == -1) { /* create the directory */
  3382. + Info(slide, 1, ((char *)slide,
  3383. + "checkdir error: cannot create %s\n\
  3384. + unable to process %s.\n",
  3385. + FnFilter2(buildpathFAT), FnFilter1(fn)));
  3386. + free(buildpathHPFS);
  3387. + free(buildpathFAT);
  3388. + free(fn);
  3389. + free(G.buildpathHPFSw);
  3390. + free(G.buildpathFATw);
  3391. + /* path didn't exist, tried to create, failed */
  3392. + return MPN_ERR_SKIP;
  3393. + }
  3394. + G.created_dir = TRUE;
  3395. + }
  3396. }
  3397. #endif /* FIX_STAT_BUG */
  3398. - if (SSTAT(G.buildpathFAT, &G.statbuf)) /* path doesn't exist */
  3399. + if (SSTATW(G.buildpathFATw, &G.statbuf)) /* path doesn't exist */
  3400. {
  3401. if (!G.create_dirs) { /* told not to create (freshening) */
  3402. - free(G.buildpathHPFS);
  3403. - free(G.buildpathFAT);
  3404. + free(buildpathHPFS);
  3405. + free(buildpathFAT);
  3406. + free(fn);
  3407. + free(G.buildpathHPFSw);
  3408. + free(G.buildpathFATw);
  3409. /* path doesn't exist: nothing to do */
  3410. return MPN_INF_SKIP;
  3411. @@ -2193,28 +3431,41 @@
  3412. Info(slide, 1, ((char *)slide,
  3413. "checkdir error: path too long: %s\n",
  3414. - FnFilter1(G.buildpathHPFS)));
  3415. - free(G.buildpathHPFS);
  3416. - free(G.buildpathFAT);
  3417. + FnFilter1(buildpathHPFS)));
  3418. + free(buildpathHPFS);
  3419. + free(buildpathFAT);
  3420. + free(fn);
  3421. + free(G.buildpathHPFSw);
  3422. + free(G.buildpathFATw);
  3423. /* no room for filenames: fatal */
  3424. return MPN_ERR_TOOLONG;
  3425. }
  3426. - if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
  3427. - Info(slide, 1, ((char *)slide,
  3428. - "checkdir error: cannot create %s\n\
  3429. - unable to process %s.\n",
  3430. - FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
  3431. - free(G.buildpathHPFS);
  3432. - free(G.buildpathFAT);
  3433. - /* path didn't exist, tried to create, failed */
  3434. - return MPN_ERR_SKIP;
  3435. - }
  3436. - G.created_dir = TRUE;
  3437. + {
  3438. + char *buildpathFAT = wchar_to_local_string(G.buildpathFATw, G.unicode_escape_all);
  3439. + int i = MKDIRW(G.buildpathFATw, 0777);
  3440. + if (i == -1) { /* create the directory */
  3441. + Info(slide, 1, ((char *)slide,
  3442. + "checkdir error: cannot create %s\n\
  3443. + unable to process %s.\n",
  3444. + FnFilter2(buildpathFAT), FnFilter1(fn)));
  3445. + free(buildpathHPFS);
  3446. + free(buildpathFAT);
  3447. + free(fn);
  3448. + free(G.buildpathHPFSw);
  3449. + free(G.buildpathFATw);
  3450. + /* path didn't exist, tried to create, failed */
  3451. + return MPN_ERR_SKIP;
  3452. + }
  3453. + G.created_dir = TRUE;
  3454. + }
  3455. } else if (!S_ISDIR(G.statbuf.st_mode)) {
  3456. Info(slide, 1, ((char *)slide,
  3457. "checkdir error: %s exists but is not directory\n \
  3458. unable to process %s.\n",
  3459. - FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
  3460. - free(G.buildpathHPFS);
  3461. - free(G.buildpathFAT);
  3462. + FnFilter2(buildpathFAT), FnFilter1(fn)));
  3463. + free(buildpathHPFS);
  3464. + free(buildpathFAT);
  3465. + free(fn);
  3466. + free(G.buildpathHPFSw);
  3467. + free(G.buildpathFATw);
  3468. /* path existed but wasn't dir */
  3469. return MPN_ERR_SKIP;
  3470. @@ -2223,15 +3474,23 @@
  3471. Info(slide, 1, ((char *)slide,
  3472. "checkdir error: path too long: %s\n",
  3473. - FnFilter1(G.buildpathHPFS)));
  3474. - free(G.buildpathHPFS);
  3475. - free(G.buildpathFAT);
  3476. + FnFilter1(buildpathHPFS)));
  3477. + free(buildpathHPFS);
  3478. + free(buildpathFAT);
  3479. + free(fn);
  3480. + free(G.buildpathHPFSw);
  3481. + free(G.buildpathFATw);
  3482. /* no room for filenames: fatal */
  3483. return MPN_ERR_TOOLONG;
  3484. }
  3485. - *G.endHPFS++ = '/';
  3486. - *G.endFAT++ = '/';
  3487. - *G.endHPFS = *G.endFAT = '\0';
  3488. + *G.endHPFSw++ = '/';
  3489. + *G.endFATw++ = '/';
  3490. + *G.endHPFSw = *G.endFATw = '\0';
  3491. Trace((stderr, "buildpathHPFS now = [%s]\nbuildpathFAT now = [%s]\n",
  3492. - FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
  3493. + FnFilter1(buildpathHPFS), FnFilter2(buildpathFAT)));
  3494. + free(buildpathHPFS);
  3495. + free(buildpathFAT);
  3496. + free(fn);
  3497. + //free(G.buildpathHPFSw);
  3498. + //free(G.buildpathFATw);
  3499. return MPN_OK;
  3500. @@ -2245,12 +3504,16 @@
  3501. if (FUNCTION == GETPATH) {
  3502. + char *buildpathFAT = wchar_to_local_string(G.buildpathFATw, G.unicode_escape_all);
  3503. + char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);
  3504. Trace((stderr, "getting and freeing FAT path [%s]\n",
  3505. - FnFilter1(G.buildpathFAT)));
  3506. + FnFilter1(buildpathFAT)));
  3507. Trace((stderr, "freeing HPFS path [%s]\n",
  3508. - FnFilter1(G.buildpathHPFS)));
  3509. - strcpy(pathcomp, G.buildpathFAT);
  3510. - free(G.buildpathFAT);
  3511. - free(G.buildpathHPFS);
  3512. - G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL;
  3513. + FnFilter1(buildpathHPFS)));
  3514. + wcscpy(pathcompw, G.buildpathFATw);
  3515. + free(buildpathFAT);
  3516. + free(buildpathHPFS);
  3517. + free(G.buildpathFATw);
  3518. + free(G.buildpathHPFSw);
  3519. + G.buildpathHPFSw = G.buildpathFATw = G.endHPFSw = G.endFATw = NULL;
  3520. return MPN_OK;
  3521. }
  3522. @@ -2262,6 +3525,8 @@
  3523. if (FUNCTION == APPEND_NAME) {
  3524. - char *p = pathcomp;
  3525. + wchar_t *pw = pathcompw;
  3526. int error = MPN_OK;
  3527. + char *pathcomp = wchar_to_local_string(pathcompw, G.unicode_escape_all);
  3528. + char *fn = wchar_to_local_string(G.unipath_widefilename, G.unicode_escape_all);
  3529. Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp)));
  3530. @@ -2270,16 +3535,19 @@
  3531. * for OS filename size limit overflow within the copy loop.
  3532. */
  3533. - while ((*G.endHPFS = *p++) != '\0') { /* copy to HPFS filename */
  3534. - ++G.endHPFS;
  3535. + while ((*G.endHPFSw = *pw++) != '\0') { /* copy to HPFS filename */
  3536. + ++G.endHPFSw;
  3537. }
  3538. /* Now, check for OS filename size overflow. When detected, the
  3539. * mapped HPFS name is truncated and a warning message is shown.
  3540. */
  3541. - if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) {
  3542. - G.buildpathHPFS[FILNAMSIZ-1] = '\0';
  3543. + if ((G.endHPFSw-G.buildpathHPFSw) >= FILNAMSIZ) {
  3544. + char *buildpathHPFS;
  3545. + G.buildpathHPFSw[FILNAMSIZ-1] = '\0';
  3546. + buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);
  3547. Info(slide, 1, ((char *)slide,
  3548. "checkdir warning: path too long; truncating\n \
  3549. %s\n -> %s\n",
  3550. - FnFilter1(G.filename), FnFilter2(G.buildpathHPFS)));
  3551. + FnFilter1(fn), FnFilter2(buildpathHPFS)));
  3552. + free(buildpathHPFS);
  3553. error = MPN_INF_TRUNC; /* filename truncated */
  3554. }
  3555. @@ -2289,12 +3557,12 @@
  3556. * within the following copy loop, either.
  3557. */
  3558. - if (G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
  3559. + if (G.pInfo->vollabel || !IsVolumeOldFATw(__G__ G.buildpathHPFSw)) {
  3560. /* copy to FAT filename, too */
  3561. - p = pathcomp;
  3562. - while ((*G.endFAT = *p++) != '\0')
  3563. - ++G.endFAT;
  3564. + pw = pathcompw;
  3565. + while ((*G.endFATw = *pw++) != '\0')
  3566. + ++G.endFATw;
  3567. } else
  3568. /* map into FAT fn, update endFAT */
  3569. - map2fat(pathcomp, &G.endFAT);
  3570. + map2fatw(pathcompw, &G.endFATw);
  3571. /* Check that the FAT path does not exceed the FILNAMSIZ limit, and
  3572. @@ -2305,8 +3573,16 @@
  3573. * has already happened.
  3574. */
  3575. - if ((G.endFAT-G.buildpathFAT) >= FILNAMSIZ)
  3576. - G.buildpathFAT[FILNAMSIZ-1] = '\0';
  3577. - Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n",
  3578. - FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
  3579. + if ((G.endFATw-G.buildpathFATw) >= FILNAMSIZ)
  3580. + G.buildpathFATw[FILNAMSIZ-1] = '\0';
  3581. + {
  3582. + char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);
  3583. + char *buildpathFAT = wchar_to_local_string(G.buildpathFATw,G.unicode_escape_all);
  3584. + Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n",
  3585. + FnFilter1(buildpathHPFS), FnFilter2(buildpathFAT)));
  3586. + free(buildpathHPFS);
  3587. + free(buildpathFAT);
  3588. + }
  3589. + free(fn);
  3590. + free(pathcomp);
  3591. return error; /* could check for existence, prompt for new name... */
  3592. @@ -2321,33 +3597,23 @@
  3593. if (FUNCTION == INIT) {
  3594. - Trace((stderr, "initializing buildpathHPFS and buildpathFAT to "));
  3595. -#ifdef ACORN_FTYPE_NFS
  3596. - if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+
  3597. - (uO.acorn_nfs_ext ? 5 : 1)))
  3598. -#else
  3599. - if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1))
  3600. -#endif
  3601. + Trace((stderr, "initializing buildpathHPFSw and buildpathFATw to "));
  3602. + if ((G.buildpathHPFSw = (wchar_t *)malloc((G.fnlen+G.rootlen+1) * sizeof(wchar_t)))
  3603. == NULL)
  3604. return MPN_NOMEM;
  3605. -#ifdef ACORN_FTYPE_NFS
  3606. - if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+
  3607. - (uO.acorn_nfs_ext ? 5 : 1)))
  3608. -#else
  3609. - if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1))
  3610. -#endif
  3611. + if ((G.buildpathFATw = (wchar_t *)malloc((G.fnlen+G.rootlen+1) * sizeof(wchar_t)))
  3612. == NULL) {
  3613. - free(G.buildpathHPFS);
  3614. + free(G.buildpathHPFSw);
  3615. return MPN_NOMEM;
  3616. }
  3617. if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */
  3618. /* GRR: for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */
  3619. - if (G.renamed_fullpath && pathcomp[1] == ':')
  3620. - *G.buildpathHPFS = (char)ToLower(*pathcomp);
  3621. + if (G.renamed_fullpath && pathcompw[1] == ':')
  3622. + *G.buildpathHPFSw = (wchar_t)towlower(*pathcompw);
  3623. else if (!G.renamed_fullpath && G.rootlen > 1 &&
  3624. - G.rootpath[1] == ':')
  3625. - *G.buildpathHPFS = (char)ToLower(*G.rootpath);
  3626. + G.rootpathw[1] == ':')
  3627. + *G.buildpathHPFSw = (wchar_t)towlower(*G.rootpathw);
  3628. else {
  3629. - char tmpN[MAX_PATH], *tmpP;
  3630. - if (GetFullPathNameA(".", MAX_PATH, tmpN, &tmpP) > MAX_PATH)
  3631. + wchar_t tmpNw[MAX_PATH], *tmpPw;
  3632. + if (GetFullPathNameW(L".", MAX_PATH, tmpNw, &tmpPw) > MAX_PATH)
  3633. { /* by definition of MAX_PATH we should never get here */
  3634. Info(slide, 1, ((char *)slide,
  3635. @@ -2355,28 +3621,33 @@
  3636. return MPN_INF_TRUNC; /* can't get drive letter */
  3637. }
  3638. - G.nLabelDrive = *tmpN - 'a' + 1;
  3639. - *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a');
  3640. + G.nLabelDrive = (char)(*tmpNw - 'a' + 1);
  3641. + *G.buildpathHPFSw = (wchar_t)(G.nLabelDrive - 1 + 'a');
  3642. }
  3643. - G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */
  3644. - if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */
  3645. + G.nLabelDrive = (char)(*G.buildpathHPFSw - 'a' + 1); /* save for mapname() */
  3646. + if (uO.volflag == 0 || *G.buildpathHPFSw < 'a' /* no labels/bogus? */
  3647. || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */
  3648. - free(G.buildpathHPFS);
  3649. - free(G.buildpathFAT);
  3650. + free(G.buildpathHPFSw);
  3651. + free(G.buildpathFATw);
  3652. return MPN_VOL_LABEL; /* skipping with message */
  3653. }
  3654. - *G.buildpathHPFS = '\0';
  3655. + *G.buildpathHPFSw = '\0';
  3656. } else if (G.renamed_fullpath) /* pathcomp = valid data */
  3657. - strcpy(G.buildpathHPFS, pathcomp);
  3658. + wcscpy(G.buildpathHPFSw, pathcompw);
  3659. else if (G.rootlen > 0)
  3660. - strcpy(G.buildpathHPFS, G.rootpath);
  3661. + wcscpy(G.buildpathHPFSw, G.rootpathw);
  3662. else
  3663. - *G.buildpathHPFS = '\0';
  3664. - G.endHPFS = G.buildpathHPFS;
  3665. - G.endFAT = G.buildpathFAT;
  3666. - while ((*G.endFAT = *G.endHPFS) != '\0') {
  3667. - ++G.endFAT;
  3668. - ++G.endHPFS;
  3669. + *G.buildpathHPFSw = '\0';
  3670. + G.endHPFSw = G.buildpathHPFSw;
  3671. + G.endFATw = G.buildpathFATw;
  3672. + while ((*G.endFATw = *G.endHPFSw) != '\0') {
  3673. + ++G.endFATw;
  3674. + ++G.endHPFSw;
  3675. }
  3676. - Trace((stderr, "[%s]\n", FnFilter1(G.buildpathHPFS)));
  3677. + {
  3678. + char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);
  3679. + Trace((stderr, "[%s]\n", FnFilter1(buildpathHPFS)));
  3680. + free(buildpathHPFS);
  3681. + }
  3682. +
  3683. return MPN_OK;
  3684. }
  3685. @@ -2395,7 +3666,9 @@
  3686. #if (!defined(SFX) || defined(SFX_EXDIR))
  3687. if (FUNCTION == ROOT) {
  3688. + char *pathcomp = wchar_to_local_string(pathcompw, G.unicode_escape_all);
  3689. Trace((stderr, "initializing root path to [%s]\n",
  3690. FnFilter1(pathcomp)));
  3691. - if (pathcomp == NULL) {
  3692. + free(pathcomp);
  3693. + if (pathcompw == NULL) {
  3694. G.rootlen = 0;
  3695. return MPN_OK;
  3696. @@ -2403,17 +3676,17 @@
  3697. if (G.rootlen > 0) /* rootpath was already set, nothing to do */
  3698. return MPN_OK;
  3699. - if ((G.rootlen = strlen(pathcomp)) > 0) {
  3700. + if ((G.rootlen = wcslen(pathcompw)) > 0) {
  3701. int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE;
  3702. - char *tmproot;
  3703. + wchar_t *tmprootw;
  3704. - if ((tmproot = (char *)malloc(G.rootlen+3)) == (char *)NULL) {
  3705. + if ((tmprootw = (wchar_t *)malloc((G.rootlen+3) * sizeof(wchar_t))) == (wchar_t *)NULL) {
  3706. G.rootlen = 0;
  3707. return MPN_NOMEM;
  3708. }
  3709. - strcpy(tmproot, pathcomp);
  3710. - if (isalpha((uch)tmproot[0]) && tmproot[1] == ':')
  3711. + wcscpy(tmprootw, pathcompw);
  3712. + if (iswalpha(tmprootw[0]) && tmprootw[1] == ':')
  3713. has_drive = TRUE; /* drive designator */
  3714. - if (tmproot[G.rootlen-1] == '/' || tmproot[G.rootlen-1] == '\\') {
  3715. - tmproot[--G.rootlen] = '\0';
  3716. + if (tmprootw[G.rootlen-1] == '/' || tmprootw[G.rootlen-1] == '\\') {
  3717. + tmprootw[--G.rootlen] = '\0';
  3718. had_trailing_pathsep = TRUE;
  3719. }
  3720. @@ -2422,9 +3695,9 @@
  3721. add_dot = TRUE; /* relative path: add '.' before '/' */
  3722. } else if (G.rootlen > 0) { /* need not check "x:." and "x:/" */
  3723. - if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
  3724. + if (SSTATW(tmprootw, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
  3725. {
  3726. /* path does not exist */
  3727. if (!G.create_dirs /* || iswild(tmproot) */ ) {
  3728. - free(tmproot);
  3729. + free(tmprootw);
  3730. G.rootlen = 0;
  3731. /* treat as stored file */
  3732. @@ -2433,12 +3706,15 @@
  3733. /* create directory (could add loop here scanning tmproot
  3734. * to create more than one level, but really necessary?) */
  3735. - if (MKDIR(tmproot, 0777) == -1) {
  3736. + if (MKDIRW(tmprootw, 0777) == -1) {
  3737. + char *tmproot = wchar_to_local_string(tmprootw, G.unicode_escape_all);
  3738. Info(slide, 1, ((char *)slide,
  3739. "checkdir: cannot create extraction directory: %s\n",
  3740. FnFilter1(tmproot)));
  3741. free(tmproot);
  3742. + free(tmprootw);
  3743. G.rootlen = 0;
  3744. /* path didn't exist, tried to create, failed: */
  3745. /* file exists, or need 2+ subdir levels */
  3746. + free(pathcomp);
  3747. return MPN_ERR_SKIP;
  3748. }
  3749. @@ -2446,13 +3722,17 @@
  3750. }
  3751. if (add_dot) /* had just "x:", make "x:." */
  3752. - tmproot[G.rootlen++] = '.';
  3753. - tmproot[G.rootlen++] = '/';
  3754. - tmproot[G.rootlen] = '\0';
  3755. - if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) {
  3756. - free(tmproot);
  3757. + tmprootw[G.rootlen++] = '.';
  3758. + tmprootw[G.rootlen++] = '/';
  3759. + tmprootw[G.rootlen] = '\0';
  3760. + if ((G.rootpathw = (wchar_t *)realloc(tmprootw, (G.rootlen+1) * sizeof(wchar_t))) == NULL) {
  3761. + free(tmprootw);
  3762. G.rootlen = 0;
  3763. return MPN_NOMEM;
  3764. }
  3765. - Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath)));
  3766. + {
  3767. + char *rootpath = wchar_to_local_string(G.rootpathw, G.unicode_escape_all);
  3768. + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath)));
  3769. + free(rootpath);
  3770. + }
  3771. }
  3772. return MPN_OK;
  3773. @@ -2467,5 +3747,5 @@
  3774. Trace((stderr, "freeing rootpath\n"));
  3775. if (G.rootlen > 0) {
  3776. - free(G.rootpath);
  3777. + free(G.rootpathw);
  3778. G.rootlen = 0;
  3779. }
  3780. @@ -2475,6 +3755,7 @@
  3781. return MPN_INVALID; /* should never reach */
  3782. -} /* end function checkdir() */
  3783. +} /* end function checkdirw() */
  3784. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  3785. @@ -2809,4 +4090,99 @@
  3786. }
  3787. +
  3788. +
  3789. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  3790. +
  3791. +int zstat_win32w(__W32STAT_GLOBALS__ const wchar_t *pathw, z_stat *buf)
  3792. +{
  3793. + if (!zstatw(pathw, buf))
  3794. + {
  3795. + char *path = wchar_to_local_string((wchar_t *)pathw, G.unicode_escape_all);
  3796. + /* stat was successful, now redo the time-stamp fetches */
  3797. +#ifndef NO_W32TIMES_IZFIX
  3798. + int fs_uses_loctime = FStampIsLocTimeW(__G__ pathw);
  3799. +#endif
  3800. + HANDLE h;
  3801. + FILETIME Modft, Accft, Creft;
  3802. +
  3803. + TTrace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime));
  3804. + h = CreateFileW(pathw, GENERIC_READ,
  3805. + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  3806. + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  3807. + if (h != INVALID_HANDLE_VALUE) {
  3808. + BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);
  3809. + CloseHandle(h);
  3810. +
  3811. + if (ftOK) {
  3812. + FTTrace((stdout, "GetFileTime returned Modft", 0, &Modft));
  3813. + FTTrace((stdout, "GetFileTime returned Creft", 0, &Creft));
  3814. +#ifndef NO_W32TIMES_IZFIX
  3815. + if (!fs_uses_loctime) {
  3816. + /* On a filesystem that stores UTC timestamps, we refill
  3817. + * the time fields of the struct stat buffer by directly
  3818. + * using the UTC values as returned by the Win32
  3819. + * GetFileTime() API call.
  3820. + */
  3821. + NtfsFileTime2utime(&Modft, &(buf->st_mtime));
  3822. + if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
  3823. + NtfsFileTime2utime(&Accft, &(buf->st_atime));
  3824. + else
  3825. + buf->st_atime = buf->st_mtime;
  3826. + if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
  3827. + NtfsFileTime2utime(&Creft, &(buf->st_ctime));
  3828. + else
  3829. + buf->st_ctime = buf->st_mtime;
  3830. + TTrace((stdout,"NTFS, recalculated modtime %08lx\n",
  3831. + buf->st_mtime));
  3832. + } else
  3833. +#endif /* NO_W32TIMES_IZFIX */
  3834. + {
  3835. + /* On VFAT and FAT-like filesystems, the FILETIME values
  3836. + * are converted back to the stable local time before
  3837. + * converting them to UTC unix time-stamps.
  3838. + */
  3839. + VFatFileTime2utime(&Modft, &(buf->st_mtime));
  3840. + if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
  3841. + VFatFileTime2utime(&Accft, &(buf->st_atime));
  3842. + else
  3843. + buf->st_atime = buf->st_mtime;
  3844. + if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
  3845. + VFatFileTime2utime(&Creft, &(buf->st_ctime));
  3846. + else
  3847. + buf->st_ctime = buf->st_mtime;
  3848. + TTrace((stdout, "VFAT, recalculated modtime %08lx\n",
  3849. + buf->st_mtime));
  3850. + }
  3851. + }
  3852. + }
  3853. + free(path);
  3854. +
  3855. + return 0;
  3856. + }
  3857. +#ifdef W32_STATROOT_FIX
  3858. + else
  3859. + {
  3860. + DWORD flags;
  3861. +
  3862. + flags = GetFileAttributesW(pathw);
  3863. + if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {
  3864. + char *path = wchar_to_local_string((wchar_t *)pathw, G.unicode_escape_all);
  3865. + Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n",
  3866. + FnFilter1(path)));
  3867. + free(path);
  3868. + memset(buf, 0, sizeof(z_stat));
  3869. + buf->st_atime = buf->st_ctime = buf->st_mtime =
  3870. + dos_to_unix_time(DOSTIME_MINIMUM); /* 1-1-80 */
  3871. + buf->st_mode = S_IFDIR | S_IREAD |
  3872. + ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);
  3873. + return 0;
  3874. + } /* assumes: stat() won't fail on non-dirs without good reason */
  3875. + }
  3876. +#endif /* W32_STATROOT_FIX */
  3877. + return -1;
  3878. +}
  3879. +
  3880. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  3881. +
  3882. #endif /* W32_STAT_BANDAID */
  3883. @@ -2939,6 +4315,5 @@
  3884. -#if 0
  3885. -#ifdef UNICODE_SUPPORT
  3886. +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
  3887. wchar_t *utf8_to_wchar_string(utf8_string)
  3888. char *utf8_string; /* path to get utf-8 name for */
  3889. @@ -3030,22 +4405,40 @@
  3890. return qw;
  3891. }
  3892. -#endif /* UNICODE_SUPPORT */
  3893. -#endif /* 0 */
  3894. +int has_win32_wide()
  3895. +{
  3896. + int is_win32_wide;
  3897. + /* test if we have wide function support */
  3898. -/* --------------------------------------------------- */
  3899. -/* Large File Support
  3900. - *
  3901. - * Initial functions by E. Gordon and R. Nausedat
  3902. - * 9/10/2003
  3903. - * Lifted from Zip 3b, win32.c and place here by Myles Bennett
  3904. - * 7/6/2004
  3905. - *
  3906. - * These implement 64-bit file support for Windows. The
  3907. - * defines and headers are in win32/w32cfg.h.
  3908. - *
  3909. - * Moved to win32i64.c by Mike White to avoid conflicts in
  3910. - * same name functions in WiZ using UnZip and Zip libraries.
  3911. - * 9/25/2003
  3912. - */
  3913. + /* first guess: On "real" WinNT, the WIN32 wide API >>is<< supported. */
  3914. + is_win32_wide = IsWinNT();
  3915. +
  3916. + if (!is_win32_wide)
  3917. + {
  3918. + /* On a non-WinNT environment (Win9x or Win32s), wide functions
  3919. + * might although supported when program is linked against the
  3920. + * Win9x Unicode support library.
  3921. + * => run a check whether a needed API function is supported.
  3922. + */
  3923. + DWORD r;
  3924. + /* get attributes for this directory */
  3925. + r = GetFileAttributesA(".");
  3926. +
  3927. + /* r should be 16 = FILE_ATTRIBUTE_DIRECTORY */
  3928. + if (r == FILE_ATTRIBUTE_DIRECTORY) {
  3929. + /* now see if it works for the wide version */
  3930. + r = GetFileAttributesW(L".");
  3931. + /* if this fails then we probably don't have wide functions */
  3932. + if (r == 0xFFFFFFFF) {
  3933. + /* error is probably "This function is only valid in Win32 mode." */
  3934. + } else if (r == FILE_ATTRIBUTE_DIRECTORY) {
  3935. + /* worked, so assume we have wide support */
  3936. + is_win32_wide = TRUE;
  3937. + }
  3938. + }
  3939. + }
  3940. + return is_win32_wide;
  3941. +}
  3942. +
  3943. +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
  3944. diff -ru2 unz60d10/windll/vc6/dll/unz32dll.dsp unz60d10_w32w/windll/vc6/dll/unz32dll.dsp
  3945. --- unz60d10/windll/vc6/dll/unz32dll.dsp Wed Dec 27 23:25:00 2006
  3946. +++ unz60d10_w32w/windll/vc6/dll/unz32dll.dsp Mon Feb 11 02:38:32 2008
  3947. @@ -46,5 +46,5 @@
  3948. # PROP Target_Dir ""
  3949. # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /YX /FD /c
  3950. -# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../.." /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /D "WINDLL" /D "DLL" /D "USE_EF_UT_TIME" /YX /FD /c
  3951. +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../.." /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /D "WINDLL" /D "DLL" /D "USE_EF_UT_TIME" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /YX /FD /c
  3952. # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
  3953. # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
  3954. @@ -72,5 +72,5 @@
  3955. # PROP Target_Dir ""
  3956. # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /YX /FD /c
  3957. -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../../.." /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /D "WINDLL" /D "DLL" /D "USE_EF_UT_TIME" /YX /FD /c
  3958. +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../../.." /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /D "WINDLL" /D "DLL" /D "USE_EF_UT_TIME" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /YX /FD /c
  3959. # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
  3960. # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
  3961. @@ -98,5 +98,5 @@
  3962. # PROP Target_Dir ""
  3963. # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /YX /FD /c
  3964. -# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../.." /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /D "WINDLL" /D "DLL" /D "USE_EF_UT_TIME" /D "ASM_CRC" /YX /FD /c
  3965. +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../.." /D "NDEBUG" /D "ASM_CRC" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /D "WINDLL" /D "DLL" /D "USE_EF_UT_TIME" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /YX /FD /c
  3966. # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
  3967. # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
  3968. @@ -124,5 +124,5 @@
  3969. # PROP Target_Dir ""
  3970. # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /YX /FD /c
  3971. -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../../.." /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /D "WINDLL" /D "DLL" /D "USE_EF_UT_TIME" /D "ASM_CRC" /YX /FD /c
  3972. +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../../.." /D "_DEBUG" /D "ASM_CRC" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /D "WINDLL" /D "DLL" /D "USE_EF_UT_TIME" /D "UNICODE_SUPPORT" /D "WIN32_WIDE" /FR /YX /FD /c
  3973. # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
  3974. # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32