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