home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / apple2 / 51 < prev    next >
Encoding:
Internet Message Format  |  1991-05-02  |  45.8 KB

  1. From: jac@yoko.rutgers.edu (Jonathan A. Chandross)
  2. Newsgroups: comp.sources.apple2
  3. Subject: v001SRC033:  Nulib - Archive Library Tools (Unix) 02/10
  4. Message-ID: <May.1.18.09.08.1991.23475@yoko.rutgers.edu>
  5. Date: 1 May 91 22:09:09 GMT
  6. Approved: jac@paul.rutgers.edu
  7.  
  8.  
  9. Submitted-by: Andy McFadden (fadden@cory.berkeley.edu)
  10. Posting-number: Volume 1, Source:33
  11. Archive-name: archive/unix/nulib/part02.10
  12. Architecture: UNIX
  13. Version-number: 3.03
  14.  
  15.  
  16. =nushk.c
  17. -/*
  18. - * nushk.c - P8 ShrinkIt compress/uncompress routines
  19. - *
  20. - * NuLib v3.0  February 1991  Freeware (distribute, don't sell)
  21. - * By Andy McFadden (fadden@cory.berkeley.edu)
  22. - */
  23. -#ifdef APW
  24. -segment "Compress"
  25. -#endif
  26. -
  27. -#include "nudefs.h"
  28. -#include <stdio.h>
  29. -#include <fcntl.h>
  30. -
  31. -#ifdef MSDOS     /* For file IO */
  32. -# include <io.h>
  33. -# include <sys/types.h>
  34. -# include <sys/stat.h>
  35. -# include <errno.h>
  36. -#endif
  37. -
  38. -#include "nuread.h"  /* need CalcCRC() */
  39. -#include "nupak.h"
  40. -#include "nuetc.h"
  41. -
  42. -#define BLKSIZ    4096
  43. -/*#define DEBUG     /* do verbose debugging output */
  44. -/*#define DEBUG1    /* debugging output in main routine */
  45. -
  46. -static onebyt *ibuf;    /* large buffer (usually set to packBuffer) */
  47. -onebyt lbuf[BLKSIZ+7];    /* temporary buffer for storing data after LZW */
  48. -onebyt rbuf[BLKSIZ+7];    /* temporary buffer for storing data after RLE */
  49. -
  50. -
  51. -/*
  52. - * P8 ShrinkIt compression routines
  53. - * Copyright 1989 Kent Dickey
  54. - *
  55. - * C translation by Kent Dickey / Andy McFadden
  56. - */
  57. -
  58. -#define ESCAPE_CHAR    0xdb
  59. -#define HSIZE 4219        /* Must be prime */
  60. -
  61. -struct ht {
  62. -    int entry;
  63. -    int prefix;
  64. -    unsigned char chr;
  65. -} htab[HSIZE];
  66. -
  67. -int s_at_bit;
  68. -int s_at_byte;
  69. -
  70. -int mask[] = {    0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f,
  71. -        0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff };
  72. -
  73. -int bit_tab[] = { 0,9,10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12 };
  74. -
  75. -
  76. -/*
  77. - * Output code to buffer.
  78. - */
  79. -int put_code(code, ent, bfr)
  80. -int code;
  81. -register int ent;
  82. -char *bfr;
  83. -{
  84. -    int lo_byte;
  85. -    long mycode;
  86. -    int bits;
  87. -
  88. -    bits = bit_tab[(ent >> 8)];
  89. -/*    if (((s_at_bit + bits + 7) / 8) + s_at_byte > BLKSIZ) {*/
  90. -    if (((s_at_bit + bits + 7) >> 3) + s_at_byte > BLKSIZ) {
  91. -        return(-1);
  92. -    }
  93. -    mycode = (long)(code & mask[bits]);
  94. -/*    fprintf(stderr,"Byte: %d, %lx\n", s_at_byte, mycode); */
  95. -    lo_byte = bfr[s_at_byte] & mask[s_at_bit];
  96. -    if (s_at_bit != 0) {
  97. -        mycode <<= s_at_bit;
  98. -    }
  99. -    bfr[s_at_byte++] = (unsigned char)lo_byte | (char)(mycode & 0xff);
  100. -    bfr[s_at_byte] = (unsigned char)((mycode >>= 8) & 0xff);
  101. -    if ((s_at_bit += bits) >= 16) {
  102. -        bfr[++s_at_byte] = (char)((mycode >>= 8) & 0xff);
  103. -    }
  104. -    s_at_bit &= 0x07;
  105. -
  106. -    return(0);
  107. -}
  108. -
  109. -
  110. -/*
  111. - * Try LZW compression on the buffer.
  112. - *
  113. - * Compresses from "buffer" to "outbuf".  "inlen" is the #of bytes of data in
  114. - * "buffer."  Returns the #of bytes of data placed into "outbuf", or -1 on
  115. - * failure.
  116. - */
  117. -int do_LZW(bufr, inlen, outbuf)
  118. -unsigned char *bufr;
  119. -int inlen;
  120. -unsigned char *outbuf;
  121. -{
  122. -    int ent, prefix;
  123. -    register int index;
  124. -    register unsigned char k;
  125. -    register unsigned char *inbuf, *endbuf;
  126. -
  127. -    s_at_byte = 0;
  128. -    s_at_bit =0;
  129. -    ent = 0x101;
  130. -    inbuf = bufr;
  131. -    endbuf = bufr + inlen;
  132. -
  133. -
  134. -    k = ((char)*inbuf++);
  135. -Loop0:
  136. -    prefix = (int)k;
  137. -Loop1:
  138. -    if (inbuf >= endbuf) {
  139. -        if (put_code(prefix, ent, outbuf) < 0) {
  140. -            return(BLKSIZ+2);
  141. -        }
  142. -        if (s_at_bit == 0) return(s_at_byte);
  143. -        else           return(s_at_byte+1);
  144. -    }
  145. -    k = (unsigned char)*inbuf++;
  146. -    index = (prefix + (k<<4)) & 0xfff;
  147. -
  148. -Check_ent:
  149. -    if (htab[index].entry == 0) {
  150. -        /* Entry is 0... */
  151. -        if (put_code(prefix, ent, outbuf) < 0) {
  152. -            return(-1);    /* failed */
  153. -        }
  154. -        htab[index].entry = ent++;
  155. -        htab[index].prefix = prefix;
  156. -        htab[index].chr = k;
  157. -        goto Loop0;
  158. -    }
  159. -    else if (htab[index].prefix == prefix) {
  160. -        /* Same prefix... */
  161. -        if (htab[index].chr == k) {
  162. -            /* It's HERE!  Yeah! */
  163. -            prefix = htab[index].entry;
  164. -            goto Loop1;
  165. -        }
  166. -        goto Sec_hash;
  167. -    }
  168. -        /* Check for more...secondary hash on index */
  169. -      else {
  170. -Sec_hash:
  171. -        index = (index + (unsigned int)(k) + 1) % HSIZE;
  172. -    /*    fprintf(stderr,"New ind: %d, k=%d\n", index, (unsigned int)k);  */
  173. -        goto Check_ent;
  174. -    }
  175. -}
  176. -
  177. -
  178. -/*
  179. - * Clear out the hash table.
  180. - */
  181. -void ClearTab()
  182. -{
  183. -    register int i;
  184. -
  185. -    for(i=0; i < HSIZE; i++) {
  186. -        htab[i].entry = 0;
  187. -    }
  188. -}
  189. -
  190. -
  191. -/*
  192. - * Do run-length encoding
  193. - *
  194. - * Takes input from srcptr, and writes to dstptr.  Maximum expansion is
  195. - * (BLKSIZ / 2) + (BLKSIZ / 2) * 3 == 2 * BLKSIZ
  196. - * Output of form  <DLE> char count
  197. - *
  198. - * This really isn't very pretty, but it works.
  199. - */
  200. -int do_RLE(srcptr, dstptr)
  201. -register onebyt *srcptr, *dstptr;
  202. -{
  203. -    int found, scount, dcount;
  204. -    register onebyt c, lastc, tlastc;
  205. -
  206. -    c = *(srcptr++);  scount = 1;
  207. -    dcount = 0;
  208. -    found = 1;  /* one char has been found */
  209. -    lastc = '\0';
  210. -    while (scount < BLKSIZ) {
  211. -    tlastc = lastc;
  212. -    lastc = c;
  213. -    c = *(srcptr++);  scount++;
  214. -
  215. -    if (found == 1) {  /* no run found */
  216. -        if (c != lastc) {  /* no run starting */
  217. -        if (lastc == ESCAPE_CHAR) {
  218. -            *(dstptr++) = ESCAPE_CHAR;  dcount++;
  219. -            *(dstptr++) = lastc;  dcount++;
  220. -            *(dstptr++) = 0;  dcount++;  /* found one */
  221. -        } else {
  222. -            *(dstptr++) = lastc;  dcount++;
  223. -        }
  224. -        found = 1;
  225. -        } else {
  226. -        found = 2;  /* they matched, so two in a row */
  227. -        }
  228. -
  229. -    } else if (found == 2) {  /* got two, try for three */
  230. -        if (c != lastc) {  /* only got two in a row */
  231. -        if (lastc == ESCAPE_CHAR) {  /* and tlastc as well */
  232. -            *(dstptr++) = ESCAPE_CHAR;  dcount++;
  233. -            *(dstptr++) = lastc;  dcount++;
  234. -            *(dstptr++) = 1;  dcount++;  /* found two */
  235. -        } else {
  236. -            *(dstptr++) = tlastc;  dcount++;
  237. -            *(dstptr++) = lastc;  dcount++;
  238. -        }
  239. -        found = 1;
  240. -        } else {  /* found 3, got a run going */
  241. -        found = 3;
  242. -        }
  243. -
  244. -    } else {  /* (found >= 3), got a run going */
  245. -        if (c == lastc) {  /* found another */
  246. -        found++;
  247. -        }
  248. -        if ((c != lastc) || (found > 256)) {  /* end, or too many */
  249. -        *(dstptr++) = ESCAPE_CHAR;  dcount++;
  250. -        *(dstptr++) = lastc;  dcount++;
  251. -        *(dstptr++) = (found > 256) ? 255 : found-1;
  252. -        dcount++;
  253. -        found = 1;  /* c has something other than the run char    */
  254. -                /* or found is 257-256 = 1             */
  255. -        }
  256. -    }
  257. -    }  /* while */
  258. -
  259. -    /* reached end of buffer; flush what was left */
  260. -    if (found == 1) {
  261. -    if (c == ESCAPE_CHAR) {
  262. -        *(dstptr++) = ESCAPE_CHAR;  dcount++;
  263. -        *(dstptr++) = c;  dcount++;
  264. -        *(dstptr++) = 0;  dcount++;
  265. -    } else {
  266. -        *(dstptr++) = c;  dcount++;
  267. -    }
  268. -
  269. -    } else if (found == 2) {
  270. -    /* maybe have if lastc == c == ESCAPE_CHAR? */
  271. -    if (lastc == ESCAPE_CHAR) {
  272. -        *(dstptr++) = ESCAPE_CHAR;  dcount++;
  273. -        *(dstptr++) = lastc;  dcount++;
  274. -        *(dstptr++) = 0;  dcount++;
  275. -    } else {
  276. -        *(dstptr++) = lastc;  dcount++;
  277. -    }
  278. -    if (c == ESCAPE_CHAR) {
  279. -        *(dstptr++) = ESCAPE_CHAR;  dcount++;
  280. -        *(dstptr++) = c;  dcount++;
  281. -        *(dstptr++) = 0;  dcount++;
  282. -    } else {
  283. -        *(dstptr++) = c;  dcount++;
  284. -    }
  285. -
  286. -    } else {  /* found >= 3, in the middle of processing a run */
  287. -    *(dstptr++) = ESCAPE_CHAR;  dcount++;
  288. -    *(dstptr++) = c;  dcount++;
  289. -    *(dstptr++) = found-1;  dcount++;
  290. -    }
  291. -
  292. -    return (dcount);
  293. -}
  294. -
  295. -
  296. -/*
  297. - * Main compression entry point.
  298. - *
  299. - * Returns actual thread_format used.
  300. - *
  301. - * Note that "copybuf" should be at least twice as big as BLKSIZ.
  302. - */
  303. -long pak_SHK(srcfd, dstfd, length, copybuf)
  304. -int srcfd, dstfd;
  305. -long length;        /* uncompressed size */
  306. -onebyt *copybuf;
  307. -{
  308. -    unsigned int partial;   /* size for partial read/write */
  309. -    onebyt *rptr, *out_buf;
  310. -    register int idx;
  311. -    onebyt scratch[8];
  312. -    long srcposn,    /* start in source file */
  313. -     startposn,    /* start in dest file */
  314. -     endposn;    /* end in dest file */
  315. -    long unc_len = length,
  316. -     comp_len = 0L;
  317. -    twobyt CRC;
  318. -    int rlesize, lzwsize, out_size;    /* length after compression */
  319. -    int sc;  /* spin counter */
  320. -    static char *procName = "pak_SHK";
  321. -
  322. -    CRC = 0;
  323. -    if ((srcposn = lseek(srcfd, 0L, S_REL)) < 0)    /* only used if */
  324. -    Fatal("Bad seek (srcposn)", procName);        /* compress fails */
  325. -    if ((startposn = lseek(dstfd, 0L, S_REL)) < 0)
  326. -    Fatal("Bad seek (startposn)", procName);
  327. -    lseek(dstfd, 4L, S_REL);  /* leave room for 4-byte header */
  328. -    comp_len += 4L;
  329. -
  330. -    sc = 0;
  331. -    do {  /* have to handle when length == 0L */
  332. -    if (length > (long) BLKSIZ) {
  333. -        partial = (unsigned int) BLKSIZ;
  334. -        length -= (long) BLKSIZ;
  335. -    } else {
  336. -        partial = (unsigned int) length;
  337. -        length = 0L;
  338. -        for (idx = partial; idx < BLKSIZ; idx++)  /* fill in zeroes */
  339. -        *(copybuf + idx) = 0;
  340. -    }
  341. -
  342. -    if (partial > 0) {  /* should work anyway, but let's be careful */
  343. -        if (read(srcfd, copybuf, partial) != partial)
  344. -        Fatal("Source read failed", procName);
  345. -    }
  346. -    /* calc CRC on all 4096 bytes */
  347. -    CRC = CalcCRC(CRC, (onebyt *) copybuf, BLKSIZ); 
  348. -    rlesize = do_RLE(copybuf, copybuf + BLKSIZ+1);  /* pack 4096 bytes */
  349. -    if (rlesize < 0x1000) {  /* did it pack or expand? */
  350. -        rptr = copybuf + BLKSIZ+1;  /* use packed version */
  351. -    } else {
  352. -        rlesize = 0x1000;  /* just store original */
  353. -        rptr = copybuf;
  354. -    }
  355. -    ClearTab();
  356. -    lzwsize = do_LZW(rptr, rlesize, lbuf);    /* compress from rle to lzw */
  357. -    if ((lzwsize > rlesize) || (lzwsize < 0)) {
  358. -        /* lzw failed, use rle'd copy */
  359. -        scratch[2] = 0;
  360. -        out_size = rlesize;
  361. -        out_buf = rptr;
  362. -    } else {
  363. -        /* lzw succeeded, use it */
  364. -        scratch[2] = 1;        /* LZW on */
  365. -        out_size = lzwsize;
  366. -        out_buf = lbuf;
  367. -    }
  368. -    scratch[0] = (onebyt) (rlesize & 0x00ff);    /* NOT out_size */
  369. -    scratch[1] = (onebyt) ((rlesize >> 8) & 0x00ff);
  370. -    if (write(dstfd, scratch, 3) != 3)
  371. -        Fatal("Dest hdr write failed", procName);
  372. -    comp_len += 3;
  373. -    comp_len += out_size;
  374. -    if (comp_len > unc_len)
  375. -        goto bad_compress;        /* you didn't see this */
  376. -    if (write(dstfd, out_buf, out_size) != out_size)  /* need to do CRLF */
  377. -        Fatal("Dest write failed", procName);
  378. -
  379. -    sc++;
  380. -    if (sc == 15) {
  381. -        sc = 0;
  382. -        Spin();
  383. -    }
  384. -    } while (length != 0L);
  385. -
  386. -    if ((endposn = lseek(dstfd, 0L, S_REL)) < 0)
  387. -    Fatal("Bad seek (now)", procName);
  388. -    if (lseek(dstfd, startposn, S_ABS) < 0)
  389. -    Fatal("Bad seek (to4)", procName);
  390. -    scratch[0] = (char) CRC;
  391. -    scratch[1] = (char) (CRC >> 8);
  392. -    scratch[2] = 0;
  393. -    scratch[3] = ESCAPE_CHAR;
  394. -    if (write(dstfd, scratch, 4) != 4)
  395. -    Fatal("Dest hdr write failed", procName);
  396. -    if (lseek(dstfd, endposn, S_ABS) < 0)
  397. -    Fatal("Bad seek (last)", procName);
  398. -
  399. -    if (comp_len != endposn - startposn) {
  400. -    printf(
  401. -        "internal error: comp_len=%ld, endposn=%ld, startposn=%ld (%ld)\n",
  402. -        comp_len, endposn, startposn, endposn - startposn);
  403. -    }
  404. -    packedSize = comp_len;
  405. -    return (0x0002);    /* SHK packing */
  406. -
  407. -bad_compress:    /* I'm too lazy to do a procedure call... */
  408. -
  409. -    if (verbose) { printf("storing...");  fflush(stdout); }
  410. -    if (lseek(srcfd, srcposn, S_ABS) < 0)
  411. -    Fatal("Bad seek (srcposn in bad_compress)", procName);
  412. -    if (lseek(dstfd, startposn, S_ABS) < 0)
  413. -    Fatal("Bad seek (startposn in bad_compress)", procName);
  414. -    FCopy(srcfd, dstfd, unc_len, copybuf, FALSE);
  415. -    packedSize = unc_len;
  416. -    return (0x0000);    /* no compression */
  417. -}
  418. -
  419. -
  420. -/*
  421. - * P8 ShrinkIt uncompression routines
  422. - *
  423. - * Copyright 1989 Kent Dickey
  424. - * C translation by Kent Dickey / Andy McFadden
  425. - * Modifications for LZW-II by Andy Nicholas
  426. - */
  427. -
  428. -static int inf;  /* to make Getc() calls happy */
  429. -static BOOLEAN type2;    /* true if working with LZW-II format */
  430. -
  431. -static onebyt escape_char;
  432. -
  433. -typedef struct {
  434. -    unsigned char chr;
  435. -    int prefix;
  436. -} Table_ent;
  437. -
  438. -static Table_ent Real_tab[BLKSIZ-256];  /* first 256 don't exist */
  439. -static Table_ent *Table;
  440. -
  441. -static int Mask_tab[16] = {
  442. -    0x0000, 0x01ff, 0x03ff, 0x03ff, 0x07ff,
  443. -    0x07ff, 0x07ff, 0x07ff, 0x0fff, 0x0fff,
  444. -    0x0fff, 0x0fff, 0x0fff, 0x0fff, 0x0fff,
  445. -    0x0fff
  446. -};
  447. -static int Number[16] = {
  448. -    0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 };
  449. -
  450. -static onebyt Stack[100];  /* simulated stack; should be <= 64 */
  451. -static int out_bytes, stack_ptr, entry, at_bit, at_byte;
  452. -static onebyt last_byte;  /* used in get_code */
  453. -
  454. -
  455. -/* fake Getc(); easier to make this a macro than to change the code */
  456. -#ifdef DEBUG
  457. -onebyt Getc(foo)
  458. -int foo;  /* this is ignored */
  459. -{
  460. -    return (*(ibuf++));
  461. -}
  462. -#else  /* if not debugging, use a macro */
  463. -# define Getc(foo) *(ibuf++)
  464. -#endif /* DEBUG */
  465. -
  466. -
  467. -/*
  468. - * Stack operations; used by undo_LZW
  469. - */
  470. -#ifdef DEBUG
  471. -void push(a_byte)
  472. -unsigned char a_byte;
  473. -{
  474. -    if (stack_ptr > 100) {
  475. -    printf("\n*** stack_ptr exceeded 100 in push() [%d]\n", stack_ptr);
  476. -    exit (-1);
  477. -    }
  478. -    Stack[stack_ptr++] = a_byte;
  479. -}
  480. -#else  /* if not debugging, use a macro */
  481. -# define push(a_byte) Stack[stack_ptr++] = a_byte
  482. -#endif /* DEBUG */
  483. -
  484. -
  485. -#ifdef DEBUG
  486. -void dump_stack(buffer)
  487. -unsigned char *buffer;
  488. -{
  489. -    printf("--- Going to dump stack, stack_ptr = %d, out_bytes = %d\n",
  490. -    stack_ptr, out_bytes);
  491. -    while (stack_ptr > 0) {
  492. -    *(buffer + out_bytes++) = Stack[--stack_ptr];
  493. -    }
  494. -}
  495. -#else  /* if not debugging, use a macro */
  496. -# define dump_stack(buffer) while (stack_ptr > 0) { \
  497. -                *( buffer +out_bytes++) = Stack[--stack_ptr];\
  498. -                }
  499. -#endif /* DEBUG */
  500. -
  501. -
  502. -/*
  503. - * Decipher LZW codes.
  504. - */
  505. -static int get_code(/*Buffer*/)
  506. -/*unsigned char *Buffer;*/
  507. -{
  508. -    register int num_bits, old_bit, last_bit;
  509. -    long value, mask;
  510. -    unsigned char byte1, byte2, byte3;  /* get compressed chars... */
  511. -
  512. -#ifdef DEBUG
  513. -    printf("ENT: bit=%d byte=%-4d last_byte=$%.2x ",
  514. -    at_bit, at_byte, last_byte);
  515. -    printf("Entry: %.4x \n", entry);
  516. -#endif
  517. -
  518. -    num_bits = ((entry+1) >> 8);  /* get hi-byte of entry */
  519. -    last_bit = at_bit + Number[num_bits] + 8;
  520. -    old_bit = at_bit;
  521. -#ifdef DEBUG
  522. -    if (at_byte >= BLKSIZ) {
  523. -    fprintf(stderr, "at_byte exceeded BLKSIZ (4096) in get_code()\n");
  524. -    exit (-1);
  525. -    }
  526. -#endif
  527. -    if (at_bit == 0)
  528. -    last_byte = Getc(inf);
  529. -    byte1 = last_byte;  /* first byte = last one used */
  530. -    byte2 = Getc(inf);
  531. -    if (last_bit > 16) {  /* get 3rd byte if nec. */
  532. -    byte3 = Getc(inf);
  533. -    last_byte = byte3;
  534. -    } else {
  535. -    byte3 = 0;
  536. -    last_byte = byte2;
  537. -    }
  538. -    value = ((((long)byte3 << 8) + (long)byte2) << 8) + (long)byte1;
  539. -/*    value = (((Buffer[at_byte+2] << 8) + Buffer[at_byte+1]) << 8) +    */
  540. -/*    Buffer[at_byte];                        */
  541. -
  542. -    mask = (long) Mask_tab[num_bits];
  543. -    at_byte += (last_bit >> 3);  /* new byte */
  544. -    at_bit = (last_bit & 0x07);
  545. -
  546. -#ifdef DEBUG
  547. -    printf("| EX: value=$%.6x mask=$%.4x return=$%.3x\n",
  548. -    value, mask, ((value >> old_bit) & mask));
  549. -#endif
  550. -    if (old_bit)
  551. -    return ((value >> old_bit) & mask);
  552. -    else
  553. -    return (value & mask);  /* shifting by zero may be undefined */
  554. -}
  555. -
  556. -
  557. -/*
  558. - * Un-LZW a range of bytes
  559. - *
  560. - * Reads data with get_code (eventually from packBuffer) and stores the
  561. - * output in "buffer".
  562. - */
  563. -static void undo_LZW(buffer, length)
  564. -unsigned char *buffer;  /* where to put output */
  565. -int length;  /* uncompressed length of output */
  566. -{
  567. -    register int oldc, incode, finalc, ptr;
  568. -
  569. -    /* initialize variables */
  570. -    Table = Real_tab-256;
  571. -    entry = 0x101;  /* start at $101 */
  572. -    at_bit = at_byte = 0;
  573. -    out_bytes = 0;
  574. -    stack_ptr = 0;
  575. -
  576. -    last_byte = 0;  /* init last_byte */
  577. -    oldc = incode = get_code(/*buffer*/);
  578. -    finalc = (oldc & 0xff);
  579. -    *(buffer + out_bytes++) = (unsigned char) incode;
  580. -
  581. -    /* main loop */
  582. -    while (out_bytes < length) {
  583. -    incode = ptr = get_code(/*buffer*/);
  584. -    if (ptr >= entry) {
  585. -        push(finalc);
  586. -        ptr = oldc;
  587. -    }
  588. -    while (ptr > 0xff) {
  589. -        push(Table[ptr].chr);
  590. -        ptr = Table[ptr].prefix;
  591. -    }
  592. -
  593. -    /* ptr is now < 0x100 */
  594. -    finalc = ptr;
  595. -    push(finalc);
  596. -    dump_stack(buffer);
  597. -    Table[entry].chr = (finalc & 0xff);  /* mask to get unsigned?? byte */
  598. -    Table[entry].prefix = oldc;
  599. -    entry++;
  600. -    oldc = incode;
  601. -    }
  602. -}
  603. -
  604. -
  605. -/*
  606. - * Un-LZW-II a range of bytes (someday!)
  607. - *
  608. - * Reads data with get_code (eventually from packBuffer) and stores the
  609. - * output in "buffer".  Has additional code to support LZW-II's table
  610. - * clears.
  611. - */
  612. -static void undo_LZW_2(buffer, length)
  613. -unsigned char *buffer;  /* where to put output */
  614. -int length;  /* uncompressed length of output */
  615. -{
  616. -    register int oldc, incode, finalc, ptr;
  617. -
  618. -    /* initialize variables */
  619. -    Table = Real_tab-256;
  620. -    entry = 0x101;  /* start at $101 */
  621. -    at_bit = at_byte = 0;
  622. -    out_bytes = 0;
  623. -    stack_ptr = 0;
  624. -
  625. -    last_byte = 0;  /* init last_byte */
  626. -    oldc = incode = get_code(/*buffer*/);
  627. -    finalc = (oldc & 0xff);
  628. -    *(buffer + out_bytes++) = (unsigned char) incode;
  629. -
  630. -    /* main loop */
  631. -    while (out_bytes < length) {
  632. -    incode = ptr = get_code(/*buffer*/);
  633. -    if (ptr >= entry) {
  634. -        push(finalc);
  635. -        ptr = oldc;
  636. -    }
  637. -    while (ptr > 0xff) {
  638. -        push(Table[ptr].chr);
  639. -        ptr = Table[ptr].prefix;
  640. -    }
  641. -
  642. -    /* ptr is now < 0x100 */
  643. -    finalc = ptr;
  644. -    push(finalc);
  645. -    dump_stack(buffer);
  646. -    Table[entry].chr = (finalc & 0xff);  /* mask to get unsigned?? byte */
  647. -    Table[entry].prefix = oldc;
  648. -    entry++;
  649. -    oldc = incode;
  650. -    }
  651. -}
  652. -
  653. -
  654. -/*
  655. - * Second pass... undo the Run Length Encoding.
  656. - *
  657. - * Copy data from inbuffer to outbuffer.  Keep going until we've got
  658. - * exactly BLKSIZ bytes.  Note that this uses codes of the form
  659. - *   <DLE> char count
  660. - * which is different from some other programs.
  661. - */
  662. -static void undo_RLE(inbuffer, outbuffer)
  663. -unsigned char *inbuffer, *outbuffer;
  664. -/*int length;  /* how many bytes from LZW; just to make sure... */
  665. -{
  666. -    register unsigned char c;
  667. -    register int total, count;  /* count is RLE reps */
  668. -
  669. -#ifdef DEBUG
  670. -    /*printf("Starting undo_RLE, length = %d\n", length);*/
  671. -#endif
  672. -    total = 0;
  673. -    while (total < BLKSIZ) {
  674. -    c = *(inbuffer++);  /*length--;*/
  675. -    if (c == (onebyt) escape_char) {
  676. -        c = *(inbuffer++);  /*length--;*/
  677. -        count = *(inbuffer++);  /*length--;*/
  678. -        total += count +1;  /* count of zero -> 1 byte */
  679. -        while (count-- >= 0) {
  680. -        *(outbuffer++) = c;  /*Putc(c, outf);*/
  681. -        }
  682. -    } else {
  683. -        *(outbuffer++) = c;  /*Putc(c, outf);*/
  684. -        total++;
  685. -    }
  686. -    }
  687. -
  688. -    if (total != 4096)
  689. -    fprintf(stderr, "internal error: bad undo_RLE\n");
  690. -#ifdef DEBUG
  691. -/*    printf("Exiting undo_RLE, length = %d (should be 0), total = %d (4096)\n",
  692. -    length, total);*/
  693. -#endif
  694. -}
  695. -
  696. -
  697. -/*
  698. - * Main entry point.
  699. - *
  700. - * This is among the more hellish things I've written.  Uses
  701. - *   a large buffer for efficiency reasons, and unpacks a stream of bytes
  702. - *   (LZW-II improves things a little).
  703. - * If you find this hard to understand, imagine what it was like to debug.
  704. - *
  705. - * Could use some cleaning up, esp argument list...
  706. - */
  707. -void
  708. -unpak_SHK(srcfd,dstfd,comp_thread_eof,thread_eof,buffer, use_type2, thread_crc)
  709. -int srcfd, dstfd;
  710. -fourbyt comp_thread_eof, thread_eof;
  711. -register onebyt *buffer;
  712. -BOOLEAN use_type2;        /* true if we should expect LZW-II */
  713. -twobyt thread_crc;
  714. -{
  715. -    twobyt CRC, blkCRC;
  716. -    onebyt vol;
  717. -    onebyt *wrbuf;  /* points to buffer we're about to write */
  718. -    short unlen, lzwflag, rleflag, complen;    /* should be short */
  719. -    unsigned int partial, toread, still_in_buf;
  720. -    fourbyt tmp4;  /* temporary 4-byte variable */
  721. -    int cc;
  722. -    static char *procName = "unpak_SHK";
  723. -
  724. -    CRC = 0;
  725. -    type2 = use_type2;
  726. -
  727. -    /* read min(PAKBUFSIZ, comp_thread_eof) bytes into buffer */
  728. -    if (comp_thread_eof > (fourbyt) PAKBUFSIZ) {
  729. -    toread = (unsigned int) PAKBUFSIZ;
  730. -    comp_thread_eof -= (fourbyt) PAKBUFSIZ;
  731. -    } else {
  732. -    toread = (unsigned int) comp_thread_eof;  /* read it all... */
  733. -    comp_thread_eof = (fourbyt) 0;
  734. -    }
  735. -
  736. -    /* do initial read */
  737. -#ifdef DEBUG1
  738. -    printf("initial read = %u\n", toread);
  739. -#endif
  740. -    if ((cc = read(srcfd, buffer, toread)) < toread) {
  741. -#ifdef DEBUG1
  742. -    printf("Only read %d bytes\n", cc);
  743. -#endif
  744. -    Fatal("Bad read during uncompress", procName);
  745. -    }
  746. -    ibuf = buffer;  /* set input pointer to start of buffer */
  747. -
  748. -    /* get header data */
  749. -    if (type2) {
  750. -    blkCRC = thread_crc;
  751. -    } else {
  752. -    blkCRC = Getc(inf);
  753. -    blkCRC += (Getc(inf) << 8);
  754. -    }
  755. -    vol = (char) Getc(inf);  /* disk volume #; not used here */
  756. -    escape_char = (char) Getc(inf);  /* RLE delimiter */
  757. -
  758. -#ifdef DEBUG1
  759. -    printf("vol = %d, escape_char = %x\n", vol, escape_char);
  760. -#endif
  761. -
  762. -    /*
  763. -     * main loop
  764. -     */
  765. -    while (thread_eof != (fourbyt) 0) {
  766. -
  767. -    /* note "unlen" is un-LZWed length (i.e., after RLE) */
  768. -    if (type2) {
  769. -        unlen = Getc(inf);
  770. -        unlen += (Getc(inf) << 8);
  771. -        lzwflag = (unlen & 0x8000) ? 1 : 0;    /* flag is hi bit */
  772. -        unlen &= 0x1fff;            /* strip extra stuff */
  773. -        rleflag = (unlen != BLKSIZ);
  774. -        if (lzwflag) {    /* will the real length bytes please stand up*/
  775. -        complen = Getc(inf);
  776. -        complen += (Getc(inf) << 8);
  777. -        }
  778. -    } else {
  779. -        unlen = Getc(inf);
  780. -        unlen += (Getc(inf) << 8);
  781. -        lzwflag = Getc(inf);
  782. -        rleflag = (unlen != BLKSIZ);
  783. -    }
  784. -#ifdef DEBUG1
  785. -    printf("Length after RLE = %d ($%.4x)\n", unlen, unlen);
  786. -    printf("LZW flag = %d, RLE flag = %d\n", lzwflag, rleflag);
  787. -    if (lzwflag != 0 && lzwflag != 1) {  /* this is weird... */
  788. -        for (lzwflag = -6; lzwflag < 3; lzwflag++) {
  789. -        printf("foo %d: %.2x\n", lzwflag, *(ibuf+lzwflag));
  790. -        }
  791. -    }
  792. -    if (type2 && lzwflag) {
  793. -        printf("Length after RLE+LZW = %d ($%.4x)\n", complen, complen);
  794. -    }
  795. -#endif
  796. -
  797. -    /* If it looks like we're going to run out of room, shift & read
  798. -    /* Mostly a guess; LZW length is less than unlen...  This is
  799. -    /* complicated and very prone to errors.
  800. -    /* tmp4 is the number of bytes between the current ptr and the end;
  801. -    /* some (16-bit) compilers yack if it's all one statement.*/
  802. -    tmp4 = (fourbyt) buffer + (fourbyt) PAKBUFSIZ;
  803. -    tmp4 -= (fourbyt) ibuf;
  804. -    if (tmp4 < (unlen + 6)) {  /* 6 = 3/4 byte header + two just in case */
  805. -        still_in_buf = tmp4;
  806. -
  807. -#ifdef DEBUG1
  808. -        printf("--- unlen = %d, space left = %d bytes\n",
  809. -            unlen, still_in_buf);
  810. -#endif
  811. -        BCopy((onebyt *) ibuf, (onebyt *) buffer, still_in_buf, FALSE);
  812. -        if (comp_thread_eof != (fourbyt) 0) {  /* no read, just shift */
  813. -        if (comp_thread_eof > ((fourbyt) PAKBUFSIZ - still_in_buf)){
  814. -            toread = (unsigned int) PAKBUFSIZ - still_in_buf;
  815. -            comp_thread_eof -= (fourbyt) PAKBUFSIZ - still_in_buf;
  816. -        } else {
  817. -            toread = (unsigned int) comp_thread_eof;
  818. -            comp_thread_eof = (fourbyt) 0;
  819. -        }
  820. -#ifdef DEBUG1
  821. -        printf("--- reading another %u bytes\n", toread);
  822. -#endif
  823. -        if (read(srcfd, buffer+still_in_buf, toread) < toread)
  824. -            Fatal("Unable to read [middle]", procName);
  825. -        if (verbose) Spin();
  826. -        }
  827. -        ibuf = buffer;
  828. -    }
  829. -    
  830. -    /* how much of the buffered data do we really need? */
  831. -    if (thread_eof > (fourbyt) BLKSIZ) {
  832. -        partial = (unsigned int) BLKSIZ;
  833. -        thread_eof -= (fourbyt) BLKSIZ;
  834. -    } else {
  835. -        partial = (unsigned int) thread_eof;  /* last block of file */
  836. -        thread_eof = (fourbyt) 0;
  837. -    }
  838. -
  839. -    /*
  840. -     * undo_LZW reads from ibuf (using Getc()) and writes to lbuf
  841. -     * undo_LZW_2 does what undo_LZW does, but for LZW-II.
  842. -     * undo_RLE reads from where you tell it and writes to rbuf
  843. -     *
  844. -     * This is really insane...
  845. -     */
  846. -    if (lzwflag && rleflag) {
  847. -        if (type2)
  848. -        undo_LZW_2(lbuf, unlen);  /* from ibuf -> lbuf */
  849. -        else
  850. -        undo_LZW(lbuf, unlen);  /* from ibuf -> lbuf */
  851. -        undo_RLE(lbuf, rbuf);  /* from lbuf -> rbuf */
  852. -        wrbuf = rbuf;  /* write rbuf */
  853. -        CRC = CalcCRC(CRC, (onebyt *) rbuf, BLKSIZ);  /* always 4K bytes */
  854. -    } else if (lzwflag && !rleflag) {
  855. -        if (type2)
  856. -        undo_LZW_2(lbuf, unlen);  /* from ibuf -> lbuf */
  857. -        else
  858. -        undo_LZW(lbuf, unlen);  /* from ibuf -> lbuf */
  859. -        wrbuf = lbuf;  /* write lbuf */
  860. -        CRC = CalcCRC(CRC, (onebyt *) lbuf, BLKSIZ);
  861. -    } else if (!lzwflag && rleflag) {
  862. -        undo_RLE(ibuf, rbuf);  /* from ibuf -> rbuf */
  863. -        wrbuf = rbuf;  /* write rbuf */
  864. -        CRC = CalcCRC(CRC, (onebyt *) rbuf, BLKSIZ);
  865. -        ibuf += unlen;  /* have to skip over RLE-only data */
  866. -            /* normally ibuf is advanced by Getc() calls */
  867. -    } else {
  868. -        wrbuf = ibuf;  /* write ibuf */
  869. -        CRC = CalcCRC(CRC, (onebyt *) ibuf, BLKSIZ);
  870. -        ibuf += partial;  /* skip over uncompressed data */
  871. -            /* normally ibuf is advanced by Getc() calls */
  872. -    }
  873. -#ifdef DEBUG1
  874. -    printf("Writing %d bytes.\n", partial);
  875. -#endif
  876. -    if (crlf(dstfd, wrbuf, partial) < partial)  /* write wrbuf */
  877. -        Fatal("Bad write", procName);
  878. -    }
  879. -
  880. -    if (CRC != blkCRC) {
  881. -    fprintf(stderr, "WARNING: CRC does not match...");
  882. -    if (verbose) fprintf(stderr, "\n");
  883. -    else fprintf(stderr, "extract with V suboption to see filenames.\n");
  884. -    }
  885. -}
  886. -
  887. =nuadd.c
  888. -/*
  889. - * nuadd.c - operations which add to a NuFX archive
  890. - *
  891. - * NuLib v3.0  February 1991  Freeware (distribute, don't sell)
  892. - * By Andy McFadden (fadden@cory.berkeley.edu)
  893. - */
  894. -#ifdef APW
  895. -segment "NuMain"
  896. -#endif
  897. -
  898. -#include "nudefs.h"
  899. -#include <stdio.h>
  900. -#include <fcntl.h>
  901. -#include <errno.h>
  902. -#include <ctype.h>
  903. -#ifdef BSD43
  904. -# include <strings.h>
  905. -#else
  906. -# include <string.h>
  907. -#endif
  908. -
  909. -#ifdef UNIX
  910. -# include <sys/types.h>
  911. -# include <sys/stat.h>
  912. -# ifdef XENIX386
  913. -#  include <sys/ndir.h>        /* maybe <sys/ndir.h>, <dirent.h>, <dir.h>...*/
  914. -# else
  915. -#  include <sys/dir.h>
  916. -# endif
  917. -#endif
  918. -#ifdef APW
  919. -# include <types.h>
  920. -# include <prodos.h>
  921. -# include <shell.h>
  922. -# include <strings.h>
  923. -#endif
  924. -#ifdef MSDOS
  925. -# include <stdlib.h>
  926. -# include <errno.h>
  927. -# include <time.h>
  928. -# include <io.h>
  929. -# include <sys/types.h>
  930. -# include <sys/stat.h>
  931. -#endif
  932. -
  933. -#include "nuread.h"
  934. -#include "nuadd.h"
  935. -#include "nupak.h"
  936. -#include "nuetc.h"
  937. -
  938. -#ifdef DATAGENERAL                    /* BAK */
  939. -# ifdef AOSVS                        /* BAK */
  940. -#  define BROKEN_ON_MVs                /* MV/UX is NOT a full UNIX */
  941. -# endif                        /* implem. so we just skip */
  942. -#endif                        /* the 'UNIX' code on MVs */
  943. -
  944. -#define MAXGSPREFIX 64
  945. -
  946. -static BOOLEAN domove;    /* are we M)oving the files in? */
  947. -static BOOLEAN docreate;  /* using the 'C' option? */
  948. -
  949. -
  950. -/*
  951. - * Expand command args into filenames
  952. - * Stuff number of names into int; build File Information Array.
  953. - * (this routine is heavily implementation-specific, since no two systems
  954. - *  expand wildcards or deal with subdirectories in the same way).
  955. - *
  956. - * Recursively expands subdirectories, unless doSubdir is FALSE.
  957. - */
  958. -int EvalArgs(count, names, FIArray, first)
  959. -int count;    /* #of filenames */
  960. -char **names;    /* array of file names */
  961. -file_info *FIArray[];  /* array to fill with file info */
  962. -BOOLEAN first;    /* first time through? */
  963. -{
  964. -    static char *procName = "EvalArgs";
  965. -#ifdef UNIX
  966. -    /* UNIX shells (sh, csh) won't expand subdirectories, but they do
  967. -     * expand wildcards in arguments before we get them
  968. -     */
  969. -    static int idx;
  970. -    struct stat st;
  971. -    char *cp;  /* temp char pointer */
  972. -    /* dir stuff */
  973. -    int newcount;
  974. -    char **newnames;
  975. -#ifndef BROKEN_ON_MVs
  976. -    DIR *dirp;
  977. -#endif
  978. -    struct direct *dp;
  979. -    int nmlen;
  980. -
  981. -    if (first) idx = 0;
  982. -
  983. -    while (count--) {
  984. -    FIArray[idx] = (file_info *) Malloc(sizeof(file_info));
  985. -
  986. -    if (stat(*names, &st) < 0) {  /* get file info */
  987. -        if (errno == ENOENT) {
  988. -        fprintf(stderr, "%s: '%s' not found\n", prgName, *names);
  989. -        names++;
  990. -        continue;  /* with while */
  991. -        }
  992. -        Fatal("Bad stat()", procName);
  993. -    }
  994. -
  995. -    if ((st.st_mode & S_IFDIR) && doSubdir) {  /* is it a directory? */
  996. -# ifndef BROKEN_ON_MVs
  997. -        newnames = (char **) Malloc(MAXARGS * sizeof(char *));
  998. -        strcpy(tmpNameBuf, *names);  /* earlier dir stuff */
  999. -        strcat(tmpNameBuf, "/");
  1000. -        nmlen = strlen(tmpNameBuf);
  1001. -
  1002. -        if ((dirp = opendir(*names)) == NULL)
  1003. -        Fatal("Unable to open subdirectory", procName);
  1004. -        for (newcount=0, dp=readdir(dirp); dp != NULL; dp=readdir(dirp)) {
  1005. -        if ((!strcmp(dp->d_name, ".")) || (!strcmp(dp->d_name, "..")))
  1006. -            continue;  /* with for */
  1007. -        newnames[newcount] = (char *) Malloc(nmlen + dp->d_namlen +1);
  1008. -        strcpy(newnames[newcount], tmpNameBuf);
  1009. -        strcat(newnames[newcount], dp->d_name);  /* append the name */
  1010. -        newcount++;
  1011. -        }
  1012. -        closedir(dirp);
  1013. -
  1014. -        EvalArgs(newcount, newnames, FIArray, FALSE);  /* do subdir */
  1015. -
  1016. -        while (newcount-- > 0)  /* free up the space we allocated */
  1017. -        free(newnames[newcount]);
  1018. -        free(newnames);
  1019. -
  1020. -        names++;
  1021. -# else                                /* BAK */
  1022. -        printf("Help, I ran into a directory and can't handle it!\n");
  1023. -# endif                                /* BAK */
  1024. -    } else if ((st.st_mode & S_IFDIR) && !doSubdir) {
  1025. -        /* maybe print message? */
  1026. -        names++;
  1027. -        continue;    /* with while */
  1028. -    } else if (st.st_mode & S_IFREG) {
  1029. -        FIArray[idx]->eof = (long) st.st_size;
  1030. -
  1031. -        if (st.st_mode & S_IWRITE)  /* write permission enabled? */
  1032. -        FIArray[idx]->fAccess = (fourbyt) 0x00e3;    /* locked */
  1033. -        else
  1034. -        FIArray[idx]->fAccess = (fourbyt) 0x0021;    /* unlocked */
  1035. -
  1036. -        FIArray[idx]->fileType = defFileType;
  1037. -        FIArray[idx]->auxType = defAuxType;
  1038. -        FIArray[idx]->fileSysID = 0x0001;  /* ProDOS */
  1039. -        FIArray[idx]->fileSysInfo = 0x2f;  /* '/' */
  1040. -        ExpandTime(&st.st_mtime, &FIArray[idx]->create_dt);  /*use mod.. */
  1041. -        ExpandTime(&st.st_mtime, &FIArray[idx]->mod_dt); /*time for both */
  1042. -        FIArray[idx]->marked = FALSE;
  1043. -
  1044. -        FIArray[idx]->pathname = (char *) Malloc(strlen(*names)+1);
  1045. -        strcpy(FIArray[idx]->pathname, *names);
  1046. -        FIArray[idx]->store_name = (char *) Malloc(strlen(*names)+1);
  1047. -        cp = *names;
  1048. -        while (*cp == '/') cp++;  /* advance past leading '/' */
  1049. -        strcpy(FIArray[idx]->store_name, cp);  /* can't otherwise fix */
  1050. -
  1051. -        names++;
  1052. -        idx++;
  1053. -    } else {
  1054. -        printf("Unknown storage type for '%s'\n", *names);
  1055. -        names++;
  1056. -        continue;    /* with while */
  1057. -    }
  1058. -
  1059. -    }
  1060. -    return (idx);
  1061. -
  1062. -#else /* UNIX */
  1063. -# ifdef APW
  1064. -    static int idx;  /* will eventually hold the total #of filenames */
  1065. -    char *nextname = (char *) Malloc(MAXFILENAME);  /* for subdir expand */
  1066. -    char prefix[MAXGSPREFIX+1];  /* Max ProDOS prefix size; now 64 */
  1067. -    char *fnptr;
  1068. -    FileRec finfo_p;
  1069. -    PrefixRec prefix_p;
  1070. -    OpenRec open_p;
  1071. -    EOFRec eof_p;
  1072. -
  1073. -    if (first) idx = 0;
  1074. -
  1075. -    prefix_p.prefixNum = 0;  /* current dir */
  1076. -    prefix_p.prefix = prefix;  /* prefix buffer */
  1077. -    GET_PREFIX( &prefix_p );
  1078. -    ToolErrChk();
  1079. -    p2cstr(prefix);
  1080. -
  1081. -    while (count) {
  1082. -    strcpy(tmpNameBuf, *names);
  1083. -    c2pstr(tmpNameBuf);
  1084. -    INIT_WILDCARD(tmpNameBuf, 0);
  1085. -    ToolErrChk();
  1086. -
  1087. -    while (*NEXT_WILDCARD(tmpNameBuf)) {
  1088. -        if (idx >= MAXARGS) {
  1089. -        fprintf(stderr, "Too many files (%d, %d max)\n", idx, MAXARGS);
  1090. -        Quit (-1);
  1091. -        }
  1092. -
  1093. -        finfo_p.pathname = tmpNameBuf;
  1094. -        GET_FILE_INFO( &finfo_p );
  1095. -        ToolErrChk();
  1096. -
  1097. -        open_p.openPathname = tmpNameBuf;
  1098. -        OPEN( &open_p );
  1099. -        ToolErrChk();
  1100. -
  1101. -        eof_p.eofRefNum = open_p.openRefNum;
  1102. -        GET_EOF( &eof_p );
  1103. -        ToolErrChk();
  1104. -
  1105. -        CLOSE( &open_p );
  1106. -        ToolErrChk();
  1107. -
  1108. -        p2cstr(tmpNameBuf);  /* also does p2cstr(finfo_p.pathname) */
  1109. -        switch (finfo_p.storageType) {
  1110. -        case 0x00:    /* standard ProDOS storage types */
  1111. -        case 0x01:
  1112. -        case 0x02:
  1113. -        case 0x03:
  1114. -        FIArray[idx] = (file_info *) Malloc(sizeof(file_info));
  1115. -
  1116. -        FIArray[idx]->eof = eof_p.eofPosition;
  1117. -        FIArray[idx]->fAccess = finfo_p.fAccess;
  1118. -        FIArray[idx]->fileType = (fourbyt) finfo_p.fileType;
  1119. -        FIArray[idx]->auxType = (fourbyt) finfo_p.auxType;
  1120. -        FIArray[idx]->storageType = finfo_p.storageType;
  1121. -        FIArray[idx]->fileSysID = 0x0001;  /* ProDOS */
  1122. -        FIArray[idx]->fileSysInfo = 0x2f;  /* '/' */
  1123. -        ExpandTime(&finfo_p.createDate, &FIArray[idx]->create_dt);
  1124. -        ExpandTime(&finfo_p.modDate, &FIArray[idx]->mod_dt);
  1125. -        FIArray[idx]->marked = FALSE;
  1126. -
  1127. -        FIArray[idx]->pathname = (char *) Malloc(strlen(tmpNameBuf)+1);
  1128. -        strcpy(FIArray[idx]->pathname, tmpNameBuf);
  1129. -
  1130. -        /* are we adding from current directory? */
  1131. -        if (!strncmp(tmpNameBuf, prefix, strlen(prefix))) {
  1132. -            FIArray[idx]->store_name =                  /* yes */
  1133. -               (char *) Malloc(strlen(tmpNameBuf) - strlen(prefix) +1);
  1134. -          strcpy(FIArray[idx]->store_name, tmpNameBuf+ strlen(prefix));
  1135. -        } else {
  1136. -            fnptr = RINDEX(tmpNameBuf, '/') + 1;          /* no  */
  1137. -            FIArray[idx]->store_name = (char *)Malloc(strlen(fnptr)+1);
  1138. -            strcpy(FIArray[idx]->store_name, fnptr);
  1139. -        }
  1140. -        idx++;
  1141. -        break;
  1142. -
  1143. -        case 0x05:
  1144. -        printf("Can't handle Extended file '%s'\n", tmpNameBuf);
  1145. -        break;
  1146. -        case 0x0d:
  1147. -        if (doSubdir) {
  1148. -            strcpy(nextname, tmpNameBuf);  /* make new copy */
  1149. -            strcat(nextname, "/=");  /* APW-only wildcard */
  1150. -            EvalArgs(1, &nextname, FIArray, FALSE);  /* read subdir */
  1151. -        }
  1152. -        break;
  1153. -        default:
  1154. -        printf("Unknown storage type for '%s'\n", tmpNameBuf);
  1155. -        break;
  1156. -        }
  1157. -
  1158. -    } /* inner while */
  1159. -
  1160. -    names++, count--;
  1161. -    }  /* outer while */
  1162. -    free (nextname);
  1163. -    return (idx);
  1164. -# endif /* APW */
  1165. -
  1166. -# ifdef MSDOS
  1167. -    /* MS-DOS or other shell wildcard expansion here */
  1168. -    int idx, error;
  1169. -    struct stat fStat;
  1170. -
  1171. -    idx = 0;
  1172. -
  1173. -    while (count--) {
  1174. -
  1175. -    error = stat (*names, &fStat);
  1176. -
  1177. -    /* If the filename is a directory, we need to expand that too! */
  1178. -
  1179. -    if (!error) {
  1180. -        FIArray[idx]              = (file_info *) Malloc(sizeof(file_info));
  1181. -        FIArray[idx]->pathname    = (char *) Malloc(strlen(*names)+1);
  1182. -        strcpy(FIArray[idx]->pathname, *names);
  1183. -        FIArray[idx]->store_name  = (char *) Malloc(strlen(*names)+1);
  1184. -        strcpy(FIArray[idx]->store_name, *names);
  1185. -        FIArray[idx]->fAccess     = 0x00e3L;  /* unlocked */
  1186. -        FIArray[idx]->fileType    = defFileType;
  1187. -        FIArray[idx]->auxType     = defAuxType;
  1188. -        FIArray[idx]->storageType = 0x0000;
  1189. -        FIArray[idx]->fileSysID   = 0x0001;  /* ProDOS */
  1190. -        FIArray[idx]->fileSysInfo = 0x1c;  /* '\' */
  1191. -        ExpandTime(&fStat.st_ctime, &FIArray[idx]->create_dt);
  1192. -        ExpandTime(&fStat.st_mtime, &FIArray[idx]->mod_dt);
  1193. -        FIArray[idx]->eof = fStat.st_size;
  1194. -
  1195. -        FIArray[idx]->marked = FALSE;
  1196. -        idx++;
  1197. -    }
  1198. -    names++;
  1199. -    }
  1200. -    return (idx);
  1201. -# endif /* MDOS */
  1202. -
  1203. -# ifndef APW
  1204. -# ifndef MSDOS
  1205. -    /* nothing else defined */
  1206. -
  1207. -    /* +PORT+ */
  1208. -    printf("\n[other] wildcard expansion/file info needs work\n");
  1209. -    while (count--) {
  1210. -    FIArray[count] = (file_info *) Malloc(sizeof(file_info));
  1211. -
  1212. -    FIArray[count]->pathname = (char *) Malloc(strlen(*names)+1);
  1213. -    strcpy(FIArray[count]->pathname, *names);
  1214. -    FIArray[count]->store_name = (char *) Malloc(strlen(*names)+1);
  1215. -    strcpy(FIArray[count]->store_name, *names);
  1216. -    FIArray[count]->fAccess = 0x00e3L;  /* unlocked */
  1217. -    FIArray[count]->fileType = 0x0006L;  /* BIN */
  1218. -    FIArray[count]->auxType = 0L;
  1219. -    FIArray[count]->storageType = 0x0000;
  1220. -    FIArray[count]->fileSysID = 0x0001;  /* ProDOS */
  1221. -    FIArray[count]->fileSysInfo = 0x1c;  /* '\' */
  1222. -    ExpandTime((char *) NULL, &FIArray[count]->create_dt);
  1223. -    ExpandTime((char *) NULL, &FIArray[count]->mod_dt);
  1224. -    FIArray[count]->marked = FALSE;
  1225. -
  1226. -    names++;
  1227. -    }
  1228. -    return (count);
  1229. -# endif /* none2 */
  1230. -# endif /* none1 */
  1231. -#endif /* UNIX */
  1232. -}
  1233. -
  1234. -
  1235. -/*
  1236. - * Add a file onto the end of an archive; does not check to see if an entry
  1237. - * already exists.
  1238. - *
  1239. - * This creates the record entry, and calls subroutines to add the various
  1240. - * threads.  The archive fd should be open, the file fd should not.  Returns
  1241. - * the size of the record added.
  1242. - */
  1243. -long AddFile(arcfd, infoptr)
  1244. -int arcfd;
  1245. -file_info *infoptr;
  1246. -{
  1247. -    int srcfd;    /* file to add */
  1248. -    onebyt *recBuf;  /* record header block */
  1249. -    twobyt *twoptr;
  1250. -    THblock thread[1];    /* thread block */
  1251. -    twobyt CRC;
  1252. -    int idx;
  1253. -    fourbyt total_threads;
  1254. -    long recposn;  /* file posn for record entry */
  1255. -    long thposn;   /* file posn for last thread */
  1256. -    long tmpposn;  /* temporary file posn */
  1257. -    static char *procName = "AddFile";
  1258. -
  1259. -    if (verbose) {
  1260. -    printf("Adding '%s' (data)...",
  1261. -                      infoptr->store_name, infoptr->eof);
  1262. -    fflush(stdout);
  1263. -    }
  1264. -
  1265. -    recBuf = (onebyt *) Malloc(ATTSIZE);
  1266. -    for (idx = 0; idx < ATTSIZE; idx++)  /* zero the buffer */
  1267. -    *(recBuf+idx) = 0;
  1268. -
  1269. -    total_threads = 0;
  1270. -
  1271. -    strncpy((char *) recBuf+0, (char *) RecordID, 4);
  1272. -    twoptr = (twobyt *) (recBuf+6);
  1273. -    *twoptr = ATTSIZE;    /* don't have an attrib_count... */
  1274. -    HiSwap((onebyt *) recBuf, 6, 7);
  1275. -    twoptr = (twobyt *) (recBuf+8);
  1276. -    *twoptr = OURVERS;    /* store new record with our rec vers */
  1277. -    HiSwap((onebyt *) recBuf, 8, 9);
  1278. -    /* total_threads */
  1279. -/*    BCopy((onebyt *) &total_threads, (onebyt *) recBuf+10, 2, TRUE); */
  1280. -    *(recBuf+12) = 0;  /* reserved1 */
  1281. -    *(recBuf+13) = 0;
  1282. -    BCopy((onebyt *) &infoptr->fileSysID, (onebyt *) recBuf+14, 2, TRUE);
  1283. -    BCopy((onebyt *) &infoptr->fileSysInfo, (onebyt *) recBuf+16, 1, TRUE);
  1284. -    *(recBuf+17) = 0;  /* reserved2 */
  1285. -    BCopy((onebyt *) &infoptr->fAccess, (onebyt *) recBuf+18, 4, TRUE);
  1286. -    BCopy((onebyt *) &infoptr->fileType, (onebyt *) recBuf+22, 4, TRUE);
  1287. -    BCopy((onebyt *) &infoptr->auxType, (onebyt *) recBuf+26, 4, TRUE);
  1288. -    BCopy((onebyt *) &infoptr->create_dt, (onebyt *) recBuf+32,
  1289. -    sizeof(Time), FALSE);
  1290. -    BCopy((onebyt *) &infoptr->mod_dt, (onebyt *) recBuf+40, sizeof(Time),
  1291. -    FALSE);
  1292. -    BCopy((onebyt *) GetTime(), (onebyt *) recBuf+48, sizeof(Time), FALSE);
  1293. -    twoptr = (twobyt *) (recBuf + (ATTSIZE - 2));
  1294. -    *twoptr = strlen(infoptr->store_name);
  1295. -
  1296. -    /* correct strlen ordering */
  1297. -    HiSwap((onebyt *) recBuf, ATTSIZE-2, ATTSIZE-1);
  1298. -
  1299. -    thread[0].thread_class = 0x0002;  /* data */
  1300. -    HiSwap((onebyt *) &thread[0].thread_class, 0, 1);
  1301. -    thread[0].thread_kind = 0x0000;  /* data fork */
  1302. -    HiSwap((onebyt *) &thread[0].thread_kind, 0, 1);
  1303. -    thread[0].thread_format = 0x0000;  /* filled in later */
  1304. -    thread[0].thread_crc = 0x0000;  /* not supported yet */
  1305. -    /* so I don't forget if I support these */
  1306. -    HiSwap((onebyt *) &thread[0].thread_crc, 0, 1); 
  1307. -    thread[0].thread_eof = infoptr->eof;
  1308. -    HiSwap((onebyt *) &thread[0].thread_eof, 0, 3);
  1309. -    HiSwap((onebyt *) &thread[0].thread_eof, 1, 2);
  1310. -    thread[0].comp_thread_eof = -1L;  /* filled in later */
  1311. -    total_threads++;
  1312. -
  1313. -    BCopy((onebyt *) &total_threads, (onebyt *) recBuf+10, 4, TRUE);
  1314. -
  1315. -    /*
  1316. -     * Because we don't know CRCs or compressed size yet, we must:
  1317. -     * skip record entry and filename.
  1318. -     * for each thread:
  1319. -     *     skip thread entry, write data, move back, write thread entry.
  1320. -     * move back, write record entry and filename.
  1321. -     * move forward to next position.
  1322. -     */
  1323. -    if ((srcfd = open(infoptr->pathname, O_RDONLY | O_BINARY)) < 0)
  1324. -    Fatal("Unable to open file", procName);
  1325. -
  1326. -    recposn = lseek(arcfd, 0L, S_REL);    /* save record posn */
  1327. -    if (lseek(arcfd, (long) (ATTSIZE + strlen(infoptr->store_name)), S_REL)<0)
  1328. -    Fatal("Bad seek (R.rel)", procName);
  1329. -
  1330. -    /* loop... */
  1331. -    thposn = lseek(arcfd, 0L, S_REL);  /* save thread posn */
  1332. -    if (lseek(arcfd, (long) THsize, S_REL) < 0)
  1333. -    Fatal("Bad seek (Th)", procName);
  1334. -
  1335. -    /*
  1336. -     * since we can store files as being packed without actually packing them,
  1337. -     * we need to check "dopack" to see if we want packMethod or zero.  Note
  1338. -     * that packing can fail for various reasons; the value returned by
  1339. -     * PackFile() is the actual algorithm used to pack the file.
  1340. -     *
  1341. -     * NuLib uses version 0 records; thread_crcs are not stored.
  1342. -     */
  1343. -
  1344. -    thread[0].thread_format = 
  1345. -        PackFile(srcfd,arcfd, infoptr->eof, dopack ? packMethod:0, pakbuf);
  1346. -    if (!dopack) thread[0].thread_format = packMethod;  /* for S subopt */
  1347. -    HiSwap((onebyt *) &thread[0].thread_format, 0, 1);
  1348. -    thread[0].comp_thread_eof = (fourbyt) packedSize;
  1349. -    HiSwap((onebyt *) &thread[0].comp_thread_eof, 0, 3);  /* correct ordering*/
  1350. -    HiSwap((onebyt *) &thread[0].comp_thread_eof, 1, 2);
  1351. -    tmpposn = lseek(arcfd, 0L, S_REL);
  1352. -
  1353. -    if (lseek(arcfd, thposn, S_ABS) < 0)  /* seek back to thread posn */
  1354. -    Fatal("Bad seek (Th2)", procName);
  1355. -    if (write(arcfd, &thread[0], THsize) < THsize)  /* write updated thread */
  1356. -    Fatal("Unable to write thread", procName);
  1357. -    if (lseek(arcfd, tmpposn, S_ABS) < 0)  /* seek back to where we were */
  1358. -    Fatal("Bad seek (TmpA)", procName);
  1359. -    /* ...loop end */
  1360. -
  1361. -    if (close(srcfd) < 0)
  1362. -    Fatal("Unable to close file", procName);
  1363. -
  1364. -    CRC = CalcCRC(0, (onebyt *) recBuf+6, ATTSIZE-6);
  1365. -    CRC = CalcCRC(CRC, (onebyt *) infoptr->store_name,
  1366. -    strlen(infoptr->store_name));
  1367. -    CRC = CalcCRC(CRC, (onebyt *) &thread[0], THsize);
  1368. -    twoptr = (twobyt *) (recBuf+4);
  1369. -    *twoptr = CRC;
  1370. -    HiSwap((onebyt *) recBuf, 4, 5);
  1371. -
  1372. -    tmpposn = lseek(arcfd, 0L, S_REL);       /* record posn (next posn) */
  1373. -    if (lseek(arcfd, recposn, S_ABS) < 0)  /* seek back to record entry */
  1374. -    Fatal("Bad seek (R.abs)", procName);
  1375. -    if (write(arcfd, recBuf, ATTSIZE) < ATTSIZE)
  1376. -    Fatal("Unable to write record", procName);
  1377. -    if (write(arcfd, infoptr->store_name, strlen(infoptr->store_name))
  1378. -                     < strlen(infoptr->store_name))
  1379. -    Fatal("Unable to store filename", procName);
  1380. -    if (lseek(arcfd, tmpposn, S_ABS) < 0)  /* seek back to where we were */
  1381. -    Fatal("Bad seek (TmpB)", procName);
  1382. -
  1383. -    if (verbose) printf("done.\n");
  1384. -    free(recBuf);
  1385. -
  1386. -    /* switch ordering back */
  1387. -    HiSwap((onebyt *) &thread[0].comp_thread_eof, 0, 3);
  1388. -    HiSwap((onebyt *) &thread[0].comp_thread_eof, 1, 2);
  1389. -    return ( (long) (THsize * total_threads) + (long) ATTSIZE +
  1390. -      (long) strlen(infoptr->store_name) + thread[0].comp_thread_eof);
  1391. -}
  1392. -
  1393. -
  1394. -/*
  1395. - * Certain options can cause an archive to be created (add, create, move).
  1396. - * If the archive does not already exist, then an empty file is created (of
  1397. - * type $e0/8002 under ProDOS) and an empty archive struct is built.
  1398. - *
  1399. - * Note that this requires certain options to deal with archive structures that
  1400. - * do not have any records, and archive files that are empty.
  1401. - *
  1402. - * If the file exists, this will call NuRead() to read it; otherwise, it will
  1403. - * create it.
  1404. - */
  1405. -static ListHdr *CreateMaybe(filename)
  1406. -char *filename;
  1407. -{
  1408. -    ListHdr *archive;
  1409. -    MHblock *MHptr;
  1410. -    onebyt *bufPtr;
  1411. -    twobyt *twoptr;
  1412. -    fourbyt *fourptr;
  1413. -    int idx;
  1414. -#ifdef APW
  1415. -    FileRec create_p;
  1416. -#endif
  1417. -    static char *procName = "CreateMaybe";
  1418. -
  1419. -    if (Exists(filename)) {
  1420. -    archive = NuRead(filename);
  1421. -    return (archive);
  1422. -    }
  1423. -
  1424. -    if (!docreate)
  1425. -    printf("Archive does not exist; creating archive file...\n");
  1426. -
  1427. -    archive = (ListHdr *) Malloc(sizeof(ListHdr));
  1428. -    archive->arc_name = (char *) Malloc(strlen(filename)+1);
  1429. -    strcpy(archive->arc_name, filename);
  1430. -    archive->MHptr = (MHblock *) Malloc(sizeof(MHblock));
  1431. -    archive->RNodePtr = (RNode *) NULL;
  1432. -    archive->nextposn = (long) MHsize;
  1433. -
  1434. -    bufPtr = (onebyt *) archive->MHptr;
  1435. -    for (idx = 0; idx < MHsize; idx++)
  1436. -    *(bufPtr+idx) = '\0';
  1437. -
  1438. -    /* total_records -> zero */
  1439. -    MHptr = archive->MHptr;
  1440. -    strncpy((char *) MHptr->ID, (char *) MasterID, 6);
  1441. -    BCopy((onebyt *) GetTime(), (onebyt *) &(MHptr->arc_create_when),8, FALSE);
  1442. -    BCopy((onebyt *) bufPtr+12, (onebyt *) &(MHptr->arc_mod_when), 8, FALSE);
  1443. -    fourptr = (fourbyt *) (&(MHptr->master_eof));
  1444. -    *fourptr = (fourbyt) MHsize;
  1445. -
  1446. -/*    twoptr = (twobyt *) (&(MHptr->master_crc));
  1447. -    *twoptr = CalcCRC(0, (onebyt *) bufPtr+8, MHsize-8); */
  1448. -
  1449. -    ArcfiCreate(filename);  /* create SHK file */
  1450. -    return (archive);
  1451. -}
  1452. -
  1453. -
  1454. -/*
  1455. - * Return a pointer to a valid Master Header block
  1456. - * Anything that isn't set to a default value needs to be passed as a
  1457. - * parameter [ right now I can't remember why ].
  1458. - */
  1459. -onebyt *MakeMHblock(archive, total_records, master_eof)
  1460. -ListHdr *archive;
  1461. -fourbyt total_records;
  1462. -fourbyt master_eof;
  1463. -{
  1464. -    static onebyt buf[MHsize];  /* must be static */
  1465. -    twobyt *twoptr;
  1466. -    fourbyt *fourptr;
  1467. -    int idx;
  1468. -    static char *procName = "MakeMHblock";
  1469. -
  1470. -    for (idx = 0; idx < MHsize ; idx++)
  1471. -    buf[idx] = '\0';
  1472. -
  1473. -    /* messy... should've used MHptr->thing here, but if it ain't broke... */
  1474. -    strncpy((char *) buf, (char *) MasterID, 6);
  1475. -    BCopy((onebyt *) &total_records, (onebyt *) &buf[8], 4, TRUE);
  1476. -    BCopy((onebyt *) &archive->MHptr->arc_create_when, (onebyt *) &buf[12],
  1477. -    sizeof(Time), FALSE);
  1478. -    BCopy((onebyt *) GetTime(), (onebyt *) &buf[20], sizeof(Time), FALSE);
  1479. -    twoptr = (twobyt *) &buf[28];  /* master version */
  1480. -    *twoptr = OURMVERS;
  1481. -    HiSwap((onebyt *) buf, 28, 29);  /* correct byte ordering */
  1482. -    BCopy((onebyt *) &master_eof, (onebyt *) &buf[38], 4, TRUE);
  1483. -    twoptr = (twobyt *) &buf[6];
  1484. -    *twoptr = CalcCRC(0, (onebyt *) &buf[8], MHsize-8);
  1485. -    HiSwap((onebyt *) buf, 6, 7);
  1486. -
  1487. -    return (buf);
  1488. -}
  1489. -
  1490. -
  1491. -/*
  1492. - * Add files to archive
  1493. - *
  1494. - * Read files from disk, adding them to the end of the archive as we go.
  1495. - * Update the master header block after all files have been added.
  1496. - */
  1497. -static void Add(filename, namecount, names)
  1498. -char *filename;
  1499. -int namecount;
  1500. -char **names;
  1501. -{
  1502. -    ListHdr *archive;
  1503. -    int arcfd;
  1504. -    file_info *FIArray[MAXARGS];  /* entries malloc()ed by EvalArgs */
  1505. -    int idx;
  1506. -    onebyt *mptr;  /* points to a MHblock suitable for writing */
  1507. -    long addSize;
  1508. -    static char *procName = "Add";
  1509. -
  1510. -    /* expand wildcards/subdirectories, and get file info */
  1511. -    namecount = EvalArgs(namecount, names, FIArray, TRUE);
  1512. -    if (!namecount) {
  1513. -    if (verbose) printf("No files selected.\n");
  1514. -    Quit (0);
  1515. -    }
  1516. -
  1517. -    archive = CreateMaybe(filename);
  1518. -    if ((arcfd = open(archive->arc_name, O_RDWR | O_BINARY)) < 0)
  1519. -    Fatal("Unable to open archive", procName);
  1520. -    if (lseek(arcfd, archive->nextposn, S_ABS) < 0)  /* seek to end */
  1521. -    Fatal("Unable to seek in archive", procName);
  1522. -
  1523. -    for (idx = 0 ; idx < namecount; idx++) {
  1524. -#ifdef APW
  1525. -    if (STOP()) Quit(1);  /* check for OA-. */
  1526. -#endif
  1527. -    addSize = AddFile(arcfd, FIArray[idx]);
  1528. -    archive->MHptr->master_eof += addSize;
  1529. -    archive->nextposn += addSize;
  1530. -    archive->MHptr->total_records++;
  1531. -    }
  1532. -
  1533. -    mptr = MakeMHblock(archive, archive->MHptr->total_records,
  1534. -        archive->MHptr->master_eof);
  1535. -    if (lseek(arcfd, 0L, S_ABS) < 0)
  1536. -    Fatal("Unable to rewind archive for master header", procName);
  1537. -
  1538. -    if (write(arcfd, mptr, MHsize) < MHsize)
  1539. -    Fatal("Unable to update master header", procName);
  1540. -    if (close(arcfd) < 0)
  1541. -    Fatal("Unable to close archive", procName);
  1542. -
  1543. -    if (domove) {
  1544. -    if (verbose) printf("Deleteing files...\n");
  1545. -    for (idx = 0; idx < namecount; idx++) {
  1546. -        if (verbose) {
  1547. -        printf("%s...", FIArray[idx]->pathname);
  1548. -        fflush(stdout);
  1549. -        }
  1550. -        if (unlink(FIArray[idx]->pathname) < 0) {
  1551. -        if (verbose) printf("failed.\n");
  1552. -        } else {
  1553. -        if (verbose) printf("done.\n");
  1554. -        }
  1555. -    }
  1556. -    }
  1557. -}
  1558. -
  1559. -
  1560. -/*
  1561. - * Main entry point for adding files.
  1562. - */
  1563. -void NuAdd(filename, namecount, names, options)
  1564. -char *filename;
  1565. -int namecount;
  1566. -char **names;
  1567. -char *options;
  1568. -{
  1569. -    char *optr;
  1570. -    int idx;
  1571. -    char type[5];
  1572. -    static char *procName = "NuAdd";
  1573. -
  1574. -    if (*options == 'm')
  1575. -    domove = TRUE;
  1576. -
  1577. -    if (*options == 'c')
  1578. -    docreate = TRUE;
  1579. -
  1580. -    /* change T subopt to convert FROM current system TO <subopt> */
  1581. -    if (transfrom >= 0) {
  1582. -    transto = transfrom;
  1583. -    transfrom = -1;
  1584. -    }
  1585. -
  1586. -    Add(filename, namecount, names);  /* do main processing */
  1587. -}
  1588. -
  1589. + END OF ARCHIVE
  1590.