home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / vmsnet / sources / 323 < prev    next >
Encoding:
Internet Message Format  |  1992-09-01  |  47.2 KB

  1. Path: sparky!uunet!cs.utexas.edu!usc!orion.oac.uci.edu!unogate!mvb.saic.com!vmsnet-sources
  2. From: goathunter@wkuvx1.bitnet
  3. Newsgroups: vmsnet.sources
  4. Subject: Zip v1.9 & UnZip v5.0, part 06/22
  5. Message-ID: <8009613@MVB.SAIC.COM>
  6. Date: Tue, 01 Sep 1992 22:50:05 GMT
  7. Organization: Western Kentucky University, Bowling Green, KY
  8. Lines: 1397
  9. Approved: Mark.Berryman@Mvb.Saic.Com
  10.  
  11. Submitted-by: goathunter@wkuvx1.bitnet
  12. Posting-number: Volume 3, Issue 128
  13. Archive-name: zip_unzip/part06
  14.  
  15. -+-+-+-+-+-+-+-+ START OF PART 6 -+-+-+-+-+-+-+-+
  16. X        /* A directory was extracted. It had a trailing /,`20
  17. X         * don't report the error below. */
  18. X        if (created) `7B
  19. X            printf("   Creating: %s", filename);
  20. X#ifdef OS2
  21. X            SetPathInfo(filename, lrec.last_mod_file_date,
  22. X                                  lrec.last_mod_file_time, -1);
  23. X            if (extra_field)
  24. X                SetEAs(filename, extra_field);
  25. X#endif
  26. X            printf("\n");
  27. X        `7D
  28. X        return 2; /* but skip file */
  29. X    `7D
  30. X
  31. X    if (*name == '\0') `7B
  32. X        fprintf(stderr, "mapname:  conversion of `5B%s`5D failed\n", filenam
  33. Ve);
  34. X        return 3;
  35. X    `7D
  36. X
  37. X#ifdef OS2
  38. X    if (!longname && ((longname = !IsFileNameValid(name)) != 0)) `7B
  39. X        /* in case of second call after user renamed the file, skip this */
  40. X        last = strrchr(name, '/');      /* THIS time, save for file_io */
  41. X        last = last ? last + 1 : name;  /* only last component */
  42. X        strcpy(longfilename, last);
  43. X        fprintf(stderr, "renaming \"%s\"", name);
  44. X        ChangeNameForFAT(last);
  45. X        fprintf(stderr, " to \"%s\"\n", name);
  46. X    `7D
  47. X#endif /* OS2 */
  48. X
  49. X#ifdef VMS
  50. X    /* convert filename to legal VMS one, substituting underscores for
  51. X     * all invalid characters */
  52. X    for (np = name;  *np;  ++np)
  53. X        if (!(isdigit(*np) `7C`7C isalpha(*np) `7C`7C (*np == '$') `7C`7C
  54. X            (*np == '-') `7C`7C (*np == '_') `7C`7C (*np == '.') `7C`7C (*np
  55. V == ';')))
  56. X            *np = '_';
  57. X#endif /* VMS */
  58. X
  59. X    if (!jflag) `7B
  60. X#ifdef VMS
  61. X        *xp++ = '`5D';                 /* proper end-of-dir-name delimiter *
  62. V/
  63. X        if (xp == cdp) `7B             /* no path-name stuff, so... */
  64. X            strcpy(filename, name);  /* copy file name into global */
  65. X            cdp -= 2;                /*   prepare to free malloc'd space */
  66. X        `7D else `7B                     /* we've added path-name stuff... *
  67. V/
  68. X            *xp = '\0';              /*   so terminate and convert to */
  69. X            dp = cdp;                /*   VMS subdir separators (skip */
  70. X            while (*++dp)            /*   first char:  better not be */
  71. X                if (*dp == '/')      /*   "/"):  change all slashes */
  72. X                    *dp = '.';       /*   to dots */
  73. X            cdp -= 2;                /*   include leading bracket and dot */
  74. X            strcpy(filename, cdp);   /* copy VMS-style path name into global
  75. V */
  76. X            strcat(filename, name);  /* concatenate file name to global */
  77. X        `7D
  78. X#else /* !VMS */
  79. X        strcpy(filename, cdp);       /* either "" or slash-terminated path *
  80. V/
  81. X        strcat(filename, name);      /* append file name to path name */
  82. X#endif /* ?VMS */
  83. X        free(cdp);
  84. X    `7D else
  85. X        strcpy(filename, name);      /* copy converted name into global */
  86. X
  87. X#if PATH_MAX < (FILNAMSIZ - 1)
  88. X    /* check the length of the file name and truncate if necessary */
  89. X    if (PATH_MAX < strlen(filename)) `7B
  90. X        fprintf(stderr, "caution:  truncating filename\n");
  91. X        filename`5BPATH_MAX`5D = '\0';
  92. X        fprintf(stderr, "`5B %s `5D\n", filename);
  93. X        return 1;             /* 1:  warning error */
  94. X    `7D
  95. X#endif
  96. X
  97. X    return 0;
  98. X`7D
  99. $ CALL UNPACK [.UNZIP50]MAPNAME.C;1 1631201166
  100. $ create 'f'
  101. X/*--------------------------------------------------------------------------
  102. V-
  103. X
  104. X  match.c
  105. X
  106. X  The match() routine recursively compares a string to a "pattern" (regular
  107. X  expression), returning TRUE if a match is found or FALSE if not.  This
  108. X  version is specifically for use with unzip.c:  as did the previous match()
  109. X  from SEA, it leaves the case (upper, lower, or mixed) of the string alone,
  110. X  but converts any uppercase characters in the pattern to lowercase if indi-
  111. X  cated by the global var pInfo->lcflag (which is to say, string is assumed
  112. X  to have been converted to lowercase already, if such was necessary).
  113. X
  114. X  --------------------------------------------------------------------------
  115. V-*/
  116. X
  117. X
  118. X#ifdef ZIPINFO
  119. X#  undef ZIPINFO   /* make certain there is only one version of match.o */
  120. X#endif /* ZIPINFO */
  121. X#include "unzip.h"
  122. X
  123. Xstatic int  matche              __((register char *p, register char *t));
  124. Xstatic int  matche_after_star   __((register char *p, register char *t));
  125. X
  126. X/* #include "filmatch.h": */
  127. X#ifndef BOOLEAN
  128. X#  define BOOLEAN short int      /* v1.2 made it short */
  129. X#endif
  130. X
  131. X/* match defines */
  132. X#define MATCH_PATTERN  6    /* bad pattern */
  133. X#define MATCH_LITERAL  5    /* match failure on literal match */
  134. X#define MATCH_RANGE    4    /* match failure on `5B..`5D construct */
  135. X#define MATCH_ABORT    3    /* premature end of text string */
  136. X#define MATCH_END      2    /* premature end of pattern string */
  137. X#define MATCH_VALID    1    /* valid match */
  138. X
  139. X/* pattern defines */
  140. X#define PATTERN_VALID  0    /* valid pattern */
  141. X#define PATTERN_ESC   -1    /* literal escape at end of pattern */
  142. X#define PATTERN_RANGE -2    /* malformed range in `5B..`5D construct */
  143. X#define PATTERN_CLOSE -3    /* no end bracket in `5B..`5D construct */
  144. X#define PATTERN_EMPTY -4    /* `5B..`5D contstruct is empty */
  145. X
  146. X/*--------------------------------------------------------------------------
  147. V--
  148. X*
  149. X*  Match the pattern PATTERN against the string TEXT;
  150. X*
  151. X*       match() returns TRUE if pattern matches, FALSE otherwise.
  152. X*       matche() returns MATCH_VALID if pattern matches, or an errorcode
  153. X*           as follows otherwise:
  154. X*
  155. X*            MATCH_PATTERN  - bad pattern
  156. X*            MATCH_RANGE    - match failure on `5B..`5D construct
  157. X*            MATCH_ABORT    - premature end of text string
  158. X*            MATCH_END      - premature end of pattern string
  159. X*            MATCH_VALID    - valid match
  160. X*
  161. X*
  162. X*  A match means the entire string TEXT is used up in matching.
  163. X*
  164. X*  In the pattern string:
  165. X*       `60*' matches any sequence of characters (zero or more)
  166. X*       `60?' matches any character
  167. X*       `5BSET`5D matches any character in the specified set,
  168. X*       `5B!SET`5D or `5B`5ESET`5D matches any character not in the specifie
  169. Vd set.
  170. X*
  171. X*  A set is composed of characters or ranges; a range looks like
  172. X*  character hyphen character (as in 0-9 or A-Z).  `5B0-9a-zA-Z_`5D is the
  173. X*  minimal set of characters allowed in the `5B..`5D pattern construct.
  174. X*  Other characters are allowed (ie. 8 bit characters) if your system
  175. X*  will support them.
  176. X*
  177. X*  To suppress the special syntactic significance of any of `60`5B`5D*?!`5E-
  178. V\',
  179. X*  in a `5B..`5D construct and match the character exactly, precede it
  180. X*  with a `60\'.
  181. X*
  182. X----------------------------------------------------------------------------
  183. V*/
  184. X
  185. X/*--------------------------------------------------------------------------
  186. V--
  187. X*
  188. X*  Match the pattern PATTERN against the string TEXT;
  189. X*
  190. X*  returns MATCH_VALID if pattern matches, or an errorcode as follows
  191. X*  otherwise:
  192. X*
  193. X*            MATCH_PATTERN  - bad pattern
  194. X*            MATCH_RANGE    - match failure on `5B..`5D construct
  195. X*            MATCH_ABORT    - premature end of text string
  196. X*            MATCH_END      - premature end of pattern string
  197. X*            MATCH_VALID    - valid match
  198. X*
  199. X*
  200. X*  A match means the entire string TEXT is used up in matching.
  201. X*
  202. X*  In the pattern string:
  203. X*       `60*' matches any sequence of characters (zero or more)
  204. X*       `60?' matches any character
  205. X*       `5BSET`5D matches any character in the specified set,
  206. X*       `5B!SET`5D or `5B`5ESET`5D matches any character not in the specifie
  207. Vd set.
  208. X*       \ is allowed within a set to escape a character like '`5D' or '-'
  209. X*
  210. X*  A set is composed of characters or ranges; a range looks like
  211. X*  character hyphen character (as in 0-9 or A-Z).  `5B0-9a-zA-Z_`5D is the
  212. X*  minimal set of characters allowed in the `5B..`5D pattern construct.
  213. X*  Other characters are allowed (ie. 8 bit characters) if your system
  214. X*  will support them.
  215. X*
  216. X*  To suppress the special syntactic significance of any of `60`5B`5D*?!`5E-
  217. V\',
  218. X*  within a `5B..`5D construct and match the character exactly, precede it
  219. X*  with a `60\'.
  220. X*
  221. X----------------------------------------------------------------------------
  222. V*/
  223. X
  224. Xstatic int matche(p, t)
  225. Xregister char *p;
  226. Xregister char *t;
  227. X`7B
  228. X    register char range_start, range_end;  /* start and end in range */
  229. X
  230. X    BOOLEAN invert;             /* is this `5B..`5D or `5B!..`5D */
  231. X    BOOLEAN member_match;       /* have I matched the `5B..`5D construct? */
  232. X    BOOLEAN loop;               /* should I terminate? */
  233. X
  234. X    for (;  *p;  p++, t++) `7B
  235. X
  236. X        /* if this is the end of the text then this is the end of the match
  237. V */
  238. X        if (!*t)
  239. X            return ((*p == '*') && (*++p == '\0'))?  MATCH_VALID : MATCH_ABO
  240. VRT;
  241. X
  242. X        /* determine and react to pattern type */
  243. X        switch (*p) `7B
  244. X
  245. X            /* single any character match */
  246. X            case '?':
  247. X                break;
  248. X
  249. X            /* multiple any character match */
  250. X            case '*':
  251. X                return matche_after_star (p, t);
  252. X
  253. X            /* `5B..`5D construct, single member/exclusion character match *
  254. V/
  255. X            case '`5B': `7B
  256. X
  257. X                /* move to beginning of range */
  258. X                p++;
  259. X
  260. X                /* check if this is a member match or exclusion match */
  261. X                invert = FALSE;
  262. X                if ((*p == '!') `7C`7C (*p == '`5E')) `7B
  263. X                    invert = TRUE;
  264. X                    p++;
  265. X                `7D
  266. X
  267. X                /* if closing bracket here or at range start then we have a
  268. X                   malformed pattern */
  269. X                if (*p == '`5D')
  270. X                    return MATCH_PATTERN;
  271. X
  272. X                member_match = FALSE;
  273. X                loop = TRUE;
  274. X
  275. X                while (loop) `7B
  276. X
  277. X                    /* if end of construct then loop is done */
  278. X                    if (*p == '`5D') `7B
  279. X                        loop = FALSE;
  280. X                        continue;
  281. X                    `7D
  282. X
  283. X                    /* matching a '!', '`5E', '-', '\' or a '`5D' */
  284. X                    if (*p == '\\')
  285. X                        range_start = range_end = *++p;
  286. X                    else
  287. X                        range_start = range_end = *p;
  288. X
  289. X                    /* if end of pattern then bad pattern (Missing '`5D') */
  290. X                    if (!*p)
  291. X                        return MATCH_PATTERN;
  292. X
  293. X                    /* check for range bar */
  294. X                    if (*++p == '-') `7B
  295. X
  296. X                        /* get the range end */
  297. X                        range_end = *++p;
  298. X
  299. X                        /* if end of pattern or construct then bad pattern *
  300. V/
  301. X                        if ((range_end == '\0') `7C`7C (range_end == '`5D'))
  302. X                            return MATCH_PATTERN;
  303. X
  304. X                        /* special character range end */
  305. X                        if (range_end == '\\') `7B
  306. X                            range_end = *++p;
  307. X
  308. X                            /* if end of text then we have a bad pattern */
  309. X                            if (!range_end)
  310. X                                return MATCH_PATTERN;
  311. X                        `7D
  312. X
  313. X                        /* move just beyond this range */
  314. X                        p++;
  315. X                    `7D
  316. X
  317. X                    /* if the text character is in range then match found.
  318. X                     * make sure the range letters have the proper
  319. X                     * relationship to one another before comparison
  320. X                     */
  321. X                    if (range_start < range_end) `7B
  322. X                        if ((*t >= range_start) && (*t <= range_end)) `7B
  323. X                            member_match = TRUE;
  324. X                            loop = FALSE;
  325. X                        `7D
  326. X                    `7D else `7B
  327. X                        if ((*t >= range_end) && (*t <= range_start)) `7B
  328. X                            member_match = TRUE;
  329. X                            loop = FALSE;
  330. X                        `7D
  331. X                    `7D
  332. X                `7D
  333. X
  334. X                /* if there was a match in an exclusion set then no match */
  335. X                /* if there was no match in a member set then no match */
  336. X                if ((invert && member_match) `7C`7C
  337. X                   !(invert `7C`7C member_match))
  338. X                    return MATCH_RANGE;
  339. X
  340. X                /* if this is not an exclusion then skip the rest of the `5B
  341. V...`5D
  342. X                    construct that already matched. */
  343. X                if (member_match) `7B
  344. X                    while (*p != '`5D') `7B
  345. X
  346. X                        /* bad pattern (Missing '`5D') */
  347. X                        if (!*p)
  348. X                            return MATCH_PATTERN;
  349. X
  350. X                        /* skip exact match */
  351. X                        if (*p == '\\') `7B
  352. X                            p++;
  353. X
  354. X                            /* if end of text then we have a bad pattern */
  355. X                            if (!*p)
  356. X                                return MATCH_PATTERN;
  357. X                        `7D
  358. X
  359. X                        /* move to next pattern char */
  360. X                        p++;
  361. X                    `7D
  362. X                `7D
  363. X
  364. X                break;
  365. X            `7D  /* switch '`5B' */
  366. X
  367. X            /* must match this character exactly */
  368. X            default:
  369. X#ifdef OLDSTUFF
  370. X                if (*p != *t)
  371. X#else /* !OLDSTUFF */
  372. X                /* do it like arcmatch() (old unzip) did it (v1.2) */
  373. X                if (*t != (char) ((pInfo->lcflag && isupper((int)(*p)))?
  374. X                    tolower((int)(*p)) : *p))
  375. X#endif /* ?OLDSTUFF */
  376. X                    return MATCH_LITERAL;
  377. X
  378. X        `7D  /* switch */
  379. X    `7D  /* for */
  380. X
  381. X        /* if end of text not reached then the pattern fails */
  382. X    if (*t)
  383. X        return MATCH_END;
  384. X    else
  385. X        return MATCH_VALID;
  386. X`7D
  387. X
  388. X
  389. X/*--------------------------------------------------------------------------
  390. V--
  391. X*
  392. X* recursively call matche() with final segment of PATTERN and of TEXT.
  393. X*
  394. X----------------------------------------------------------------------------
  395. V*/
  396. X
  397. Xstatic int matche_after_star (p,t)
  398. Xregister char *p;
  399. Xregister char *t;
  400. X`7B
  401. X    register int match = 0;
  402. X    register int nextp;
  403. X
  404. X    /* pass over existing ? and * in pattern */
  405. X    while ((*p == '?') `7C`7C (*p == '*')) `7B
  406. X
  407. X        /* take one char for each ? and +; if end of text then no match */
  408. X        if ((*p == '?') && (!*t++))
  409. X                return MATCH_ABORT;
  410. X
  411. X        /* move to next char in pattern */
  412. X        p++;
  413. X    `7D
  414. X
  415. X    /* if end of pattern we have matched regardless of text left */
  416. X    if (!*p)
  417. X        return MATCH_VALID;
  418. X
  419. X    /* get the next character to match which must be a literal or '`5B' */
  420. X    nextp = *p;
  421. X
  422. X    /* Continue until we run out of text or definite result seen */
  423. X    do `7B
  424. X        /* a precondition for matching is that the next character
  425. X         * in the pattern match the next character in the text or that
  426. X         * the next pattern char is the beginning of a range.  Increment
  427. X         * text pointer as we go here.
  428. X         */
  429. X        if ((nextp == *t) `7C`7C (nextp == '`5B'))
  430. X            match = matche(p, t);
  431. X
  432. X        /* if the end of text is reached then no match */
  433. X        if (!*t++)
  434. X            match = MATCH_ABORT;
  435. X
  436. X    `7D while ((match != MATCH_VALID) &&
  437. X             (match != MATCH_ABORT) &&
  438. X             (match != MATCH_PATTERN));
  439. X
  440. X    /* return result */
  441. X    return match;
  442. X`7D
  443. X
  444. X
  445. X/*--------------------------------------------------------------------------
  446. V--
  447. X*
  448. X* match() is a shell to matche() to return only BOOLEAN values.
  449. X*
  450. X----------------------------------------------------------------------------
  451. V*/
  452. X
  453. Xint match(string,pattern)
  454. Xchar *string;
  455. Xchar *pattern;
  456. X`7B
  457. X    int error_type;
  458. X    error_type = matche(pattern,string);
  459. X    return (error_type == MATCH_VALID ) ? TRUE : FALSE;
  460. X`7D
  461. X
  462. X
  463. X#ifdef TEST_MATCH
  464. X
  465. X/*--------------------------------------------------------------------------
  466. V--
  467. X*
  468. X* Return TRUE if PATTERN has any special wildcard characters
  469. X*
  470. X----------------------------------------------------------------------------
  471. V*/
  472. X
  473. XBOOLEAN is_pattern (char *pattern);
  474. X
  475. X/*--------------------------------------------------------------------------
  476. V--
  477. X*
  478. X* Return TRUE if PATTERN has is a well formed regular expression according
  479. X* to the above syntax
  480. X*
  481. X* error_type is a return code based on the type of pattern error.  Zero is
  482. X* returned in error_type if the pattern is a valid one.  error_type return
  483. X* values are as follows:
  484. X*
  485. X*   PATTERN_VALID - pattern is well formed
  486. X*   PATTERN_RANGE - `5B..`5D construct has a no end range in a '-' pair (ie
  487. V `5Ba-`5D)
  488. X*   PATTERN_CLOSE - `5B..`5D construct has no end bracket (ie `5Babc-g )
  489. X*   PATTERN_EMPTY - `5B..`5D construct is empty (ie `5B`5D)
  490. X*
  491. X----------------------------------------------------------------------------
  492. V*/
  493. X
  494. XBOOLEAN is_valid_pattern (char *pattern, int *error_type);
  495. Xint fast_match_after_star (register char *pattern, register char *text);
  496. X
  497. X/*--------------------------------------------------------------------------
  498. V--
  499. X*
  500. X* Return TRUE if PATTERN has any special wildcard characters
  501. X*
  502. X----------------------------------------------------------------------------
  503. V*/
  504. X
  505. XBOOLEAN is_pattern (char *p)
  506. X`7B
  507. X    while (*p)
  508. X        switch (*p++) `7B
  509. X            case '?':
  510. X            case '*':
  511. X            case '`5B':
  512. X                return TRUE;
  513. X        `7D
  514. X    return FALSE;
  515. X`7D
  516. X
  517. X
  518. X/*--------------------------------------------------------------------------
  519. V--
  520. X*
  521. X* Return TRUE if PATTERN has is a well formed regular expression according
  522. X* to the above syntax
  523. X*
  524. X* error_type is a return code based on the type of pattern error.  Zero is
  525. X* returned in error_type if the pattern is a valid one.  error_type return
  526. X* values are as follows:
  527. X*
  528. X*   PATTERN_VALID - pattern is well formed
  529. X*   PATTERN_RANGE - `5B..`5D construct has a no end range in a '-' pair (ie
  530. V `5Ba-`5D)
  531. X*   PATTERN_CLOSE - `5B..`5D construct has no end bracket (ie `5Babc-g )
  532. X*   PATTERN_EMPTY - `5B..`5D construct is empty (ie `5B`5D)
  533. X*
  534. X----------------------------------------------------------------------------
  535. V*/
  536. X
  537. XBOOLEAN is_valid_pattern (char *p, int *error_type)
  538. X`7B
  539. X    /* init error_type */
  540. X    *error_type = PATTERN_VALID;
  541. X
  542. X    /* loop through pattern to EOS */
  543. X    while (*p) `7B
  544. X
  545. X        /* determine pattern type */
  546. X        switch (*p) `7B
  547. X
  548. X            /* the `5B..`5D construct must be well formed */
  549. X            case '`5B':
  550. X                p++;
  551. X
  552. X                /* if the next character is '`5D' then bad pattern */
  553. X                if (*p == '`5D') `7B
  554. X                    *error_type = PATTERN_EMPTY;
  555. X                    return FALSE;
  556. X                `7D
  557. X
  558. X                /* if end of pattern here then bad pattern */
  559. X                if (!*p) `7B
  560. X                    *error_type = PATTERN_CLOSE;
  561. X                    return FALSE;
  562. X                `7D
  563. X
  564. X                /* loop to end of `5B..`5D construct */
  565. X                while (*p != '`5D') `7B
  566. X
  567. X                    /* check for literal escape */
  568. X                    if (*p == '\\') `7B
  569. X                        p++;
  570. X
  571. X                        /* if end of pattern here then bad pattern */
  572. X                        if (!*p++) `7B
  573. X                            *error_type = PATTERN_ESC;
  574. X                            return FALSE;
  575. X                        `7D
  576. X                    `7D else
  577. X                        p++;
  578. X
  579. X                    /* if end of pattern here then bad pattern */
  580. X                    if (!*p) `7B
  581. X                        *error_type = PATTERN_CLOSE;
  582. X                        return FALSE;
  583. X                    `7D
  584. X
  585. X                    /* if this a range */
  586. X                    if (*p == '-') `7B
  587. X
  588. X                        /* we must have an end of range */
  589. X                        if (!*++p `7C`7C (*p == '`5D')) `7B
  590. X                            *error_type = PATTERN_RANGE;
  591. X                            return FALSE;
  592. X                        `7D else `7B
  593. X
  594. X                            /* check for literal escape */
  595. X                            if (*p == '\\')
  596. X                                p++;
  597. X
  598. X                            /* if end of pattern here then bad pattern */
  599. X                            if (!*p++) `7B
  600. X                                *error_type = PATTERN_ESC;
  601. X                                return FALSE;
  602. X                            `7D
  603. X                        `7D
  604. X                    `7D
  605. X                `7D
  606. X                break;
  607. X
  608. X            /* all other characters are valid pattern elements */
  609. X            case '*':
  610. X            case '?':
  611. X            default:
  612. X                p++;                /* "normal" character */
  613. X                break;
  614. X        `7D    /* switch */
  615. X    `7D
  616. X
  617. X    return TRUE;
  618. X`7D
  619. X
  620. X
  621. X    /*
  622. X    * This test main expects as first arg the pattern and as second arg
  623. X    * the match string.  Output is yay or nay on match.  If nay on
  624. X    * match then the error code is parsed and written.
  625. X    */
  626. X
  627. X#include <stdio.h>
  628. X
  629. Xint main(int argc, char *argv`5B`5D)
  630. X`7B
  631. X    int error;
  632. X    int is_valid_error;
  633. X
  634. X    if (argc != 3)
  635. X        printf("Usage:  MATCH Pattern Text\n");
  636. X    else `7B
  637. X        printf("Pattern: %s\n", argv`5B1`5D);
  638. X        printf("Text   : %s\n", argv`5B2`5D);
  639. X
  640. X        if (!is_pattern(argv`5B1`5D))
  641. X            printf("    First Argument Is Not A Pattern\n");
  642. X        else `7B
  643. X            match(argv`5B1`5D,argv`5B2`5D) ? printf("TRUE") : printf("FALSE"
  644. V);
  645. X            error = matche(argv`5B1`5D,argv`5B2`5D);
  646. X            is_valid_pattern(argv`5B1`5D,&is_valid_error);
  647. X
  648. X            switch (error) `7B
  649. X                case MATCH_VALID:
  650. X                    printf("    Match Successful");
  651. X                    if (is_valid_error != PATTERN_VALID)
  652. X                        printf(" -- is_valid_pattern() is complaining\n");
  653. X                    else
  654. X                        printf("\n");
  655. X                    break;
  656. X                case MATCH_RANGE:
  657. X                    printf("    Match Failed on `5B..`5D\n");
  658. X                    break;
  659. X                case MATCH_ABORT:
  660. X                    printf("    Match Failed on Early Text Termination\n");
  661. X                    break;
  662. X                case MATCH_END:
  663. X                    printf("    Match Failed on Early Pattern Termination\n"
  664. V);
  665. X                    break;
  666. X                case MATCH_PATTERN:
  667. X                    switch (is_valid_error) `7B
  668. X                        case PATTERN_VALID:
  669. X                            printf("    Internal Disagreement On Pattern\n")
  670. V;
  671. X                            break;
  672. X                        case PATTERN_RANGE:
  673. X                            printf("    No End of Range in `5B..`5D Construc
  674. Vt\n");
  675. X                            break;
  676. X                        case PATTERN_CLOSE:
  677. X                            printf("    `5B..`5D Construct is Open\n");
  678. X                            break;
  679. X                        case PATTERN_EMPTY:
  680. X                            printf("    `5B..`5D Construct is Empty\n");
  681. X                            break;
  682. X                        default:
  683. X                            printf("    Internal Error in is_valid_pattern()
  684. V\n");
  685. X                    `7D
  686. X                    break;
  687. X                default:
  688. X                    printf("    Internal Error in matche()\n");
  689. X                    break;
  690. X            `7D /* switch */
  691. X        `7D
  692. X
  693. X    `7D
  694. X    return(0);
  695. X`7D
  696. X
  697. X#endif  /* TEST_MATCH */
  698. $ CALL UNPACK [.UNZIP50]MATCH.C;1 119022413
  699. $ create 'f'
  700. X/*--------------------------------------------------------------------------
  701. V-
  702. X
  703. X  misc.c
  704. X
  705. X  This file contains a number of useful but not particularly closely related
  706. X  functions; their main claim to fame is that they don't change much, so thi
  707. Vs
  708. X  file should rarely need to be recompiled.  The CRC-32 stuff is from crc32.
  709. Vc;
  710. X  do_string() is from nunzip.c; makeword() and makelong() are from unzip.c;
  711. X  memset() and memcpy() are from zmemset.c and zmemcpy.c, respectively; and
  712. X  dos_to_unix_time() is from set_file_time_and_close() in file_io.c.  ebcdic
  713. V`5B`5D,
  714. X  check_for_newer(), dateformat(), and return_VMS() are new.  Things lumped
  715. X  together here to cut down on the size of unzip.c and the number of associ-
  716. X  ated files floating around.
  717. X
  718. X  --------------------------------------------------------------------------
  719. V-
  720. X
  721. X  Copyrights:  see accompanying file "COPYING" in UnZip source distribution.
  722. X
  723. X  --------------------------------------------------------------------------
  724. V-*/
  725. X
  726. X
  727. X#include "unzip.h"
  728. X#ifdef MSWIN
  729. X#  include "wizunzip.h"
  730. X#endif
  731. X
  732. X
  733. X
  734. X#ifndef ZIPINFO   /* no need to calculate CRCs */
  735. X
  736. X/**************************/
  737. X/*  Function UpdateCRC()  */
  738. X/**************************/
  739. X
  740. X /*--------------------------------------------------------------------
  741. X
  742. X   First, the polynomial itself and its table of feedback terms.  The
  743. X   polynomial is
  744. X   X`5E32+X`5E26+X`5E23+X`5E22+X`5E16+X`5E12+X`5E11+X`5E10+X`5E8+X`5E7+X`5E5
  745. V+X`5E4+X`5E2+X`5E1+X`5E0
  746. X
  747. X   Note that we take it "backwards" and put the highest-order term in
  748. X   the lowest-order bit.  The X`5E32 term is "implied"; the LSB is the
  749. X   X`5E31 term, etc.  The X`5E0 term (usually shown as "+1") results in
  750. X   the MSB being 1.
  751. X
  752. X   Note that the usual hardware shift register implementation, which
  753. X   is what we're using (we're merely optimizing it by doing eight-bit
  754. X   chunks at a time) shifts bits into the lowest-order term.  In our
  755. X   implementation, that means shifting towards the right.  Why do we
  756. X   do it this way?  Because the calculated CRC must be transmitted in
  757. X   order from highest-order term to lowest-order term.  UARTs transmit
  758. X   characters in order from LSB to MSB.  By storing the CRC this way,
  759. X   we hand it to the UART in the order low-byte to high-byte; the UART
  760. X   sends each low-bit to hight-bit; and the result is transmission bit
  761. X   by bit from highest- to lowest-order term without requiring any bit
  762. X   shuffling on our part.  Reception works similarly.
  763. X
  764. X   The feedback terms table consists of 256, 32-bit entries.  Notes:
  765. X
  766. X       The table can be generated at runtime if desired; code to do so
  767. X       is shown later.  It might not be obvious, but the feedback
  768. X       terms simply represent the results of eight shift/xor opera-
  769. X       tions for all combinations of data and CRC register values.
  770. X
  771. X       The values must be right-shifted by eight bits by the "updcrc"
  772. X       logic; the shift must be unsigned (bring in zeroes).  On some
  773. X       hardware you could probably optimize the shift in assembler by
  774. X       using byte-swap instructions.
  775. X       polynomial $edb88320
  776. X
  777. X   --------------------------------------------------------------------*/
  778. X
  779. XULONG crc_32_tab`5B`5D =
  780. X`7B
  781. X    0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  782. X    0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  783. X    0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  784. X    0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  785. X    0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  786. X    0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  787. X    0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  788. X    0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  789. X    0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  790. X    0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  791. X    0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  792. X    0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  793. X    0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  794. X    0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  795. X    0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  796. X    0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  797. X    0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  798. X    0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  799. X    0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  800. X    0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  801. X    0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  802. X    0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  803. X    0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  804. X    0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  805. X    0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  806. X    0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  807. X    0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  808. X    0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  809. X    0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  810. X    0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  811. X    0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  812. X    0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  813. X    0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  814. X    0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  815. X    0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  816. X    0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  817. X    0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  818. X    0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  819. X    0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  820. X    0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  821. X    0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  822. X    0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  823. X    0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  824. X    0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  825. X    0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  826. X    0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  827. X    0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  828. X    0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  829. X    0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  830. X    0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  831. X    0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  832. X    0x2d02ef8dL
  833. X`7D; /* end crc_32_tab`5B`5D */
  834. X
  835. X
  836. Xvoid UpdateCRC(s, len)
  837. X    register byte *s;
  838. X    register int len;
  839. X`7B
  840. X    register ULONG crcval = crc32val;
  841. X
  842. X    /* update running CRC calculation with contents of a buffer */
  843. X    while (len--)
  844. X        crcval = crc_32_tab`5B((byte) crcval `5E (*s++)) & 0xff`5D `5E (crcv
  845. Val >> 8);
  846. X    crc32val = crcval;
  847. X`7D
  848. X
  849. X#endif /* !ZIPINFO */
  850. X
  851. X
  852. X
  853. X
  854. X
  855. X/**************************/
  856. X/*  Function do_string()  */
  857. X/**************************/
  858. X
  859. Xint do_string(len, option)      /* return PK-type error code */
  860. X    unsigned int len;           /* without prototype, UWORD converted to thi
  861. Vs */
  862. X    int option;
  863. X`7B
  864. X    int block_length, error = 0;
  865. X    UWORD comment_bytes_left, extra_len;
  866. X
  867. X
  868. X/*--------------------------------------------------------------------------
  869. V-
  870. X    This function processes arbitrary-length (well, usually) strings.  Three
  871. X    options are allowed:  SKIP, wherein the string is skipped pretty logical
  872. V,
  873. X    eh?); DISPLAY, wherein the string is printed to standard output after un
  874. V-
  875. X    dergoing any necessary or unnecessary character conversions; and FILENAM
  876. VE,
  877. X    wherein the string is put into the filename`5B`5D array after undergoing
  878. V ap-
  879. X    propriate conversions (including case-conversion, if that is indicated:
  880. X    see the global variable pInfo->lcflag).  The latter option should be OK,
  881. X    since filename is now dimensioned at 1025, but we check anyway.
  882. X
  883. X    The string, by the way, is assumed to start at the current file-pointer
  884. X    position; its length is given by len.  So start off by checking length
  885. X    of string:  if zero, we're already set.
  886. X  --------------------------------------------------------------------------
  887. V-*/
  888. X
  889. X    if (!len)
  890. X        return (0);             /* 0:  no error */
  891. X
  892. X    switch (option) `7B
  893. X
  894. X    /*
  895. X     * First case:  print string on standard output.  First set loop vari-
  896. X     * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
  897. X     * converting formats and printing as we go.  The second half of the
  898. X     * loop conditional was added because the file might be truncated, in
  899. X     * which case comment_bytes_left will remain at some non-zero value for
  900. X     * all time.  outbuf is used as a scratch buffer because it is avail-
  901. X     * able (we should be either before or in between any file processing).
  902. X     * `5BThe typecast in front of the MIN() macro was added because of the
  903. X     * new promotion rules under ANSI C; readbuf() wants an int, but MIN()
  904. X     * returns a signed long, if I understand things correctly.  The proto-
  905. X     * type should handle it, but just in case...`5D
  906. X     */
  907. X
  908. X    case DISPLAY:
  909. X        comment_bytes_left = len;
  910. X        block_length = OUTBUFSIZ;    /* for the while statement, first time
  911. V */
  912. X        while (comment_bytes_left > 0 && block_length > 0) `7B
  913. X            if ((block_length = readbuf((char *)outbuf,
  914. X                   (int) MIN(OUTBUFSIZ, comment_bytes_left))) <= 0)
  915. X                return 51;                      /* 51:  unexpected EOF */
  916. X            comment_bytes_left -= block_length;
  917. X            NUKE_CRs(outbuf, block_length);     /* (modifies block_length) *
  918. V/
  919. X
  920. X            /*  this is why we allocated an extra byte for outbuf: */
  921. X            outbuf`5Bblock_length`5D = '\0';        /* terminate w/zero:  AS
  922. VCIIZ */
  923. X
  924. X            A_TO_N(outbuf);     /* translate string to native */
  925. X
  926. X            printf("%s", outbuf);
  927. X        `7D
  928. X#ifdef MSWIN
  929. X        /* ran out of local mem -- had to cheat */
  930. X        WriteStringToMsgWin(outbuf, bRealTimeMsgUpdate);
  931. X#else /* !MSWIN */
  932. X        printf("\n");   /* assume no newline at end */
  933. X#endif /* ?MSWIN */
  934. X        break;
  935. X
  936. X    /*
  937. X     * Second case:  read string into filename`5B`5D array.  The filename sh
  938. Vould
  939. X     * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check
  940. V,
  941. X     * just to be sure.
  942. X     */
  943. X
  944. X    case FILENAME:
  945. X        extra_len = 0;
  946. X        if (len >= FILNAMSIZ) `7B
  947. X            fprintf(stderr, "warning:  filename too long--truncating.\n");
  948. X            error = 1;          /* 1:  warning error */
  949. X            extra_len = len - FILNAMSIZ + 1;
  950. X            len = FILNAMSIZ - 1;
  951. X        `7D
  952. X        if (readbuf(filename, len) <= 0)
  953. X            return 51;          /* 51:  unexpected EOF */
  954. X        filename`5Blen`5D = '\0';   /* terminate w/zero:  ASCIIZ */
  955. X
  956. X        A_TO_N(filename);       /* translate string to native */
  957. X
  958. X#ifndef ZIPINFO
  959. X        if (pInfo->lcflag)
  960. X            TOLOWER(filename, filename);  /* replace with lowercase filename
  961. V */
  962. X#endif
  963. X
  964. X        if (!extra_len)         /* we're done here */
  965. X            break;
  966. X
  967. X        /*
  968. X         * We truncated the filename, so print what's left and then fall
  969. X         * through to the SKIP routine.
  970. X         */
  971. X        fprintf(stderr, "`5B %s `5D\n", filename);
  972. X        len = extra_len;
  973. X        /*  FALL THROUGH...  */
  974. X
  975. X    /*
  976. X     * Third case:  skip string, adjusting readbuf's internal variables
  977. X     * as necessary (and possibly skipping to and reading a new block of
  978. X     * data).
  979. X     */
  980. X
  981. X    case SKIP:
  982. X        LSEEK(cur_zipfile_bufstart + (inptr-inbuf) + len)
  983. X        break;
  984. X
  985. X    /*
  986. X     * Fourth case:  assume we're at the start of an "extra field"; malloc
  987. X     * storage for it and read data into the allocated space.
  988. X     */
  989. X
  990. X    case EXTRA_FIELD:
  991. X        if (extra_field != (byte *)NULL)
  992. X            free(extra_field);
  993. X        if ((extra_field = (byte *)malloc(len)) == (byte *)NULL) `7B
  994. X            fprintf(stderr,
  995. X              "warning:  extra field too long (%d).  Ignoring...\n", len);
  996. X            LSEEK(cur_zipfile_bufstart + (inptr-inbuf) + len)
  997. X        `7D else
  998. X            if (readbuf((char *)extra_field, len) <= 0)
  999. X                return 51;      /* 51:  unexpected EOF */
  1000. X        break;
  1001. X
  1002. X    `7D /* end switch (option) */
  1003. X    return error;
  1004. X
  1005. X`7D /* end function do_string() */
  1006. X
  1007. X
  1008. X
  1009. X
  1010. X
  1011. X#ifndef ZIPINFO
  1012. X#ifndef VMS
  1013. X
  1014. X/*********************************/
  1015. X/*  Function dos_to_unix_time()  */
  1016. X/*********************************/
  1017. X
  1018. Xtime_t dos_to_unix_time(ddate, dtime)
  1019. X    unsigned ddate, dtime;
  1020. X`7B
  1021. X    static short yday`5B`5D=`7B0, 31, 59, 90, 120, 151, 181, 212, 243, 273,
  1022. V 304, 334`7D;
  1023. X    int yr, mo, dy, hh, mm, ss, leap;
  1024. X    long m_time, days=0;
  1025. X#if (!defined(MACOS) && !defined(MSC) && !defined(__GO32__))
  1026. X#if (defined(BSD) `7C`7C defined(MTS))
  1027. X#ifndef __386BSD__
  1028. X    static struct timeb tbp;
  1029. X#endif /* __386BSD__ */
  1030. X#else /* !(BSD `7C`7C MTS) */
  1031. X    extern long timezone;    /* declared in <time.h> for MSC (& Borland?) */
  1032. X#endif /* ?(BSD `7C`7C MTS) */
  1033. X#endif /* !MACOS && !MSC && !__GO32__ */
  1034. X
  1035. X#   define YRBASE  1970
  1036. X
  1037. X    /* dissect date */
  1038. X    yr = ((ddate >> 9) & 0x7f) + (1980 - YRBASE);
  1039. X    mo = ((ddate >> 5) & 0x0f) - 1;
  1040. X    dy = (ddate & 0x1f) - 1;
  1041. X
  1042. X    /* dissect time */
  1043. X    hh = (dtime >> 11) & 0x1f;
  1044. X    mm = (dtime >> 5) & 0x3f;
  1045. X    ss = (dtime & 0x1f) * 2;
  1046. X
  1047. X    /* leap = # of leap years from BASE up to but not including current year
  1048. V */
  1049. X    leap = ((yr + YRBASE - 1) / 4);   /* leap year base factor */
  1050. X
  1051. X    /* How many days from BASE to this year? (& add expired days this year)
  1052. V */
  1053. X    days = (yr * 365) + (leap - 492) + yday`5Bmo`5D;
  1054. X
  1055. X    /* if year is a leap year and month is after February, add another day *
  1056. V/
  1057. X    if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
  1058. X        ++days;                 /* OK through 2199 */
  1059. X
  1060. X    /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
  1061. X    m_time = ((long)(days + dy) * 86400L) + ((long)hh * 3600) + (mm * 60) +
  1062. V ss;
  1063. X      /* - 1;   MS-DOS times always rounded up to nearest even second */
  1064. X
  1065. X#if (!defined(MACOS) && !defined(__GO32__))
  1066. X#if (defined(BSD) `7C`7C defined(MTS))
  1067. X#ifndef __386BSD__
  1068. X    ftime(&tbp);
  1069. X    m_time += tbp.timezone * 60L;
  1070. X#endif
  1071. X#else /* !(BSD `7C`7C MTS) */
  1072. X#ifdef WIN32
  1073. X    /* later... */
  1074. X#else /* !WIN32 */
  1075. X    tzset();                    /* set `60timezone' */
  1076. X#endif /* ?WIN32 */
  1077. X    m_time += timezone;         /* account for timezone differences */
  1078. X#endif /* ?(BSD `7C`7C MTS) */
  1079. X#endif /* !MACOS && !__GO32__ */
  1080. X
  1081. X#ifdef __386BSD__
  1082. X    m_time += localtime((time_t *) &m_time))->tm_gmtoff;
  1083. X#else
  1084. X    if (localtime((time_t *)&m_time)->tm_isdst)
  1085. X        m_time -= 60L * 60L;    /* adjust for daylight savings time */
  1086. X#endif /* __386BSD__ */
  1087. X
  1088. X    return m_time;
  1089. X
  1090. X`7D /* end function dos_to_unix_time() */
  1091. X
  1092. X#endif /* !VMS */
  1093. X
  1094. X
  1095. X
  1096. X
  1097. X
  1098. X/********************************/
  1099. X/*  Function check_for_newer()  */  /* could make this into a macro for Unix
  1100. V */
  1101. X/********************************/
  1102. X
  1103. Xint check_for_newer(filename)   /* return 1 if existing file newer or equal;
  1104. V */
  1105. X    char *filename;             /*  0 if older; -1 if doesn't exist yet */
  1106. X`7B
  1107. X#ifdef VMS
  1108. X    unsigned short timbuf`5B7`5D;
  1109. X    int dy, mo, yr, hh, mm, ss, dy2, mo2, yr2, hh2, mm2, ss2;
  1110. X    struct FAB fab;
  1111. X    struct XABDAT xdat;
  1112. X
  1113. X
  1114. X    if (stat(filename, &statbuf))
  1115. X        return DOES_NOT_EXIST;
  1116. X
  1117. X    fab  = cc$rms_fab;
  1118. X    xdat = cc$rms_xabdat;
  1119. X
  1120. X    fab.fab$l_xab = &xdat;
  1121. X    fab.fab$l_fna = filename;
  1122. X    fab.fab$b_fns = strlen(filename);
  1123. X    fab.fab$l_fop = FAB$M_GET `7C FAB$M_UFO;
  1124. X
  1125. X    if ((sys$open(&fab) & 1) == 0)       /* open failure:  report exists and
  1126. V */
  1127. X        return EXISTS_AND_OLDER;         /*  older so new copy will be made
  1128. V  */
  1129. X    sys$numtim(&timbuf,&xdat.xab$q_cdt);
  1130. X    fab.fab$l_xab = 0L;
  1131. X
  1132. X    sys$dassgn(fab.fab$l_stv);
  1133. X    sys$close(&fab);   /* be sure file is closed and RMS knows about it */
  1134. X
  1135. X    yr = timbuf`5B0`5D;
  1136. X    yr2 = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
  1137. X    if (yr > yr2)
  1138. X        return EXISTS_AND_NEWER;
  1139. X    else if (yr < yr2)
  1140. X        return EXISTS_AND_OLDER;
  1141. X
  1142. X    mo = timbuf`5B1`5D;
  1143. X    mo2 = ((lrec.last_mod_file_date >> 5) & 0x0f);
  1144. X    if (mo > mo2)
  1145. X        return EXISTS_AND_NEWER;
  1146. X    else if (mo < mo2)
  1147. X        return EXISTS_AND_OLDER;
  1148. X
  1149. X    dy = timbuf`5B2`5D;
  1150. X    dy2 = (lrec.last_mod_file_date & 0x1f);
  1151. X    if (dy > dy2)
  1152. X        return EXISTS_AND_NEWER;
  1153. X    else if (dy < dy2)
  1154. X        return EXISTS_AND_OLDER;
  1155. X
  1156. X    hh = timbuf`5B3`5D;
  1157. X    hh2 = (lrec.last_mod_file_time >> 11) & 0x1f;
  1158. X    if (hh > hh2)
  1159. X        return EXISTS_AND_NEWER;
  1160. X    else if (hh < hh2)
  1161. X        return EXISTS_AND_OLDER;
  1162. X
  1163. X    mm = timbuf`5B4`5D;
  1164. X    mm2 = (lrec.last_mod_file_time >> 5) & 0x3f;
  1165. X    if (mm > mm2)
  1166. X        return EXISTS_AND_NEWER;
  1167. X    else if (mm < mm2)
  1168. X        return EXISTS_AND_OLDER;
  1169. X
  1170. X    /* round to nearest 2 secs--may become 60, but doesn't matter for compar
  1171. Ve */
  1172. X    ss = (int)((float)timbuf`5B5`5D + (float)timbuf`5B6`5D*.01 + 1.) & -2;
  1173. X    ss2 = (lrec.last_mod_file_time & 0x1f) * 2;
  1174. X    if (ss >= ss2)
  1175. X        return EXISTS_AND_NEWER;
  1176. X
  1177. X    return EXISTS_AND_OLDER;
  1178. X
  1179. X#else /* !VMS */
  1180. X#ifdef OS2
  1181. X    long existing, archive;
  1182. X
  1183. X    if ((existing = GetFileTime(filename)) == -1)
  1184. X        return DOES_NOT_EXIST;
  1185. X    archive = ((long) lrec.last_mod_file_date) << 16 `7C lrec.last_mod_file_
  1186. Vtime;
  1187. X
  1188. X    return (existing >= archive);
  1189. X#else /* !OS2 */
  1190. X    time_t existing, archive;
  1191. X
  1192. X    if (stat(filename, &statbuf))
  1193. X        return DOES_NOT_EXIST;
  1194. X
  1195. X    /* round up existing filetime to nearest 2 seconds for comparison */
  1196. X    existing = (statbuf.st_mtime & 1) ? statbuf.st_mtime+1 : statbuf.st_mtim
  1197. Ve;
  1198. X    archive  = dos_to_unix_time(lrec.last_mod_file_date,
  1199. X                                lrec.last_mod_file_time);
  1200. X
  1201. X    return (existing >= archive);
  1202. X#endif /* ?OS2 */
  1203. X#endif /* ?VMS */
  1204. X
  1205. X`7D /* end function check_for_newer() */
  1206. X
  1207. X
  1208. X
  1209. X
  1210. X
  1211. X/***************************/
  1212. X/*  Function dateformat()  */
  1213. X/***************************/
  1214. X
  1215. Xint dateformat()
  1216. X`7B
  1217. X
  1218. X/*--------------------------------------------------------------------------
  1219. V---
  1220. X  For those operating systems which support it, this function returns a valu
  1221. Ve
  1222. X  which tells how national convention says that numeric dates are displayed.
  1223. X
  1224. X  Return values are DF_YMD, DF_DMY and DF_MDY.  The meanings should be fairl
  1225. Vy
  1226. X  obvious.
  1227. X ---------------------------------------------------------------------------
  1228. V--*/
  1229. X
  1230. X#ifdef OS2
  1231. X    switch (GetCountryInfo()) `7B
  1232. X            case 0 /* DATEFMT_MM_DD_YY */ :
  1233. X                return DF_MDY;
  1234. X            case 1 /* DATEFMT_DD_MM_YY */ :
  1235. X                return DF_DMY;
  1236. X            case 2 /* DATEFMT_YY_MM_DD */ :
  1237. X                return DF_YMD;
  1238. X        `7D
  1239. X#else /* !OS2 */
  1240. X#if (defined(MSDOS) && !defined(MSWIN))
  1241. X    unsigned short _CountryInfo`5B18`5D;
  1242. X#ifdef __GO32__
  1243. X    unsigned short *CountryInfo = _CountryInfo;
  1244. X
  1245. X    bdos(0x38, (unsigned)CountryInfo, 0);
  1246. X#else /* !__GO32__ */
  1247. X    unsigned short far *CountryInfo = _CountryInfo;
  1248. X    union REGS regs;
  1249. X    struct SREGS sregs;
  1250. X
  1251. X    regs.x.ax = 0x3800;
  1252. X    regs.x.dx = FP_OFF(CountryInfo);
  1253. X    sregs.ds  = FP_SEG(CountryInfo);
  1254. X    int86x(0x21, ®s, ®s, &sregs);
  1255. X#endif /* ?__GO32__ */
  1256. X
  1257. X    switch(CountryInfo`5B0`5D) `7B
  1258. X        case 0:
  1259. X            return DF_MDY;
  1260. X        case 1:
  1261. X            return DF_DMY;
  1262. X        case 2:
  1263. X            return DF_YMD;
  1264. X    `7D
  1265. X#endif /* MSDOS && !MSWIN */
  1266. X#endif /* ?OS2 */
  1267. X
  1268. X    return DF_MDY;   /* default for Unix, VMS, etc. */
  1269. X
  1270. X`7D /* end function dateformat() */
  1271. X
  1272. X#endif /* !ZIPINFO */
  1273. X
  1274. X
  1275. X
  1276. X
  1277. X
  1278. X#ifdef EBCDIC
  1279. X
  1280. X/*
  1281. X * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1
  1282. X * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC.
  1283. X */
  1284. X
  1285. Xunsigned char ebcdic`5B`5D =
  1286. X`7B
  1287. X    0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
  1288. X    0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  1289. X    0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26,
  1290. X    0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
  1291. X    0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
  1292. X    0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
  1293. X    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
  1294. X    0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
  1295. X    0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
  1296. X    0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
  1297. X    0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
  1298. X    0xe7, 0xe8, 0xe9, 0xba, 0xe0, 0xbb, 0xb0, 0x6d,
  1299. X    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  1300. X    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
  1301. X    0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
  1302. X    0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
  1303. X    0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,
  1304. X    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
  1305. X    0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08,
  1306. X    0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xff,
  1307. X    0x41, 0xaa, 0x4a, 0xb1, 0x9f, 0xb2, 0x6a, 0xb5,
  1308. X    0xbd, 0xb4, 0x9a, 0x8a, 0x5f, 0xca, 0xaf, 0xbc,
  1309. X    0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3,
  1310. X    0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab,
  1311. X    0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68,
  1312. X    0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,
  1313. X    0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf,
  1314. X    0x80, 0xfd, 0xfe, 0xfb, 0xfc, 0xad, 0xae, 0x59,
  1315. X    0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48,
  1316. X    0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,
  1317. X    0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1,
  1318. X    0x70, 0xdd, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf
  1319. X`7D; /* end ebcdic`5B`5D */
  1320. X
  1321. X#endif                          /* EBCDIC */
  1322. X
  1323. X
  1324. X
  1325. X
  1326. X
  1327. X/*************************/
  1328. X/*  Function makeword()  */
  1329. X/*************************/
  1330. X
  1331. XUWORD makeword(b)
  1332. X    byte *b;
  1333. X`7B
  1334. X    /*
  1335. X     * Convert Intel style 'short' integer to non-Intel non-16-bit
  1336. X     * host format.  This routine also takes care of byte-ordering.
  1337. X     */
  1338. X    return ((b`5B1`5D << 8) `7C b`5B0`5D);
  1339. X`7D
  1340. X
  1341. X
  1342. X
  1343. X
  1344. X
  1345. X/*************************/
  1346. X/*  Function makelong()  */
  1347. X/*************************/
  1348. X
  1349. XULONG makelong(sig)
  1350. X    byte *sig;
  1351. X`7B
  1352. X    /*
  1353. X     * Convert intel style 'long' variable to non-Intel non-16-bit
  1354. X     * host format.  This routine also takes care of byte-ordering.
  1355. X     */
  1356. X    return (((ULONG) sig`5B3`5D) << 24)
  1357. X        + (((ULONG) sig`5B2`5D) << 16)
  1358. X        + (((ULONG) sig`5B1`5D) << 8)
  1359. X        + ((ULONG) sig`5B0`5D);
  1360. X`7D
  1361. X
  1362. X
  1363. X
  1364. X
  1365. X
  1366. X#ifdef VMS
  1367. X
  1368. X/***************************/
  1369. X/*  Function return_VMS()  */
  1370. X/***************************/
  1371. X
  1372. Xvoid return_VMS(zip_error)
  1373. X    int zip_error;
  1374. X`7B
  1375. X#ifdef RETURN_CODES
  1376. X/*--------------------------------------------------------------------------
  1377. V-
  1378. X    Do our own, explicit processing of error codes and print message, since
  1379. X    VMS misinterprets return codes as rather obnoxious system errors ("acces
  1380. Vs
  1381. X    violation," for example).
  1382. X  --------------------------------------------------------------------------
  1383. V-*/
  1384. X
  1385. X    switch (zip_error) `7B
  1386. X
  1387. X    case 0:
  1388. X        break;   /* life is fine... */
  1389. X    case 1:
  1390. X        fprintf(stderr, "\n`5Breturn-code 1:  warning error \
  1391. X(e.g., failed CRC or unknown compression method)`5D\n");
  1392. X        break;
  1393. X    case 2:
  1394. X    case 3:
  1395. X        fprintf(stderr, "\n`5Breturn-code %d:  error in zipfile \
  1396. X(e.g., can't find local file header sig)`5D\n",
  1397. X                zip_error);
  1398. X        break;
  1399. X    case 4:
  1400. X    case 5:
  1401. X    case 6:
  1402. X    case 7:
  1403. X    case 8:
  1404. X        fprintf(stderr, "\n`5Breturn-code %d:  insufficient memory`5D\n",
  1405. X          zip_error);
  1406. X        break;
  1407. +-+-+-+-+-+-+-+-  END  OF PART 6 +-+-+-+-+-+-+-+-
  1408.