home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / z / zoo210sr.zip / ZOO210SR.TAZ / ZOO210SR.tar / zoo / portable.c < prev    next >
C/C++ Source or Header  |  1991-07-14  |  22KB  |  723 lines

  1. #ifndef LINT
  2. /* @(#) portable.c 2.24 88/08/24 01:22:06 */
  3. static char sccsid[]="@(#) portable.c 2.24 88/08/24 01:22:06";
  4. #endif /* LINT */
  5.  
  6. #include "options.h"
  7. /*
  8. Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  9. (C) Copyright 1988 Rahul Dhesi -- All rights reserved
  10. */
  11. /**********************
  12. portable.c contains functions needed to make Zoo portable to various
  13. implementations of C.
  14.  
  15. Note:  Provided a 2's complement machine is used, all functions in
  16. this file are themselves machine-independent and need not be changed
  17. when implementing Zoo on a different machine.  Some code will choke
  18. on 1's complement machines--I think.  
  19.  
  20. For machine-dependent declarations see files "machine.h" and "options.h". 
  21.  
  22. For machine-dependent functions see file "machine.c"
  23. */
  24.  
  25. #include "zoo.h"
  26. #include "zooio.h"
  27.  
  28. #include "various.h"
  29. #include "zoofns.h"
  30.  
  31. #include "machine.h"
  32. #include "debug.h"
  33. #include "assert.h"
  34.  
  35. #ifdef NEEDCTYP
  36. #include <ctype.h>              /* for tolower() */
  37. #endif
  38.  
  39. #include "portable.h"
  40.  
  41. #ifdef TRACE_IO
  42. extern int verbose;
  43. #endif
  44.  
  45. /* Functions defined for use within this file only.  */
  46. long to_long PARMS((BYTE[]));
  47. int to_int PARMS((BYTE[]));
  48. void b_to_zooh PARMS((struct zoo_header *, BYTE[]));
  49. void b_to_dir PARMS((struct direntry *, BYTE[]));
  50. int dir_to_b PARMS((BYTE[], struct direntry *));
  51. void zooh_to_b PARMS((BYTE[], struct zoo_header *));
  52. void splitlong PARMS((BYTE[], long));
  53. void splitint PARMS((BYTE[], int));
  54.  
  55. #ifdef TRACE_IO
  56. void show_h PARMS ((struct zoo_header *));
  57. void show_dir PARMS ((struct direntry *));
  58. #endif /* TRACE_IO */
  59.  
  60. extern unsigned int crccode;
  61.  
  62. /************************************************************************/
  63. /* I/O functions */
  64. /************************************************************************/
  65.  
  66. /* some functions get defined only if they aren't already macros */
  67.  
  68. #ifndef zooread
  69. int zooread (file, buffer, count)
  70. ZOOFILE file; char *buffer; int count;
  71. { return (fread (buffer, 1, count, file)); }
  72. #endif /* zooread */
  73.  
  74. #ifndef FIZ
  75. #ifndef zoowrite
  76. int zoowrite (file, buffer, count)
  77. ZOOFILE file; char *buffer; int count;
  78.     if (file == NULLFILE)
  79.        return (count);
  80.     else
  81.         return (fwrite (buffer, 1, count, file)); 
  82. }
  83. #endif /* zoowrite */
  84.  
  85. ZOOFILE zoocreate (fname)
  86. char *fname;
  87. { return ((ZOOFILE) fopen (fname, Z_NEW)); }
  88.  
  89. #endif /* FIZ */
  90.  
  91. #ifndef zooseek
  92. long zooseek (file, offset, whence)
  93. ZOOFILE file; long offset; int whence;
  94. { return (fseek (file, offset, whence)); }
  95. #endif /* zooseek */
  96.  
  97. ZOOFILE zooopen (fname, option)
  98. char *fname; char *option;
  99. { return ((ZOOFILE) fopen (fname, option)); }
  100.  
  101. #ifndef zootell
  102. long zootell (file)
  103. ZOOFILE file;
  104. { return ftell (file); }
  105. #endif /* zootell */
  106.  
  107. int zooclose (file)
  108. ZOOFILE file;
  109. { return fclose (file); }
  110.  
  111. /**********************
  112. low_ch() is a macro that returns a lowercased char; it may be
  113. used with any char, whether or not it is uppercase.   It will
  114. be used below by one or two functions.
  115. */
  116.  
  117. #define low_ch(c)        (isupper(c) ? tolower(c) : c)
  118.  
  119. /************************************************************************/
  120. /*** Following are functions that make up for various implementations ***/
  121. /*** of C not having certain library routines.                        ***/
  122. /************************************************************************/
  123.  
  124. #ifndef FIZ
  125. /**********************
  126. str_lwr() converts a string to lowercase and returns a pointer to the string
  127. */
  128. char *str_lwr (str)
  129. char *str;
  130. {
  131.    register char *s;
  132.    s = str;
  133.    while (*s != '\0') {
  134.       *s = toascii(*s);
  135.         *s = low_ch(*s);
  136.       s++;
  137.    }
  138.    return (str);
  139. }
  140.  
  141. /**********************
  142. str_icmp() compares strings just like strcmp() but it does it without regard to
  143. case.
  144. */
  145. int str_icmp (s1, s2)
  146. register char *s1, *s2;
  147. {
  148.    for ( ; low_ch(*s1) == low_ch(*s2);  s1++, s2++)
  149.       if (*s1 == '\0')
  150.          return(0);
  151.    return(low_ch(*s1) - low_ch(*s2));
  152. }
  153.  
  154. #ifdef NEED_MEMSET
  155. /**********************
  156. memset() it sets the first "count" bytes of "dest" to the character
  157. "c" and returns a pointer to "dest".
  158. */
  159. VOIDPTR memset (dest, c, count)
  160. register VOIDPTR dest;
  161. int c;
  162. unsigned count;
  163. {
  164.    register unsigned i;
  165.    for (i = 0; i < count; i++) {
  166.       *((char *) (dest + i)) = c;
  167.    }
  168.    return dest;
  169. }
  170. #endif /* NEED_MEMSET */
  171.  
  172. #ifdef NEED_MEMCPY
  173. /**********************
  174. memcpy() copies "count" bytes from "src" to "dest" and returns 
  175. a pointer to "dest".  Not necessarily safe for overlapping moves. */
  176.  
  177. VOIDPTR memcpy(dest, src, count)
  178. register VOIDPTR dest;
  179. register VOIDPTR src;
  180. unsigned count;
  181. {
  182.     VOIDPTR savedest = dest;
  183.     while (count > 0) {
  184.         *((char *) dest++) = *((char *) src++);
  185.         count--;
  186.     }
  187. }
  188. #endif /* NEED_MEMCPY */
  189.  
  190. #ifndef FPUTCHAR
  191. /**********************
  192. fputchar() writes a character to stdout.  It is identical to putchar
  193. but is a function, not a macro.
  194. */
  195. int fputchar (c)
  196. int c;
  197. {
  198.    return (fputc(c, stdout));
  199. }
  200. #endif /* FPUTCHAR */
  201. #endif /* FIZ */
  202.  
  203. /***********************************************************************/
  204. /*** Following are declarations and functions that are written in a  ***/
  205. /*** machine-independent way but they implement machine-dependent    ***/
  206. /*** activities                                                      ***/
  207. /***********************************************************************/
  208.  
  209. #ifndef DIRECT_CONVERT
  210. /**********************
  211. to_long() converts four consecutive bytes, in order of increasing
  212. significance, to a long integer.  It is used to make Zoo independent of the
  213. byte order of the system.  
  214. */
  215. long to_long(data)
  216. BYTE data[];
  217. {
  218.    return (long) ((unsigned long) data[0] | ((unsigned long) data[1] << 8) |
  219.          ((unsigned long) data[2] << 16) | ((unsigned long) data[3] << 24));
  220. }
  221.  
  222. #ifndef FIZ
  223. /********************
  224. splitlong() converts a long integer to four consecutive BYTEs in order
  225. of increasing significance.
  226. */
  227. void splitlong(bytes, bigword)
  228. BYTE bytes[];
  229. long bigword;
  230. {
  231.    int i;
  232.    for (i = 0; i < 4; i++) {
  233.       bytes[i] = bigword & 0xff;
  234.       bigword = (unsigned long) bigword >> 8;
  235.    }
  236. }     
  237. #endif /* FIZ */
  238.  
  239. /*******************
  240. splitint() converts an integer to two consecutive BYTEs in order
  241. of increasing significance.
  242. */
  243. void splitint(bytes, word)
  244. BYTE bytes[];
  245. int word;
  246. {
  247.    bytes[0] = word & 0xff;
  248.    word = (unsigned int) word >> 8;
  249.    bytes[1] = word & 0xff;
  250. }
  251.  
  252. /**********************
  253. to_int() converts two consecutive bytes, in order of increasing
  254. significance, to an integer, in a machine-independent manner
  255. */
  256. int to_int(data)
  257. BYTE data[];
  258. {
  259.    return (int) ((unsigned int) data[0] | ((unsigned int) data[1] << 8));
  260. }
  261.  
  262. #else /* else of ifndef DIRECT_CONVERT */
  263.  
  264. long to_long(data)
  265. BYTE data[];
  266. {
  267.    return ( * (long *) data );
  268. }
  269.  
  270. #ifndef FIZ
  271. /********************
  272. splitlong() converts a long integer to four consecutive BYTEs in order
  273. of increasing significance.
  274. */
  275. void splitlong(bytes, bigword)
  276. BYTE bytes[];
  277. long bigword;
  278. {
  279.    * (long *) bytes = bigword;
  280. }
  281. #endif /* FIZ */
  282.  
  283. /*******************
  284. splitint() converts an integer to two consecutive BYTEs in order
  285. of increasing significance.
  286. */
  287. void splitint(bytes, word)
  288. BYTE bytes[];
  289. int word;
  290. {
  291.    * (int *) bytes = word;
  292. }
  293.  
  294. /**********************
  295. to_int() converts two consecutive bytes, in order of increasing
  296. significance, to an integer.
  297. */
  298. int to_int(data)
  299. BYTE data[];
  300. {
  301.    return (*(int *) data);
  302. }
  303.  
  304. #endif /* ifndef DIRECT_CONVERT .. else ... */
  305.  
  306. #ifndef FIZ
  307. /**********************
  308. Function frd_zooh() reads the header of a Zoo archive in a machine-
  309. independent manner, from a ZOOFILE.
  310. */
  311. int frd_zooh(zoo_header, zoo_file)
  312. struct zoo_header *zoo_header;
  313. ZOOFILE zoo_file;
  314. {
  315.    int status;
  316.    BYTE bytes[SIZ_ZOOH];         /* canonical header representation */
  317. #ifdef TRACE_IO
  318.    if (verbose) {
  319.       printf("At file position [%8lx] ", ftell(zoo_file));
  320.    }
  321. #endif
  322.    status = zooread (zoo_file, (char *) bytes, SIZ_ZOOH);
  323.    b_to_zooh (zoo_header, bytes);   /* convert array to structure */
  324. #ifdef TRACE_IO
  325.    if (verbose) {
  326.       printf("frd_zooh: reading\n");
  327.       show_h(zoo_header);
  328.    }
  329. #endif
  330.    if (status < MINZOOHSIZ)
  331.       return (-1);
  332.    else
  333.       return (0);
  334. }
  335. #endif /* FIZ */
  336.  
  337. /**********************
  338. Function frd_dir() reads a directory entry in a machine-independent manner,
  339. from a ZOOFILE.
  340. */
  341. int frd_dir(direntry, zoo_file) 
  342. struct direntry *direntry; 
  343. ZOOFILE zoo_file;
  344. {
  345.    int status;
  346.    BYTE bytes[MAXDIRSIZE];    /* big enough to hold variable part too */
  347.  
  348.    /* To simplify things, we read the maximum possible size of the
  349.    directory entry including the variable size and discard what is not
  350.    needed */
  351. #ifdef TRACE_IO
  352.    if (verbose) {
  353.       printf("At file position [%8lx] ", ftell(zoo_file));
  354.    }
  355. #endif
  356.    status = zooread (zoo_file, (char *) bytes, MAXDIRSIZE);
  357.    if (status < SIZ_DIR)
  358.       return (-1);
  359.    b_to_dir (direntry, bytes);
  360. #ifdef TRACE_IO
  361.    if (verbose) {
  362.       printf("frd_dir: reading\n");
  363.       show_dir(direntry);
  364.    }
  365. #endif
  366.    return (0);
  367. }
  368.  
  369. #ifndef FIZ
  370. /***********************
  371. Function fwr_dir() writes a directory entry in a machine-independent manner
  372. to a ZOOFILE.  Return value is -1 on error, else 0.
  373. */
  374. int fwr_dir(direntry, zoo_file)
  375. struct direntry *direntry;
  376. ZOOFILE zoo_file;
  377. {
  378.    int size;
  379.    BYTE bytes[MAXDIRSIZE];
  380.    assert (direntry->type <= 2);
  381.    size = dir_to_b (bytes, direntry);
  382. #ifdef TRACE_IO
  383.    if (verbose) {
  384.       printf("At file position [%8lx] ", ftell(zoo_file));
  385.       printf("fwr_dir: writing\n");
  386.       show_dir(direntry);
  387.    }
  388. #endif
  389.  
  390.    if (zoowrite (zoo_file, (char *) bytes, size) != size)
  391.       return (-1);
  392.    else
  393.       return (0);
  394. }
  395.  
  396. /***********************
  397. Function fwr_zooh() writes an archive header in a machine-independent manner
  398. to a ZOOFILE.  Return value is -1 if error else 0.
  399. */
  400. int fwr_zooh(zoo_header, zoo_file)
  401. struct zoo_header *zoo_header;
  402. ZOOFILE zoo_file;
  403. {
  404.    BYTE bytes[SIZ_ZOOH];    /* was SIZ_DIR -- probably a typo */
  405.     int hsize;                    /* how much to write -- depends on header type */
  406.     hsize = MINZOOHSIZ;                /* in case it's an old type 0 header */
  407.     if (zoo_header->type > 0)        /* but if it's a newer header... */
  408.         hsize = SIZ_ZOOH;                /* ...size of new type 1 header */
  409.    zooh_to_b (bytes, zoo_header);
  410.    if (zoowrite (zoo_file, (char *) bytes, hsize) != hsize)
  411.       return (-1);
  412.    else
  413.       return (0);
  414. }
  415.  
  416. /***********************
  417. b_to_zooh() converts an array of BYTE to a zoo_header structure.
  418. */
  419. void b_to_zooh (zoo_header, bytes)
  420. struct zoo_header *zoo_header;
  421. BYTE bytes[];
  422. {
  423.    int i;
  424.    for (i = 0; i < SIZ_TEXT; i++)                     /* copy text */
  425.       zoo_header->text[i] = bytes[TEXT_I + i];
  426.    zoo_header->zoo_tag = to_long(&bytes[ZTAG_I]);     /* copy zoo_tag */
  427.    zoo_header->zoo_start = to_long(&bytes[ZST_I]);    /* copy zoo_start */
  428.    zoo_header->zoo_minus = to_long(&bytes[ZSTM_I]);
  429.    zoo_header->major_ver = bytes[MAJV_I];          /* copy versions */
  430.    zoo_header->minor_ver = bytes[MINV_I];
  431.     /* default is no archive comment and a header type of 0 */
  432.     zoo_header->type = 0;
  433.     zoo_header->acmt_pos = 0L;
  434.     zoo_header->acmt_len = 0;
  435.     zoo_header->vdata        = 0;
  436.     if (zoo_header->zoo_start != FIXED_OFFSET) {            /* if newer header */
  437.         zoo_header->type = bytes[HTYPE_I];
  438.         zoo_header->acmt_pos = to_long(&bytes[ACMTPOS_I]);
  439.         zoo_header->acmt_len = to_int(&bytes[ACMTLEN_I]);
  440.         zoo_header->vdata        = bytes[HVDATA_I];
  441.     }
  442. }
  443.  
  444. /***********************
  445. zooh_to_b() converts a zoo_header structure to an array of BYTE.
  446. */
  447. void zooh_to_b (bytes, zoo_header)
  448. struct zoo_header *zoo_header;
  449. BYTE bytes[];
  450. {
  451.    int i;
  452.    for (i = 0; i < SIZ_TEXT; i++)                     /* copy text */
  453.       bytes[TEXT_I + i] = zoo_header->text[i];
  454.    splitlong (&bytes[ZTAG_I], zoo_header->zoo_tag);
  455.    splitlong (&bytes[ZST_I], zoo_header->zoo_start);
  456.    splitlong (&bytes[ZSTM_I], zoo_header->zoo_minus);
  457.    bytes[MAJV_I] =   zoo_header->major_ver;           /* copy versions */ 
  458.    bytes[MINV_I] =   zoo_header->minor_ver;
  459.     bytes[HTYPE_I] =    zoo_header->type;                        /* header type */
  460.     if (zoo_header->type > 0) {
  461.         splitlong (&bytes[ACMTPOS_I], zoo_header->acmt_pos);    /* comment posn */
  462.         splitint (&bytes[ACMTLEN_I], zoo_header->acmt_len);    /* comment len */
  463.         bytes[HVDATA_I] = zoo_header->vdata;                    /* version data */
  464.     }
  465. } /* zooh_to_b() */
  466.  
  467. /************************
  468. dir_to_b() converts a directory entry structure to an array of BYTE.
  469. */
  470. int dir_to_b (bytes, direntry)
  471. struct direntry *direntry;
  472. BYTE bytes[];
  473. {
  474.    int i;
  475.    int cursize;
  476.    int fixsize;
  477.     int totalsize;
  478.    splitlong(&bytes[DTAG_I], direntry->zoo_tag);
  479.    bytes[DTYP_I] = direntry->type ;
  480.    bytes[PKM_I] = direntry->packing_method ;
  481.    splitlong(&bytes[NXT_I], direntry->next);
  482.    splitlong(&bytes[OFS_I], direntry->offset);
  483.    splitint(&bytes[DAT_I], direntry->date);
  484.    splitint(&bytes[TIM_I], direntry->time);
  485.    splitint(&bytes[CRC_I], direntry->file_crc);
  486.    splitlong(&bytes[ORGS_I], direntry->org_size);
  487.    splitlong(&bytes[SIZNOW_I], direntry->size_now);
  488.    bytes[DMAJ_I] = direntry->major_ver;
  489.    bytes[DMIN_I] = direntry->minor_ver;
  490.    bytes[DEL_I] = direntry->deleted;
  491.    bytes[STRUC_I] = direntry->struc;
  492.    splitlong(&bytes[CMT_I], direntry->comment);
  493.    splitint(&bytes[CMTSIZ_I], direntry->cmt_size);
  494.    for (i = 0; i < FNM_SIZ; i++)
  495.       bytes[FNAME_I + i] = direntry->fname[i];
  496.    bytes[TZ_I] = NO_TZ;       /* assume unknown */
  497.    bytes[NAMLEN_I] = 0;
  498.    bytes[DIRLEN_I] = 0;
  499.  
  500.    cursize = SIZ_DIR;         /* to count size of directory */
  501.    fixsize = SIZ_DIR;         /* size of fixed part */
  502.    assert (direntry->type <= 2);
  503.    if (direntry->type == 2) { /* handle stuff relevant to type 2 */
  504.       cursize = SIZ_DIRL;
  505.       fixsize = SIZ_DIRL;
  506.       bytes[TZ_I] = direntry->tz;
  507.       assert(direntry->namlen < 256 && direntry->namlen >= 0);
  508.         cursize += 2;        /* space for namlen and dirlen */
  509.       if (direntry->namlen != 0) {
  510.          bytes[NAMLEN_I] = direntry->namlen;
  511.          for (i = 0; i < direntry->namlen; i++)
  512.             bytes[LFNAME_I+i] = direntry->lfname[i];
  513.          cursize += direntry->namlen;
  514.       }
  515.       assert(direntry->dirlen < 256 && direntry->dirlen >= 0);
  516.       if (direntry->dirlen != 0) {
  517.          bytes[DIRLEN_I] = direntry->dirlen;
  518.          for (i = 0; i < direntry->dirlen; i++)
  519.             bytes[cursize+i] = direntry->dirname[i];
  520.          cursize += direntry->dirlen;
  521.       }
  522.         /* Can't store system id if no namlen & dirlen...BUG!...now fixed.
  523.             Fortunately, system_id was always 0 so far so it probably
  524.             got interpreted as namlen=0 and dirlen=0 (2 bytes) */
  525.       splitint(&bytes[cursize], direntry->system_id);
  526.         cursize += 2;
  527.         bytes[cursize] = direntry->fattr & 0xff;                              /* byte 0 */
  528.         splitint(&bytes[cursize+1], (int) (direntry->fattr >> 8));  /* 1 & 2 */
  529.         cursize += 3;
  530.         bytes[cursize] = (direntry->vflag & 0xff);            /* version flag */
  531.         splitint(&bytes[cursize+1], direntry->version_no);    /* version number */
  532.         cursize += 3;
  533.    }
  534.  
  535.    splitint(&bytes[VARDIRLEN_I], direntry->var_dir_len);
  536.    assert(cursize == 
  537.             ((bytes[DIRLEN_I] > 0 || bytes[NAMLEN_I] > 0) ? 2 : 0) +
  538.             fixsize + bytes[DIRLEN_I] + bytes[NAMLEN_I]
  539.          );
  540.  
  541.     /* total size of dir entry is size of fixed part + size of var. part */
  542.     totalsize = fixsize + direntry->var_dir_len;
  543.  
  544.    /* Do CRC assuming CRC field is zero, and stuff CRC into field. */
  545.    splitint(&bytes[DCRC_I], 0);           /* fill with zeroes */
  546.    crccode = 0;
  547.    /* avoid mixing pointers to signed and unsigned char */
  548.    addbfcrc((char *) bytes, totalsize);         /* update CRC */
  549.    splitint(&bytes[DCRC_I], crccode);
  550.  
  551.    /* return total length of directory entry */
  552.    return (totalsize);
  553.  
  554. } /* dir_to_b() */
  555. #endif /* FIZ */
  556.  
  557. /* b_to_dir() converts bytes to directory entry structure.  The CRC of the
  558. directory bytes, if any, is checked and a zero or nonzero value is returned
  559. in direntry->dir_crc according as the check is good or bad */
  560.  
  561. void b_to_dir(direntry, bytes)
  562. struct direntry *direntry;
  563. BYTE bytes[];
  564. {
  565.    int i;
  566.     int sysid_offs;            /* temp variable */
  567.    unsigned int savecrc;
  568.    direntry->zoo_tag = to_long(&bytes[DTAG_I]);
  569.    direntry->type = bytes[DTYP_I];
  570.    direntry->packing_method = bytes[PKM_I];
  571.    direntry->next = to_long(&bytes[NXT_I]);
  572.    direntry->offset = to_long(&bytes[OFS_I]);
  573.    direntry->date = to_int(&bytes[DAT_I]);
  574.    direntry->time = to_int(&bytes[TIM_I]);
  575.    direntry->file_crc = to_int(&bytes[CRC_I]);
  576.    direntry->org_size = to_long(&bytes[ORGS_I]);
  577.    direntry->size_now = to_long(&bytes[SIZNOW_I]);
  578.    direntry->major_ver = bytes[DMAJ_I];
  579.    direntry->minor_ver = bytes[DMIN_I];
  580.    direntry->deleted = bytes[DEL_I];
  581.    direntry->struc = bytes[STRUC_I];
  582.    direntry->comment = to_long(&bytes[CMT_I]);
  583.    direntry->cmt_size = to_int(&bytes[CMTSIZ_I]);
  584.     /* for now, versions not implemented */
  585.     direntry->vflag = 0;
  586.     direntry->version_no = 0;
  587.    for (i = 0; i < FNM_SIZ; i++)
  588.       direntry->fname[i] = bytes[FNAME_I + i];
  589.  
  590.    /* start by assuming variable part is zero bytes */
  591.    direntry->var_dir_len = direntry->dir_crc    = 0;
  592.    direntry->namlen      = direntry->dirlen     = 0;
  593.    direntry->lfname[0]   = direntry->dirname[0] = '\0';
  594.    direntry->tz = NO_TZ;               /* assume unknown */
  595.    direntry->system_id = SYSID_NIX;    /* default system_id if not present */
  596.     direntry->fattr = NO_FATTR;            /* assume none */
  597.  
  598.    assert (direntry->type <= 2);
  599.    if (direntry->type == 2) {
  600.       direntry->var_dir_len = to_int(&bytes[VARDIRLEN_I]);
  601.       assert(direntry->var_dir_len <= MAXDIRSIZE);
  602.       if (direntry->var_dir_len > MAXDIRSIZE)
  603.          direntry->var_dir_len = MAXDIRSIZE;
  604.       direntry->tz = bytes[TZ_I];   
  605.       if (direntry->var_dir_len > 0)
  606.          direntry->namlen = bytes[NAMLEN_I];
  607.       if (direntry->var_dir_len > 1)
  608.          direntry->dirlen = bytes[DIRLEN_I];
  609.       for (i = 0; i < direntry->namlen; i++)
  610.          direntry->lfname[i] = bytes[LFNAME_I + i];
  611.       for (i = 0; i < direntry->dirlen; i++)
  612.          direntry->dirname[i] = bytes[DIRNAME_I + direntry->namlen + i];
  613.         sysid_offs = DIRNAME_I + direntry->namlen + i;    /* offset of system id */
  614.         if (direntry->var_dir_len > direntry->namlen + direntry->dirlen + 2) {
  615.             direntry->system_id = to_int(&bytes[sysid_offs]);
  616.         }
  617.         if (direntry->var_dir_len > direntry->namlen + direntry->dirlen + 4) {
  618.             direntry->fattr = ((unsigned long) bytes[sysid_offs + 2]) |
  619.                                     ((unsigned long) bytes[sysid_offs + 3] << 8) |
  620.                                     ((unsigned long) bytes[sysid_offs + 4] << 16);
  621.         }
  622.         if (direntry->var_dir_len > direntry->namlen + direntry->dirlen + 7) {
  623.             direntry->vflag = bytes[sysid_offs + 5];
  624.             direntry->version_no = to_int(&bytes[sysid_offs + 6]);
  625.         }
  626.       /* do CRC calculation */
  627.       savecrc = (unsigned int) to_int(&bytes[DCRC_I]);
  628.       crccode = 0;
  629.       splitint(&bytes[DCRC_I], 0);
  630.       addbfcrc((char *) bytes, SIZ_DIRL + direntry->var_dir_len);
  631.       direntry->dir_crc = crccode - savecrc;
  632.    }
  633. }
  634.  
  635. #ifdef FILTER
  636. #define TWOBYTES    2    /* better than literal 2;  figure out why */
  637.  
  638. /* rdint() reads two bytes from standard input in archive order */
  639. int rdint (val)
  640. unsigned int *val;
  641. {
  642.     BYTE bytes[TWOBYTES];
  643.     if (zooread (STDIN, bytes, TWOBYTES) == TWOBYTES) {
  644.         *val = to_int(bytes);
  645.         return (0);
  646.     } else
  647.         return (1);
  648. }
  649.  
  650. /* wrint() writes an unsigned int to standard output in archive order */
  651. int wrint (val)
  652. unsigned int val;
  653. {
  654.     BYTE bytes[TWOBYTES];
  655.     splitint (bytes, val);
  656.     if (zoowrite (STDOUT, bytes, TWOBYTES) == TWOBYTES)
  657.         return (0);
  658.     else
  659.         return (1);
  660. }
  661. #endif /* FILTER */
  662.  
  663. #ifdef TRACE_IO
  664. /* dump contents of archive header */
  665. void show_h (zoo_header)
  666. struct zoo_header *zoo_header;
  667. {
  668.    int i;
  669.    printf ("Header text:\n");
  670.    for (i = 0; i < SIZ_TEXT;  i++) {      /* ASSUMES ASCII TEXT */
  671.       int c;
  672.       c = zoo_header->text[i];
  673.       if (c >= ' ' && c < 0x7f)
  674.          putchar (c);
  675.       else {
  676.          putchar ('^');
  677.          putchar (i & 0x40);
  678.       }
  679.    }
  680.    putchar('\n');
  681.    printf ("zoo_tag = [%8lx] zoo_start = [%8lx] zoo_minus = [%8lx]\n",
  682.             zoo_header->zoo_tag, zoo_header->zoo_start, 
  683.             zoo_header->zoo_minus);
  684.    printf ("major_ver.minor_ver = [%d.%d]\n",
  685.             zoo_header->major_ver, zoo_header->minor_ver);
  686.     if (zoo_header->zoo_start != FIXED_OFFSET) {
  687.         printf ("type = [%d] ", zoo_header->type);
  688.         printf ("acmt_pos = [%8lx] acmt_len = [%4x] vdata = [%2x]",
  689.                     zoo_header->acmt_pos, zoo_header->acmt_len, zoo_header->vdata);
  690.         printf ("\n");
  691.     }
  692.    printf ("---------\n");
  693. }
  694.  
  695. /* dump contents of directory entry */
  696. void show_dir (direntry)
  697. struct direntry *direntry;
  698. {
  699.    printf ("Directory entry for file [%s][%s]:\n",
  700.             direntry->fname, direntry->lfname);
  701.    printf ("tag = [%8lx] type = [%d] PM = [%d] Next = [%8lx] Offset = [%8lx]\n",
  702.             direntry->zoo_tag, (int) direntry->type, 
  703.             (int) direntry->packing_method, direntry->next, 
  704.             direntry->offset);
  705.    printf ("Orig size = [%ld] Size now = [%ld] dmaj_v.dmin_v = [%d.%d]\n",
  706.          direntry->org_size, direntry->size_now,
  707.          (int) direntry->major_ver, (int) direntry->minor_ver);
  708.    printf ("Struc = [%d] DEL = [%d] comment_offset = [%8lx] cmt_size = [%d]\n",
  709.          (int) direntry->struc, (int) direntry->deleted, direntry->comment,
  710.          direntry->cmt_size);
  711.    printf ("var_dir_len = [%d] TZ = [%d] dir_crc = [%4x]\n",
  712.             direntry->var_dir_len, (int) direntry->tz, direntry->dir_crc);
  713.    printf ("system_id = [%d]  dirlen = [%d]  namlen = [%d] fattr=[%24lx]\n", 
  714.         direntry->system_id, direntry->dirlen, direntry->namlen, direntry->fattr);
  715.     printf ("vflag = [%4x] version_no = [%4x]\n",
  716.                 direntry->vflag, direntry->version_no);
  717.    if (direntry->dirlen > 0)
  718.       printf ("dirname = [%s]\n", direntry->dirname);
  719.    printf ("---------\n");
  720. }
  721. #endif   /* TRACE_IO */
  722.