util.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450
  1. /*
  2. util.c
  3. Copyright (c) 1990-2008 Info-ZIP. All rights reserved.
  4. See the accompanying file LICENSE, version 2007-Mar-4 or later
  5. (the contents of which are also included in zip.h) for terms of use.
  6. If, for some reason, all these files are missing, the Info-ZIP license
  7. also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
  8. */
  9. /*
  10. * util.c by Mark Adler.
  11. */
  12. #define __UTIL_C
  13. #include "zip.h"
  14. #include "ebcdic.h"
  15. #include <ctype.h>
  16. #ifdef MSDOS16
  17. # include <dos.h>
  18. #endif
  19. #ifdef NO_MKTIME
  20. # ifndef IZ_MKTIME_ONLY
  21. # define IZ_MKTIME_ONLY /* only mktime() related code is pulled in */
  22. # endif
  23. # include "timezone.c"
  24. #endif
  25. uch upper[256], lower[256];
  26. /* Country-dependent case map table */
  27. #ifndef UTIL /* UTIL picks out namecmp code (all utils) */
  28. /* RISC OS uses # as its single-character wildcard */
  29. #ifdef RISCOS
  30. # define WILDCHR_SINGLE '#'
  31. # define WILDCHR_MULTI '*'
  32. # define DIRSEP_CHR '.'
  33. #endif
  34. #ifdef VMS
  35. # define WILDCHR_SINGLE '%'
  36. # define WILDCHR_MULTI '*'
  37. # define DIRSEP_CHR '.'
  38. #endif
  39. #ifndef WILDCHR_SINGLE
  40. # define WILDCHR_SINGLE '?'
  41. #endif
  42. #ifndef WILDCHR_MULTI
  43. # define WILDCHR_MULTI '*'
  44. #endif
  45. #ifndef DIRSEP_CHR
  46. # define DIRSEP_CHR '/'
  47. #endif
  48. /* Local functions */
  49. local int recmatch OF((ZCONST char *, ZCONST char *, int));
  50. #if defined(UNICODE_SUPPORT) && defined(WIN32)
  51. local long recmatchw OF((ZCONST wchar_t *, ZCONST wchar_t *, int));
  52. #endif
  53. local int count_args OF((char *s));
  54. #ifdef MSDOS16
  55. local unsigned ident OF((unsigned chr));
  56. #endif
  57. #ifndef HAVE_FSEEKABLE
  58. /* 2004-11-12 SMS.
  59. Changed to use z*o() functions, and ftell() test from >= 0 to != -1.
  60. This solves problems with negative 32-bit offsets, even on small-file
  61. products.
  62. */
  63. int fseekable( fp)
  64. FILE *fp;
  65. {
  66. zoff_t x;
  67. return (fp == NULL ||
  68. ((zfseeko( fp, ((zoff_t) -1), SEEK_CUR) == 0) && /* Seek ok. */
  69. ((x = zftello( fp)) != ((zoff_t) -1)) && /* Tell ok. */
  70. (zfseeko( fp, ((zoff_t) 1), SEEK_CUR) == 0) && /* Seek ok. */
  71. (zftello( fp) == x+ 1))); /* Tells agree. */
  72. }
  73. #endif /* HAVE_FSEEKABLE */
  74. char *isshexp(p)
  75. char *p; /* candidate sh expression */
  76. /* If p is a sh expression, a pointer to the first special character is
  77. returned. Otherwise, NULL is returned. */
  78. {
  79. for (; *p; INCSTR(p))
  80. if (*p == '\\' && *(p+1))
  81. p++;
  82. #ifdef VMS
  83. else if (*p == WILDCHR_SINGLE || *p == WILDCHR_MULTI)
  84. #else /* !VMS */
  85. else if (*p == WILDCHR_SINGLE || *p == WILDCHR_MULTI || *p == '[')
  86. #endif /* ?VMS */
  87. return p;
  88. return NULL;
  89. }
  90. #ifdef UNICODE_SUPPORT
  91. # ifdef WIN32
  92. wchar_t *isshexpw(pw)
  93. wchar_t *pw; /* candidate sh expression */
  94. /* If pw is a sh expression, a pointer to the first special character is
  95. returned. Otherwise, NULL is returned. */
  96. {
  97. for (; *pw; pw++)
  98. if (*pw == (wchar_t)'\\' && *(pw+1))
  99. pw++;
  100. else if (*pw == (wchar_t)WILDCHR_SINGLE || *pw == (wchar_t)WILDCHR_MULTI ||
  101. *pw == (wchar_t)'[')
  102. return pw;
  103. return NULL;
  104. }
  105. # endif
  106. #endif
  107. #ifdef UNICODE_SUPPORT
  108. # ifdef WIN32
  109. local long recmatchw(pw, sw, cs)
  110. ZCONST wchar_t *pw; /* sh pattern to match */
  111. ZCONST wchar_t *sw; /* string to match it to */
  112. int cs; /* flag: force case-sensitive matching */
  113. /* Recursively compare the sh pattern p with the string s and return 1 if
  114. they match, and 0 or 2 if they don't or if there is a syntax error in the
  115. pattern. This routine recurses on itself no deeper than the number of
  116. characters in the pattern. */
  117. {
  118. long c; /* pattern char or start of range in [-] loop */
  119. /* Get first character, the pattern for new recmatch calls follows */
  120. c = (long)*(pw++);
  121. /* If that was the end of the pattern, match if string empty too */
  122. if (c == 0)
  123. return *sw == 0;
  124. /* '?' matches any character (but not an empty string) */
  125. if ((wchar_t)c == (wchar_t)WILDCHR_SINGLE) {
  126. if (wild_stop_at_dir)
  127. return (*sw && *sw != (wchar_t)DIRSEP_CHR) ? recmatchw(pw, sw + 1, cs) : 0;
  128. else
  129. return *sw ? recmatchw(pw, sw + 1, cs) : 0;
  130. }
  131. /* WILDCHR_MULTI ('*') matches any number of characters, including zero */
  132. if (!no_wild && (wchar_t)c == (wchar_t)WILDCHR_MULTI)
  133. {
  134. if (wild_stop_at_dir) {
  135. /* Check for an immediately following WILDCHR_MULTI */
  136. if (*pw != (wchar_t)WILDCHR_MULTI) {
  137. /* Single WILDCHR_MULTI ('*'): this doesn't match slashes */
  138. for (; *sw && *sw != (wchar_t)DIRSEP_CHR; sw++)
  139. if ((c = recmatchw(pw, sw, cs)) != 0)
  140. return c;
  141. /* end of pattern: matched if at end of string, else continue */
  142. if (*pw == 0)
  143. return (*sw == 0);
  144. /* continue to match if at DIRSEP_CHR in pattern, else give up */
  145. return (*pw == (wchar_t)DIRSEP_CHR || (*pw == (wchar_t)'\\' &&
  146. pw[1] == (wchar_t)DIRSEP_CHR))
  147. ? recmatchw(pw, sw, cs) : 2;
  148. }
  149. /* Two consecutive WILDCHR_MULTI ("**"): this matches DIRSEP_CHR ('/') */
  150. pw++; /* move p past the second WILDCHR_MULTI */
  151. /* continue with the normal non-WILD_STOP_AT_DIR code */
  152. } /* wild_stop_at_dir */
  153. /* Not wild_stop_at_dir */
  154. if (*pw == 0)
  155. return 1;
  156. if (!isshexpw((wchar_t *)pw))
  157. {
  158. /* optimization for rest of pattern being a literal string */
  159. /* optimization to handle patterns like *.txt */
  160. /* if the first char in the pattern is '*' and there */
  161. /* are no other shell expression chars, i.e. a literal string */
  162. /* then just compare the literal string at the end */
  163. ZCONST wchar_t *swrest;
  164. swrest = sw + (wcslen(sw) - wcslen(pw));
  165. if (swrest - sw < 0)
  166. /* remaining literal string from pattern is longer than rest of
  167. test string, there can't be a match
  168. */
  169. return 0;
  170. else
  171. /* compare the remaining literal pattern string with the last bytes
  172. of the test string to check for a match */
  173. return ((cs ? wcscmp(pw, swrest) : _wcsicmp(pw, swrest)) == 0);
  174. }
  175. else
  176. {
  177. /* pattern contains more wildcards, continue with recursion... */
  178. for (; *sw; sw++)
  179. if ((c = recmatchw(pw, sw, cs)) != 0)
  180. return c;
  181. return 2; /* 2 means give up--shmatch will return false */
  182. }
  183. }
  184. /* Parse and process the list of characters and ranges in brackets */
  185. if (!no_wild && allow_regex && (wchar_t)c == '[')
  186. {
  187. int e; /* flag true if next char to be taken literally */
  188. ZCONST wchar_t *qw; /* pointer to end of [-] group */
  189. int r; /* flag true to match anything but the range */
  190. if (*sw == 0) /* need a character to match */
  191. return 0;
  192. pw += (r = (*pw == (wchar_t)'!' || *pw == (wchar_t)'^')); /* see if reverse */
  193. for (qw = pw, e = 0; *qw; qw++) /* find closing bracket */
  194. if (e)
  195. e = 0;
  196. else
  197. if (*qw == (wchar_t)'\\')
  198. e = 1;
  199. else if (*qw == (wchar_t)']')
  200. break;
  201. if (*qw != (wchar_t)']') /* nothing matches if bad syntax */
  202. return 0;
  203. for (c = 0, e = *pw == (wchar_t)'-'; pw < qw; pw++) /* go through the list */
  204. {
  205. if (e == 0 && *pw == (wchar_t)'\\') /* set escape flag if \ */
  206. e = 1;
  207. else if (e == 0 && *pw == (wchar_t)'-') /* set start of range if - */
  208. c = *(pw-1);
  209. else
  210. {
  211. wchar_t cc = (cs ? *sw : towupper(*sw));
  212. wchar_t uc = (wchar_t) c;
  213. if (*(pw+1) != (wchar_t)'-')
  214. for (uc = uc ? uc : *pw; cc <= *pw; uc++)
  215. /* compare range */
  216. if ((cs ? uc : towupper(uc)) == cc)
  217. return r ? 0 : recmatchw(qw + 1, sw + 1, cs);
  218. c = e = 0; /* clear range, escape flags */
  219. }
  220. }
  221. return r ? recmatchw(qw + 1, sw + 1, cs) : 0;
  222. /* bracket match failed */
  223. }
  224. /* If escape ('\'), just compare next character */
  225. if (!no_wild && (wchar_t)c == (wchar_t)'\\')
  226. if ((c = *pw++) == '\0') /* if \ at end, then syntax error */
  227. return 0;
  228. /* Just a character--compare it */
  229. return (cs ? (wchar_t)c == *sw : towupper((wchar_t)c) == towupper(*sw)) ?
  230. recmatchw(pw, sw + 1, cs) : 0;
  231. }
  232. # endif
  233. #endif
  234. local int recmatch(p, s, cs)
  235. ZCONST char *p; /* sh pattern to match */
  236. ZCONST char *s; /* string to match it to */
  237. int cs; /* flag: force case-sensitive matching */
  238. /* Recursively compare the sh pattern p with the string s and return 1 if
  239. they match, and 0 or 2 if they don't or if there is a syntax error in the
  240. pattern. This routine recurses on itself no deeper than the number of
  241. characters in the pattern. */
  242. {
  243. int c; /* pattern char or start of range in [-] loop */
  244. /* Get first character, the pattern for new recmatch calls follows */
  245. /* This fix provided by akt@m5.dion.ne.jp for Japanese.
  246. See 21 July 2006 mail.
  247. It only applies when p is pointing to a doublebyte character and
  248. things like / and wildcards are not doublebyte. This probably
  249. should not be needed. */
  250. #ifdef _MBCS
  251. if (CLEN(p) == 2) {
  252. if (CLEN(s) == 2) {
  253. return (*p == *s && *(p+1) == *(s+1)) ?
  254. recmatch(p + 2, s + 2, cs) : 0;
  255. } else {
  256. return 0;
  257. }
  258. }
  259. #endif /* ?_MBCS */
  260. c = *POSTINCSTR(p);
  261. /* If that was the end of the pattern, match if string empty too */
  262. if (c == 0)
  263. return *s == 0;
  264. /* '?' (or '%' or '#') matches any character (but not an empty string) */
  265. if (c == WILDCHR_SINGLE) {
  266. if (wild_stop_at_dir)
  267. return (*s && *s != DIRSEP_CHR) ? recmatch(p, s + CLEN(s), cs) : 0;
  268. else
  269. return *s ? recmatch(p, s + CLEN(s), cs) : 0;
  270. }
  271. /* WILDCHR_MULTI ('*') matches any number of characters, including zero */
  272. #ifdef AMIGA
  273. if (!no_wild && c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */
  274. c = WILDCHR_MULTI, p++;
  275. #endif /* AMIGA */
  276. if (!no_wild && c == WILDCHR_MULTI)
  277. {
  278. if (wild_stop_at_dir) {
  279. /* Check for an immediately following WILDCHR_MULTI */
  280. # ifdef AMIGA
  281. if ((c = p[0]) == '#' && p[1] == '?') /* "#?" is Amiga-ese for "*" */
  282. c = WILDCHR_MULTI, p++;
  283. if (c != WILDCHR_MULTI) {
  284. # else /* !AMIGA */
  285. if (*p != WILDCHR_MULTI) {
  286. # endif /* ?AMIGA */
  287. /* Single WILDCHR_MULTI ('*'): this doesn't match slashes */
  288. for (; *s && *s != DIRSEP_CHR; INCSTR(s))
  289. if ((c = recmatch(p, s, cs)) != 0)
  290. return c;
  291. /* end of pattern: matched if at end of string, else continue */
  292. if (*p == 0)
  293. return (*s == 0);
  294. /* continue to match if at DIRSEP_CHR in pattern, else give up */
  295. return (*p == DIRSEP_CHR || (*p == '\\' && p[1] == DIRSEP_CHR))
  296. ? recmatch(p, s, cs) : 2;
  297. }
  298. /* Two consecutive WILDCHR_MULTI ("**"): this matches DIRSEP_CHR ('/') */
  299. p++; /* move p past the second WILDCHR_MULTI */
  300. /* continue with the normal non-WILD_STOP_AT_DIR code */
  301. } /* wild_stop_at_dir */
  302. /* Not wild_stop_at_dir */
  303. if (*p == 0)
  304. return 1;
  305. if (!isshexp((char *)p))
  306. {
  307. /* optimization for rest of pattern being a literal string */
  308. /* optimization to handle patterns like *.txt */
  309. /* if the first char in the pattern is '*' and there */
  310. /* are no other shell expression chars, i.e. a literal string */
  311. /* then just compare the literal string at the end */
  312. ZCONST char *srest;
  313. srest = s + (strlen(s) - strlen(p));
  314. if (srest - s < 0)
  315. /* remaining literal string from pattern is longer than rest of
  316. test string, there can't be a match
  317. */
  318. return 0;
  319. else
  320. /* compare the remaining literal pattern string with the last bytes
  321. of the test string to check for a match */
  322. #ifdef _MBCS
  323. {
  324. ZCONST char *q = s;
  325. /* MBCS-aware code must not scan backwards into a string from
  326. * the end.
  327. * So, we have to move forward by character from our well-known
  328. * character position s in the test string until we have advanced
  329. * to the srest position.
  330. */
  331. while (q < srest)
  332. INCSTR(q);
  333. /* In case the byte *srest is a trailing byte of a multibyte
  334. * character, we have actually advanced past the position (srest).
  335. * For this case, the match has failed!
  336. */
  337. if (q != srest)
  338. return 0;
  339. return ((cs ? strcmp(p, q) : namecmp(p, q)) == 0);
  340. }
  341. #else /* !_MBCS */
  342. return ((cs ? strcmp(p, srest) : namecmp(p, srest)) == 0);
  343. #endif /* ?_MBCS */
  344. }
  345. else
  346. {
  347. /* pattern contains more wildcards, continue with recursion... */
  348. for (; *s; INCSTR(s))
  349. if ((c = recmatch(p, s, cs)) != 0)
  350. return c;
  351. return 2; /* 2 means give up--shmatch will return false */
  352. }
  353. }
  354. #ifndef VMS /* No bracket matching in VMS */
  355. /* Parse and process the list of characters and ranges in brackets */
  356. if (!no_wild && allow_regex && c == '[')
  357. {
  358. int e; /* flag true if next char to be taken literally */
  359. ZCONST char *q; /* pointer to end of [-] group */
  360. int r; /* flag true to match anything but the range */
  361. if (*s == 0) /* need a character to match */
  362. return 0;
  363. p += (r = (*p == '!' || *p == '^')); /* see if reverse */
  364. for (q = p, e = 0; *q; q++) /* find closing bracket */
  365. if (e)
  366. e = 0;
  367. else
  368. if (*q == '\\')
  369. e = 1;
  370. else if (*q == ']')
  371. break;
  372. if (*q != ']') /* nothing matches if bad syntax */
  373. return 0;
  374. for (c = 0, e = *p == '-'; p < q; p++) /* go through the list */
  375. {
  376. if (e == 0 && *p == '\\') /* set escape flag if \ */
  377. e = 1;
  378. else if (e == 0 && *p == '-') /* set start of range if - */
  379. c = *(p-1);
  380. else
  381. {
  382. uch cc = (cs ? (uch)*s : case_map((uch)*s));
  383. uch uc = (uch) c;
  384. if (*(p+1) != '-')
  385. for (uc = uc ? uc : (uch)*p; uc <= (uch)*p; uc++)
  386. /* compare range */
  387. if ((cs ? uc : case_map(uc)) == cc)
  388. return r ? 0 : recmatch(q + CLEN(q), s + CLEN(s), cs);
  389. c = e = 0; /* clear range, escape flags */
  390. }
  391. }
  392. return r ? recmatch(q + CLEN(q), s + CLEN(s), cs) : 0;
  393. /* bracket match failed */
  394. }
  395. #endif /* !VMS */
  396. /* If escape ('\'), just compare next character */
  397. if (!no_wild && c == '\\')
  398. if ((c = *p++) == '\0') /* if \ at end, then syntax error */
  399. return 0;
  400. #ifdef VMS
  401. /* 2005-11-06 SMS.
  402. Handle "..." wildcard in p with "." or "]" in s.
  403. */
  404. if ((c == '.') && (*p == '.') && (*(p+ CLEN( p)) == '.') &&
  405. ((*s == '.') || (*s == ']')))
  406. {
  407. /* Match "...]" with "]". Continue after "]" in both. */
  408. if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))
  409. return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), cs);
  410. /* Else, look for a reduced match in s, until "]" in or end of s. */
  411. for (; *s && (*s != ']'); INCSTR(s))
  412. if (*s == '.')
  413. /* If reduced match, then continue after "..." in p, "." in s. */
  414. if ((c = recmatch( (p+ CLEN( p)), s, cs)) != 0)
  415. return (int)c;
  416. /* Match "...]" with "]". Continue after "]" in both. */
  417. if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))
  418. return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), cs);
  419. /* No reduced match. Quit. */
  420. return 2;
  421. }
  422. #endif /* def VMS */
  423. /* Just a character--compare it */
  424. return (cs ? c == *s : case_map((uch)c) == case_map((uch)*s)) ?
  425. recmatch(p, s + CLEN(s), cs) : 0;
  426. }
  427. int shmatch(p, s, cs)
  428. ZCONST char *p; /* sh pattern to match */
  429. ZCONST char *s; /* string to match it to */
  430. int cs; /* force case-sensitive match if TRUE */
  431. /* Compare the sh pattern p with the string s and return true if they match,
  432. false if they don't or if there is a syntax error in the pattern. */
  433. {
  434. return recmatch(p, s, cs) == 1;
  435. }
  436. #if defined(DOS) || defined(WIN32)
  437. #ifdef UNICODE_SUPPORT
  438. int dosmatchw(pw, sw, cs)
  439. ZCONST wchar_t *pw; /* dos pattern to match */
  440. ZCONST wchar_t *sw; /* string to match it to */
  441. int cs; /* force case-sensitive match if TRUE */
  442. /* Treat filenames without periods as having an implicit trailing period */
  443. {
  444. wchar_t *sw1; /* revised string to match */
  445. int r; /* result */
  446. if (wcschr(pw, (wchar_t)'.') && !wcschr(sw, (wchar_t)'.') &&
  447. ((sw1 = (wchar_t *)malloc((wcslen(sw) + 2) * sizeof(wchar_t))) != NULL))
  448. {
  449. wcscpy(sw1, sw);
  450. wcscat(sw1, L".");
  451. }
  452. else
  453. {
  454. /* will usually be OK */
  455. sw1 = (wchar_t *)sw;
  456. }
  457. r = recmatchw(pw, sw1, cs) == 1;
  458. if (sw != sw1)
  459. free((zvoid *)sw1);
  460. return r == 1;
  461. }
  462. #endif
  463. /* XXX also suitable for OS2? Atari? Human68K? TOPS-20?? */
  464. int dosmatch(p, s, cs)
  465. ZCONST char *p; /* dos pattern to match */
  466. ZCONST char *s; /* string to match it to */
  467. int cs; /* force case-sensitive match if TRUE */
  468. /* Treat filenames without periods as having an implicit trailing period */
  469. {
  470. char *s1; /* revised string to match */
  471. int r; /* result */
  472. if (strchr(p, '.') && !strchr(s, '.') &&
  473. ((s1 = malloc(strlen(s) + 2)) != NULL))
  474. {
  475. strcpy(s1, s);
  476. strcat(s1, ".");
  477. }
  478. else
  479. {
  480. /* will usually be OK */
  481. s1 = (char *)s;
  482. }
  483. r = recmatch(p, s1, cs) == 1;
  484. if (s != s1)
  485. free((zvoid *)s1);
  486. return r == 1;
  487. }
  488. #endif /* DOS || WIN32 */
  489. zvoid far **search(b, a, n, cmp)
  490. ZCONST zvoid *b; /* pointer to value to search for */
  491. ZCONST zvoid far **a; /* table of pointers to values, sorted */
  492. extent n; /* number of pointers in a[] */
  493. int (*cmp) OF((ZCONST zvoid *, ZCONST zvoid far *)); /* comparison function */
  494. /* Search for b in the pointer list a[0..n-1] using the compare function
  495. cmp(b, c) where c is an element of a[i] and cmp() returns negative if
  496. *b < *c, zero if *b == *c, or positive if *b > *c. If *b is found,
  497. search returns a pointer to the entry in a[], else search() returns
  498. NULL. The nature and size of *b and *c (they can be different) are
  499. left up to the cmp() function. A binary search is used, and it is
  500. assumed that the list is sorted in ascending order. */
  501. {
  502. ZCONST zvoid far **i; /* pointer to midpoint of current range */
  503. ZCONST zvoid far **l; /* pointer to lower end of current range */
  504. int r; /* result of (*cmp)() call */
  505. ZCONST zvoid far **u; /* pointer to upper end of current range */
  506. l = (ZCONST zvoid far **)a; u = l + (n-1);
  507. while (u >= l) {
  508. i = l + ((unsigned)(u - l) >> 1);
  509. if ((r = (*cmp)(b, (ZCONST char far *)*(struct zlist far **)i)) < 0)
  510. u = i - 1;
  511. else if (r > 0)
  512. l = i + 1;
  513. else
  514. return (zvoid far **)i;
  515. }
  516. return NULL; /* If b were in list, it would belong at l */
  517. }
  518. #endif /* !UTIL */
  519. #ifdef MSDOS16
  520. local unsigned ident(unsigned chr)
  521. {
  522. return chr; /* in al */
  523. }
  524. void init_upper()
  525. {
  526. static struct country {
  527. uch ignore[18];
  528. int (far *casemap)(int);
  529. uch filler[16];
  530. } country_info;
  531. struct country far *info = &country_info;
  532. union REGS regs;
  533. struct SREGS sregs;
  534. unsigned int c;
  535. regs.x.ax = 0x3800; /* get country info */
  536. regs.x.dx = FP_OFF(info);
  537. sregs.ds = FP_SEG(info);
  538. intdosx(&regs, &regs, &sregs);
  539. for (c = 0; c < 128; c++) {
  540. upper[c] = (uch) toupper(c);
  541. lower[c] = (uch) c;
  542. }
  543. for (; c < sizeof(upper); c++) {
  544. upper[c] = (uch) (*country_info.casemap)(ident(c));
  545. /* ident() required because casemap takes its parameter in al */
  546. lower[c] = (uch) c;
  547. }
  548. for (c = 0; c < sizeof(upper); c++ ) {
  549. unsigned int u = upper[c];
  550. if (u != c && lower[u] == (uch) u) {
  551. lower[u] = (uch)c;
  552. }
  553. }
  554. for (c = 'A'; c <= 'Z'; c++) {
  555. lower[c] = (uch) (c - 'A' + 'a');
  556. }
  557. }
  558. #else /* !MSDOS16 */
  559. # ifndef OS2
  560. void init_upper()
  561. {
  562. unsigned int c;
  563. #if defined(ATARI) || defined(CMS_MVS)
  564. #include <ctype.h>
  565. /* this should be valid for all other platforms too. (HD 11/11/95) */
  566. for (c = 0; c< sizeof(upper); c++) {
  567. upper[c] = islower(c) ? toupper(c) : c;
  568. lower[c] = isupper(c) ? tolower(c) : c;
  569. }
  570. #else
  571. for (c = 0; c < sizeof(upper); c++) upper[c] = lower[c] = (uch)c;
  572. for (c = 'a'; c <= 'z'; c++) upper[c] = (uch)(c - 'a' + 'A');
  573. for (c = 'A'; c <= 'Z'; c++) lower[c] = (uch)(c - 'A' + 'a');
  574. #endif
  575. }
  576. # endif /* !OS2 */
  577. #endif /* ?MSDOS16 */
  578. int namecmp(string1, string2)
  579. ZCONST char *string1, *string2;
  580. /* Compare the two strings ignoring case, and correctly taking into
  581. * account national language characters. For operating systems with
  582. * case sensitive file names, this function is equivalent to strcmp.
  583. */
  584. {
  585. int d;
  586. for (;;)
  587. {
  588. d = (int) (uch) case_map(*string1)
  589. - (int) (uch) case_map(*string2);
  590. if (d || *string1 == 0 || *string2 == 0)
  591. return d;
  592. string1++;
  593. string2++;
  594. }
  595. }
  596. #ifdef EBCDIC
  597. char *strtoasc(char *str1, ZCONST char *str2)
  598. {
  599. char *old;
  600. old = str1;
  601. while (*str1++ = (char)ascii[(uch)(*str2++)]);
  602. return old;
  603. }
  604. char *strtoebc(char *str1, ZCONST char *str2)
  605. {
  606. char *old;
  607. old = str1;
  608. while (*str1++ = (char)ebcdic[(uch)(*str2++)]);
  609. return old;
  610. }
  611. char *memtoasc(char *mem1, ZCONST char *mem2, unsigned len)
  612. {
  613. char *old;
  614. old = mem1;
  615. while (len--)
  616. *mem1++ = (char)ascii[(uch)(*mem2++)];
  617. return old;
  618. }
  619. char *memtoebc(char *mem1, ZCONST char *mem2, unsigned len)
  620. {
  621. char *old;
  622. old = mem1;
  623. while (len--)
  624. *mem1++ = (char)ebcdic[(uch)(*mem2++)];
  625. return old;
  626. }
  627. #endif /* EBCDIC */
  628. #ifdef IZ_ISO2OEM_ARRAY
  629. char *str_iso_to_oem(dst, src)
  630. ZCONST char *src;
  631. char *dst;
  632. {
  633. char *dest_start = dst;
  634. while (*dst++ = (char)iso2oem[(uch)(*src++)]);
  635. return dest_start;
  636. }
  637. #endif
  638. #ifdef IZ_OEM2ISO_ARRAY
  639. char *str_oem_to_iso(dst, src)
  640. ZCONST char *src;
  641. char *dst;
  642. {
  643. char *dest_start = dst;
  644. while (*dst++ = (char)oem2iso[(uch)(*src++)]);
  645. return dest_start;
  646. }
  647. #endif
  648. /* DBCS support for Info-ZIP's zip (mainly for japanese (-: )
  649. * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)
  650. * This code is public domain! Date: 1998/12/20
  651. */
  652. #ifdef _MBCS
  653. char *___tmp_ptr;
  654. int lastchar(ptr)
  655. ZCONST char *ptr;
  656. {
  657. ZCONST char *oldptr = ptr;
  658. while(*ptr != '\0'){
  659. oldptr = ptr;
  660. INCSTR(ptr);
  661. }
  662. return (int)(unsigned)*oldptr;
  663. }
  664. unsigned char *zmbschr(str, c)
  665. ZCONST unsigned char *str;
  666. unsigned int c;
  667. {
  668. while(*str != '\0'){
  669. if (*str == c) {return (unsigned char *)str;}
  670. INCSTR(str);
  671. }
  672. return NULL;
  673. }
  674. unsigned char *zmbsrchr(str, c)
  675. ZCONST unsigned char *str;
  676. unsigned int c;
  677. {
  678. unsigned char *match = NULL;
  679. while(*str != '\0'){
  680. if (*str == c) {match = (unsigned char*)str;}
  681. INCSTR(str);
  682. }
  683. return match;
  684. }
  685. #endif /* _MBCS */
  686. #ifndef UTIL
  687. /*****************************************************************
  688. | envargs - add default options from environment to command line
  689. |----------------------------------------------------------------
  690. | Author: Bill Davidsen, original 10/13/91, revised 23 Oct 1991.
  691. | This program is in the public domain.
  692. |----------------------------------------------------------------
  693. | Minor program notes:
  694. | 1. Yes, the indirection is a tad complex
  695. | 2. Parenthesis were added where not needed in some cases
  696. | to make the action of the code less obscure.
  697. ****************************************************************/
  698. void envargs(Pargc, Pargv, envstr, envstr2)
  699. int *Pargc;
  700. char ***Pargv;
  701. char *envstr;
  702. char *envstr2;
  703. {
  704. char *envptr; /* value returned by getenv */
  705. char *bufptr; /* copy of env info */
  706. int argc; /* internal arg count */
  707. register int ch; /* spare temp value */
  708. char **argv; /* internal arg vector */
  709. char **argvect; /* copy of vector address */
  710. /* see if anything in the environment */
  711. envptr = getenv(envstr);
  712. if (envptr != NULL) /* usual var */
  713. while (isspace((uch)*envptr)) /* we must discard leading spaces */
  714. envptr++;
  715. if (envptr == NULL || *envptr == '\0')
  716. if ((envptr = getenv(envstr2)) != NULL) /* alternate */
  717. while (isspace((uch)*envptr))
  718. envptr++;
  719. if (envptr == NULL || *envptr == '\0')
  720. return;
  721. /* count the args so we can allocate room for them */
  722. argc = count_args(envptr);
  723. bufptr = malloc(1 + strlen(envptr));
  724. if (bufptr == NULL)
  725. ziperr(ZE_MEM, "Can't get memory for arguments");
  726. strcpy(bufptr, envptr);
  727. /* allocate a vector large enough for all args */
  728. argv = (char **)malloc((argc + *Pargc + 1) * sizeof(char *));
  729. if (argv == NULL) {
  730. free(bufptr);
  731. ziperr(ZE_MEM, "Can't get memory for arguments");
  732. }
  733. argvect = argv;
  734. /* copy the program name first, that's always true */
  735. *(argv++) = *((*Pargv)++);
  736. /* copy the environment args first, may be changed */
  737. do {
  738. #if defined(AMIGA) || defined(UNIX)
  739. if (*bufptr == '"') {
  740. char *argstart = ++bufptr;
  741. *(argv++) = argstart;
  742. for (ch = *bufptr; ch != '\0' && ch != '\"';
  743. ch = *PREINCSTR(bufptr))
  744. if (ch == '\\' && bufptr[1] != '\0')
  745. ++bufptr; /* skip to char after backslash */
  746. if (ch != '\0') /* overwrite trailing '"' */
  747. *(bufptr++) = '\0';
  748. /* remove escape characters */
  749. while ((argstart = MBSCHR(argstart, '\\')) != NULL) {
  750. strcpy(argstart, argstart + 1);
  751. if (*argstart)
  752. ++argstart;
  753. }
  754. } else {
  755. *(argv++) = bufptr;
  756. while ((ch = *bufptr) != '\0' && !isspace((uch)ch)) INCSTR(bufptr);
  757. if (ch != '\0') *(bufptr++) = '\0';
  758. }
  759. #else
  760. # ifdef WIN32
  761. /* We do not support backslash-quoting of quotes in quoted */
  762. /* strings under Win32, because backslashes are directory */
  763. /* separators and double quotes are illegal in filenames. */
  764. if (*bufptr == '"') {
  765. *(argv++) = ++bufptr;
  766. while ((ch = *bufptr) != '\0' && ch != '\"') INCSTR(bufptr);
  767. if (ch != '\0') *(bufptr++) = '\0';
  768. } else {
  769. *(argv++) = bufptr;
  770. while ((ch = *bufptr) != '\0' && !isspace((uch)ch)) INCSTR(bufptr);
  771. if (ch != '\0') *(bufptr++) = '\0';
  772. }
  773. # else
  774. *(argv++) = bufptr;
  775. while ((ch = *bufptr) != '\0' && !isspace((uch)ch)) INCSTR(bufptr);
  776. if (ch != '\0') *(bufptr++) = '\0';
  777. # endif
  778. #endif /* ?(AMIGA || UNIX) */
  779. while ((ch = *bufptr) != '\0' && isspace((uch)ch)) INCSTR(bufptr);
  780. } while (ch);
  781. /* now save old argc and copy in the old args */
  782. argc += *Pargc;
  783. while (--(*Pargc)) *(argv++) = *((*Pargv)++);
  784. /* finally, add a NULL after the last arg, like UNIX */
  785. *argv = NULL;
  786. /* save the values and return */
  787. *Pargv = argvect;
  788. *Pargc = argc;
  789. }
  790. local int count_args(s)
  791. char *s;
  792. {
  793. int count = 0;
  794. char ch;
  795. do {
  796. /* count and skip args */
  797. ++count;
  798. #if defined(AMIGA) || defined(UNIX)
  799. if (*s == '\"') {
  800. for (ch = *PREINCSTR(s); ch != '\0' && ch != '\"';
  801. ch = *PREINCSTR(s))
  802. if (ch == '\\' && s[1] != '\0')
  803. INCSTR(s);
  804. if (*s) INCSTR(s); /* trailing quote */
  805. } else
  806. while ((ch = *s) != '\0' && !isspace((uch)ch)) INCSTR(s);
  807. #else
  808. # ifdef WIN32
  809. if (*s == '\"') {
  810. ++s; /* leading quote */
  811. while ((ch = *s) != '\0' && ch != '\"') INCSTR(s);
  812. if (*s) INCSTR(s); /* trailing quote */
  813. } else
  814. while ((ch = *s) != '\0' && !isspace((uch)ch)) INCSTR(s);
  815. # else
  816. while ((ch = *s) != '\0' && !isspace((uch)ch)) INCSTR(s);
  817. # endif
  818. #endif /* ?(AMIGA || UNIX) */
  819. while ((ch = *s) != '\0' && isspace((uch)ch)) INCSTR(s);
  820. } while (ch);
  821. return(count);
  822. }
  823. /* Extended argument processing -- by Rich Wales
  824. * This function currently deals only with the MKS shell, but could be
  825. * extended later to understand other conventions.
  826. *
  827. * void expand_args(int *argcp, char ***argvp)
  828. *
  829. * Substitutes the extended command line argument list produced by
  830. * the MKS Korn Shell in place of the command line info from DOS.
  831. *
  832. * The MKS shell gets around DOS's 128-byte limit on the length of
  833. * a command line by passing the "real" command line in the envi-
  834. * ronment. The "real" arguments are flagged by prepending a tilde
  835. * (~) to each one.
  836. *
  837. * This "expand_args" routine creates a new argument list by scanning
  838. * the environment from the beginning, looking for strings begin-
  839. * ning with a tilde character. The new list replaces the original
  840. * "argv" (pointed to by "argvp"), and the number of arguments
  841. * in the new list replaces the original "argc" (pointed to by
  842. * "argcp").
  843. */
  844. void expand_args(argcp, argvp)
  845. int *argcp;
  846. char ***argvp;
  847. {
  848. #ifdef DOS
  849. /* Do NEVER include (re)definiton of `environ' variable with any version
  850. of MSC or BORLAND/Turbo C. These compilers supply an incompatible
  851. definition in <stdlib.h>. */
  852. #if defined(__GO32__) || defined(__EMX__)
  853. extern char **environ; /* environment */
  854. #endif /* __GO32__ || __EMX__ */
  855. char **envp; /* pointer into environment */
  856. char **newargv; /* new argument list */
  857. char **argp; /* pointer into new arg list */
  858. int newargc; /* new argument count */
  859. /* sanity check */
  860. if (environ == NULL
  861. || argcp == NULL
  862. || argvp == NULL || *argvp == NULL)
  863. return;
  864. /* find out how many environment arguments there are */
  865. for (envp = environ, newargc = 0;
  866. *envp != NULL && (*envp)[0] == '~';
  867. envp++, newargc++) ;
  868. if (newargc == 0)
  869. return; /* no environment arguments */
  870. /* set up new argument list */
  871. newargv = (char **) malloc(sizeof(char **) * (newargc+1));
  872. if (newargv == NULL)
  873. return; /* malloc failed */
  874. for (argp = newargv, envp = environ;
  875. *envp != NULL && (*envp)[0] == '~';
  876. *argp++ = &(*envp++)[1]) ;
  877. *argp = NULL; /* null-terminate the list */
  878. /* substitute new argument list in place of old one */
  879. *argcp = newargc;
  880. *argvp = newargv;
  881. #else /* !DOS */
  882. if (argcp || argvp) return;
  883. #endif /* ?DOS */
  884. }
  885. /* Fast routine for detection of plain text
  886. * (ASCII or an ASCII-compatible extension such as ISO-8859, UTF-8, etc.)
  887. * Author: Cosmin Truta.
  888. * See "proginfo/txtvsbin.txt" for more information.
  889. *
  890. * This function returns the same result as set_file_type() in "trees.c".
  891. * Unlike in set_file_type(), however, the speed depends on the buffer size,
  892. * so the optimal implementation is different.
  893. */
  894. int is_text_buf(buf_ptr, buf_size)
  895. ZCONST char *buf_ptr;
  896. unsigned buf_size;
  897. {
  898. int result = 0;
  899. unsigned i;
  900. unsigned char c;
  901. for (i = 0; i < buf_size; ++i)
  902. {
  903. c = (unsigned char)buf_ptr[i];
  904. if (c >= 32) /* speed up the loop by checking this first */
  905. result = 1; /* white-listed character found; keep looping */
  906. else /* speed up the loop by inlining the following check */
  907. if ((c <= 6) || (c >= 14 && c <= 25) || (c >= 28 && c <= 31))
  908. return 0; /* black-listed character found; stop */
  909. }
  910. return result;
  911. }
  912. #endif /* UTIL */
  913. #ifdef DEBUGNAMES
  914. #undef free
  915. int Free(x)
  916. void *x;
  917. {
  918. if (x == (void *) 0xdeadbeef)
  919. exit(-1);
  920. free(x);
  921. return 0;
  922. }
  923. int printnames()
  924. {
  925. struct zlist far *z;
  926. for (z = zfiles; z != NULL; z = z->nxt)
  927. fprintf(mesg, "%s %s %s %p %p %p %08x %08x %08x\n",
  928. z->name, z->zname, z->iname,
  929. z->name, z->zname, z->iname,
  930. *((int *) z->name), *((int *) z->zname),
  931. *((int *) z->iname));
  932. return 0;
  933. }
  934. #endif /* DEBUGNAMES */
  935. /* Below is used to format zoff_t values, which can be either long or long long
  936. depending on if LARGE FILES are supported. Function provided by SMS.
  937. 10/17/04 EG */
  938. /* 2004-12-01 SMS.
  939. * Brought in fancy fzofft() from UnZip.
  940. */
  941. /* This implementation assumes that no more than FZOFF_NUM values will be
  942. needed in any printf using it. */
  943. /* zip_fzofft(): Format a zoff_t value in a cylindrical buffer set.
  944. This version renamed from fzofft because of name conflict in unzip
  945. when combined in WiZ. */
  946. /* 2004-12-19 SMS.
  947. * I still claim than the smart move would have been to disable one or
  948. * the other instance with #if for Wiz. But fine. We'll change the
  949. * name.
  950. */
  951. /* This is likely not thread safe. Needs to be done without static storage.
  952. 12/29/04 EG */
  953. /* zip_fzofft(): Format a zoff_t value in a cylindrical buffer set. */
  954. #define FZOFFT_NUM 4 /* Number of chambers. */
  955. #define FZOFFT_LEN 24 /* Number of characters/chamber. */
  956. /* Format a zoff_t value in a cylindrical buffer set. */
  957. char *zip_fzofft( val, pre, post)
  958. zoff_t val;
  959. char *pre;
  960. char *post;
  961. {
  962. /* Storage cylinder. */
  963. static char fzofft_buf[ FZOFFT_NUM][ FZOFFT_LEN];
  964. static int fzofft_index = 0;
  965. /* Temporary format string storage. */
  966. static char fmt[ 16] = "%";
  967. /* Assemble the format string. */
  968. fmt[ 1] = '\0'; /* Start after initial "%". */
  969. if (pre == FZOFFT_HEX_WID) /* Special hex width. */
  970. {
  971. strcat( fmt, FZOFFT_HEX_WID_VALUE);
  972. }
  973. else if (pre == FZOFFT_HEX_DOT_WID) /* Special hex ".width". */
  974. {
  975. strcat( fmt, ".");
  976. strcat( fmt, FZOFFT_HEX_WID_VALUE);
  977. }
  978. else if (pre != NULL) /* Caller's prefix (width). */
  979. {
  980. strcat( fmt, pre);
  981. }
  982. strcat( fmt, FZOFFT_FMT); /* Long or long-long or whatever. */
  983. if (post == NULL)
  984. strcat( fmt, "d"); /* Default radix = decimal. */
  985. else
  986. strcat( fmt, post); /* Caller's radix. */
  987. /* Advance the cylinder. */
  988. fzofft_index = (fzofft_index+ 1)% FZOFFT_NUM;
  989. /* Write into the current chamber. */
  990. sprintf( fzofft_buf[ fzofft_index], fmt, val);
  991. /* Return a pointer to this chamber. */
  992. return fzofft_buf[ fzofft_index];
  993. }
  994. /* Format a uzoff_t value in a cylindrical buffer set. */
  995. /* Added to support uzoff_t type. 12/29/04 */
  996. char *zip_fuzofft( val, pre, post)
  997. uzoff_t val;
  998. char *pre;
  999. char *post;
  1000. {
  1001. /* Storage cylinder. */
  1002. static char fuzofft_buf[ FZOFFT_NUM][ FZOFFT_LEN];
  1003. static int fuzofft_index = 0;
  1004. /* Temporary format string storage. */
  1005. static char fmt[ 16] = "%";
  1006. /* Assemble the format string. */
  1007. fmt[ 1] = '\0'; /* Start after initial "%". */
  1008. if (pre == FZOFFT_HEX_WID) /* Special hex width. */
  1009. {
  1010. strcat( fmt, FZOFFT_HEX_WID_VALUE);
  1011. }
  1012. else if (pre == FZOFFT_HEX_DOT_WID) /* Special hex ".width". */
  1013. {
  1014. strcat( fmt, ".");
  1015. strcat( fmt, FZOFFT_HEX_WID_VALUE);
  1016. }
  1017. else if (pre != NULL) /* Caller's prefix (width). */
  1018. {
  1019. strcat( fmt, pre);
  1020. }
  1021. strcat( fmt, FZOFFT_FMT); /* Long or long-long or whatever. */
  1022. if (post == NULL)
  1023. strcat( fmt, "u"); /* Default radix = decimal. */
  1024. else
  1025. strcat( fmt, post); /* Caller's radix. */
  1026. /* Advance the cylinder. */
  1027. fuzofft_index = (fuzofft_index+ 1)% FZOFFT_NUM;
  1028. /* Write into the current chamber. */
  1029. sprintf( fuzofft_buf[ fuzofft_index], fmt, val);
  1030. /* Return a pointer to this chamber. */
  1031. return fuzofft_buf[ fuzofft_index];
  1032. }
  1033. /* Display number to mesg stream
  1034. 5/15/05 EG */
  1035. int DisplayNumString(file, i)
  1036. FILE *file;
  1037. uzoff_t i;
  1038. {
  1039. char tempstrg[100];
  1040. int j;
  1041. char *s = tempstrg;
  1042. WriteNumString(i, tempstrg);
  1043. /* skip spaces */
  1044. for (j = 0; j < 3; j++) {
  1045. if (*s != ' ') break;
  1046. s++;
  1047. }
  1048. fprintf(file, "%s", s);
  1049. return 0;
  1050. }
  1051. /* Read numbers with trailing size multiplier (like 10M) and return number.
  1052. 10/30/04 EG */
  1053. uzoff_t ReadNumString( numstring )
  1054. char *numstring;
  1055. {
  1056. zoff_t num = 0;
  1057. char multchar = ' ';
  1058. int i;
  1059. uzoff_t mult = 1;
  1060. /* check if valid number (currently no negatives) */
  1061. if (numstring == NULL) {
  1062. zipwarn("Unable to read empty number in ReadNumString", "");
  1063. return (uzoff_t)-1;
  1064. }
  1065. if (numstring[0] < '0' || numstring[0] > '9') {
  1066. zipwarn("Unable to read number (must start with digit): ", numstring);
  1067. return (uzoff_t)-1;
  1068. }
  1069. if (strlen(numstring) > 8) {
  1070. zipwarn("Number too long to read (8 characters max): ", numstring);
  1071. return (uzoff_t)-1;
  1072. }
  1073. /* get the number part */
  1074. num = atoi(numstring);
  1075. /* find trailing multiplier */
  1076. for (i = 0; numstring[i] && isdigit(numstring[i]); i++) ;
  1077. /* return if no multiplier */
  1078. if (numstring[i] == '\0') {
  1079. return (uzoff_t)num;
  1080. }
  1081. /* nothing follows multiplier */
  1082. if (numstring[i + 1]) {
  1083. return (uzoff_t)-1;
  1084. }
  1085. /* get multiplier */
  1086. multchar = toupper(numstring[i]);
  1087. if (multchar == 'K') {
  1088. mult <<= 10;
  1089. } else if (multchar == 'M') {
  1090. mult <<= 20;
  1091. } else if (multchar == 'G') {
  1092. mult <<= 30;
  1093. #ifdef LARGE_FILE_SUPPORT
  1094. } else if (multchar == 'T') {
  1095. mult <<= 40;
  1096. #endif
  1097. } else {
  1098. return (uzoff_t)-1;
  1099. }
  1100. return (uzoff_t)num * mult;
  1101. }
  1102. /* Write the number as a string with a multiplier (like 10M) to outstring.
  1103. Always writes no more than 3 digits followed maybe by a multiplier and
  1104. returns the characters written or -1 if error.
  1105. 10/30/04 EG */
  1106. int WriteNumString( num, outstring )
  1107. uzoff_t num;
  1108. char *outstring;
  1109. {
  1110. int mult;
  1111. int written = 0;
  1112. int i;
  1113. int j;
  1114. char digits[4];
  1115. int dig;
  1116. *outstring = '\0';
  1117. /* shift number 1 K until less than 10000 */
  1118. for (mult = 0; num >= 10240; mult++) {
  1119. num >>= 10;
  1120. }
  1121. /* write digits as " 0" */
  1122. for (i = 1; i < 4; i++) {
  1123. digits[i] = ' ';
  1124. }
  1125. digits[0] = '0';
  1126. if (num >= 1000) {
  1127. i = 3;
  1128. num *= 10;
  1129. num >>= 10;
  1130. mult++;
  1131. digits[0] = (char) (num % 10) + '0';
  1132. digits[1] = '.';
  1133. digits[2] = (char) (num / 10) + '0';
  1134. } else {
  1135. for (i = 0; num; i++) {
  1136. dig = (int) (num % 10);
  1137. num /= 10;
  1138. digits[i] = dig + '0';
  1139. }
  1140. }
  1141. if (i == 0) i = 1;
  1142. for (j = i; j > 0; j--) {
  1143. *outstring = digits[j - 1];
  1144. outstring++;
  1145. written++;
  1146. }
  1147. /* output multiplier */
  1148. if (mult == 0) {
  1149. } else if (mult == 1) {
  1150. *outstring = 'K';
  1151. outstring++;
  1152. written++;
  1153. } else if (mult == 2) {
  1154. *outstring = 'M';
  1155. outstring++;
  1156. written++;
  1157. } else if (mult == 3) {
  1158. *outstring = 'G';
  1159. outstring++;
  1160. written++;
  1161. } else if (mult == 4) {
  1162. *outstring = 'T';
  1163. outstring++;
  1164. written++;
  1165. } else {
  1166. *outstring = '?';
  1167. outstring++;
  1168. written++;
  1169. }
  1170. *outstring = '\0';
  1171. return written;
  1172. }
  1173. #if 0 /* not used anywhere, should get removed by next release... */
  1174. /* Apply the Adler-16 checksum to a set of bytes.
  1175. * Use this function as you would use crc32():
  1176. * - First call this function by passing a NULL pointer instead of buf
  1177. * OR initialize the checksum register with ADLERVAL_INITIAL.
  1178. * - Iteratively call this function for each buffer fragment.
  1179. * This function returns the updated checksum.
  1180. *
  1181. * IN assertion: chksum is a valid Adler-16 checksum:
  1182. * (chksum & 0xffU) < ADLER16_BASE && ((chksum >> 8) & 0xffU) < ADLER16_BASE
  1183. *
  1184. * Author: Cosmin Truta.
  1185. * See "proginfo/adler16.txt" for more information.
  1186. */
  1187. #define ADLER16_BASE 251 /* The largest prime smaller than 256 */
  1188. unsigned int adler16(chksum, buf, len)
  1189. unsigned int chksum;
  1190. ZCONST uch *buf;
  1191. extent len;
  1192. {
  1193. unsigned int sum1 = chksum & 0xff;
  1194. unsigned int sum2 = (chksum >> 8) & 0xff;
  1195. extent i;
  1196. Assert((sum1 < ADLER16_BASE) && (sum2 < ADLER16_BASE),
  1197. "adler16: invalid checksum");
  1198. if (buf == NULL)
  1199. return 1;
  1200. for (i = 0; i < len; ++i)
  1201. {
  1202. sum1 += buf[i];
  1203. if (sum1 >= ADLER16_BASE) /* this is faster than modulo ADLER16_BASE */
  1204. sum1 -= ADLER16_BASE;
  1205. sum2 += sum1;
  1206. if (sum2 >= ADLER16_BASE) /* ditto */
  1207. sum2 -= ADLER16_BASE;
  1208. }
  1209. return (sum2 << 8) | sum1;
  1210. }
  1211. #endif /* 0, not used anywhere */
  1212. /* returns true if abbrev is abbreviation for matchstring */
  1213. int abbrevmatch (matchstring, abbrev, case_sensitive, minmatch)
  1214. char *matchstring;
  1215. char *abbrev;
  1216. int case_sensitive;
  1217. int minmatch;
  1218. {
  1219. int cnt = 0;
  1220. char *m;
  1221. char *a;
  1222. m = matchstring;
  1223. a = abbrev;
  1224. for (; *m && *a; m++, a++) {
  1225. cnt++;
  1226. if (case_sensitive) {
  1227. if (*m != *a) {
  1228. /* mismatch */
  1229. return 0;
  1230. }
  1231. } else {
  1232. if (toupper(*m) != toupper(*a)) {
  1233. /* mismatch */
  1234. return 0;
  1235. }
  1236. }
  1237. }
  1238. if (cnt < minmatch) {
  1239. /* not big enough string */
  1240. return 0;
  1241. }
  1242. if (*a != '\0') {
  1243. /* abbreviation longer than match string */
  1244. return 0;
  1245. }
  1246. /* either abbreviation or match */
  1247. return 1;
  1248. }