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